summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorart <art@openbsd.org>1998-09-14 21:52:50 +0000
committerart <art@openbsd.org>1998-09-14 21:52:50 +0000
commitb99f08ec7ea163cd8955cddd916caa7f42324fdd (patch)
treeed599437c09ca5911e9f1d726f57d53f6b2ce491
parentsync (diff)
downloadwireguard-openbsd-b99f08ec7ea163cd8955cddd916caa7f42324fdd.tar.xz
wireguard-openbsd-b99f08ec7ea163cd8955cddd916caa7f42324fdd.zip
Initial version of Arla, a free implementation of an AFS cache-manager.
(second try, hopefully into the correct repository this time)
-rw-r--r--usr.sbin/afs/Applflags.inc9
-rw-r--r--usr.sbin/afs/Makefile29
-rw-r--r--usr.sbin/afs/Makefile.inc12
-rw-r--r--usr.sbin/afs/afsd/Makefile12
-rw-r--r--usr.sbin/afs/afsd/afsd.8130
-rw-r--r--usr.sbin/afs/fs/Makefile12
-rw-r--r--usr.sbin/afs/libarla/Makefile22
-rw-r--r--usr.sbin/afs/libarla/Makefile.ko.inc15
-rw-r--r--usr.sbin/afs/libarla/Makefile.lwp.inc23
-rw-r--r--usr.sbin/afs/libarla/Makefile.rx.inc5
-rw-r--r--usr.sbin/afs/libarla/Makefile.rxdef.inc37
-rw-r--r--usr.sbin/afs/libarla/Makefile.rxkad.inc7
-rw-r--r--usr.sbin/afs/libroken/Makefile24
-rw-r--r--usr.sbin/afs/libroken/atypes.h11
-rw-r--r--usr.sbin/afs/libroken/config.h659
-rw-r--r--usr.sbin/afs/libroken/version.h3
-rw-r--r--usr.sbin/afs/pts/Makefile11
-rw-r--r--usr.sbin/afs/src/ChangeLog2940
-rw-r--r--usr.sbin/afs/src/INSTALL230
-rw-r--r--usr.sbin/afs/src/NEWS187
-rw-r--r--usr.sbin/afs/src/README162
-rw-r--r--usr.sbin/afs/src/THANKS23
-rw-r--r--usr.sbin/afs/src/TODO38
-rw-r--r--usr.sbin/afs/src/appl/appl_locl.h120
-rw-r--r--usr.sbin/afs/src/appl/arlalib.c248
-rw-r--r--usr.sbin/afs/src/appl/arlalib.h90
-rw-r--r--usr.sbin/afs/src/appl/fs.c1637
-rw-r--r--usr.sbin/afs/src/appl/fs_lib.c306
-rw-r--r--usr.sbin/afs/src/appl/fs_local.h148
-rw-r--r--usr.sbin/afs/src/appl/pts.c723
-rw-r--r--usr.sbin/afs/src/appl/udebug.c263
-rw-r--r--usr.sbin/afs/src/appl/vos.c915
-rw-r--r--usr.sbin/afs/src/appl/vos_local.h57
-rw-r--r--usr.sbin/afs/src/arlad/adir.c635
-rw-r--r--usr.sbin/afs/src/arlad/adir.h75
-rw-r--r--usr.sbin/afs/src/arlad/afs_dir.h111
-rw-r--r--usr.sbin/afs/src/arlad/afsdir_check.c281
-rw-r--r--usr.sbin/afs/src/arlad/arla.c870
-rw-r--r--usr.sbin/afs/src/arlad/arla_local.h161
-rw-r--r--usr.sbin/afs/src/arlad/arladeb.c201
-rw-r--r--usr.sbin/afs/src/arlad/arladeb.h118
-rw-r--r--usr.sbin/afs/src/arlad/bsd-subr.c156
-rw-r--r--usr.sbin/afs/src/arlad/cmcb.c153
-rw-r--r--usr.sbin/afs/src/arlad/cmcb.h47
-rw-r--r--usr.sbin/afs/src/arlad/conn.c468
-rw-r--r--usr.sbin/afs/src/arlad/conn.h90
-rw-r--r--usr.sbin/afs/src/arlad/cred.c317
-rw-r--r--usr.sbin/afs/src/arlad/cred.h111
-rw-r--r--usr.sbin/afs/src/arlad/fbuf.c377
-rw-r--r--usr.sbin/afs/src/arlad/fbuf.h63
-rw-r--r--usr.sbin/afs/src/arlad/fcache.c2457
-rw-r--r--usr.sbin/afs/src/arlad/fcache.h252
-rw-r--r--usr.sbin/afs/src/arlad/fprio.c300
-rw-r--r--usr.sbin/afs/src/arlad/fprio.h70
-rw-r--r--usr.sbin/afs/src/arlad/inter.c1034
-rw-r--r--usr.sbin/afs/src/arlad/inter.h129
-rw-r--r--usr.sbin/afs/src/arlad/kernel.c119
-rw-r--r--usr.sbin/afs/src/arlad/kernel.h49
-rw-r--r--usr.sbin/afs/src/arlad/messages.c2452
-rw-r--r--usr.sbin/afs/src/arlad/messages.h54
-rw-r--r--usr.sbin/afs/src/arlad/service.h51
-rw-r--r--usr.sbin/afs/src/arlad/subr.h54
-rw-r--r--usr.sbin/afs/src/arlad/volcache.c627
-rw-r--r--usr.sbin/afs/src/arlad/volcache.h106
-rw-r--r--usr.sbin/afs/src/conf/CellServDB693
-rw-r--r--usr.sbin/afs/src/conf/ThisCell1
-rw-r--r--usr.sbin/afs/src/conf/arla.conf49
-rw-r--r--usr.sbin/afs/src/include/.cvsignore1
-rw-r--r--usr.sbin/afs/src/include/bits.c207
-rw-r--r--usr.sbin/afs/src/include/config.h657
-rw-r--r--usr.sbin/afs/src/include/stds.h62
-rw-r--r--usr.sbin/afs/src/lib/ko/gensysname.c242
-rw-r--r--usr.sbin/afs/src/lib/ko/ko.h85
-rw-r--r--usr.sbin/afs/src/lib/ko/ko_locl.h81
-rw-r--r--usr.sbin/afs/src/lib/ko/kocell.c566
-rw-r--r--usr.sbin/afs/src/lib/ko/kodebug.c53
-rw-r--r--usr.sbin/afs/src/lib/ko/kodebug.h61
-rw-r--r--usr.sbin/afs/src/lib/ko/koerror.c160
-rw-r--r--usr.sbin/afs/src/lib/ko/ports.c104
-rw-r--r--usr.sbin/afs/src/lib/ko/ports.h55
-rw-r--r--usr.sbin/afs/src/lib/roken/ChangeLog29
-rw-r--r--usr.sbin/afs/src/lib/roken/base64.c150
-rw-r--r--usr.sbin/afs/src/lib/roken/base64.h48
-rw-r--r--usr.sbin/afs/src/lib/roken/chown.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/daemon.c89
-rw-r--r--usr.sbin/afs/src/lib/roken/err.c54
-rw-r--r--usr.sbin/afs/src/lib/roken/err.h77
-rw-r--r--usr.sbin/afs/src/lib/roken/errx.c54
-rw-r--r--usr.sbin/afs/src/lib/roken/fchown.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/flock.c93
-rw-r--r--usr.sbin/afs/src/lib/roken/fnmatch.c174
-rw-r--r--usr.sbin/afs/src/lib/roken/fnmatch.h50
-rw-r--r--usr.sbin/afs/src/lib/roken/get_window_size.c97
-rw-r--r--usr.sbin/afs/src/lib/roken/getarg.c474
-rw-r--r--usr.sbin/afs/src/lib/roken/getarg.h87
-rw-r--r--usr.sbin/afs/src/lib/roken/getcwd.c63
-rw-r--r--usr.sbin/afs/src/lib/roken/getdtablesize.c107
-rw-r--r--usr.sbin/afs/src/lib/roken/getopt.c129
-rw-r--r--usr.sbin/afs/src/lib/roken/getusershell.c161
-rw-r--r--usr.sbin/afs/src/lib/roken/hstrerror.c93
-rw-r--r--usr.sbin/afs/src/lib/roken/inaddr2str.c96
-rw-r--r--usr.sbin/afs/src/lib/roken/inet_aton.c76
-rw-r--r--usr.sbin/afs/src/lib/roken/initgroups.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/k_getpwnam.c70
-rw-r--r--usr.sbin/afs/src/lib/roken/k_getpwuid.c70
-rw-r--r--usr.sbin/afs/src/lib/roken/lstat.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/memmove.c70
-rw-r--r--usr.sbin/afs/src/lib/roken/mini_inetd.c114
-rw-r--r--usr.sbin/afs/src/lib/roken/mkstemp.c90
-rw-r--r--usr.sbin/afs/src/lib/roken/parse_time.c72
-rw-r--r--usr.sbin/afs/src/lib/roken/parse_time.h51
-rw-r--r--usr.sbin/afs/src/lib/roken/parse_units.c325
-rw-r--r--usr.sbin/afs/src/lib/roken/parse_units.h79
-rw-r--r--usr.sbin/afs/src/lib/roken/putenv.c82
-rw-r--r--usr.sbin/afs/src/lib/roken/rcmd.c58
-rw-r--r--usr.sbin/afs/src/lib/roken/readv.c73
-rw-r--r--usr.sbin/afs/src/lib/roken/recvmsg.c74
-rw-r--r--usr.sbin/afs/src/lib/roken/resolve.c346
-rw-r--r--usr.sbin/afs/src/lib/roken/resolve.h111
-rw-r--r--usr.sbin/afs/src/lib/roken/roken.def10
-rw-r--r--usr.sbin/afs/src/lib/roken/roken.h458
-rw-r--r--usr.sbin/afs/src/lib/roken/roken.mak316
-rw-r--r--usr.sbin/afs/src/lib/roken/sendmsg.c71
-rw-r--r--usr.sbin/afs/src/lib/roken/setegid.c63
-rw-r--r--usr.sbin/afs/src/lib/roken/setenv.c72
-rw-r--r--usr.sbin/afs/src/lib/roken/seteuid.c63
-rw-r--r--usr.sbin/afs/src/lib/roken/signal.c87
-rw-r--r--usr.sbin/afs/src/lib/roken/snprintf.c621
-rw-r--r--usr.sbin/afs/src/lib/roken/strcasecmp.c119
-rw-r--r--usr.sbin/afs/src/lib/roken/strdup.c56
-rw-r--r--usr.sbin/afs/src/lib/roken/strerror.c63
-rw-r--r--usr.sbin/afs/src/lib/roken/strftime.c302
-rw-r--r--usr.sbin/afs/src/lib/roken/strlwr.c59
-rw-r--r--usr.sbin/afs/src/lib/roken/strnlen.c54
-rw-r--r--usr.sbin/afs/src/lib/roken/strsep.c67
-rw-r--r--usr.sbin/afs/src/lib/roken/strtok_r.c71
-rw-r--r--usr.sbin/afs/src/lib/roken/strupr.c59
-rw-r--r--usr.sbin/afs/src/lib/roken/tm2time.c67
-rw-r--r--usr.sbin/afs/src/lib/roken/unsetenv.c76
-rw-r--r--usr.sbin/afs/src/lib/roken/verify.c68
-rw-r--r--usr.sbin/afs/src/lib/roken/verr.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/verrx.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/vsyslog.c63
-rw-r--r--usr.sbin/afs/src/lib/roken/vwarn.c51
-rw-r--r--usr.sbin/afs/src/lib/roken/vwarnx.c52
-rw-r--r--usr.sbin/afs/src/lib/roken/warn.c54
-rw-r--r--usr.sbin/afs/src/lib/roken/warnerr.c87
-rw-r--r--usr.sbin/afs/src/lib/roken/warnx.c54
-rw-r--r--usr.sbin/afs/src/lib/roken/writev.c70
-rw-r--r--usr.sbin/afs/src/lib/roken/xdbm.h76
-rw-r--r--usr.sbin/afs/src/lib/sl/ChangeLog8
-rw-r--r--usr.sbin/afs/src/lib/sl/sl.c285
-rw-r--r--usr.sbin/afs/src/lib/sl/sl.h63
-rw-r--r--usr.sbin/afs/src/lib/sl/sl_locl.h48
-rw-r--r--usr.sbin/afs/src/lwp/fasttime.c184
-rw-r--r--usr.sbin/afs/src/lwp/iomgr.c868
-rw-r--r--usr.sbin/afs/src/lwp/lock.c251
-rw-r--r--usr.sbin/afs/src/lwp/lock.h225
-rw-r--r--usr.sbin/afs/src/lwp/lwp.c1055
-rw-r--r--usr.sbin/afs/src/lwp/lwp.h209
-rw-r--r--usr.sbin/afs/src/lwp/make-process.o.sh.in161
-rw-r--r--usr.sbin/afs/src/lwp/preempt.c146
-rw-r--r--usr.sbin/afs/src/lwp/preempt.h43
-rw-r--r--usr.sbin/afs/src/lwp/process.S1427
-rw-r--r--usr.sbin/afs/src/lwp/process.s.hpux219
-rw-r--r--usr.sbin/afs/src/lwp/q.c54
-rw-r--r--usr.sbin/afs/src/lwp/q.h5
-rw-r--r--usr.sbin/afs/src/lwp/testlwp.c314
-rw-r--r--usr.sbin/afs/src/lwp/testprocess.c23
-rw-r--r--usr.sbin/afs/src/lwp/timer.c266
-rw-r--r--usr.sbin/afs/src/lwp/timer.h74
-rw-r--r--usr.sbin/afs/src/rx/LICENSE27
-rw-r--r--usr.sbin/afs/src/rx/doyle17
-rw-r--r--usr.sbin/afs/src/rx/rx.c4067
-rw-r--r--usr.sbin/afs/src/rx/rx.h1065
-rw-r--r--usr.sbin/afs/src/rx/rx_clock.c104
-rw-r--r--usr.sbin/afs/src/rx/rx_clock.h154
-rw-r--r--usr.sbin/afs/src/rx/rx_event.c230
-rw-r--r--usr.sbin/afs/src/rx/rx_event.h102
-rw-r--r--usr.sbin/afs/src/rx/rx_globs.c31
-rw-r--r--usr.sbin/afs/src/rx/rx_globs.h290
-rw-r--r--usr.sbin/afs/src/rx/rx_kern.h81
-rw-r--r--usr.sbin/afs/src/rx/rx_locl.h104
-rw-r--r--usr.sbin/afs/src/rx/rx_mach.h93
-rw-r--r--usr.sbin/afs/src/rx/rx_misc.c92
-rw-r--r--usr.sbin/afs/src/rx/rx_misc.h49
-rw-r--r--usr.sbin/afs/src/rx/rx_multi.c112
-rw-r--r--usr.sbin/afs/src/rx/rx_multi.h81
-rw-r--r--usr.sbin/afs/src/rx/rx_null.c44
-rw-r--r--usr.sbin/afs/src/rx/rx_null.h40
-rw-r--r--usr.sbin/afs/src/rx/rx_pkt.c1329
-rw-r--r--usr.sbin/afs/src/rx/rx_pkt.h291
-rw-r--r--usr.sbin/afs/src/rx/rx_queue.h186
-rw-r--r--usr.sbin/afs/src/rx/rx_rdwr.c465
-rw-r--r--usr.sbin/afs/src/rx/rx_strm.h102
-rw-r--r--usr.sbin/afs/src/rx/rx_trace.c159
-rw-r--r--usr.sbin/afs/src/rx/rx_trace.h21
-rw-r--r--usr.sbin/afs/src/rx/rx_user.c600
-rw-r--r--usr.sbin/afs/src/rx/rx_user.h106
-rw-r--r--usr.sbin/afs/src/rx/transarc135
-rw-r--r--usr.sbin/afs/src/rxdef/cb.xg33
-rw-r--r--usr.sbin/afs/src/rxdef/common.h166
-rw-r--r--usr.sbin/afs/src/rxdef/fs.xg146
-rw-r--r--usr.sbin/afs/src/rxdef/pts.xg303
-rw-r--r--usr.sbin/afs/src/rxdef/ubik.xg88
-rw-r--r--usr.sbin/afs/src/rxdef/vldb.xg265
-rw-r--r--usr.sbin/afs/src/rxdef/volumeserver.xg239
-rw-r--r--usr.sbin/afs/src/rxkad/compat.c177
-rw-r--r--usr.sbin/afs/src/rxkad/osi_alloc.c63
-rw-r--r--usr.sbin/afs/src/rxkad/rxk_clnt.c355
-rw-r--r--usr.sbin/afs/src/rxkad/rxk_crpt.c767
-rw-r--r--usr.sbin/afs/src/rxkad/rxk_info.c75
-rw-r--r--usr.sbin/afs/src/rxkad/rxk_locl.c276
-rw-r--r--usr.sbin/afs/src/rxkad/rxk_serv.c558
-rw-r--r--usr.sbin/afs/src/rxkad/rxkad.h169
-rw-r--r--usr.sbin/afs/src/rxkad/rxkad_locl.h195
-rw-r--r--usr.sbin/afs/src/util/atom.c72
-rw-r--r--usr.sbin/afs/src/util/atom.h48
-rw-r--r--usr.sbin/afs/src/util/bool.h61
-rw-r--r--usr.sbin/afs/src/util/date_rfc822.c80
-rw-r--r--usr.sbin/afs/src/util/date_rfc822.h48
-rw-r--r--usr.sbin/afs/src/util/efile.c102
-rw-r--r--usr.sbin/afs/src/util/efile.h53
-rw-r--r--usr.sbin/afs/src/util/fnameutil.c92
-rw-r--r--usr.sbin/afs/src/util/fnameutil.h48
-rw-r--r--usr.sbin/afs/src/util/freelist.c107
-rw-r--r--usr.sbin/afs/src/util/freelist.h57
-rw-r--r--usr.sbin/afs/src/util/hash.c251
-rw-r--r--usr.sbin/afs/src/util/hash.h101
-rw-r--r--usr.sbin/afs/src/util/ip.c88
-rw-r--r--usr.sbin/afs/src/util/ip.h52
-rw-r--r--usr.sbin/afs/src/util/list.c283
-rw-r--r--usr.sbin/afs/src/util/list.h99
-rw-r--r--usr.sbin/afs/src/util/log.c261
-rw-r--r--usr.sbin/afs/src/util/log.h75
-rw-r--r--usr.sbin/afs/src/util/mem.c89
-rw-r--r--usr.sbin/afs/src/util/mem.h50
-rw-r--r--usr.sbin/afs/src/util/minmax.h50
-rw-r--r--usr.sbin/afs/src/util/mmaptime.c203
-rw-r--r--usr.sbin/afs/src/util/mmaptime.h53
-rw-r--r--usr.sbin/afs/src/util/mmaptime_test.c131
-rw-r--r--usr.sbin/afs/src/util/prio.c173
-rw-r--r--usr.sbin/afs/src/util/prio.h69
-rw-r--r--usr.sbin/afs/src/util/strmatch.c84
-rw-r--r--usr.sbin/afs/src/util/strmatch.h48
-rw-r--r--usr.sbin/afs/src/util/strsplit.c102
-rw-r--r--usr.sbin/afs/src/util/strsplit.h50
-rw-r--r--usr.sbin/afs/src/util/strutil.c105
-rw-r--r--usr.sbin/afs/src/util/strutil.h49
-rw-r--r--usr.sbin/afs/src/util/timeprio.c114
-rw-r--r--usr.sbin/afs/src/util/timeprio.h70
-rw-r--r--usr.sbin/afs/src/util/timeval.c81
-rw-r--r--usr.sbin/afs/src/util/timeval.h57
-rw-r--r--usr.sbin/afs/src/util/util-tester.c161
-rw-r--r--usr.sbin/afs/src/ydr/lex.h47
-rw-r--r--usr.sbin/afs/src/ydr/lex.l167
-rw-r--r--usr.sbin/afs/src/ydr/main.c118
-rw-r--r--usr.sbin/afs/src/ydr/output.c1428
-rw-r--r--usr.sbin/afs/src/ydr/output.h63
-rw-r--r--usr.sbin/afs/src/ydr/parse.y314
-rw-r--r--usr.sbin/afs/src/ydr/sym.h79
-rw-r--r--usr.sbin/afs/src/ydr/symbol.c143
-rw-r--r--usr.sbin/afs/src/ydr/types.c176
-rw-r--r--usr.sbin/afs/src/ydr/types.h87
-rw-r--r--usr.sbin/afs/vos/Makefile12
-rw-r--r--usr.sbin/afs/ydr/Makefile22
266 files changed, 58047 insertions, 0 deletions
diff --git a/usr.sbin/afs/Applflags.inc b/usr.sbin/afs/Applflags.inc
new file mode 100644
index 00000000000..645fc17c0a6
--- /dev/null
+++ b/usr.sbin/afs/Applflags.inc
@@ -0,0 +1,9 @@
+LDADD += -lkrb -ldes ../libarla/libarla.a -ltermcap ../libroken/libroken.a -lreadline
+DPADD += ../libroken/libroken.a ../libarla/libarla.a ${LIBKRB} ${LIBDES} ${LIBREADLINE} ${LIBTERMCAP}
+CFLAGS += -I${.CURDIR}/../src/util -I${.CURDIR}/../src/lib/roken \
+ -I${.CURDIR}/../src/include -I${.CURDIR}/../libroken \
+ -I${.CURDIR}/../src/rxdef -I${.CURDIR}/../src/lwp -I../libarla \
+ -I${.CURDIR}/../src/arlad -I${.CURDIR}/../src \
+ -I${.CURDIR}/../src/lib/ko -I${.CURDIR}/../src/rxkad \
+ -I${.CURDIR}/../src/lib/sl
+
diff --git a/usr.sbin/afs/Makefile b/usr.sbin/afs/Makefile
new file mode 100644
index 00000000000..5aa4474a68d
--- /dev/null
+++ b/usr.sbin/afs/Makefile
@@ -0,0 +1,29 @@
+# $OpenBSD: Makefile,v 1.1.1.1 1998/09/14 21:52:50 art Exp $
+
+#
+# This is hairy. libroken (originally libroken and libutil) has to be built
+# before ydr. But libroken should be a part of libarla (because libarla uses
+# libroken), but libarla needs ydr to be able to build. Yuck.
+#
+# To the future maintainer (if I get hit by a car or something): The structure
+# is like this (everything in src, except the makefiles), because we want
+# the upgrade process to be easy, without building and installing 5 different
+# libs and without making a hairy Makefile.bsd-wrapper
+#
+
+.if !make(install)
+SUBDIR += libroken
+SUBDIR += ydr
+SUBDIR += libarla
+.endif
+SUBDIR += afsd fs vos pts
+
+## To be able to make depend in libarla we have to have ydr (that needs
+## libroken) and libroken used by gensysname in (libarla/Makefile.ko.inc)
+
+beforedepend:
+ (cd libroken && make depend && make)
+ (cd ydr && make depend && make)
+
+.include <bsd.dep.mk>
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/afs/Makefile.inc b/usr.sbin/afs/Makefile.inc
new file mode 100644
index 00000000000..b7f0d3de027
--- /dev/null
+++ b/usr.sbin/afs/Makefile.inc
@@ -0,0 +1,12 @@
+OS_VER != uname -r
+BINDIR ?=/usr/sbin
+CFLAGS += -DHAVE_CONFIG_H -DSYSCONFDIR=\"/etc\" \
+ -DARLACACHEDIR=\"/var/spool/afs\"\
+ -DARLACONFFILE=\"/etc/arla.conf\" -DKERBEROS \
+ -DARLAVENDOR=\"unknown\" -DARLACPU=\"${MACHINE_ARCH}\" \
+ -DARLAOS=\"openbsd${OS_VER}\" \
+
+.if (${MACHINE_ARCH} == "sparc")
+CFLAGS += -DBROKEN_MMAP
+.endif
+
diff --git a/usr.sbin/afs/afsd/Makefile b/usr.sbin/afs/afsd/Makefile
new file mode 100644
index 00000000000..69731473967
--- /dev/null
+++ b/usr.sbin/afs/afsd/Makefile
@@ -0,0 +1,12 @@
+# $OpenBSD: Makefile,v 1.1.1.1 1998/09/14 21:53:33 art Exp $
+PROG = afsd
+MAN = afsd.8
+BINDIR = /usr/libexec
+SRCS = adir.c arla.c arladeb.c cmcb.c conn.c cred.c fbuf.c fcache.c \
+ fprio.c inter.c kernel.c messages.c volcache.c bsd-subr.c
+
+.include "../Applflags.inc"
+
+.PATH: ${.CURDIR}/../src/arlad
+
+.include <bsd.prog.mk> \ No newline at end of file
diff --git a/usr.sbin/afs/afsd/afsd.8 b/usr.sbin/afs/afsd/afsd.8
new file mode 100644
index 00000000000..d8c6623e193
--- /dev/null
+++ b/usr.sbin/afs/afsd/afsd.8
@@ -0,0 +1,130 @@
+.\" $OpenBSD: afsd.8,v 1.1.1.1 1998/09/14 21:53:33 art Exp $
+.\"
+.Dd September 5, 1998
+.Dt AFSD 8
+.Os
+.Sh NAME
+.Nm afsd
+.Nd AFS cache manager for xfs.
+.Sh SYNOPSIS
+.Nm
+.Op Fl t | Fl -test
+.Oo Fl c Ar string \*(Ba Xo
+.Fl -conffile= Ns Ar string Oc
+.Xc
+.Oo Fl l Ar string \*(Ba Xo
+.Fl -log= Ns Ar string Oc
+.Xc
+.Op Fl -debug= Ns Ar string
+.Oo Fl d Ar string \*(Ba Xo
+.Fl -device= Ns Ar string Oc
+.Xc
+.Op Fl -connected-mode= Ns Ar string
+.Op Fl n | Fl -no-fork
+.Oo Fl r Ar string \*(Ba Xo
+.Fl -rxkad-level= Ns Ar string Oc
+.Xc
+.Oo Fl s Ar string \*(Ba Xo
+.Fl -sysname= Ns Ar string Oc
+.Xc
+.Op Fl -root-volume= Ns Ar string
+.Op Fl -port= Ns Ar number
+.Op Fl z | Fl -recover
+.Op Fl -cache-dir= Ns Ar string
+.Op Fl -version
+.Op Fl -help
+.Ar [device]
+.Sh DESCRIPTION
+.Nm afsd
+runs on AFS client machines. It is used to manage the file cache, fetch files
+from AFS servers, handle callbacks and manage the authentication information
+for users. In normal cases you will not need to run it by yourself. It is
+automatically started when
+.Nm mount_afs
+is run.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl t Ns ,
+.Fl -test
+.Xc
+run in test mode
+.It Xo
+.Fl c Ar string Ns ,
+.Fl -conffile= Ns Ar string
+.Xc
+path to configuration file (default: /etc/arla.conf)
+.It Xo
+.Fl l Ar string Ns ,
+.Fl -log= Ns Ar string
+.Xc
+where to write log [stderr|syslog|path] (default: stderr)
+.It Xo
+.Fl -debug= Ns Ar string
+.Xc
+what to write in the log (default: none)
+.It Xo
+.Fl d Ar string Ns ,
+.Fl -device= Ns Ar string
+.Xc
+the XFS device to use (default: /dev/xfs0)
+.It Xo
+.Fl -connected-mode= Ns Ar string
+.Xc
+initial connected mode [conncted|fetch-only|disconnected]
+.It Xo
+.Fl n Ns ,
+.Fl -no-fork
+.Xc
+don't fork and daemonize
+.It Xo
+.Fl r Ar string Ns ,
+.Fl -rxkad-level= Ns Ar string
+.Xc
+the rxkad level to use [clear|auth|crypt] (default: auth)
+.It Xo
+.Fl s Ar string Ns ,
+.Fl -sysname= Ns Ar string
+.Xc
+set the sysname of this system
+.It Xo
+.Fl -root-volume= Ns Ar string
+.Xc
+name of the root volume
+.It Xo
+.Fl -port= Ns Ar number
+.Xc
+port number to use
+.It Xo
+.Fl z Ns ,
+.Fl -recover
+.Xc
+don't recover state
+.It Xo
+.Fl -cache-dir= Ns Ar string
+.Xc
+cache directory (default: /var/spool/afs)
+.It Xo
+.Fl -version
+.Xc
+print version information
+.It Xo
+.Fl -help
+.Xc
+print usage information
+.El
+.Sh FILES
+/etc/arla.conf - default configuration for afsd.
+.Pp
+/var/spool/afs - default cache directory. It is highly recommended that this
+directory is a separate filesystem. When enough memory is available this
+could be a mfs to drastically improve performance.
+.Sh SEE ALSO
+.Xr mount_afs 8 .
+.Sh BUGS
+This code is still in the experimental stage and some bugs are present. If
+.Nm afsd
+happens to crash, it's recommended to restart it with the
+.Fl z
+flag. Otherwise a corrupted cache can be reused.
diff --git a/usr.sbin/afs/fs/Makefile b/usr.sbin/afs/fs/Makefile
new file mode 100644
index 00000000000..0b1d0052549
--- /dev/null
+++ b/usr.sbin/afs/fs/Makefile
@@ -0,0 +1,12 @@
+PROG = fs
+MAN =
+BINDIR = /usr/sbin
+SRCS = fs.c arlalib.c fs_lib.c
+LDADD += -lkafs
+DPADD += ${LIBKAFS}
+
+.include "../Applflags.inc"
+
+.PATH: ${.CURDIR}/../src/appl
+
+.include <bsd.prog.mk> \ No newline at end of file
diff --git a/usr.sbin/afs/libarla/Makefile b/usr.sbin/afs/libarla/Makefile
new file mode 100644
index 00000000000..08f3587881f
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile
@@ -0,0 +1,22 @@
+# $OpenBSD: Makefile,v 1.1.1.1 1998/09/14 21:53:28 art Exp $
+
+#
+# You don't want to understand this makefile.
+#
+
+LIB = arla
+NOPIC =
+NOPROFILE=
+MAN =
+
+CFLAGS += -DHAVE_CONFIG_H -I${.CURDIR}/../src/include -I. \
+ -I${.CURDIR}/../src/lib/roken -I${.CURDIR}/../src/util \
+ -I${.CURDIR}/../src -I${.CURDIR}/../libroken
+
+.include "Makefile.lwp.inc"
+.include "Makefile.rx.inc"
+.include "Makefile.rxdef.inc"
+.include "Makefile.rxkad.inc"
+.include "Makefile.ko.inc"
+
+.include <bsd.lib.mk>
diff --git a/usr.sbin/afs/libarla/Makefile.ko.inc b/usr.sbin/afs/libarla/Makefile.ko.inc
new file mode 100644
index 00000000000..016822331f7
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile.ko.inc
@@ -0,0 +1,15 @@
+### ko stuff
+OS_VER != uname -r
+
+SRCS += koerror.c kocell.c ports.c kodebug.c
+SRCS += sysname.c
+CLEANFILES += sysname.c gensysname
+CFLAGS += -I${.CURDIR}/../src/lib/ko
+
+.PATH: ${.CURDIR}/../src/lib/ko
+
+sysname.c: gensysname
+ ./gensysname -c > sysname.c
+
+gensysname: gensysname.c
+ ${CC} ${CFLAGS} -o gensysname ${.CURDIR}/../src/lib/ko/gensysname.c ../libroken/libroken.a
diff --git a/usr.sbin/afs/libarla/Makefile.lwp.inc b/usr.sbin/afs/libarla/Makefile.lwp.inc
new file mode 100644
index 00000000000..6f585eb538d
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile.lwp.inc
@@ -0,0 +1,23 @@
+### lwp stuff
+SRCS += lwp.c lock.c iomgr.c timer.c fasttime.c preempt.c q.c
+OBJS += process.o
+CLEANFILES += process.o
+.PATH: ${.CURDIR}/../src/lwp
+CFLAGS += -DFD_SPEED_HACK -I${.CURDIR}/../src/lwp
+
+
+process.o: process.S
+ HOST_CPU=${MACHINE_ARCH}; \
+ case "$$HOST_CPU" in \
+ sparc) CPUDEF="-Dsparc" ;; \
+ i*86*) CPUDEF="-DAFS_386i_ENV" ;; \
+ m68k) CPUDEF="-Dmc68000" ;; \
+ mips) CPUDEF="-Dmips" ;; \
+ alpha) CPUDEF="-Dalpha" ;; \
+ hppa*) CPUDEF="" ;; \
+ powerpc) CPUDEF="-D__powerpc__" ;; \
+ rs6000) CPUDEF="-DRIOS" ;; \
+ *) echo "Unknown host_cpu, good luck" ;; \
+ esac; \
+ OSDEF="-DAFS_NETBSD_ENV"; \
+ ${CC} $$CPUDEF $$OSDEF -c ${.CURDIR}/../src/lwp/process.S
diff --git a/usr.sbin/afs/libarla/Makefile.rx.inc b/usr.sbin/afs/libarla/Makefile.rx.inc
new file mode 100644
index 00000000000..51076d702f5
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile.rx.inc
@@ -0,0 +1,5 @@
+### rx stuff
+SRCS += rx_clock.c rx_event.c rx_user.c rx.c rx_globs.c rx_null.c \
+ rx_misc.c rx_pkt.c rx_rdwr.c rx_multi.c rx_trace.c
+CFLAGS += -I${.CURDIR}/../src/rx
+.PATH: ${.CURDIR}/../src/rx
diff --git a/usr.sbin/afs/libarla/Makefile.rxdef.inc b/usr.sbin/afs/libarla/Makefile.rxdef.inc
new file mode 100644
index 00000000000..19f0629a524
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile.rxdef.inc
@@ -0,0 +1,37 @@
+### rxdef stuff
+## No, cb.ss.c is _not_ a mistake. The _client_ is the callback server.
+SRCS += vldb.cs.c fs.cs.c cb.ss.c pts.cs.c \
+ volumeserver.cs.c ubik.cs.c
+
+CLEANFILES += vldb.ss.c vldb.cs.c vldb.ydr.c vldb.ss.h vldb.cs.h vldb.h \
+ fs.ss.c fs.cs.c fs.ydr.c fs.cs.h fs.ss.h fs.h \
+ cb.ss.c cb.cs.c cb.ydr.c cb.cs.h cb.ss.h cb.h \
+ pts.ss.c pts.cs.c pts.ydr.c pts.cs.h pts.ss.h pts.h \
+ volumeserver.ss.c volumeserver.cs.c volumeserver.ydr.c \
+ volumeserver.ss.h volumeserver.cs.h volumeserver.h \
+ ubik.ss.c ubik.cs.c ubik.ydr.c ubik.cs.h ubik.ss.h ubik.h
+
+CFLAGS += -I${.CURDIR}/../src/rxdef
+
+YDR = ../ydr/ydr
+YDRFLAGS = -I${.CURDIR}
+.PATH: ${.CURDIR}/../src/rxdef
+
+vldb.cs.c vldb.cs.h vldb.ss.c vldb.ss.h vldb.ydr.c vldb.h: vldb.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/vldb.xg
+
+fs.cs.c fs.cs.h fs.ss.c fs.ss.h fs.ydr.c fs.h: fs.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/fs.xg
+
+cb.cs.c cb.cs.h cb.ss.c cb.ss.h cb.ydr.c cb.h: cb.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/cb.xg
+
+pts.cs.c pts.cs.h pts.ss.c pts.ss.h pts.ydr.c pts.h: pts.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/pts.xg
+
+volumeserver.cs.c volumeserver.cs.h volumeserver.ss.c volumeserver.ss.h volumeserver.ydr.c volumeserver.h: volumeserver.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/volumeserver.xg
+
+ubik.cs.c ubik.cs.h ubik.ss.c ubik.ss.h ubik.ydr.c ubik.h: ubik.xg
+ $(YDR) $(YDRFLAGS) ${.CURDIR}/../src/rxdef/ubik.xg
+
diff --git a/usr.sbin/afs/libarla/Makefile.rxkad.inc b/usr.sbin/afs/libarla/Makefile.rxkad.inc
new file mode 100644
index 00000000000..372437aab5c
--- /dev/null
+++ b/usr.sbin/afs/libarla/Makefile.rxkad.inc
@@ -0,0 +1,7 @@
+### rxkad stuff
+SRCS += rxk_locl.c rxk_clnt.c rxk_serv.c rxk_crpt.c rxk_info.c \
+ osi_alloc.c compat.c
+
+CFLAGS += -I${.CURDIR}/../src/rxkad
+
+.PATH: ${.CURDIR}/../src/rxkad
diff --git a/usr.sbin/afs/libroken/Makefile b/usr.sbin/afs/libroken/Makefile
new file mode 100644
index 00000000000..2d42d672906
--- /dev/null
+++ b/usr.sbin/afs/libroken/Makefile
@@ -0,0 +1,24 @@
+# $OpenBSD: Makefile,v 1.1.1.1 1998/09/14 21:53:31 art Exp $
+LIB = roken
+# roken stuff
+SRCS = base64.c getarg.c k_getpwuid.c k_getpwnam.c signal.o tm2time.c \
+ verify.c inaddr2str.c mini_inetd.c get_window_size.c warnerr.c \
+ snprintf.c resolve.c parse_units.c strnlen.c strtok_r.c strupr.c
+# util stuff
+SRCS += atom.c date_rfc822.c efile.c fnameutil.c freelist.c hash.c ip.c \
+ list.c log.c mem.c mmaptime.c prio.c strmatch.c strsplit.c \
+ strutil.c timeprio.c timeval.c
+# sl stuff
+SRCS += sl.c
+CFLAGS += -DHAVE_CONFIG_H -I${.CURDIR}/../src/lib/roken \
+ -I${.CURDIR}/../src/util -I${.CURDIR}/../src/include \
+ -I${.CURDIR}/../src/lib/sl
+
+NOPROFILE=
+NOPIC=
+
+.PATH: ${.CURDIR}/../src/lib/roken
+.PATH: ${.CURDIR}/../src/util
+.PATH: ${.CURDIR}/../src/lib/sl
+
+.include <bsd.lib.mk> \ No newline at end of file
diff --git a/usr.sbin/afs/libroken/atypes.h b/usr.sbin/afs/libroken/atypes.h
new file mode 100644
index 00000000000..e67339a5988
--- /dev/null
+++ b/usr.sbin/afs/libroken/atypes.h
@@ -0,0 +1,11 @@
+/* $OpenBSD: atypes.h,v 1.1.1.1 1998/09/14 21:53:31 art Exp $ */
+/* atypes.h -- this file was generated for i386-unknown-openbsd2.3 by
+ $KTH: bits.c,v 1.4 1998/03/28 09:24:30 lha Exp $ */
+
+#ifndef __atypes_h__
+#define __atypes_h__
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#endif /* __atypes_h__ */
diff --git a/usr.sbin/afs/libroken/config.h b/usr.sbin/afs/libroken/config.h
new file mode 100644
index 00000000000..30f2df67411
--- /dev/null
+++ b/usr.sbin/afs/libroken/config.h
@@ -0,0 +1,659 @@
+/* $OpenBSD: config.h,v 1.1.1.1 1998/09/14 21:53:31 art Exp $ */
+/* include/config.h. Generated automatically by configure. */
+/* include/config.h.in. Generated automatically from configure.in by autoheader. */
+
+#ifndef BROKEN_MMAP
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+#endif
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define this if we can include both sys/dir.h and dirent.h */
+#define USE_SYS_DIR_H 1
+
+/* Define this if RETSIGTYPE == void */
+/* #undef VOID_RETSIGTYPE */
+
+/* Define this if struct winsize is declared in sys/termios.h */
+#define HAVE_STRUCT_WINSIZE 1
+
+/* Define this if struct winsize have ws_xpixel */
+#define HAVE_WS_XPIXEL 1
+
+/* Define this if struct winsize have ws_ypixel */
+#define HAVE_WS_YPIXEL 1
+
+/* Define this if `struct sockaddr' includes sa_len */
+#define SOCKADDR_HAS_SA_LEN 1
+
+/* define if the system is missing a prototype for strtok_r() */
+#define NEED_STRTOK_R_PROTO 1
+
+/* define if you have h_errno */
+#define HAVE_H_ERRNO 1
+
+/* define if you have h_errlist but not hstrerror */
+#define HAVE_H_ERRLIST 1
+
+/* define if you have h_nerr but not hstrerror */
+#define HAVE_H_NERR 1
+
+/* define if your system has a declaration for h_errlist */
+/* #undef HAVE_H_ERRLIST_DECLARATION */
+
+/* define if your system has a declaration for h_nerr */
+/* #undef HAVE_H_NERR_DECLARATION */
+
+/* define if your system has a declaration for h_errno */
+#define HAVE_H_ERRNO_DECLARATION 1
+
+/* define if your system has optreset */
+#define HAVE_OPTRESET 1
+
+/* define if your system has a declaration for optreset */
+#define HAVE_OPTRESET_DECLARATION 1
+
+/* define if your compiler has __FUNCTION__ */
+#define HAVE___FUNCTION__ 1
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Check if select need a prototype */
+/* #undef NEED_SELECT_PROTO */
+
+/* Define if you have the FOUR_ARGUMENT_VFS_BUSY function. */
+#define HAVE_FOUR_ARGUMENT_VFS_BUSY 1
+
+/* Define if you have the THREE_ARGUMENT_VFS_BUSY function. */
+/* #undef HAVE_THREE_ARGUMENT_VFS_BUSY */
+
+/* Define if you have the THREE_ARGUMENT_VGET function. */
+#define HAVE_THREE_ARGUMENT_VGET 1
+
+/* Define if you have the THREE_ARGUMENT_VOP_LOCK function. */
+#define HAVE_THREE_ARGUMENT_VOP_LOCK 1
+
+/* Define if you have the TWO_ARGUMENT_VFS_GETNEWFSID function. */
+/* #undef HAVE_TWO_ARGUMENT_VFS_GETNEWFSID */
+
+/* Define if you have the TWO_ARGUMENT_VGET function. */
+/* #undef HAVE_TWO_ARGUMENT_VGET */
+
+/* Define if you have the TWO_ARGUMENT_VOP_LOCK function. */
+/* #undef HAVE_TWO_ARGUMENT_VOP_LOCK */
+
+/* Define if you have the asnprintf function. */
+/* #undef HAVE_ASNPRINTF */
+
+/* Define if you have the asprintf function. */
+#define HAVE_ASPRINTF 1
+
+/* Define if you have the chown function. */
+#define HAVE_CHOWN 1
+
+/* Define if you have the daemon function. */
+#define HAVE_DAEMON 1
+
+/* Define if you have the dbm_firstkey function. */
+#define HAVE_DBM_FIRSTKEY 1
+
+/* Define if you have the dn_expand function. */
+#define HAVE_DN_EXPAND 1
+
+/* Define if you have the el_init function. */
+#define HAVE_EL_INIT 1
+
+/* Define if you have the err function. */
+#define HAVE_ERR 1
+
+/* Define if you have the errx function. */
+#define HAVE_ERRX 1
+
+/* Define if you have the fchown function. */
+#define HAVE_FCHOWN 1
+
+/* Define if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define if you have the flock function. */
+#define HAVE_FLOCK 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getdtablesize function. */
+#define HAVE_GETDTABLESIZE 1
+
+/* Define if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define if you have the getopt function. */
+#define HAVE_GETOPT 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrlimit function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if you have the getspnam function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define if you have the getspuid function. */
+/* #undef HAVE_GETSPUID */
+
+/* Define if you have the getusershell function. */
+#define HAVE_GETUSERSHELL 1
+
+/* Define if you have the getvfsbyname function. */
+/* #undef HAVE_GETVFSBYNAME */
+
+/* Define if you have the hstrerror function. */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the inet_aton function. */
+#define HAVE_INET_ATON 1
+
+/* Define if you have the initgroups function. */
+#define HAVE_INITGROUPS 1
+
+/* Define if you have the kvm_nlist function. */
+#define HAVE_KVM_NLIST 1
+
+/* Define if you have the kvm_open function. */
+#define HAVE_KVM_OPEN 1
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mkstemp function. */
+#define HAVE_MKSTEMP 1
+
+/* Define if you have the mktime function. */
+#define HAVE_MKTIME 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the rcmd function. */
+#define HAVE_RCMD 1
+
+/* Define if you have the readline function. */
+#define HAVE_READLINE 1
+
+/* Define if you have the readv function. */
+#define HAVE_READV 1
+
+/* Define if you have the recvmsg function. */
+#define HAVE_RECVMSG 1
+
+/* Define if you have the res_search function. */
+#define HAVE_RES_SEARCH 1
+
+/* Define if you have the sendmsg function. */
+#define HAVE_SENDMSG 1
+
+/* Define if you have the setegid function. */
+#define HAVE_SETEGID 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the seteuid function. */
+#define HAVE_SETEUID 1
+
+/* Define if you have the setregid function. */
+#define HAVE_SETREGID 1
+
+/* Define if you have the setresuid function. */
+/* #undef HAVE_SETRESUID */
+
+/* Define if you have the setreuid function. */
+#define HAVE_SETREUID 1
+
+/* Define if you have the setsid function. */
+#define HAVE_SETSID 1
+
+/* Define if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define if you have the snprintf function. */
+#define HAVE_SNPRINTF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strlwr function. */
+/* #undef HAVE_STRLWR */
+
+/* Define if you have the strnlen function. */
+/* #undef HAVE_STRNLEN */
+
+/* Define if you have the strsep function. */
+#define HAVE_STRSEP 1
+
+/* Define if you have the strtok_r function. */
+/* #undef HAVE_STRTOK_R */
+
+/* Define if you have the strupr function. */
+/* #undef HAVE_STRUPR */
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the sysctl function. */
+#define HAVE_SYSCTL 1
+
+/* Define if you have the syslog function. */
+#define HAVE_SYSLOG 1
+
+/* Define if you have the tgetent function. */
+#define HAVE_TGETENT 1
+
+/* Define if you have the unsetenv function. */
+#define HAVE_UNSETENV 1
+
+/* Define if you have the vasnprintf function. */
+/* #undef HAVE_VASNPRINTF */
+
+/* Define if you have the vasprintf function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the verr function. */
+#define HAVE_VERR 1
+
+/* Define if you have the verrx function. */
+#define HAVE_VERRX 1
+
+/* Define if you have the vfsisloadable function. */
+/* #undef HAVE_VFSISLOADABLE */
+
+/* Define if you have the vfsload function. */
+/* #undef HAVE_VFSLOAD */
+
+/* Define if you have the vsnprintf function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define if you have the vsyslog function. */
+#define HAVE_VSYSLOG 1
+
+/* Define if you have the vwarn function. */
+#define HAVE_VWARN 1
+
+/* Define if you have the vwarnx function. */
+#define HAVE_VWARNX 1
+
+/* Define if you have the warn function. */
+#define HAVE_WARN 1
+
+/* Define if you have the warnx function. */
+#define HAVE_WARNX 1
+
+/* Define if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <crypt.h> header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define if you have the <dbm.h> header file. */
+/* #undef HAVE_DBM_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the <ktypes.h> header file. */
+/* #undef HAVE_KTYPES_H */
+
+/* Define if you have the <kvm.h> header file. */
+#define HAVE_KVM_H 1
+
+/* Define if you have the <libelf/nlist.h> header file. */
+/* #undef HAVE_LIBELF_NLIST_H */
+
+/* Define if you have the <linux/types.h> header file. */
+/* #undef HAVE_LINUX_TYPES_H */
+
+/* Define if you have the <miscfs/genfs/genfs.h> header file. */
+/* #undef HAVE_MISCFS_GENFS_GENFS_H */
+
+/* Define if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in6.h> header file. */
+/* #undef HAVE_NETINET_IN6_H */
+
+/* Define if you have the <netinet/in6_machtypes.h> header file. */
+/* #undef HAVE_NETINET_IN6_MACHTYPES_H */
+
+/* Define if you have the <netinet6/in6.h> header file. */
+/* #undef HAVE_NETINET6_IN6_H */
+
+/* Define if you have the <nlist.h> header file. */
+#define HAVE_NLIST_H 1
+
+/* Define if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <rpcsvc/dbm.h> header file. */
+/* #undef HAVE_RPCSVC_DBM_H */
+
+/* Define if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define if you have the <sys/bitypes.h> header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define if you have the <sys/dirent.h> header file. */
+#define HAVE_SYS_DIRENT_H 1
+
+/* Define if you have the <sys/filedesc.h> header file. */
+#define HAVE_SYS_FILEDESC_H 1
+
+/* Define if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/lkm.h> header file. */
+#define HAVE_SYS_LKM_H 1
+
+/* Define if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/proc.h> header file. */
+#define HAVE_SYS_PROC_H 1
+
+/* Define if you have the <sys/queue.h> header file. */
+#define HAVE_SYS_QUEUE_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/sysconfig.h> header file. */
+/* #undef HAVE_SYS_SYSCONFIG_H */
+
+/* Define if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define if you have the <sys/sysent.h> header file. */
+/* #undef HAVE_SYS_SYSENT_H */
+
+/* Define if you have the <sys/sysproto.h> header file. */
+/* #undef HAVE_SYS_SYSPROTO_H */
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/tty.h> header file. */
+#define HAVE_SYS_TTY_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the curses library (-lcurses). */
+/* #undef HAVE_LIBCURSES */
+
+/* Define if you have the db library (-ldb). */
+/* #undef HAVE_LIBDB */
+
+/* Define if you have the edit library (-ledit). */
+#define HAVE_LIBEDIT 1
+
+/* Define if you have the gdbm library (-lgdbm). */
+/* #undef HAVE_LIBGDBM */
+
+/* Define if you have the kvm library (-lkvm). */
+#define HAVE_LIBKVM 1
+
+/* Define if you have the ndbm library (-lndbm). */
+/* #undef HAVE_LIBNDBM */
+
+/* Define if you have the nsl library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the readline library (-lreadline). */
+/* #undef HAVE_LIBREADLINE */
+
+/* Define if you have the resolv library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define if you have the socket library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define if you have the syslog library (-lsyslog). */
+/* #undef HAVE_LIBSYSLOG */
+
+/* Define if you have the termcap library (-ltermcap). */
+#define HAVE_LIBTERMCAP 1
+
+#define HAVE_INT8_T 1
+#define HAVE_INT16_T 1
+#define HAVE_INT32_T 1
+#define HAVE_INT64_T 1
+#define HAVE_U_INT8_T 1
+#define HAVE_U_INT16_T 1
+#define HAVE_U_INT32_T 1
+#define HAVE_U_INT64_T 1
+/* #undef HAVE_BOOL */
+#define HAVE_SSIZE_T 1
+#define HAVE_REGISTER_T 1
+/* #undef HAVE_INT32 */
+/* #undef HAVE_U_INT32 */
+
+#define EFF_NTOHL ntohl
+
+/* RCSID */
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+#define VERSION "0.9"
+#define PACKAGE "arla"
+
+/* Check for posix signals */
+#define HAVE_POSIX_SIGNALS 1
+
+#define HAVE_READLINE 1
+
+/* prefix for /dev/fd */
+/* #undef DEV_FD_PREFIX */
+
+/* does the system have /dev/fd? */
+/* #undef HAVE_DEV_FD */
+
+/* we always have stds.h */
+#define HAVE_STDS_H
+
+/* We have krb_principal from kth-krb ? */
+#define HAVE_KRB_PRINCIPAL 1
+
+/* If we have _res */
+/* #undef HAVE__RES */
+
+/* Define if you have kerberos */
+#define KERBEROS 1
+
+/* Define if your kernel has a vop_nolock */
+/* #undef HAVE_KERNEL_VOP_NOLOCK */
+
+/* Define if your kernel has a vop_nounlock */
+/* #undef HAVE_KERNEL_VOP_NOUNLOCK */
+
+/* Define if your kernel has a vop_noislocked */
+/* #undef HAVE_KERNEL_VOP_NOISLOCKED */
+
+/* Define if your kernel has a vop_revoke */
+/* #undef HAVE_KERNEL_VOP_REVOKE */
+
+/* Define if your kernel has a genfs_nolock */
+/* #undef HAVE_KERNEL_GENFS_NOLOCK */
+
+/* Define if your kernel has a genfs_nounlock */
+/* #undef HAVE_KERNEL_GENFS_NOUNLOCK */
+
+/* Define if your kernel has a genfs_noislocked */
+/* #undef HAVE_KERNEL_GENFS_NOISLOCKED */
+
+/* Define if your kernel has a genfs_revoke */
+/* #undef HAVE_KERNEL_GENFS_REVOKE */
+
+/* Define if your kernel has a vfs_opv_init_default */
+#define HAVE_KERNEL_VFS_OPV_INIT_DEFAULT 1
+
+/* Define if your kernel has a vfs_attach */
+/* #undef HAVE_KERNEL_VFS_ATTACH */
+
+/* Define if your kernel has a vfs_getnewfsid */
+#define HAVE_KERNEL_VFS_GETNEWFSID 1
+
+/* Define if your kernel has a vfs_opv_init_explicit */
+#define HAVE_KERNEL_VFS_OPV_INIT_EXPLICIT 1
+
+/* Define if your struct dirent has a field d_type */
+#define HAVE_STRUCT_DIRENT_D_TYPE 1
+
+/* Define if your struct vfsconf has a field vfc_refcount */
+#define HAVE_STRUCT_VFSCONF_VFC_REFCOUNT 1
+
+/* Define if your struct uio has a field uio_procp */
+/* #undef HAVE_STRUCT_UIO_UIO_PROCP */
+
+/* Define if your struct vfsops has a field vfs_opv_descs */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_OPV_DESCS */
+
+/* Define if your struct vfsops has a field vfs_name */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_NAME */
+
+/* Define if you want to use mmap:ed time */
+/* #undef USE_MMAPTIME */
+
+/* Define if your hstrerror needs const like SunOS 5.6 */
+#define NEED_HSTRERROR_CONST 1
+
+/* Define if your hstrerror need proto */
+/* #undef NEED_HSTRERROR_PROTO */
+
+/* Define if you have gnu libc */
+/* #undef HAVE_GLIBC */
+
+/* Define this if `struct sockaddr' includes sa_len */
+#define SOCKADDR_HAS_SA_LEN 1
+
+/* Define this if htnol is broken, but can be fixed with define magic */
+/* #undef HAVE_REPAIRABLE_HTONL */
+
+/* Define this if struct ViceIoctl is defined by linux/fs.h */
+/* #undef HAVE_STRUCT_VICEIOCTL_IN */
+
+/* Linux kernel types */
+/* #undef HAVE_LINUX_KERNEL_INT8_T */
+/* #undef HAVE_LINUX_KERNEL_INT16_T */
+/* #undef HAVE_LINUX_KERNEL_INT32_T */
+/* #undef HAVE_LINUX_KERNEL_INT64_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT8_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT16_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT32_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT64_T */
+
+/* Define this if you have a type vop_t */
+/* #undef HAVE_VOP_T */
+
+/* Define this is you have a vfssw */
+/* #undef HAVE_VFSSW */
+
+/* Define this if struct proc have p_sigmask */
+#define HAVE_STRUCT_PROC_P_SIGMASK 1
+
diff --git a/usr.sbin/afs/libroken/version.h b/usr.sbin/afs/libroken/version.h
new file mode 100644
index 00000000000..eda2502f5fd
--- /dev/null
+++ b/usr.sbin/afs/libroken/version.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: version.h,v 1.1.1.1 1998/09/14 21:53:31 art Exp $ */
+char *arla_long_version = "arla-0.9 on "ARLACPU"-"ARLAVENDOR"-"ARLAOS;
+char *arla_version = "arla-0.9";
diff --git a/usr.sbin/afs/pts/Makefile b/usr.sbin/afs/pts/Makefile
new file mode 100644
index 00000000000..cc8e1ce9de0
--- /dev/null
+++ b/usr.sbin/afs/pts/Makefile
@@ -0,0 +1,11 @@
+PROG = pts
+MAN =
+SRCS = pts.c arlalib.c fs_lib.c
+LDADD += -lkafs
+DPADD += ${LIBKAFS}
+
+.include "../Applflags.inc"
+
+.PATH: ${.CURDIR}/../src/appl
+
+.include <bsd.prog.mk> \ No newline at end of file
diff --git a/usr.sbin/afs/src/ChangeLog b/usr.sbin/afs/src/ChangeLog
new file mode 100644
index 00000000000..80a48ee8064
--- /dev/null
+++ b/usr.sbin/afs/src/ChangeLog
@@ -0,0 +1,2940 @@
+Mon Aug 24 02:48:19 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/solaris/xfs_vnodeops.c (xfs_create): truncate the file if
+ needed
+
+ * xfs/solaris/xfs_vnodeops.c (xfs_create): existing file is no
+ error
+ (xfs_write): update mtime and size from cache vnode
+
+Tue Aug 11 18:34:33 1998 Johan Danielsson <joda@blubb.pdc.kth.se>
+
+ * arlad/arla.c (read_conffile): use parse_units
+
+Tue Aug 4 02:19:06 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_vfsops-bsd.c (xfs_vfsops): conditionalize vfc_name
+
+ * configure.in: check for `vfs_name' in `struct vfsops'
+
+Fri Jul 31 00:15:38 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * Release 0.9
+
+ * xfs/solaris: compiler warning cleanup
+
+Thu Jul 30 23:04:46 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in (netbsd): comments are `dnl' and not `/*' :-)
+
+ * configure.in: --with-krb{4,5}: better values for include and lib
+ directory
+
+ * xfs/linux/xfs_inodeops.c (xfs_write_file): set the f_pos of the
+ cached file before calling its write
+
+Wed Jul 29 22:35:31 1998 Assar Westerlund <assar@sics.se>
+
+ * TODO: optimistically remove the items that I think have been
+ fixed
+
+ * arlad/fcache.c (unlink_lru_entry): don't remove entries with
+ refcount > 0
+ (followmountpoint): set refcount on the root of the new volume, not on
+ the mount point in the old one.
+
+ * arlad/inter.c (cm_lookup): fix the handling of `..' over mount
+ points.
+
+ * arlad/volcache.c (recycle_entry): decrement the refcounts of all
+ fcacheentries pointing to the root of any of the volumes of `e'
+
+ * arlad/volcache.h (volcacheentry): remove `mount_point'
+
+ * INSTALL: removed mknod from BSD installation instructions
+
+ * xfs/bsd/bin/xfs_makedev: new file
+
+ * xfs/bsd/bin/startarla.in: use xfs_makedev
+
+ * xfs/bsd/bin/Makefile.in: install xfs_makedev
+
+ * xfs/bsd/xfs_wrap-bsd.c: made it into a LKM_DEV.
+
+ * xfs/bsd/xfs_dev-bsd.c (xfs_install_device, xfs_uninstall_device,
+ xfs_stat_device): removed all code for adding the device to the
+ cdevsw.
+
+ * xfs/bsd/Makefile.in (load): use -p xfs_makedev
+
+ * arlad/adir.c (adir_remove, adir_creat): assert the directory
+ having data
+
+ * arlad/inter.c (cm_create, cm_mkdir, cm_symlink, cm_link,
+ cm_remove, cm_rmdir, cm_rename): make sure we have the data of the
+ directory
+
+ * arlad/fbuf.c (malloc_truncate): call ftruncate
+
+ * xfs/bsd/xfs_vfsops-common.c (xfs_mount_common): handle two
+ argument vfs_getnewfsid
+
+ * configure.in: test for two argument vfs_getnewfsid
+
+Tue Jul 28 23:36:47 1998 Assar Westerlund <assar@sics.se>
+
+ * lwp/process.S: Applied patch for NetBSD/alpha from John Davison
+ <davisoja@clarkson.edu>
+
+ * ydr/output.c: try to handle error returns from rx_Read and
+ rx_Write
+
+ * lib/ko/kocell.c: check memory allocation and clean-up
+
+ * appl/fs.c (afs_listquota): don't divide by zero
+
+ * arlad/fcache.c (followmountpoint): close fd if fbuf_create fails
+
+1998-07-28 Love <lha@e.kth.se>
+
+ * xfs/bsd/xfs_vfsops-osf.c(xfs_install_fs): Be paranoid about the size
+ of the private data of struct vnode.
+
+ * xfs/bsd/xfs_dev-common.c: (xfs_message_rpc):No code for sigwaitmask
+
+1998-07-24 Love <lha@e.kth.se>
+
+ * xfs/bsd/xfs_vfsops-osf.c: (xfs_root): Added uid check for osf.
+
+ * appl/fs.c: Added VIOCNOP.
+
+Fri Jul 24 19:15:45 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/messages.c: Added VIOCGETCELL, VIOCWHEREIS, VIOCNOP,
+ VIOCUNPAG and VIOC_AFS_STAT_MT_PT.
+
+Fri Jul 24 09:53:19 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in (int32, u_int32): test for
+
+ * arlad/messages.c (xfs_message_create): try installing data for
+ the new file.
+
+ * arlad/arla.c (temp_sysname): const-ize
+
+Fri Jul 24 06:49:32 1998 Magnus Ahltorp <map@stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: Merged in patch from
+ Aaron M. Ucko <amu@mit.edu>.
+
+ * xfs/linux: Made things work better on 2.0 and i386.
+
+1998-07-24 Love <lha@e.kth.se>
+
+ * appl/fs.c: fixed small bug in fs lsm.
+
+Thu Jul 23 03:55:12 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_vfsops-common.c (xfs_mount_common): use
+ vfs_getnewfsid is there's one. From Dan Winship <danw@MIT.EDU>
+
+ * xfs/bsd/xfs_vfsops-bsd.c: use `struct vnodeopv_desc',
+ vfs_attach, and vfs_detach when applicable. From Dan Winship
+ <danw@MIT.EDU>
+
+ * configure.in: more tests for modern NetBSD. From Dan Winship
+ <danw@MIT.EDU>
+
+ * arlad/inter.c (expand_sys): new function for expanding @sys
+ (cm_lookup): expand @sys anywhere in the name
+
+ * xfs/bsd/xfs_vnodeops-common.c (xfs_inactive_common): handle the
+ case of an already clean vnode.
+
+ * xfs/bsd/xfs_node-bsd.c (free_xfs_node): remove bogus comment
+
+ * arlad/fcache.c (create_{file,symlink,directory}): update the
+ acccache and anonacess
+
+ * arlad/volcache.c: rename recover_state -> volcache_recover_state
+
+ * xfs/bsd/xfs_vnodeops-bsd.c (xfs_islocked): return 0 as a
+ fallback
+
+ * xfs/bsd/xfs_vnodeops.h (xfs_vfs_readlock, xfs_vfs_writelock,
+ xfs_vfs_unlock): new macros for encapsulating the locking
+
+ * xfs/bsd/xfs_vfsops-osf.c (xfs_root): remove ifdef __osf__
+
+ * xfs/bsd/xfs_vfsops-bsd.c (xfs_root): remove ifdef __osf__
+
+Wed Jul 22 05:00:08 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.h (create_symlink): update prototype
+
+ * arlad/fcache.c: keep better track of the number of used bytes
+ (usedbytes)
+
+ * rxdef/fs.xg (Symlink): correct
+
+ * arlad/fcache.c (fcache_file_name): cast `inode' to unsigned
+
+ * lib/ko/gensysname.c: restructured, cleaned up and added new
+ sysnames
+
+ * util/strmatch.c: const-ize
+
+ * arlad/adir.c: replace magic numbers with expressions based on
+ constants from afs_dir.h
+
+ * arlad/arla.c (main): set the sysname from arla_getsysname
+
+Tue Jul 21 04:55:00 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/adir.c (adir_remove): eliminate trailing empty pages
+
+ * arlad/adir.c (adir_remove): use the actual size of the converted
+ directory instead of that from status
+
+ * arlad/adir.c (adir_lookup, adir_readdir): use the actual size of
+ the converted directory instead of that from status
+
+ * xfs/bsd/xfs_vnodeops-bsd.c (xfs_revoke): implement
+
+ * configure.in (vop_revoke, genfs_revoke): check for
+
+ * configure.in (vop_noislocked, genfs_nolock, genfs_nounlock,
+ genfs_noislocked): check for
+
+ * xfs/bsd/xfs_vnodeops-bsd.c (xfs_lock, xfs_unlock, xfs_islocked):
+ try to use default operations
+
+Mon Jul 20 04:51:11 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: openbsd2.3: remove
+ more kernel tests
+
+ * lwp/lwp.h (lwp_context): add linkRegister and conditionRegister
+ for powerpc
+
+ * xfs/bsd: restructured
+
+ * arlad/arla.c (connected_levels): fix misspelling
+
+Mon Jul 20 01:49:28 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * Release 0.8
+
+Sun Jul 19 10:41:44 1998 Mattias Amnefelt <mattiasa@stacken.kth.se>
+
+ * appl/vos.c: added support for busy volumes
+
+Fri Jul 17 18:21:10 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * configure.in, xfs/linux/Makefile.in, xfs/linux/getcwd.c: Added
+ getcwd shared library to make getcwd work better in 2.1.
+
+Fri Jul 17 03:10:48 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (fcache_recover_state): make sure the volume of
+ the entry we read back actually exists, otherwise just ignore it.
+
+Thu Jul 16 02:06:28 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: selinfo.si_pid test removed
+
+ * lib/ko/gensysname.c (printsysname): arla_getsysname should
+ return a const string
+
+ * lib/ko/ko.h (arla_getsysname): const-ize
+
+ * arlad/volcache.c (volcache_getbyname, volcache_getbyid):
+ restructure tail so that refcount is return whenn e != NULL
+
+ * xfs/openbsd2.3/xfs_vnodeops.c (xfs_lookup): set *vpp to NULL at
+ the beginning
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_lookup_common): set *vpp to NULL at
+ the beginning
+
+1998-07-15 Love <lha@s3.kth.se>
+
+ * lib/ko/gensysname.c: Added generation of a sysname function.
+
+Tue Jul 14 16:35:31 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/bin/mount_xfs.c: conditionalize on autoconf symbols
+ instead of on __FreeBSD__
+
+ * configure.in (getvfsbyname,vfsisloadable,vfsload): check for
+ them
+
+1998-07-14 Love <lha@s3.kth.se>
+
+ * arlad/services.h: Added VOTE_SERVICE and DISK_SERVICE
+
+ * appl/udebug.c: Added the udebug program.
+
+ * appl/vos.c: Added command syncsite (only work on local cell)
+
+ * appl/arlalib.[ch]: arlalib_getsyncsite() does not work,
+ I can't see why it shouldn't work thou.
+
+ * appl/appl_locl.h: added <err.h> and <ubib*>
+
+ * appl/Makefile: Added udebug
+
+ * rxdef/ubik.xg: Added
+
+ * xfs/bsd/bin/mount_xfs.c: Added patch from Alec Wolman
+ <wolman@cs.washington.edu> to add the right argument to mount
+ for FreeBSD
+
+Mon Jul 13 20:50:09 1998 Assar Westerlund <assar@sics.se>
+
+ * lwp/make-process.o.sh.in (aix): for some odd reason the aix
+ assembler is happier if we always say we have a RIOS
+
+ * ydr/Makefile.in: compat with stupid makes
+
+ * xfs/sunos/Makefile.in: compat with stupid makes
+
+ * xfs/linux/Makefile.in: compat with stupid makes
+
+ * util/Makefile.in: compat with stupid makes
+
+ * rxdef/Makefile.in: compat with stupid makes
+
+ * lwp/process.S: rhapsody fixes
+
+ * arlad/volcache.c (recycle_entry): only decrement fe->refcount
+ if we found the node.
+
+ * arlad/kernel.c (process_message): remove `proc_msg: byte = %d'
+
+ * arlad/fcache.c (count): rename to inode_count
+ (fcache_stale_entry): always call stale
+ (fcache_find): check if find_entry succeeded
+
+ * arlad/conn.c (conn_get): check securityindex and cred, otherwise
+ we could end up not having any connection for (0,0) and loose when
+ we get a callback
+
+ * arlad/arla.c (newwalk): patches from Alec Wolman
+ <wolman@cs.washington.edu>
+
+ * arlad/Makefile.in: compat with stupid makes
+
+ * lib/Makefile.in: compat with stupid makes
+
+ * appl/Makefile.in: compat with stupid makes
+
+ * THANKS: Alec Wolman <wolman@cs.washington.edu>
+
+ * Makefile.in: compat with stupid makes
+
+ * configure.in (KERNEL_INCLUDE): include -I
+ (rhapsody): add
+ some more field tests
+
+ * config.{guess,sub}: rhapsody
+
+ * xfs/rhapsody: Rhapsody port from Alexandra Ellwood <lxs@MIT.EDU>
+
+Thu Jul 9 16:14:50 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_inodeops.c (xfs_write_file): 2.0-fix
+
+Mon Jul 13 06:35:55 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux: Locking corrected and locking debugging added
+
+ * xfs/linux: Changed to new lookup method
+
+Sun Jul 12 16:39:05 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * xfs/bsd/*: Merge OSF/1 changes.
+
+ * xfs/bsd/xfs_dev.h: make xfs_devopen static, and add prototype
+ for xfs_func_is_devopen that does the comparison
+
+ * xfs/bsd/xfs_deb.h: unsigned int
+
+ * xfs/bsd/xfs_deb.c: unsigned int
+
+ * xfs/bsd/xfs_common.c: use xfs_malloc
+
+ * configure.in: Add support for OSF/1.
+
+ * xfs/bsd/bin/{mount_xfs,umount_xfs}.c: use <mount_locl.h>
+
+ * xfs/bsd/bin/mount_locl.h: common include file for mount/umount
+
+ * xfs/bsd/bin/mntopts.h: remove __P from the single prototype (to
+ avoid having to add a definition for __P) -- all compilers (gcc
+ and DEC CC knows prototypes anyway).
+
+ * xfs/bsd/bin/Makefile.in: some fixes for OSF/1: conditionally
+ build `startarla', and add include and link paths for roken.
+
+ * rxkad/rxk_crpt.c: __alpha is LE
+
+Thu Jul 9 22:18:25 MET DST 1998 Mattias Amnefelt <mattiasa@stacken.kth.se>
+
+ * appl/Makefile.in: Changed so we use libroken included in
+ arla insead of the one which comes with kth-krb.
+
+1998-07-08 Love <lha@e.kth.se>
+
+ * xfs/bsd/{xfs_vfsops.c,xfs_wrap.c} Check if we can unload
+ before we even try, since on NetBSD you can unload a
+ mounted filesystem, that will crash in next sync.
+
+Wed Jul 8 01:44:15 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (creat_nodes): use IOMGR_Select instead of
+ LWP_DispatchProcess to give the iomgr thread the chance to run
+
+ * xfs/aix/xfs_syscalls.c (xfs_setpag_call): generate the pag
+ correctly
+
+1998-07-07 Love <lha@e.kth.se>
+
+ * util/{time,}prio.[ch], util-tester.c: Added.
+
+Tue Jul 7 02:41:05 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_vfsops.c: Use print_aliases() and
+ set xfsp->root to NULL when unmounting
+
+ * xfs/linux/xfs_common.[ch]: Added print_aliases()
+
+Mon Jul 6 19:56:34 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_dev.c: obvious xfs_vfs_busy fix
+
+Mon Jul 6 12:59:51 1998 Mattias Amnefelt <mattiasa@sundance.stacken.kth.se>
+
+ * appl/vos.c: correct parsing of partition names
+
+ * appl/appl_locl.h: #include <ctype.h>
+
+Mon Jul 6 12:29:04 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * xfs/bsd/Makefile.in: Get KERNEL_CFLAGS from configure.
+
+ * xfs/bsd/xfs_dev.c: Add wrapper for vfs_busy.
+
+ * xfs/bsd/xfs_vnodeops.c: Add wrapper for VOP_LOCK/VOP_UNLOCK.
+
+ * configure.in: Add KERNEL_CFLAGS for *BSD and OSF/1. Test for
+ three valued vfs_busy, and two valued VOP_LOCK.
+
+ * aclocal.m4: AC_TRY_COMPILE_KERNEL, that adds KERNEL_CFLAGS to
+ CFLAGS during test.
+
+Sun Jul 5 20:26:02 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (fcache_find): new function add invalidating and
+ vnode creating threads
+
+ * arlad/fcache.h (FCacheEntry): rename `listentry' -> `lru_le'.
+ add `invalid_le'
+ (fcache_find): add prototype
+
+ * util/list.c (listaddbefore, listaddafter): new functions
+
+Sun Jul 5 03:28:44 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c: new option `--cache-dir'
+
+Sun Jul 5 04:28:02 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_vfsops.c: Fix 2.1 {put,delete}_inode weirdness
+
+ * xfs/linux/xfs_message.c: Fix callback handling
+
+Sun Jul 5 04:24:14 1998 Magnus Ahltorp <magnus@dike.aladdin.se>
+
+ * xfs/linux/xfs_inodeops.c: Clear vm maps when closing file.
+
+Sat Jul 4 16:21:44 1998 Magnus Ahltorp <magnus@dike.aladdin.se>
+
+ * xfs/linux/xfs_inodeops.c: 2.0 fixes
+
+Sat Jul 4 05:53:01 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/*: Big rewrite of different things. Works somewhat
+ (writes sometimes do the wrong thing) on 2.1, 2.0 is untested.
+ The file system may now be mounted before arlad is started.
+
+Fri Jul 3 19:38:22 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla_local.h: this ugliness seems required
+
+Wed Jul 1 21:34:42 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (fcache_get): remove the old entry from the free
+ list before adding the new one.
+
+Sat Jun 27 12:46:20 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_syscalls.c (sys_afs): correct check for
+ copy_{from,to}_user. Always return -errno.
+
+ * xfs/linux/xfs_common.h (copy_to_user, copy_from_user): these
+ functions should return the number of uncopied bytes.
+
+ * configure.in: remove uid_t size test
+
+ * xfs/include/xfs_message.h: use __kernel_foo_t
+
+ * xfs/include/xfs_attr.h: define __kernel_foo_t if they are not
+ already defined and use them.
+
+ * xfs/bsd/xfs_node.c (vattr2xfs_attr): cast to `mode_t' otherwise
+ it breaks on modern NetBSD
+
+Thu Jun 25 06:04:01 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/adir.c (add_to_page): don't index off the end of the page.
+
+1998-06-24 Love Hornquist-Astrand <root@junkyard.stacken.kth.se>
+
+ * doc/partsofarla.texi: Added info about libkafs and pioctl()
+
+Mon Jun 22 17:34:53 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * xfs/solaris/xfs_vfsops.c: debug panic patch from:
+ John Hawkinson <jhawk@bbnplanet.com>
+
+1998-06-22 Love <lha@e.kth.se>
+
+ * Added doc/*.texi
+
+1998-06-21 Love <lha@e.kth.se>
+
+ * lib/sl/sl.[ch]: Added SL_BADCOMMAND
+
+ * appl/{fs,vos}.c: Fixes for sl.
+
+ * configure.in: Added patch for afslib from:
+ Mark Eichin <eichin@kitten.gen.ma.us>
+
+Fri Jun 19 20:43:42 1998 Assar Westerlund <assar@sics.se>
+
+ * appl/fs.c (connect_cmd): correct comparison against `dis'
+
+Wed Jun 17 17:08:39 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * Release 0.7.2
+
+Sat Jun 13 03:32:39 1998 Assar Westerlund <assar@sics.se>
+
+ * appl/vos.c (printpartinfo): use bogus field
+
+1998-06-09 Love <lha@e.kth.se>
+
+ * lwp/make-process.o.sh.in: The new magic way of building process.o
+
+Tue Jun 9 10:11:03 1998 Magnus Ahltorp <map@stacken.kth.se>
+
+ * Release 0.7.1
+
+ * major bug fixes
+
+Mon Jun 8 18:07:12 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * Release 0.7
+
+1998-06-08 Love <lha@e.kth.se>
+
+ * arlad/fcache.c: Try to do sane things with callback->ExpirationTime.
+ (Assume that ExpirationTime is a relative time)
+
+ * util/log.c(log_vprint_file): Print date when logging to file/stderr.
+
+Mon Jun 8 15:14:10 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/openbsd2.3/xfs_syscalls.c: merge in
+ xfs/bsd/xfs_syscalls.c:1.26->1.27
+
+ * xfs/bsd/xfs_syscalls.c (xfs_setpag_call): only copy the required
+ gids and return the new cred
+
+Sun Jun 7 10:57:18 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: add irix
+
+Sun Jun 7 07:23:07 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * xfs/{solaris,aix,sunos}/xfs_messages.c
+ (xfs_message_invalidroot): clear tokens when invalidating
+
+ * arlad/fcache.c (fcache_init): set fprioritylevel at init
+
+Sun Jun 7 07:19:35 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * acconfig.h, configure.in, lib/roken/roken.h:
+ Autodetect linux htonl weirdness
+
+Thu Jun 4 00:12:37 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c: new option `--recover' or `-z' for recovering
+ (not) stored state
+
+ * arlad/fcache.c (fcache_init): new parameter `recover'
+
+ * arlad/volcache.c (volcache_init): new parameter `recover'
+
+Wed Jun 3 23:41:42 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (do_read_attr): make sure we don't return -1
+
+Tue Jun 2 19:16:15 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_locl.h: include <linux/modversions.h> to get
+ versioned names of exported kernel symbols
+
+Tue May 26 22:54:33 1998 Assar Westerlund <assar@sics.se>
+
+ * acconfig.h (VFS_NEED_PROCP): remove
+
+ * configure.in (openbsd2.3): remove old junk
+
+Mon May 25 04:16:26 1998 Artur Grabowski <art@stacken.kth.se>
+
+ * arlad/messages.c: fix reading of links when only having
+ 'l' rights
+
+ * xfs/*bsd*/xfs_vnodeops.c: change size and mtime of files when
+ writing to them.
+
+Mon May 25 00:58:17 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.6
+
+ * lwp/Makefile.in: more uglyness for process.S
+
+ * util/Makefile.in: link mmaptime_test with libroken
+
+1998-05-24 Love <lha@e.kth.se>
+
+ * util/mmaptime_test.c: Added
+
+ * arlad/messages.c(vioc_fpriostatus): FPRIO_{GET,SET}MAX
+
+ * arlad/fcache.c(restore_state): Set priority too.
+ (do_read_attr): Check for disconnected mode, if we got
+ attr just return, otherwise return ENETDOWN.
+ (read_data): Check for disconnected mode.
+ (fcache_get): Check for disconnected mode.
+ (uptodatep): Check for connected logging mode.
+
+ * arlad/conn.c(conn_free): When in disconnected mode conn
+ sets to NULL.
+
+ * appl/{arlalib.h,fs.c,fs_lib.c,fs_local.h}: Added
+ {set,get}maxfprio.
+
+Sat May 23 07:24:22 1998 Assar Westerlund <assar@sics.se>
+
+ * appl/appl_locl.h: include <sys/param.h>
+
+ * arlad/aix-subr.c: new file
+
+ * arlad/linux-subr.c (conv_dir): got rid of stupid warning
+
+ * arlad/arla.c (arla_cat): check return values from fcache*
+
+ * configure.in: check for h_errno, h_errlist, and h_nerr
+
+ * aclocal.m4: add check-declaration and check-var
+
+Fri May 22 21:34:30 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (fcache_get): check return value from
+ volcache_getbyid.
+
+Wed May 20 02:56:14 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c: add `--port'
+
+ * getarg.c: fix some of the getarg bugs
+
+Tue May 19 17:18:31 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux: Fixed varous pointer conversions.
+ Moved glibc support to the correct place.
+ Added random code for debug control syscall.
+
+1998-05-18 Love <lha@e.kth.se>
+
+ * lwp/process.S: Add linux alpha support
+
+ * xfs/bsd/xfs_syscalls.c: Log to XDEBSYS instead of XDEBMSG
+
+ * include/kafs.h: Added new PIOCTL (50) for VIOC_FPRIOSTATUS
+ Added defines and structs for FPRIOSTATUS.
+
+ * conf/arla.conf: Added fpriority, default to 100
+
+ * arlad/messages.c: Added vioc_fpriostatus
+
+ * arlad/inter.c:(log_operation) dont log operations when in
+ connected mode.
+
+ * arlad/fcache.c: Added fprioritylevel and made use of it in
+ emergency_remove_file() and in cleaner thread.
+
+ * arla/arla_local.h: Added new state of connected_mode,
+ CONNECTEDLOG
+
+ * arlad/arla.c: Added fpriority to the conf file
+
+ * appl/fs.c: (getarg) Added {add,remove,get}removepriority,
+ and version.
+ (connect) changed fs_connect syntax
+ ({get,set}crypt) changed fs_*crypt syntax
+ ({set,get,remove}prio) added calls
+ (fserr) moved to fs_lib.c and changed syntax
+ (fsversion) print version of fs.c and fs_lib.c
+ (afs_getfid) moved to fs_lib
+
+ * appl/arlalib.h: Added fs_* prototypes
+
+Sat May 16 11:41:19 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux: Merged in Linux 2.1 support
+
+Sat May 16 06:44:16 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/solaris/xfs_vnodeops.c: fix use of VOP_RWLOCK and
+ VOP_RWUNLOCK
+
+ * xfs/aix/bin: add umount_xfs and mount_xfs.
+
+ * xfs/aix/xfs_vfsops.c (xfs_mount): find the device path
+
+ * xfs/aix/xfs_dev.c: init `event_word' to EVENT_NULL
+
+ * xfs/aix/xfs_deb.h: Use uprintf instead of printf to make it
+ possible to see the messages.
+
+Tue May 12 17:29:39 1998 Assar Westerlund <assar@sics.se>
+
+ * lwp/process.S: grammar fix
+
+Sun May 10 02:25:47 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: Fixed create, mkdir, rmdir, rename
+ in 2.1 branch
+
+ * xfs/linux/{xfs_message.c,xfs_inodeops.c}:
+ Addded more correct handling of dcache in 2.1 branch
+
+Sat May 9 11:41:10 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/solaris/xfs_vnodeops.c: replace VN_HOLD/VN_RELE by
+ VOP_RWLOCk/VOP_RWUNLOCK before calling VOP-funktions in ufs.
+
+ * configure.in: aix
+
+ * xfs/solaris/xfs_message.c (xfs_message_installdata): replace
+ printf by XFSDEB. Extra ASSERT for rb.
+
+Thu May 7 04:00:30 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/aix: new directory
+
+1998-05-06 Assar Westerlund <assar@sics.se>
+
+ * xfs/solaris/xfs_message.c: try to purge the dnlc once in a while
+
+ * xfs/solaris/xfs_node.c (vattr2xfs_attr): check for AT_TYPE
+ (vattr2xfs_attr, xfs_attr2vattr): correct panic string
+
+Tue May 5 10:45:15 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/output.c (encode_string): zero-terminate string when
+ decoding.
+
+1998-05-05 Love <lha@s3.kth.se>
+
+ * configure.in: Check for dbm.
+
+ * arla/arla.c: Added flushfid command in -t mode.
+
+ * milko/bufcache.{c,h}: Added experimental bufcache.
+
+Sun May 3 04:29:01 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/solaris/xfs_vnodeops.c: return ENOSYS instead of EINVAL.
+ implement some trivial vnodeops
+
+ * xfs/solaris/xfs_vfsops.c: return ENOSYS instead of EINVAL for
+ non-implemented vfs-operations
+
+Sat May 2 03:00:35 1998 Assar Westerlund <assar@sics.se>
+
+ * **/Makefile.in: add `DESTDIR' and `uninstall:'
+
+ * arlad/fcache.c: got rid of some stupid warnings
+ updated to new volcache root volume stuff
+
+ * arlad/volcache.c: renamed volcache_rootvolume ->
+ volcache_get_rootvolume
+ (volcache_set_rootvolume): new function
+
+ * arlad/cred.c (cred_add): remove any old entry before adding the
+ new one.
+
+ * arlad/messages.c: try to handle expiring credentials in lots of
+ places
+ (viocgettok): remember to free the cred.
+
+ * arlad/fcache.c (read_data): handle the case of the file not
+ fitting in the cache.
+ (getroot): print the errors correctly
+ (getacl, setacl, getvolumestatus, setvolumestatus): don't destroy the
+ error code
+
+ * arlad/fbuf.c: rename all arguments fbuf -> f to avoid namespace
+ invasion.
+
+ * arlad/bsd-subr.c (conv_dir): get rid of a stupid varning
+
+ * arlad/cred.c (cred_expire): new function
+
+ * arlad/messages.c: try to handle expiring credentials.
+
+Fri May 1 22:20:23 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: call AC_C___ATTRIBUTE__
+
+ * aclocal.m4 (AC_C___ATTRIBUTE__): new macro for testing for
+ `__attribute__'
+ (AC_C___FUNCTION__, AC_FUNC_NTOHL): conservative default when
+ cross-compiling
+
+1998-04-30 Love <lha@s3.kth.se>
+
+ * ydr/output.c: No #define FOO_BAR_SIZE 0
+
+ * conf/services.h: No more errormessages...
+
+ * arlad/{fcache.c, arlad.c}: Added --root-vol=root.afs
+
+ * milko/* Added random stuff.
+
+Mon Apr 27 22:11:55 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/lex.l: parse more types of #line-lines.
+ renamed all tokens to T_FOO
+
+ * lwp/lwp.h: <sys/types.h> and <sys/select.h>
+
+ * lwp/Makefile.in: rs6000.
+ try harder preprocessing process.S
+
+ * appl/Makefile.in: add AIX_EXTRA_KAFS
+
+ * configure.in: aix
+
+ * aclocal.m4: AC_KRB_SYS_AIX added
+
+Sun Apr 19 15:36:35 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/Makefile.in (vop_defs.h): generate list of vops. From
+ "Per Boussard, ERA/T/ED" <per@era-t.ericsson.se>
+
+ * xfs/bsd/xfs_locl.h: include vop_defs.h
+
+Sun Apr 19 08:09:43 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/openbsd2.3/xfs_vfsops.c (xfs_mount): set `f_files' correctly
+
+ * xfs/bsd/xfs_vfsops.c (xfs_mount): set `f_files' correctly
+
+Wed Apr 15 04:52:27 1998 Robert Burgess <rb@abc.se>
+
+ * Release 0.5
+
+ * xfs/solaris/xfs_node.c: set blksize/nblocks
+
+Tue Apr 14 23:59:08 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_load.c: Changed major number to the newly
+ allocated 103
+
+Tue Apr 7 05:32:26 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * arlad/fcache.c: Added VIOCSETAL support
+
+ * arlad/messages.c: Moved some checks here from xfs_syscalls.c
+
+Mon Apr 6 05:19:44 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_vfsops.c: Added xfs_statfs
+
+ * xfs/linux/xfs_syscalls.c: Merged in new syscall style from bsd
+
+ * arlad/messages.c: Free opaque after use
+
+Sun Apr 5 12:50:56 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_node.c (xfs_dnlc_lookup): print debug output
+ correctly.
+
+ * arlad/cred.c (cred_delete): new function
+
+Sun Apr 5 05:49:27 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * arlad/fcache.c: Added VIOCGETVOLSTAT/VOLCSETVOLSTAT support
+
+Sun Apr 5 05:31:52 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (truncate_file): decrement usedbytes iff the data
+ was cached.
+
+ * arlad/adir.c (adir_mkdir): zero out hash table.
+
+ * arlad/afsdir_check.c: use arla_log
+
+ * arlad/Makefile.in (afsdir_check): link with arladeb.o
+
+Sun Apr 5 01:25:00 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/output.c (gendeclare): handle strings
+
+Sat Apr 4 20:39:18 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: add a --disable-mmap
+
+ * aclocal.m4 (AC_HAVE_GETCONF): call AC_CHECK_PROG properly
+
+Sat Apr 4 14:00:06 1998 Assar Westerlund <assar@sics.se>
+
+ * appl/Makefile.in: link with RXKAD and KAFS in the correct order
+
+Fri Apr 3 09:19:53 1998 Love H-Astrand <lha@ksk.sala.se>
+
+ * lib/ko/port.[ch]: Moved and added more ports.
+
+Fri Apr 3 05:30:19 1998 Assar Westerlund <assar@sics.se>
+
+ * lib/ko/koerror.c: const-ize
+
+ * arlad/arla.c: new option `-n'
+
+ * arlad/*.c: rationalize and use new debug levels and functions
+
+ * util/log.c: change LOG_DEBUG -> LOG_INFO
+
+ * util/log.h: add __attribute__
+
+ * arlad/arladeb.c: add new debug levels.
+ add arla_{v,}{err,warn}{,x}
+
+Thu Apr 2 05:07:29 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: use AC_STRUCT_SOCKADDR_HAS_SA_LEN
+
+ * aclocal.m4 (AC_STRUCT_SOCKADDR_HAS_SA_LEN): added
+
+ * rx/rx_user.c (GetIFInfo): rewrite so that it actually works.
+
+Tue Mar 31 07:52:39 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_lookup): better debug output for
+ negative caching
+
+ * xfs/bsd/xfs_message.c (xfs_message_installnode): purge the name
+ cache
+ (xfs_message_installdata): purge the name cache iff it's a directory
+
+Mon Mar 30 17:45:45 1998 Love Hörnquist-Åstrand <lha@stacken.kth.se>
+
+ * Added autoconf test for glibc.
+ From: Brad Keryan <keryan@andrew.cmu.edu>
+
+Mon Mar 30 12:01:50 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: added mkdir and rmdir
+
+ * xfs/linux/xfs_inodeops.c: xfs_readdir checks for inode numbers
+ in the name cache
+
+Mon Mar 30 00:27:22 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * aclocal.m4: Autoconf test for getconf, and getconf LFS_{C,LD}FLAGS
+
+Sun Mar 29 14:25:28 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux: Merged in access control from bsd.
+
+ * xfs/linux: Fixed various things. Should work much better.
+
+Sun Mar 29 03:21:39 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c: new option `connected-mode' for setting initial
+ connected mode
+
+ * arlad/fcache.c (do_read_attr, read_data): set anonaccess
+
+ * configure.in: remove test for winsock.h. added test for recvmsg
+ and sendmsg.
+
+ * rx/rx_mach.h: cygwin doesn't have SIOCGIFCONF. From Dan Winship
+ <danw@MIT.EDU>
+
+ * arlad/*.c: Use O_BINARY. From Dan Winship <danw@mit.edu>
+
+Sat Mar 28 10:34:30 1998 assar westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_common.c (install): use DESTDIR
+
+ * arlad/bsd-subr.c (write_dirent): conditionalize on
+ HAVE_STRUCT_DIRENT_D_TYPE
+
+ * configure.in: check for `d_type' in `struct dirent'
+
+Sat Mar 28 10:15:29 1998 Assar Westerlund <assar@sics.se>
+
+ * aclocal.m4 (AC_HAVE_STRUCT_FIELD): added
+
+1998-03-28 Love Hörnquist-Åstrand <lha@s3.kth.se>
+
+ * *: USE_MMAPTIME
+
+ * configure.in: Added --enable-mmaptime
+
+ * arlad/{messages,arlad}.c: Added no kerberos fix from
+ Dan Winship <danw@mit.edu>
+
+1998-03-27 Love Hornquist-Astrand <lha@ksk.sala.se>
+
+ * util/mmaptime.[ch]: Added (not working yet)
+
+Fri Mar 27 03:41:45 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c (newwalk): handle symlink followed by more path
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_lookup): enter negative entires in
+ name cache when arlad returns ENOENT
+
+ * xfs/bsd/xfs_node.c (xfs_dnlc_lookup): change signature to be
+ more compatible with cache_lookup
+
+ * arlad/arla.c (arla_cat): release lock
+
+Thu Mar 26 02:21:48 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.4
+
+ * lwp/process.S: rhapsody/powerpc
+
+ * lwp/Makefile.in: Add powerpc and rhapsody.
+
+ * **/Makefile.in: Use KRB_INC_FLAGS
+
+ * configure.in, aclocal.m4: Test for krb v5. From <lxs@mit.edu>
+
+Wed Mar 25 04:26:56 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_dev.c (xfs_devwrite): return the correct value.
+ also check for bogus size == 0
+
+ * xfs/{linux,sunos,solaris}: update to new style xfs_message.h
+
+ * xfs/bsd/xfs_msg_locl.h: new file
+
+ * xfs/bsd/xfs_wrap.c: do DISPATCH the `correct' way
+
+ * xfs/bsd/xfs_message.c: add `struct proc *p' to xfs_message_*
+
+ * xfs/bsd/xfs_node.c (new_xfs_node): now takes a `struct proc *p'
+
+ * xfs/bsd/xfs_dev.c: add `struct proc *p' to xfs_message_*
+
+ * xfs/bsd/xfs_dev.h: add prototypes for xfs_message_*
+
+ * arlad/messages.c: made all xfs_message_* functions static
+
+ * arlad/messages.h: add proto for xfs_message_receive
+
+ * xfs/include/xfs_message.h: Removed all the prototypes.
+
+ * xfs/bsd/xfs_vnodeops.c: s/EINVAL/EOPNOTSUPP/
+
+ * xfs/bsd/xfs_dev.c (xfs_message_wakeup_data): correct debug
+ output
+
+ * arlad/messages.c(afsrights2xfsrights): change arguments.
+
+ * xfs/linux/xfs_load.c (init_module): don't print
+ xfs_message_installnode, it's static now.
+
+Tue Mar 24 00:24:18 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_vfsops.c (xfs_mount): copy in the arguments. From
+ Karl Ramm <kcr@mit.edu>.
+
+Tue Mar 24 19:53:50 1998 Robert Burgess <rb@stacken.kth.se>
+
+ * arlad/fcache.c: Added VIOCGETAL support
+
+Tue Mar 24 02:03:43 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_dev.c (xfs_devwrite): fix?
+
+ * arlad/kernel.c: also collect statistics on the number of
+ messages per read
+
+ * arlad/messages.c: more stats
+
+ * arlad/messages.c: count the number of send/recd messages
+
+ * xfs/include/xfs_message.h (XFS_MSG_COUNT): added
+
+ * arlad/*-subr.c (conv_dir): use `fcache_extra_file_name' and do
+ locking correctly.
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_seek): return 0.
+
+ * Makefile.in (configure): ignore errors
+
+ * arlad/arla.c (main): don't malloc and free device_file
+
+ * appl/fs.c: added `getcrypt' and `setcrypt'
+
+ * xfs/bsd/xfs_syscalls.c (xfs_pioctl_call): add
+ VIOC_[GS]ETRXKCRYPT
+
+ * include/kafs.h (VIOC_[GS]ETRXKCRYPT): added
+
+ * arlad/bsd-subr.c (write_dirent): set `d_type'
+
+Sun Mar 22 19:25:18 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.3
+
+ * configure.in: don't clobber CFLAGS
+
+ * xfs/bsd/xfs_syscalls.c (xfs_pioctl_call): use
+ `a_followSymlinks'. Call `suser' instead of == 0
+
+ * arlad/solaris-subr.c: handle the weirdness in the solaris dirent
+ format
+
+ * arlad/afsdir_check.c (check): removed bogus code
+
+ * xfs/solaris: major rewriting and fixing.
+
+Sun Mar 22 02:47:59 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * appl/fs.c,arlad/messages.c,xfs/{bsd,openbsd2.3,linux}:
+ Added VIOCCONNECTMODE
+
+Sat Mar 21 15:20:52 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (read_data, write_data, truncate_file): kill the
+ call if an error occurs.
+
+ * configure.in: tweak CFLAGS and -I/usr/athena
+
+ * arlad/conn.c (conn_get): connected_mode test
+
+ * arlad/volcache.c (volume_uptodatep): look at connected_mode
+
+ * arlad/fcache.c (uptodatep): look at `connected_mode'
+
+ * arlad/arla.c: new option `--debug'
+
+ * arlad/arladeb.c (arla_log_set_level, arla_log_get_level,
+ arla_log_print_levels): new functions
+
+ * arlad/kernel.c (process_message): handle multiple messages
+
+ * xfs/{sunos,solaris,linux}/xfs_dev.c: merge in changes from bsd
+
+ * arlad/messages.c(xfs_send_message_wakeup_multiple): new
+ function. use it.
+
+ * lwp/iomgr.c: re-wrote the handling of fd_set's
+
+ * xfs/bsd/xfs_dev.c (xfs_devread, xfs_devwrite): implement
+ multiple messages per read/write
+
+Sat Mar 21 06:45:42 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * doc/* : added a few docs about Arla.
+
+Fri Mar 20 08:19:36 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs/{openbsd2.3,bsd}/xfs_vfsops.c (xfs_unmount): fix unmounting.
+
+Fri Mar 20 04:30:33 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_fetch_rights): new function used by
+ `xfs_access'
+ (xfs_read, xfs_write, xfs_readdir, xfs_readlink): vop_lock and
+ vop_unlock
+
+Thu Mar 19 22:31:20 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/output.c (init_generate): change path of rx.h
+
+ * xfs/bsd/xfs_vnodeops.c(xfs_fsync): send correct flags to
+ do_fsync
+
+ * arlad/fbuf.c (mmap_copyrx2fd, malloc_copyrx2fd): check result of
+ ftruncate
+
+ * arlad: moved kerberos includes to arla_local.h
+
+ * include/Makefile.in: remove stds.h, kafs.h add rxkad.h service.h
+
+ * **/Makefile.in: remove unused INCLUDES
+
+Thu Mar 19 12:27:47 1998 Love Hörnquist-Åstrand <lha@s3.kth.se>
+
+ * app/fs/fs.c:
+ (fserr): Implemented and changed on all used use on all places.
+ (afs_getfid): Added VIOCGETFID
+ (quit_cmd): use return instead of exit();
+
+Wed Mar 18 21:52:31 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (create_directory): create the directory locally
+ instead of fetching it from the file server
+
+ * arlad/adir.c (dir_mkdir): new function
+
+ * arlad/fcache.c (stale): don't bother if the callback is already
+ dropped
+
+Wed Mar 18 10:58:44 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_vfsops.c: Added xfs_write_inode
+
+ * xfs/linux/xfs_inodeops.c: Added permission checking and write support
+
+Wed Mar 18 03:11:51 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs/{openbsd2.3,bsd}/{xfs_fs.h,xfs_node.c}: xfs_has_pag implemented.
+
+ * xfs/{openbsd2.3,bsd}/xfs_node.c (new_xfs_node): set anonrights.
+
+ * xfs/openbsd2.3/xfs_vfsops.c: small fix to {un,}installation.
+
+ * xfs/{openbsd2.3,bsd}/xfs_vnodeops.c
+ (xfs_access): implement correctly
+
+ * xfs/{openbsd2.3,bsd}/xfs_node.h: add an anonrights field to
+ xfs_node.
+
+ * xfs/{openbsd2.3,bsd}/xfs_message.c
+ (xfs_message_installattr, xfs_message_installdata): set anonrights.
+
+ * xfs/include/xfs_message.h: add anonrights, change id from u_int
+ to pag_t, add masks for rights.
+
+ * arlad/messages.c
+ (afsrights2xfsrights): implement.
+ (fcacheentry2xfsnode): add handling of access rights.
+ (most functions): access rights handling with changed cm_attr.
+
+ * arlad/inter.c
+ (getrights): correct implementation.
+ (checkright): correct implementation.
+ (cm_getattr): handling of access rights.
+
+ * arlad/fcache.c
+ (create_new_entries): initialize acccache.
+ (recover_state): Do not recover rights.
+ (findaccess): pag 0 doesn't mean that it's unauthorized.
+
+ * ChangeLog: updated.
+
+Tue Mar 17 06:05:26 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * lwp/iomgr.c: some speed optimizations on selecting.
+
+Tue Mar 17 03:09:56 1998 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * Make arlad /dev/xfs0 working again.
+
+ * lib/ko/koerror.c: Fallback on strerror().
+
+ * xfs/bsd/{xfs_dev.c,xfs_vnodeops.c,xfs_locl.h}: Started to
+ use #ifdef HAVE_VOP_FOO for everything.
+
+ * xfs/bsd/xfs_dev.c: NetBSD 1.3 and OpenBSD 2.2 doesn't have
+ vop_{get,put}pages_desc.
+
+Tue Mar 17 01:24:55 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/*: moved xfs/*.h to .
+
+ * xfs/bsd/xfs_vnodeops.c: fixed vop_t
+
+ * xfs/solaris/Makefile.in: renamed xfs.mod -> xfs
+
+ * lwp/Makefile.in: check if the compiler is gcc not if it's called
+ gcc
+
+ * **: renames lots of `errno' to `error'
+
+ * xfs/linux/Makefile.in: include KRB_INC_DIR last
+
+Mon Mar 16 21:38:06 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * lwp/process.S: close a comment and let lwp work on ppc. (reported
+ to work)
+
+Mon Mar 16 20:55:52 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: Fixed bug in xfs_readdir
+
+Mon Mar 16 02:54:53 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.2
+
+ * NEWS, THANKS: new files.
+
+ * include/Makefile.in: add parse_units.h and resolve.h
+
+Sun Mar 15 00:56:47 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/volcache.c (volume_uptodatep): new function
+ (recover_state): don't mark recovered volumes as valid
+
+ * xfs/sunos/xfs_vnodeops.c (xfs_inactive): use the flag field on
+ the inactivenode message
+
+ * xfs/solaris/xfs_vnodeops.c (xfs_inactive): use the flag field on
+ the inactivenode message
+
+ * xfs/openbsd2.3/xfs_vnodeops.c (xfs_reclaim): use the flag field
+ on the inactivenode message
+
+ * xfs/linux/xfs_vfsops.c (xfs_put_inode): set flag in inactivenode
+ message
+
+ * xfs/include/xfs_message.h (xfs_message_inactivenode): new `flag'
+ field
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_close): only call `do_fsync' if the
+ file was oppened for writing and was actually changed.
+ (xfs_inactive): send an inactivenode message
+ (xfs_reclaim): use the correct flag on the inactivenode message
+
+ * arlad/messages.c (xfs_message_inactive): look at the flags
+ (xfs_message_create & c:o): use the correct realfid
+
+ * arlad/inter.c: update to new FCacheEntry
+
+ * arlad/fcache.c (throw_entry): only give up a callback if we have
+ any.
+ (recover_state): init `count'
+ (fcache_stale_entry): call stale iff flags.kernelp
+ (fcache_get_data): don't get data if the shows that it hasn't changed.
+
+ * arlad/fcache.h (FCacheEntry): remove `nreaders' and `nwriters'.
+ add `flags.kernelp'
+
+ * arlad/adir.c (create_new_page): return page1
+ (add_to_page): only loop till ENTRIESPERPAGE - 2
+ (adir_creat): don't use status.Length, it might already have been
+ increased by the file server. more and more correct checks.
+
+ * appl/vos.c (printvolstat): const-ized
+
+ * appl/arlalib.h: const-ized
+
+ * appl/arlalib.c: const-ized
+
+Sat Mar 14 14:39:25 1998 Assar Westerlund <assar@sics.se>
+
+ * include/Makefile.in: add err.h
+
+ * rx/rx_pkt.[ch]: don't assume sizeof(void) == 1
+
+Sat Mar 14 14:08:02 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/cmcb.c (RXAFSCB_CallBack): remove warning message
+
+ * arlad/{ports,arla,messages}.c: no \n to arla_log
+
+ * rxkad/rxk_locl.c (rxkad_check_packet): kludge around.
+
+ * README: update installation instructions
+
+ * arlad/arla.c: add options for rxkad_level and device.
+
+Sat Mar 14 13:56:55 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/Makefile.in: Added libko dependencies in arlad
+
+Fri Mar 13 05:06:37 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_inodeops.c (xfs_readlink): call `set_fs'
+
+ * xfs/bsd/xfs_vnodeops.c (do_fsync): reset the XFS_DATA_DIRTY flag
+ (xfs_remove): remove the name from the dnlc
+ (xfs_mmap, xfs_bmap, xfs_getpages, xfs_putpages): dummy functions
+
+ * xfs/bsd/xfs_message.c: spell-check the printfs
+
+ * util/fnameutil.[ch]: rename {base,dir}name to copy_\1name
+
+ * rxdef/pts.xg: fix broken declarations
+
+ * include/Makefile.in: add getarg.h
+
+ * arlad/volcache.h (volcacheentry): add `validp'
+
+ * arlad/volcache.c: change `freelist' to be a `lrulist'
+ (recover_state, volcache_store_state): new functions
+ (volcache_invalidate): new function
+
+ * arlad/inter.c (cm_init,cm_store_state,log_operation): new
+ functions
+ (*): call log_operation
+ (*): const-ized some arguments
+
+ * arlad/fcache.h: update prototypes
+
+ * arlad/fcache.c (fcache_store_state,recover_state): new functions
+ (fcache_init): don't create cachedir. try to recover state.
+ (*): return ENETDOWN if findconn fails
+ (do_read_attr): throw data if DataVersion has changed
+ (truncate_file): use O_CREAT
+ (create_file): create a empty cache file
+ (*): const-ized some arguments
+ (fcache_get_data): DTRT
+
+ * arlad/cmcb.c (RXAFSCB_CallBack): handle volume callbacks.
+
+ * arlad/arladeb.h: add ADEBVOLCACHE and ADEBCM
+
+ * arlad/arla.c (newwalk): return int. change callers. handle
+ signals by storing state
+ (main): use getarg. chdir to cachedir before initializing
+
+ * configure.in: fix sys/dir.h and dirent.h test.
+ call AC_KRB_VERSION
+
+ * aclocal.m4 (AC_KRB_VERSION): new macro
+
+ * TODO: update
+
+Thu Mar 12 15:22:50 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * configure.in,aclocal.m4,acconfig.h,lib/roken/resolve.c:
+ Added HAVE__RES
+
+ * configure.in, aclocal.m4: Added tests for krb-libs,and includes.
+
+Thu Mar 5 22:20:54 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: More correct error handling
+ and -Wall pleasing.
+
+Thu Mar 7 05:50:10 1998 Love Hörnquist-Åstrand <lha@s3.kth.se>
+
+ * rxdef/pts.xg: Added broken xg def.
+
+Wed Mar 4 03:23:19 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arla/*.c: Added arla_log and started to used.
+
+ * util/log.c: Added log_vlog.
+
+ * arlad/messages.c: Moved vicofluchvolume outsize #ifdef KERBEROS
+ and added stub for VIOCGETAL.
+
+Tue Mar 3 21:16:06 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: fixes memoryleak and xfs_readdir()
+ on linux != sparc. from amu@mit.edu (Aaron M. Ucko)
+
+Tue Mar 3 00:00:55 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/inter.c (cm_lookup): const-ized parameters
+
+ * xfs/{sunos,solaris}/{,bin/}Makefile.in: set exec_prefix
+ (install): removed '-m 444'
+
+ * rxdef/volumeserver.xg: remove stds.h
+
+ * lib/{ko,tl}/Makefile.in (install): removed '-m 444'
+
+ * arlad/arla.c (newwalk): follow symlinks
+ (main): try harder getting kerberos credentials
+
+ * appl/appl_locl.h: include <atypes.h>
+
+Mon Mar 2 13:32:42 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * appl/vos.c: Vos exa now uses libko/kocell.
+
+ * lib/ko/kocell.c: Moved from arlad/cell.c, and turned
+ arlad/cell.c to a dummy.
+
+ * configure.in,include/stds.h.in: Added autoconf test
+ for krb_principal
+
+ * Made a bunch of links to include/ from all .h files
+ to make the compile lines more sane.
+
+ * arla/{fcache.c,volcache.c} Added use of libkoerror.
+
+Mon Mar 2 01:00:09 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * arlad/bsd-subr.c: Horrible hack for DEC Unix.
+
+Sun Mar 1 06:42:00 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.1
+
+ * arlad/fcache.c (do_read_attr): invalidate data if we have it
+ cached and DataVersion has changed.
+
+ * xfs/bsd/xfs_node.c (new_xfs_node): postpone vget-ing
+
+ * xfs/bsd/bin/Makefile.in: set PROGS and clean properly
+
+ * xfs/bsd/xfs_message.c (xfs_message_isntallnode): more debug
+
+ * xfs/bsd/Makefile.in (doclean): clean properly
+ (CFLAGS): remove Wall (it is set by configure)
+
+ * rx/rx.h: remove stupid includes
+
+ * conf/Makefile.in: don't overwrite existing configuration files
+
+ * configure.in: remove unused tests
+
+ * xfs/bsd/xfs_message.c (xfs_message_installdata): don't
+ VOP_UNLOCK unlocked vnode.
+
+ * util/list.c: more paranoia
+
+ * arlad/bsd-subr.c (conv_dir): free buf
+
+ * arlad/adir.c (adir_readdir): do `.' and `..'-magic correctly.
+
+Fri Feb 27 23:37:39 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c: better error reports when rx calls fail.
+
+Fri Feb 27 07:09:08 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * arlad/*-subr.c: truncate files when opening a dircache file.
+
+Fri Feb 27 04:56:58 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * arlad/arladeb.h: ADEBFCACHE added
+
+ * arlad/fcache.c: don't break dead xfs-callbacks.
+
+ * arlad/adir.c: put '.' and '..' in front of a readdir. Some systems
+ seem to like it that way.
+
+Thu Feb 26 01:30:44 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/fcache.c,messages.c: VIOC_FLUSHVOLUME
+
+ * Now semiworking (no good parsing) vos listvol, it was a feature
+ in ydr.
+
+ * ydr/output.c:
+ - long -> int32 fix
+ - Fix for use of temporary variables.
+
+Mon Feb 23 06:38:18 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/bsd/xfs_syscalls.c: Merged in changes from obsd23.
+
+ * lib/roken/roken.h: ssize_t added.
+
+ * lib/roken/roken.h: sunos select fix.
+
+ * lib/roken/roken.h,acconfig.h, configure.in: sunos select fix.
+
+ * VIOC_VENUSLOG: Almost.
+
+Mon Feb 23 01:17:43 1998 Artur Grabowski <art@stacken.kth.se>
+
+ * xfs/openbsd2.3: (xfs_pioctl) cleanup and VIOCSETCACHE
+
+ * arlad/messages.c, fcache.c: VIOCSETCACHE
+
+Mon Feb 23 02:10:51 1998 Assar Westerlund <assar@sics.se>
+
+ * Release 0.0
+
+ * arlad/arla.c (main): try to get tokens for the local cell.
+
+ * appl/appl_locl.h: include rxkad.h iff KERBEROS
+
+ * arlad/fcache.c (read_data): make sure we never go over
+ `highbytes'
+
+ * lwp/Makefile.in: add hpux
+
+ * configure.in: add hpux
+
+ * rx/rx_pkt.c(rxi_ReadPacket): fix from <per@era-t.ericsson.se>
+ for handling strange packets.
+
+ * rxdef/vldb.xg: MAXNAMELEN -> VLDB_MAXNAMELEN
+
+ * rx/rx_locl.h: include <atypes.h>
+
+ * lib/ko/ko.h: include <atypes.h>
+
+ * arlad/messages.c: always include <kafs.h>
+
+ * arlad/arla.c: made `conf_params' static to make it initable.
+
+ * arlad/Makefile.in: coompatible with stupid make
+
+ * appl/Makefile.in: use KAFS_LIBS
+
+ * configure.in: set KAFS_LIBS
+
+ * arlad/arla.c: allow setting of low and high-water marks.
+
+ * configure.in: test if strtok_r needs a prototype
+
+ * rxdef/Makefile.in: remove new junk files
+
+ * ydr/main.c: changed the way of running cpp :-(
+
+Mon Feb 23 05:55:54 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs/openbsd2.3: (xfs_pioctl) cleanup and VIOCSETCACHE
+
+ * arlad/messages.c, fcache.c: VIOCSETCACHE
+
+ * appl/fs.c: setcachesize implmeneted.
+
+ * arlad/arla.c: Added reading of a configuration file.
+
+Sun Feb 22 20:51:47 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/bsd/xfs_vnodeops.c(xfs_link): Added OpenBSD and NetBSD
+ compability
+
+ * configure.in, include/stds.h, rxkad/rxkad.h: Added test for
+ {,u_}int32, and added those for rxkad.
+
+ * appl/vos.c: Fixing listpart, but the total is still wrong.
+
+ * appl/vos.c: Added libko to parts of vos.c
+
+ * lib/ko: Added libko, vlserver, volserver and rxkad errorcodes
+ and messages.
+
+Sun Feb 22 15:59:30 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/volcache.c (print_entry): print every volume only once.
+
+Sun Feb 22 15:23:31 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * lwp/iomgr.c (struct IoRequest): add `next' pointer instead of
+ bogus use of `result'.
+
+ * lwp/lwp.c: Include <string.h>, replace "0x%x" with "%p".
+
+ * rx/*: Use rx_locl.h
+ - replace bcopy with memcpy
+ - remove `register'
+ - change long -> int32
+ - don't depend on sizeof(whatever) being correct
+
+ * rx/rx_user.c: Clean up osi_Panic.
+
+ * rx/rx_pkt.c: Cleanup rx_Slow{Read,Write}Packet.
+
+ * appl/vos.c: htonl(vlentry.serverNumber)
+
+Sun Feb 22 06:10:55 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/lex.l (yywrap): conditionalize
+
+Sun Feb 22 01:11:17 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/messages.c (xfs_message_pioctl): implement VIOCGETTOK
+
+ * xfs/bsd/xfs_syscalls.c (xfs_pioctl_call): implement `VIOCGETTOK'
+
+ * rxkad: updated to a more modern version.
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_link, xfs_rename): implement
+
+ * arlad/messages.c (xfs_message_link, xfs_message_rename):
+ implement
+
+ * arlad/inter.c (cm_link, cm_rename): new functions
+
+ * arlad/fcache.c (create_link, rename_file): new functions
+ all functions are now careful not to use any OUT parameters from
+ rpc's that fail.
+
+ * xfs/bsd/xfs_node.c (xfs_node_find): cleaner
+
+ * arlad/fbuf.c: re-did the fbuf-interface
+
+ * arlad/bsd-subr.c (write_dirent): do special for ".." iff
+ flags.mountp
+
+ * arlad/volcache.c (recycle_entry): removed a bogus `hashtabdel'
+
+ * rx/rx_pkt.c (rxi_ReadPacket): case `RX_HEADER_SIZE' to int when
+ comparing again `nbytes', otherwise we lose :-(
+
+ * xfs/bsd/xfs_node.c (xfs_node_find): a dead vnode might still be
+ on the mount-list, check for that.
+
+Sat Feb 21 23:14:47 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * arlad/adir.c(adir_remove): Use length when deleting a entry
+ in a afsdir.
+
+ * arlad/fcache.c: Return ENOMEM when not finding a cred for the
+ new cell (this should never fail, we should allways be able to find a
+ rx_null cred.)
+
+ * xfs/bsd/xfs_vnodeops.c: Define xfs_vop_t for Open|NetBSD for
+ typecasting --> getting less errors.
+
+ * arlad/fcache.c: Use CRED_ANY when we hit a remote cell,
+ and doesn't find a "native" cred.
+
+Sat Feb 21 18:14:47 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/messages.c (xfs_message_symlink): new function
+
+ * arlad/inter.c (cm_symlink): new function
+
+ * arlad/fcache.c (create_symlink): new function
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_symlink): implement
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_lookup): more SAVENAME voodoo
+ (xfs_remove, xfs_rmdir, xfs_abortop): implement functions
+
+ * arlad/messages.c (xfs_message_mkdir, xfs_message_rmdir): new
+ functions
+
+ * arlad/inter.c (cm_mkdir, cm_rmdir): new functions
+
+ * arlad/fcache.c (create_directory, remove_file,
+ remove_directory): new files
+
+ * arlad/afsdir_check.c: more paranoid tests
+
+ * arlad/adir.c: squash some almost fence-post bugs.
+
+ * xfs/include/xfs_message.h (xfs_message_remove): added cred
+
+ * arlad/afs_dir.h: start using sized types
+
+ * arlad/messages.c (xfs_message_create): convert and push down the
+ updated directory
+
+ * arlad/inter.c (cm_create): create the file in the local cached
+ copy of the directory.
+
+ * arlad/fbuf.c: re-organized.
+ (truncatefilebuffer): new function
+
+ * arlad/adir.c (adir_lookup): test to see that `dir' is a
+ directory.
+ (adir_readdir): dito
+ (adir_creat): new function for adding an entry to a directory.
+ (aidr_remove): new function for removing an entry from a directory.
+
+ * arald/afsdir_check.c: new program
+
+Sat Feb 21 16:00:00 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * arlad/arla.c, rx/r.c: Added rx-status.
+
+Fri Feb 20 09:32:52 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c: return better error codes than ENODEV (except in
+ two cases)
+
+Thu Feb 19 23:17:25 1998 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * xfs/bsd/xfs_syscalls.c, arlad/messages.c: Added VIOC_GET_WS_CELL.
+
+ * xfs/include/xfs_messages.h: Added handle to pioctl msg.
+
+Thu Feb 19 02:47:52 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/bsd/syscalls.c, arlad/message.c: VIOC_FILE_CELL_NAME.
+
+ * xfs/bsd/xfs_vnodeops.c(xfs_mkdir): Send right message and
+ save us a panic
+
+ * include/kafs.h: Added more pioctl calls.
+
+ * appl/vos.c: Added to option to query a specific server in vos exa
+ and added options -host, -cell and -noauth.
+
+ * arlad/arla.c: begining for sysname in -t mode.
+
+ * arlad/cell.c: Ask diffrent vldb-server each time.
+
+Thu Feb 19 06:05:43 1998 Assar Westerlund <assar@sics.se>
+
+ * include/kafs.h: added
+
+ * arlad/fcache.c: re-wrote
+
+ * arlad/volcache.c: re-wrote
+
+ * arlad/messages.c (VIOC_AFS_SYSNAME): remove
+ (afsstatus2xfs_attr): fix
+ (xfs_message_*): updated
+
+ * arlad/inter.c (getrights, checkright): commented out, I didn't
+ bother to fix them now.
+ (cm_lookup): add test for `@sys'
+ (cm_remove, cm_link): commented out
+
+ * arlad/fbuf.c: remove #undef HAVE_MMAP and make the code compile.
+
+ * arlad/conn.c: re-wrote
+
+ * arlad/cred.c: re-wrote
+
+ * arlad/cmcb.c (RXAFSCB_InitCallBackState): do something
+
+ * arlad/cell.c: rename all functions to cell_
+ (cell_num2name): new function
+ fix fopen format strings
+ removed all locks (sorry Love)
+
+ * arlad/arla.c: Use `tmpce'
+ (arla_{conn,vol,cred,fcache}_status): new functions
+
+ * arlad/adir.c (adir_lookup): update to new fcache-interface. use
+ CredCacheEntry. don't handle @sys
+ (adir_readdir): update to new fcache-interface. use CredCacheEntry
+
+ * ydr/output.c: add copyright
+ (gen1): make TIN arguments `const'
+
+ * xfs/bsd/Makefile.in (CFLAGS): add `-Wno-unused'
+
+ * xfs/bsd/xfs_node.c (xfs_attr2vattr): set `va_blocksize' to a
+ reasonable value.
+
+ * util/hash.c (hashtabnew): check malloc return value at correct
+ place.
+
+ * arlad/Makefile.in: more includes link with libraries in correct
+ order
+
+ * makesnap: don't hardcode cvsbin and CVSROOT
+
+Thu Feb 12 01:38:21 1998 Assar Westerlund <assar@sics.se>
+
+ * ydr/output.c: include rx.h
+
+ * ydr/main.c: does it have to be this hairy to run a simple cpp
+ portably?
+
+ * xfs/solaris/xfs_node.c (new_xfs_node): use correct set of
+ attributes
+
+ * xfs/include/xfs_message.h: moved xfs_msg_node and related
+ defintions here from xfs/*/xfs/xfs_node.h
+
+ * lwp/q.c: renamed {ins,rem}que to lwp_\1
+
+ * arlad/irix-subr.c: new file
+
+ * aclocal.m4: stolen BASH_CHECK_DEV_FD from bash
+
+ * configure.in: Add testing for /dev/fd.
+ correct gcc test.
+ stub support for irix.
+
+Wed Feb 11 02:18:51 1998 Assar Westerlund <assar@sics.se>
+
+ * lib/roken/{snprintf.c,mini_inetd.c,getarg.c}: merged in newer
+ code.
+
+ * configure.in: moved util and ydr from subdirs to AC_OUTPUT
+
+1998-02-10 Per Andersson <ppan@joker.cntw.com>
+
+ * INSTALL: Changed sunos(4) instructions to match current version
+
+Tue Feb 10 02:52:51 1998 Assar Westerlund <assar@sics.se>
+
+ * lwp: renamed process.s -> process.S
+
+ * aclocal.m4(AC_GROK_TYPE): test for ktypes.h
+
+ * xfs/sunos/Makefile.in: rewrote and vpath-ed.
+
+ * xfs/sunos: updated to changes elsewhere.
+
+ * arlad/arla_local.h: use <dirent.h> xor <sys/dir.h>
+
+ * arlad/afs_dir.h: rename PAGESIZE -> AFS_PAGESIZE
+
+ * include/bits.c: test for ktypes.h
+
+ * configure.in: test for ktypes.h
+
+ * include/{bits.c,Makefile.in}: generate atypes.h
+
+ * xfs/solaris: new directory
+
+ * arlad/solaris-subr.c: new file
+
+ * ydr/lex.l: handle more kinds of #-lines
+
+ * rxkad/Makefile.in: work-around for stupid solaris make
+
+ * rxdef/Makefile.in: remove BSD/GNU-special and use explicit rules
+ instead.
+
+ * rx/Makefile.in: work-around for stupid solaris make
+
+ * lwp/iomgr.c: add <fcntl.h>
+
+ * lwp/Makefile.in: more magic for preprocessing and assembling
+ process.s
+
+ * arlad/sunos-subr.c (fcacheentry2xfsnode, conv_dir): update to
+ new signatures
+
+ * arlad/conn.c (markasdown): don't initialize `d' in declaration
+
+ * Makefile.in: add include to SUBDIRS
+
+ * configure.in: replace @CANONICAL_HOST@
+ add solaris
+ check for -lsocket, -lnsl and -lresolv
+ generate Makefile in include
+
+Tue Feb 3 16:16:42 1998 Love Hörnquist-Åstrand <lha@e.kth.se>
+
+ * util/hash.c(hashjpw): Some typecasting to save the world.
+
+ * lib/roken/snprint.c: Removed #if 0
+
+ * configure.in: Added check for gcc and -Wall
+
+Fri Jan 30 19:58:51 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/{conn.c,fcache.c,volcache.c}: Fixed conn locking.
+
+Wed Jan 28 05:43:44 1998 Artur Grabowski <art@stacken.kth.se>
+
+ * Cleaned up most of the warnings in arlad, lwp, rx* and some other
+ small things.
+
+ * lwp: ANSI-prototypes.
+
+ * rx: ANSI-prototypes. Indentation, cleanup
+
+Wed Jan 28 01:00:00 1998 Niklas Hallqvist <nh@stacken.kth.se>
+
+ * BSDmake compatibility
+
+ * Build from local libsl
+
+Thu Jan 22 22:13:57 1998 Magnus Holmberg <mho@stacken.kth.se>
+
+ * xfs/include/xfs_message.h: Argh! Whoever came up with the bright
+ idea of having userland xfs_message_receive() and kernel
+ xfs_message_receive() have the same name and share the same
+ prototype?
+
+ * xfs/include/xfs_message.h, configure.in, acconfig.h:
+ Gross hack to support both old and new VFS.
+
+Wed Jan 21 12:52:44 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs_inodeops.c (xfs_close): use XFS_{READ,WRITE}
+
+ * xfs/bsd/xfs_vnodeops.c (xfs_close): use XFS_{READ,WRITE}.
+ always call cm_close, independent of the dirty flag. arlad needs
+ to now how many processes have this file open.
+
+ * arlad/inter.c(cm_close): use XFS_READ & c:o
+
+ * xfs/include/xfs_message.h: introduced flags:
+ XFS_{READ,WRITE,...}
+
+Wed Jan 21 03:54:15 1998 Magnus Holmberg <mho@stacken.kth.se>
+
+ * xfs/openbsd2.3:
+ VFS Lite2 changes.
+ Merged from .../xfs/bsd.
+ -Wall.
+
+Mon Jan 19 03:30:53 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/*-subr.c, arlad/messages.c: Merged xfs_attr stuff into messages.c
+
+ * Changed linux xfs to use xfs_attr and changed everything to include
+ xfs/include/xfs_message.h
+
+Mon Jan 19 04:46:36 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/include/xfs_message.h: add ID. remove old junk
+
+ * xfs/include/xfs_attr.h (XA_SET_*): Use correct field name.
+ (xfs_file_type): fix typo
+
+ * xfs/bsd/xfs_node.c (vattr2xfs_attr, xfs_attr2vattr): new
+ functions
+
+Sun Jan 18 12:19:26 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/bsd/Makefile.in (MODULE): use `mv -f'
+ (unload): correct symbol is `xfs_mod'
+
+ * arlad/fcache.c (writefile): don't send the length of data in the
+ stream.
+
+Sun Jan 18 23:57:11 1998 Love H-Åstrand <lha@foo.ksk.sala.se>
+
+ * xfs/bsd/bin/startarla.in: a startscript, using autoconf.
+
+ * xfs/bsd/xfs_dev.c(xfs_devclose): Make sure we dont unmount a
+ not mounted filesystem.
+
+Sun Jan 18 12:19:26 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/conn.c (getconnection): restructured. Make all
+ unauthenticated connections with cred == 0. Try to add an
+ unauthenticated connection at the same time as a authenticated
+ one. This is used when receiving and breaking callbacks.
+
+ * arlad/conn.h (ConnCacheEntry): add `securityclass'
+
+ * xfs/bsd/bin/mount_xfs.c: DTRT with __progname and err*
+
+ * xfs/bsd/Makefile.in (unload): use modunload
+
+ * arlad/*-subr.c: no need to specify cachedir.
+
+ * arlad/fcache.c: allow specification of cachedir
+
+ * arlad/arla.c (main): specify cachedir when calling initfcache
+
+ * Makefile.in: clean and simplify
+
+ * xfs/bsd/xfs_dev.c: use = instead of bcopy
+
+Sun Jan 18 15:14:58 CET 1998 Love H-Åstrand <lha@foo.ksk.sala.se>
+
+ * Added configure option --with-arlacachedir
+
+Sun Jan 18 01:20:45 1998 Love H-Åstrand <lha@foo.ksk.sala.se>
+
+ * arla/cafe-au-lait.c: Added new file.
+
+ * Added target install and made arla/cell.c use prefix for
+ CellServDB and ThisCell.
+
+ * xfs/bsd/xfs_dev.c(xfs_uninstall_device): Fixed unload bug for
+ net|open-bsd
+
+ * xfs/bsd/xfs_vfs_ops.c: Fixed kernel panic for net|openbsd,
+ it may work now. Tried to fix it for freebsd too.
+
+Thu Jan 15 23:24:52 1998 Magnus Holmberg <mho@stacken.kth.se>
+
+ * xfs/openbsd2.3/xfs_vnodeops.c: Fixed arguments to vnode
+ functions to match new vfs.
+
+Thu Jan 15 06:10:37 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: test for symorder. use xfs/bsd
+
+ * xfs/bsd: new unified bsd xfs-module
+
+Thu Jan 15 01:14:35 1998 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * xfs/openbsd/xfs_vnodeops.c: Added use of XFS_ANONYMOUSID when we
+ dont have a cred. Setting pag_t.pag to 0 is a bad idea, since we
+ use uid when the user doesn't have a pag...
+
+Thu Jan 15 00:52:16 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_vfsops.c: Made xfs_put_inode tell arla when an
+ inode goes inactive
+
+ * arlad/fcache.c: Hopefully more correct locking
+
+Tue Jan 13 23:10:03 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c (openfile): changed to return error and fd as
+ parameter.
+
+ * arlad/Makefile.in: use @LIB_readline@
+
+ * configure.in: stolen editline-tests from krb4
+
+ * aclocal.m4: stolen AC_FIND_FUNC_NO_LIBS from krb4
+
+ * arlad/arla.c: junked lots of old code.
+ wrote a new simple command-line mode for `-t'.
+
+ * arlad/cmcb.c (RXAFSCB_Probe, RXAFSCB_InitCallBackState,
+ RXAFSCB_CallBack): print the IP-address
+
+ * arlad/Makefile.in: renamed arla -> arlad.
+ link with sl and related libraries
+
+ * configure.in: make sure we have a working version of autoconf
+ don't create any xfs-makefiles if we have a unsupported OS
+
+1998-01-13 Per Andersson <ppan@joker.cntw.com>
+
+ * Arladaemons name changed to 'arlad' in INSTALL
+
+Tue Jan 13 19:23:10 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * Added sl and editline
+
+ * Added pag support for net/open-bsd
+
+ * Added libroken
+
+Mon Jan 12 23:12:15 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/messages.c,xfs/{linux,openbsd,freebsd}:
+ Moved to pag authentication, added set sysname,
+ added set pag in linux
+
+Mon Jan 12 00:59:55 1998 Magnus Ahltorp <magnus@dike.aladdin.se>
+
+ * xfs/linux/xfs_syscalls.c: Added set pag.
+
+Sun Jan 11 05:14:44 1998 Assar Westerlund <assar@sics.se>
+
+ * rxkad/rxk_crpt.c: resurrect bswap and conditionalize it on
+ EFF_NTOHL
+
+ * configure.in: use AC_FUNC_NTOHL
+
+ * aclocal.m4 (AC_FUNC_NTOHL): new macro
+
+ * ydr: added support for the 'multi' keyword
+
+Sun Jan 11 00:19:46 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/openbsd/xfs_locl.h: Added prototype for xfs_get_pag and
+ added som include files (removed those include files all over)
+
+ * xfs/openbsd/xfs_vfsops.c: Added the type of fs to the
+ mp->mnt_stat struct
+
+ * xfs/openbsd/xfs_syscalls.c: Added pag support
+
+ * xfs/openbsd/xdeb.h: Added XDEBSYS
+
+ * xfs/openbsd/xfs_dev.c(xfs_devclose): Lock the mointpoint when
+ freeing the xfsnodes
+
+Sat Jan 10 04:21:31 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/{bsd,linux,sunos}-subr.c (conv_dir): don't ReleaseReadLock
+
+ * arlad/fcache.c: allow reuse of the cache files
+
+ * arlad/messages.c (xfs_message_getroot): use `cm_getattr'
+
+ * arlad/inter.c (cm_getattr): return real_fid as a parameter.
+
+ * arla/thash.[ch], arla/vlstr.h: removed.
+
+ * ydr/output.c (generate_server_switch): write prototype to header
+ file.
+
+ * lwp/Makefile.in: add mips/irix
+
+ * arlad/volcache.c: clean-up:
+ cell -> int32_t
+ const-ize
+
+ * arlad/ports.c (initports): use the official IANA names and
+ enable the code.
+
+ * arlad/{linux,sunos,bsd}-subr.c (write_dirent): const-ize
+
+ * arlad/conn.c: all cells are int32_t
+
+ * arlad/cell.c: all cells are int32_t
+
+ * arlad/cmcb.c: clean-up
+
+ * arlad/adir.c (afs_lookup): return int. removed old code.
+ clean-up.
+
+ * lwp/Makefile.in: fix ranlib
+
+ * arlad/cell.c: restructured a tiny bit and added some (void)
+
+ * arlad/fcache.c (getroot): return error code. changed all callers.
+
+ * arlad/kernel.c: `struct fd_set' should be `fd_set'
+
+ * include/config.h.in: removed
+
+ * xfs/openbsd2.3/xfs_vfsops.c (xfs_mount): replaced VOP_UNLOCK by
+ vput
+
+ * xfs/openbsd/xfs_vfsops.c (xfs_mount): do vput instead of
+ VOP_UNLOCK.
+
+Fri Jan 9 21:32:54 1998 Assar Westerlund <assar@sics.se>
+
+ * configure.in: test for header files used by fs
+
+Fri Jan 9 20:55:05 1998 Robert Burgess <rb@bobby.stacken.kth.se>
+
+ * appl/fs.{c,h}: added
+
+Fri Jan 9 18:29:28 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs/*/xfs/xfs_node.h: define xfs_attr
+
+ * xfs/linux/xfs/attr.h: xfs_attr must be a type and not a struct.
+
+ * bin/umount_xfs.c: does not work. replaced with the
+ openbsd-version.
+
+ * arlad/kernel.c: new file with generic kernel interface code.
+
+ * arlad/{bsd,sunos,linux}-subr.c: OS-specific functions
+
+ * arlad/messages.c: new file with the generic message code.
+
+ * conf/CellServDB: A recent version.
+
+Fri Jan 9 17:23:08 1998 Love H-Astrand <lha@ksk.sala.se>
+
+ * Added milko/aefs: Added Äckligt fs, and cleaned up
+
+ * configure: Removed
+
+Fri Jan 9 17:25:21 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/linux-messages.c: getattr and creds fixed
+
+Fri Jan 9 13:53:50 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs/openbsd: cleanup
+
+ * xfs/openbsd: add flags to free_all_xfs_nodes to allow forced unmount
+
+Fri Jan 9 12:17:20 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * Made the definite move of mount_xfs and other binaries into
+ xfs/@sys/bin
+
+Fri Jan 9 05:23:13 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/adir.c: Moved pointer dereference to after initialization
+ of the pointer
+
+1998-01-08 Per Andersson <ppan@joker.cntw.com>
+
+ * Added very preliminary installation instructions in ./INSTALL
+
+Thu Jan 8 11:05:40 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/fbuf.c: Truncate file before close
+
+ * arlad/inter.c, arlad/fcache.c: Made cm_lookup handle EACCES
+
+Thu Jan 8 03:28:55 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/fcache.c: changed getfile and getattr to return an error
+ code. fixed all callers.
+
+ * lwp/preempt.c: ifdef SA_NODEFER
+
+ * ydr/lex.l: always print error messages with `error_message'.
+ use global `filename'.
+ be careful when setting `filename' from cpp-lines
+
+ * ydr/types.h: add TINOUT
+
+ * ydr/parse.y: add INOUT and int
+
+ * ydr/output.c (encode_symbol): add default catch-all.
+ add handling of INOUT.
+ rename `result' -> `_result'
+
+ * ydr/lex.l: add INOUT
+
+ * rxdef/Makefile.in (CLIENTLIB, SERVERLIB): run ranlib.
+ (clean): remove more files.
+
+ * rx/rx_queue.h: renamed _Q() to _RX_QUEUE(): it conflicts with _Q
+ from <ctype.h>
+
+ * configure, include/config.h.in: regenerated
+
+ * configure.in: remove rxgen
+
+ * rxdef/Makefile.in: add more file types to ydr rule
+
+ * lwp/preempt.c, lwp/iomgr.c: use RETSIGTYPE
+
+ * arlad/volcache.c: use `u_int32_t' for volumes.
+
+ * arlad/fcache.c (writefile): fix sprintf call.
+
+ * configure.in: add AC_TYPE_SIGNAL
+
+ * arlad/msg.c: removed
+
+Wed Jan 7 19:54:57 1998 Love H-Astrand <lha@ksk.sala.se>
+
+ * arlad/*.xg, arlad/common.h: Removed them, then live in rxdef/ now
+
+Wed Jan 7 10:00:25 1998 Magnus Ahltorp <magnus@dike.aladdin.se>
+
+ * xfs/linux/Makefile: removed
+
+ * xfs/linux/Makefile.in: Added
+
+Wed Jan 7 07:40:02 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs: mount_xfs and umount_xfs moved from openbsd to xfs/bin
+
+ * xfs/bin: new mount_xfs with argument parsing and correct syntax
+
+Wed Jan 7 05:31:16 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * xfs/openbsd/mount_xfs.c: mount_xfs mow mounts with fstype "xfs"
+ and not from command-line
+
+Tue Jan 6 07:03:38 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * appl/vos.c: new command-interface for vos
+
+Tue Jan 6 05:22:13 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/inter.c(cm_setattr): Using error from writeattr()
+
+ * arlad/fcache.c(writeattr): Using the error we got back from
+ RXAFSStoreStatus()
+
+ * xfs/openbsd/Makefile.in: Added -e to modload
+
+Tue Jan 6 05:06:40 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/adir.c: Added @sys support
+
+ * arlad/linux-messages.c: Added putdata, putattr, create,
+ pioctl. Cleaned up a lot.
+
+ * xfs/linux/xfs_syscalls.c: First real version
+
+ * xfs/linux/xfs_inodeops.c: Added open, read, readdir, readlink,
+ followlink
+
+ * xfs/linux/xfs_dev.c: Added xfs_message_wakeup_data
+
+Tue Jan 6 04:16:53 1998 Artur Grabowski <art@squit.stacken.kth.se>
+
+ * fixed xfs/openbsd/umount_xfs and compilation problems with mount
+ and umount
+
+Mon Jan 5 17:30:41 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/openbsd/mod.c: Dont need the diffence between net and open,
+ use modload -e
+
+ * arlad/fcache.c: Fixed bug that made arla write the old length of
+ the file
+
+ * xfs/openbsd/xfs_node.c: Fixed long filename, and added a one
+ entry cache for them.
+
+ * xfs/openbsd/xfs_dev.c: Added some really ugly workarounds for
+ differences between *BSD
+
+Mon Jan 5 05:10:41 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/openbsd/mount_xfs.c: More errorchecking and removed compat
+ junk
+
+Sun Jan 4 22:30:37 1998 Love Hörnquist-Åstrand <lha@stacken.kth.se>
+
+ * */*/*: Removed all (?) reference to u_long cred and started to
+ use pag_t cred. Dont know how much vill break.
+
+ * xfs/openbsd/xfs/xfs_message.h: added xfs_cred and pag_t
+
+Sat Jan 3 21:51:56 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_syscalls.c: Added
+
+ * xfs/linux/xfs_inodeops.c: Released inode after use
+
+Sat Jan 3 20:24:37 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_cache.c: Added
+
+ * xfs/linux/xfs_node.c: Added cache purging in
+ free_all_xfs_nodes()
+
+ * xfs/linux/xfs_common.h: Cleaned up and changed syntax for xfs_free
+
+ * xfs/linux/xfs_common.c, xfs/linux/xfs_dev.c,
+ xfs/linux/xfs_node.c: Changed syntax for xfs_free
+
+ * xfs/linux/xfs_inodeops.c, xfs/linux/xfs_message.c: Changed to xfs_cache
+
+ * xfs/linux/xfs_vfsops.c: Added xfs_put_inode
+
+Sat Jan 3 08:37:08 1998 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/bsd-messages.c(xfs_message_create): New function
+
+ * arlad/inter.c(cm_close): Fixed flags semantics
+
+ * arlad/fcache.c(writefile): Fix AFSStoreStatus mask
+
+ * xfs/openbsd/xfs/xfs_message.h: Added flag to struct
+ xfs_message_putdata, so we know what to do.
+
+ * arlad/bsd-messages.c: Implemented xfs_message_putdata()
+
+ * xfs/openbsd/xfs_vnodeops.c(xfs_close, xfs_fsync): Added writesupport
+
+Sat Jan 3 05:27:51 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs_message.c: merge in changes from ../openbsd
+
+ * xfs_vnodeops.c (xfs_read): panic if cache vnode == NULL
+
+ * arlad/bsd-messages.c (xfs_message_getnode,xfs_message_getattr):
+ mask XFS_DATA_MASK from `msg.node.tokens'
+
+Sat Jan 3 00:55:46 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/inter.c: Changed cm_getattr to check for the correct rights
+
+ * xfs/linux/xfs_inodeops.c: Fixed return value from xfs_lookup
+
+Fri Jan 2 23:34:22 1998 Love Hörnquist-Åstrand <e96_lho@e.kth.se>
+
+ * xfs/openbsd/xfs_message.c(xfs_message_invalidnode): Fixed tokens
+ in xfsnode
+
+Fri Jan 2 20:46:03 1998 Assar Westerlund <assar@sics.se>
+
+ * xfs_vnodeops.c: mrege in changes from ../openbsd
+
+ * arlad/bsd-messages.c (vattr2afsstorestatus): remove mask
+
+Fri Jan 2 20:47:20 1998 Love Hörnquist-Åstrand <e96_lho@e.kth.se>
+
+ * xfs/openbsd/xfs_vnodeops.c: Fixed xfs_write()
+
+ * arlad/bsd-messages.c: Added vattr2afsstorestatus() and cleaned up
+
+ * arlad/arla_local.h: Added vattr2afsstorestatus() defines
+
+Fri Jan 2 12:47:20 1998 Love Hörnquist-Åstrand <e96_lho@e.kth.se>
+
+ * xfs/openbsd/xfs_vnodeops.c: putattr support working when ATTR
+ not opened RW
+
+ * arlad/inter.c (cm_setattr): Return error message if writeattr fail
+
+ * arlad/fcache.h: Fixed writeattr call
+
+ * arlad/fcache.c: Adding support for chmod
+
+ * arlad/arla_local.h: Added {fs,vldb}.cs.c to get prototypes,
+ and fixed the error that was discoved
+
+Fri Jan 2 04:27:06 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/cmcb.c (RXAFSCB_CallBack): handle the case of there not
+ being enough callbacks.
+
+Fri Jan 2 03:42:43 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * arlad/linux-messages.c: Made getnode and getroot work
+
+ * xfs/linux/xfs_inodeops.c: Added xfs_lookup
+
+ * xfs/linux/xfs_message.c: Fixed inode number bug
+
+Thu Jan 1 22:53:15 1998 Assar Westerlund <assar@sics.se>
+
+ * rx/Makefile.in: removed all xdr*
+
+ * rx/rx_misc.c: remove xdr.h and use malloc/free instead of
+ mem_alloc/mem_free
+
+ * ydr/Makefile.in: bsd-make compatible
+
+Thu Jan 1 19:13:40 1998 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_dev.c: Fixed some inits.
+
+Thu Jan 1 17:31:08 1998 Assar Westerlund <assar@sics.se>
+
+ * arlad/arla.c (main): fix call to conv_dir
+
+Wed Dec 31 18:17:15 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * milko/ss2fs/file.c: Bugfixes, not done
+
+ * milko/mutil/dirpage.c: Moved to here
+
+ * milko/mutil/fdrxop.c: Added file
+
+Wed Dec 31 13:11:01 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * milko/ss2fs/ss2dir.c: Added file
+
+Wed Dec 31 00:30:07 1997 Assar Westerlund <assar@sics.se>
+
+ * xfs/xfs_message.h (xfs_message_wakeup_data): added
+
+ * xfs_dev.c (xfs_message_wakeup_data): copied from ../openbsd
+
+ * Makefile.in: removed duplicate ydr
+
+ * rx/rx_pkt.c (rxi_ReadPcket): use a sensible length test.
+
+ * rx/rx_null.h: prototypize
+ rxnull_New{Server,Client}SecurityObject
+
+ * xfs/xfs_message.h (xfs_message_pioctl): add `outsize' add some
+ prototypes
+
+ * arlad/cred.h: only include <des.h> and <krb.h> iff KERBEROS
+
+ * arlad/conn.c (getconnection): ifdef KERBEROS for krbdata
+
+ * arlad/bsd-messages.c (xfs_message_pioctl): (VIOCSETTOK,
+ VIOCUNLOG): ifdef KERBEROS
+
+ * arlad/arla.c (get_cred): ifdef KERBEROS.
+
+ * arlad/Makefile.in: use autoconf'd RXKAD_LIBS
+
+ * configure.in: set RXKAD_LIBS
+
+ * util/fnameutil.c (dirname): return "." for local files.
+
+ * ydr/output.c (init_generate): include the same set of headers in
+ all generated .c-files.
+
+ * lwp/Makefile.in: separate cpu vs OS definitions
+
+Tue Dec 30 22:08:55 1997 Magnus Ahltorp <map@lroken.stacken.kth.se>
+
+ * xfs/linux/xfs_inodeops.c: Added
+
+ * xfs/linux/xfs_node.c: Inode values now based on xfs_node
+ pointer. Some more functions ported.
+
+ * xfs/linux/xfs_message.c: Initial linux port
+
+Tue Dec 30 21:11:01 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * milko/ss2fs/file.c: Added even more junk
+
+ * rxdef/Makefile.in: Removed that common.h link, using -I
+
+Mon Dec 29 17:23:25 1997 Assar Westerlund <assar@sics.se>
+
+ * util/fnameutil.c (dirname): new function
+
+Fri Dec 26 22:54:12 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * configure.in: Added ufs01fs & co
+
+ * milko/ss2fs: Added
+
+ * milko/ufs01fs: Added
+
+ * milko: Cleaned up and started to migrate in ss2fs
+
+Wed Dec 24 03:25:51 1997 Magnus Ahltorp <map@hefaistos.abc.se>
+
+ * xfs/linux: Added nfs like allocation of inodes
+
+ * xfs/linux/xfs/attr.h, arlad/linux-messages.c: Added xfs_attr
+
+Mon Dec 22 12:38:26 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * ydr/lex.l: We now recognise {u_,}int{16,32}_t
+
+Sun Dec 21 10:30:42 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * Makefile.in: Added rxdef
+
+Fri Dec 19 05:08:24 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/openbsd/xfs_dev.c: Added wakedup_data function in xfs end
+
+ * arlad/fcache.c: Added sysname
+
+ * xfs/openbsd/xfs/xfs_message.h: Added wakedup_data function and
+ struct
+
+ * xfs/openbsd/xfs_syscalls.c: Started adding of sysname
+
+ * arlad/volcache.c: Added VOLCACHEADDDYNAMIC
+
+Wed Dec 17 08:39:02 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * TODO: Fixed getcwd() ?
+
+ * arlad/bsd-messages.c: Added error checking and fixed error msg
+
+ * arlad/arla_local.h: Added debuggingmacro
+
+ * Makefile.in: Changed to ydr
+
+ * arlad/fcache.c: getcwd & ydr
+
+ * arlad/bsd-messages.c: Working pwd, there is still bugs in
+ there...
+
+1997-12-10 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * arlad/inter.c: Made tokens support more sane
+
+ * xfs/openbsd/*: Added support for NetBSD
+
+Tue Dec 9 03:38:52 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/inter.c: cm_open(): Not quite ready yet.
+
+ * arlad/inter.c: Added test för datausedp;
+
+Mon Dec 8 20:52:09 1997 Assar Westerlund <assar@sics.se>
+
+ * arlad/bsd-messages.c (afsstatus2vattr): use VNOVAL
+ (xfs_message_getnode): cleanup
+
+ * configure.in: test for more header files.
+
+ * ydr: new version.
+
+Thu Dec 4 14:51:05 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * TODO: Added vos and rxdef
+
+Sat Nov 29 02:18:57 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * appl/vos.c: listvol does not work, yet
+
+ * appl/vos.c: Almost working, just lacking CellServDB parsing
+
+ * appl/arlalib.c: Added more junk
+
+Fri Nov 28 17:00:17 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * appl/vos.c: More working code
+
+ * appl/arlalib.c: First version
+
+Tue Nov 25 20:45:20 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * rxgen/main.c: Fixed configure test for CPP
+
+Wed Nov 19 13:03:58 1997 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * milko/dirpage.c: Added
+
+ * milko/inodedb.c: Added
+
+ * milko/diskio.c: Made more usable
+
+Tue Nov 18 23:54:11 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * configure.in: Fixed bug that turned off kerberos default
+
+Tue Nov 18 06:13:17 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * Added support for different include and lib paths in kerberos.
+ Clean up configure.
+
+Sat Nov 15 15:31:24 1997 Love H-Astrand <lha@jenny.ksk.sala.se>
+
+ * lwp/lwp.c: Added support for posix signals, added RCSID()
+
+ * lwp/preempt.c: Added support for posix signals
+
+ * lwp/lwp.h: Added check for posix-signals
+
+ * acconfig.h: Added check for posix-signals
+
+ * configure.in: Added check for sys/ioccom.h
+
+ * arla/Makefile.in: Added @CFLAGS@
+
+Sat Nov 15 11:41:33 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * configure.in, Makefile.in: Added support for conditional
+ build of rxkad
+
+Fri Nov 14 09:36:20 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * configure.in: Cleaned up and added messages
+
+Fri Nov 14 08:54:26 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * configure.in: Added support for --with-krb4.
+
+ * acconfig.h: Removed superfluous #define KERBEROS
+
+Thu Nov 13 05:42:30 1997 Artur Grabowski <art@stacken.kth.se>
+
+ * xfs/openbsd/xfs_node.c: Fixed the removing of vnodes from the
+ list of all vnodes in the fs. :)
+
+Wed Nov 12 22:00:28 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/volcache.c: Added gc
+
+Wed Nov 12 04:40:46 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/conn.c: Added gc
+
+ * arlad/bsd-messages.c: Added check for invalid rpc calls
+
+ * arlad/cred.c: Made a cred_remove() remove all connection in the
+ connection cache too.
+
+ * arlad/bsd-messages.c: Cleaned up the code.
+
+ * arlad/conn.c: Added support to remove a connection from the
+ connection cache, we still dont gc.
+
+ * util/hash.c: Added hashtabcleantab()
+
+Mon Nov 10 01:11:38 1997 Assar Westerlund <assar@sics.se>
+
+ * added lots of copyrights.
+
+ * lib/rxkad: updated
+
+ * acconfig.h: -DKERBEROS
+
+ * xfs/freebsd/xfs/xfs_message.h: added pioctl
+
+Sun Nov 9 19:16:25 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/cred.h: Cleanup, added support to clean tokens based on
+ uid.
+
+ * xfs/openbsd/xfs_syscalls.c: Added support for VIOCUNLOG
+
+ * xfs/openbsd/xfs/xfs_message.h: Added uid to struct
+ xfs_message_pioctl, in some magic way we should support PAGs too.
+
+ * arlad/bsd-messages.c: Added support for VIOCUNLOG
+
+Sun Nov 9 17:25:27 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * xfs/openbsd/xfs/xfs_message.h: Added xfs_message_pioctl
+
+ * xfs/openbsd/kafs.h: Added
+
+ * xfs/openbsd/xfs_syscalls.c: Added VIOCSETTOK
+
+ * arlad/bsd-messages.c: Working cred
+
+Sat Nov 8 19:58:46 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/cred.c: Added putkrb4cred()
+
+Fri Nov 7 20:57:09 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * rx/rx_user.c: Removed rx warning messages
+
+ * arlad/conn.c: After 24h hacking, working rxkad !
+
+Thu Nov 6 22:28:33 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/arla.c: Added kerberos support, not working, yet.
+
+ * arlad/Makefile.in: Added support for rxkad, assume krb4 world
+
+ * Makefile.in: Added rxkad
+
+ * arlad/cred.h: Fixed.
+
+ * arlad/cred.c: Fixed some more
+
+Thu Nov 6 18:05:59 1997 Artur Grabowski <art@bobby.stacken.kth.se>
+
+ * arlad/bsd-kernel.c: fixed exit on error from device.
+
+Thu Nov 6 17:34:27 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/arla.c: Init credcache
+
+ * arlad/conn.c: Added support for rxkad
+
+Thu Nov 6 17:34:27 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * arlad/cred.h: Made it buildable and spell checked.
+
+ * arlad/cred.c: Made it buildable.
+
+Thu Nov 6 17:31:09 1997 Artur Grabowski <art@bobby.stacken.kth.se>
+
+ * xfs/openbsd/xfs_vfsops.c: fixed the releasing of vnodes.
+
+ * xfs/openbsd/xfs_vnodeops.c: cleaned up.
+
+ * Learned to use ChangeLog. (hopefully)
+
+Thu Nov 6 02:38:20 1997 Love Hornquist-Astrand <lha@foo.ksk.sala.se>
+
+ * arlad/cred.h: Added
+
+ * arlad/cred.c: Added
+
+ * milko/diskio.c: Started to read the inode instead of makeing up data.
+
+ * milko/build_a_inode.c: more features
+
+Tue Nov 4 03:03:03 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * rxkad/*.[ch]: s/int32/int32_t/g
+
+ * configure.in: Added some more tests.
+
+ * rxkad/Makefile.in: Living in a krb4 work, assar will shot me.
+
+ * aclocal.m4: Added checks for types (int32 & co)
+
+Sun Nov 2 17:24:22 1997 Assar Westerlund <assar@sics.se>
+
+ * xfs_vnodeops.c (xfs_data_valid): set `msg.tokens'
+ (xfs_lookup): copy name to `msg' correctly
+
+ * xfs_vfsops.c (xfs_root): set `msg.cred'
+
+ * xfs_node.c (free_xfs_node): reset data
+
+ * xfs_message.c (xfs_message_installdata): unlock the cache vnode
+ after lookup
+
+ * xfs_dev.c (xfs_message_rpc): copy back from temporary memory to
+ `message'
+
+ * arlad/inter.c (cm_open): set enty->tokens correctly
+
+ * arlad/Makefile.in: use `test -h' instead of `test -L'
+
+Sat Nov 1 02:06:18 1997 Love H-Astrand <lha@ksk.sala.se>
+
+ * arlad/Makefile.in: Fixed so we can build in another directory
+ then src
+
+ * aclocal.m4: Added
+
+Thu Oct 30 01:46:51 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * configure.in: Fixed linux include stuff
+
+ * arlad/linux*: Added linux specific files
+
+ * configure.in: Added milko.
+
+ * milko/Makefile.in: Fixed for merging into arla-tree
+
+Wed Oct 29 22:52:15 1997 Assar Westerlund <assar@sics.se>
+
+ * arlad/volcache.c (findvolname, findvolid): check for getvolname
+ returning an error
+
+Sun Oct 26 17:59:11 1997 Magnus Ahltorp <map@wakko.stacken.kth.se>
+
+ * xfs/linux/xfs_common.c: Linuxified
+
+Sat Oct 25 19:01:45 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * lwp/lwp.c: Ansified
+
+ * lwp/iomgr.c: Ansified
+
+Sat Oct 25 17:05:21 1997 Assar Westerlund <assar@sics.se>
+
+ * xfs/freebsd: use mp->mnt_vnodelist instead of xfsp->nodes
+
+ * xfs/freebsd/Makefile.in: new autoconf'ed makefile
+
+Sat Oct 25 15:53:31 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * lwp/Makefile.in: Grrrr gcc -E är dum.
+
+ * Makefile.in: Added rx and rxgenbuilding
+
+ * lwp/Makefine.in: Added support for multippel processors
+
+Sat Oct 25 15:48:38 1997 Assar Westerlund <assar@sics.se>
+
+ * xfs/linux/xfs: new files
+
+Sat Oct 25 14:23:45 1997 Love Hornquist-Astrand <lha@stacken.kth.se>
+
+ * configure.in: Removed some configure.in's
+
+Sat Oct 25 14:15:11 1997 Magnus Ahltorp <map@wakko.stacken.kth.se>
+
+ * xfs/linux/xfs_dev.c: Merged in the real file and adopted it to
+ Linux
+
+Sat Oct 25 05:46:29 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * xfs/linux/xfs_dev.c: Moved device stuff here
+
+ * xfs/linux/super.c: Working filesystem
+
+Fri Oct 24 18:33:36 1997 Magnus Ahltorp <map@stacken.kth.se>
+
+ * xfs/linux/super.c: Almost working empty filesystem.
+
+Fri Oct 24 17:20:40 1997 Assar Westerlund <assar@sics.se>
+
+ * rx/Makefile.in: replaced junk makefile with a new one
+
+ * arlad/Makefile.in: much clean-up and improvements
+
+ * Makefile.in: much clean-up and improvements
+
+ * configure.in: much clean-up and improvements
+
+ * xfs/Makefile.in: stub makefile
+
+ * lib/util/ip.[ch]: resurrected
+
+ * lib/lwp/q.c: resurrected
+
+
diff --git a/usr.sbin/afs/src/INSTALL b/usr.sbin/afs/src/INSTALL
new file mode 100644
index 00000000000..cf276efeab5
--- /dev/null
+++ b/usr.sbin/afs/src/INSTALL
@@ -0,0 +1,230 @@
+$Id: INSTALL,v 1.1.1.1 1998/09/14 21:52:51 art Exp $ ($Name: $)
+
+Building arla
+
+Arla is configured with autoconf. Start the configuration process by
+typing:
+
+- `./configure' in the source directory, or
+- `SRCDIR/configure' in the directory where you want to build arla.
+ (this is the recommended way but requires a make that understands VPATH)
+
+If you want to install somewhere different from the default
+`/usr/arla' give `--prefix=PATH' as an argument to configure. There
+are also some arla-specific arguments to configure:
+
+ --with-arlacachedir=dir use dir as cachedir instead of $prefix/cache
+ --with-arlaconffile=file use file for configuration instead of $prefix/etc/arla.conf
+ --with-krb4=dir use kerberos 4 in dir
+ --with-krb4-lib=dir use krb4-lib in dir
+ --with-krb4-include=dir use krb4-include in dir
+ --with-krbafs=dir use cmu's krbafs lib (If you not are using kth-krb.
+ This is not needed when using kth-krb since
+ libkafs is included there.)
+ --with-krb5=dir use kerberos 4 compat from kerberos 5 in dir
+ --disable-mmap don't use mmap at all
+ --enable-mmaptime use mmap:ed time from /dev/kmem
+ (known to work in FreeBSD)
+
+By default configure will use gcc if it finds it. If you want to use
+a specific compiler or some special options you can specify that when
+running configure. Running in a sh-style shell, type:
+
+ CC=my-compiler CFLAGS='magic-flags' ./configure
+
+If you are stuck with a broken shell, try using the env program:
+
+ env CC=my-compiler CFLAGS='magic-flags' ./configure
+
+If there's no kernel support for your operating system, configure will
+print a warning to that effect and only the user-level stuff will be
+configured.
+
+Once configured has completed, just run `make'.
+
+One common problem is the file lwp/process.S. This has to be
+preprocessed with the appropriate defines and then assembled. If the
+magic in lwp/make-process.o.sh.in for some reason fails, try doing it
+by hand. Then figure out what should be added and send us a patch to
+lwp/make-process.o.sh.in.
+
+Installing arla
+
+Run `make install'. It will create and populate these directories:
+
+/usr/arla/bin all binaries used
+/usr/arla/cache the cached files will be stored here
+ (core-dumps from arlad as well)
+/usr/arla/etc configuration files:
+ ThisCell, CellServDB, arla.conf
+/usr/arla/lib random libraries
+
+If you're already part of an AFS cell, modify /usr/arla/etc/ThisCell
+and make sure your cell is mentioned in /usr/arla/etc/CellServDB. If
+you don't have a cell you'll still be able to run as a client in the
+cell `stacken.kth.se' and access all cells listed in CellServDB.
+
+Services
+
+Everything works fine even if your /etc/services is not updated, but
+programs will print warning messages. To get rid of these, add the
+contents of SRCDIR/conf/services to /etc/services.
+
+ cat SRCDIR/conf/services >> /etc/services
+
+Starting arla
+
+First try running arlad in test mode with `-t'. If all goes well, it
+should print some messages and then give you the prompt `arla>'.
+There are very minimal commands for navigating the AFS space (ls, cd
+and cat). Type `help' to get a list of all the commands.
+
+Run `arlad --help' for a list of the options supported.
+
+If you have a kernel module you can try to load it and mount the
+file system. That's done somewhat differently depending on the
+operating system:
+
+Linux:
+
+ The linux major device number has changed in arla 0.5. Please
+ remove your old device and create a new one with the command
+ below if you have used arla before 0.5.
+
+ mknod /dev/xfs0 c 103 0
+ insmod /usr/arla/bin/xfs.o
+ /usr/arla/bin/arlad
+ mkdir /afs
+ mount -t xfs arla /afs
+
+ If you are using Linux 2.1, you may want to copy /usr/arla/lib/getcwd.so
+ to /lib and add this line to your /etc/ld.so.preload:
+
+ /lib/getcwd.so
+
+ This enables the getcwd syscall, which works much better than the old
+ way of doing getcwd. Be careful though, and execute /bin/pwd as a test
+ before you exit your editor. If /bin/pwd fails with a message like
+ "/bin/pwd: can't load library '/lib/getcwd.so'", remove the line from
+ /etc/ld.so.preload, and report the problem.
+
+ DO NOT load the file from /usr/arla/lib, since /usr probably is not
+ part of the root partition of your system. If you do this, your system
+ will probably not be able to boot, even in single user, since in most
+ Linux installations, init, sh, mount and other programs are dynamically
+ linked.
+
+SunOS4:
+
+ modload /usr/arla/bin/libxfs.o
+ modstat
+ mknod /dev/xfs0 c <C-major from modstat> 0
+ mkdir /afs
+ /usr/arla/bin/mount_xfs /afs /dev/xfs0
+ /usr/arla/bin/arlad
+
+{Net|Open}BSD:
+
+ modload -e xfs_mod -o /var/tmp/symbols -p /usr/arla/bin/xfs_makedev /usr/arla/bin/xfs_mod.o
+ mkdir /afs
+ /usr/arla/bin/mount_xfs /dev/xfs0 /afs
+ /usr/arla/bin/arlad
+
+FreeBSD
+
+Do like in {Net|Open} except for doing the modload you can just do:
+
+ mkdir /lkm
+ cp /usr/arla/bin/xfs_mod.o /lkm/xfs_mod.o
+
+And mount_xfs vill load the filesystem into the kernel.
+
+Solaris:
+
+add a line to /etc/name_to_major with (134 should be any unused number)
+
+ xfs 134
+
+and another one to /etc/name_to_sysnum (105 is the preferred system
+call number, if that's already used by Transarc AFS on your machine,
+pick some other number)
+
+ xfs 105
+
+You might have to reboot for these changes to take effect. Then, type:
+
+ modload xfs
+
+You should probably add a file in /usr/kernel/drv/xfs.conf with:
+
+ name="xfs" parent="pseudo" instance=0;
+
+and then run:
+
+ drvconfig -i xfs
+
+Create a device with the name_to_major number and a directory:
+
+ mknod /dev/xfs0 c 134 0
+ mkdir /afs
+
+Now you can try mounting the file system and start the daemon:
+
+ /usr/arla/bin/mount_xfs /dev/xfs0 /afs
+ /usr/arla/bin/arlad
+
+
+If you want to, you can copy the xfs/solaris/xfs module to /kernel/fs
+and xfs/solaris/bin/mount_xfs to /lib/fs/xfs/mount which enables you to
+automatically load the xfs module when mounting the xfs file system.
+
+AIX:
+
+Create the device node:
+
+ mknod /dev/xfs0 c 100 0
+
+And add a line like the following to /etc/vfs:
+
+ arla 8 none none
+
+Now you can try mounting the file system and start the daemon:
+
+ /usr/arla/bin/mount_xfs /dev/xfs0 /afs
+ /usr/arla/bin/arlad
+
+Digital Unix (aka OSF/1)
+
+Copy the xfs.mod to /subsystems.
+
+Load (configure) the module with sysconfig -c xfs
+
+Query the module to see if it loaded ok and get the
+character device and syscall number from it with:
+sysconfig -q xfs
+
+Create the char-device "mknod /dev/xfs0 c <MAJOR> 0"
+where <MAJOR> is the number obtained above.
+
+Create the afs directory: mkdir /afs
+
+Mount the device and start the daemon:
+ /usr/arla/bin/mount_xfs /dev/xfs0 /afs
+ /usr/arla/bin/arlad
+
+It could look something like this:
+
+datan:~# sysconfig -c xfs
+datan:~# sysconfig -q xfs
+syscall = 34
+major = 68
+debug = 255
+datan:~# mknod /dev/xfs0 c 68 0
+datan:~# mkdir /afs
+datan:~# /usr/arla/bin/mount_xfs /dev/xfs0 /afs
+datan:~# /usr/arla/bin/arlad
+datan:~# ls /afs | head
+.stacken.kth.se
+afs.brain.de
+afs.hursley.ibm.com
+afs1.scri.fsu.edu
diff --git a/usr.sbin/afs/src/NEWS b/usr.sbin/afs/src/NEWS
new file mode 100644
index 00000000000..d55237ea5e1
--- /dev/null
+++ b/usr.sbin/afs/src/NEWS
@@ -0,0 +1,187 @@
+Changes in release 0.9:
+
+* merging of all BSD codes
+
+* support for more pioctl calls
+
+* use readpage instead of bmap in linux 2.0
+
+* lots of bug fixes
+
+Changes in release 0.8:
+
+* It should build with all makes
+
+* port to Rhapsody (contributed by Alexandra Ellwood <lxs@MIT.EDU>)
+
+* more functionality in arlad --test (from Alec Wolman <wolman@cs.washington.edu>)
+
+* port to OSF/1 (by Johan Danielsson <joda@pdc.kth.se>)
+
+* create the cache vnodes in the background
+
+* invalidate nodes when the callback expires
+
+* better linux 2.[01] support
+
+* handle the case of different user and kernel types with glibc
+
+* udebug program added
+
+* some documentation written
+
+* lots of bug fixes
+
+Changes in release 0.7.2:
+
+* New way of building process.o
+
+Changes in release 0.7.1:
+
+* Bug fixes
+
+Changes in release 0.7:
+
+* IRIX support added though it does need more work
+
+* Autodetection of Linux htonl weirdness
+
+* Linux xfs now includes modversions.h to get versioned names
+ of exported kernel symbols
+
+* New arlad option for recovering (not) stored state
+
+* Merged token clearing bugfix which fixed some panics
+
+Changes in release 0.6:
+
+* AIX support added
+
+* Linux 2.1 support added
+
+* Linux/alpha support in process.S
+
+* Solaris support updated with some new vnode ops
+
+* New --root-vol option to arlad
+
+* Expiring credential handling
+
+* Added fs library
+
+* Added fpriority to arlad
+
+Changes in release 0.5:
+
+* reserved major number for Linux
+
+* pts added
+
+* minor fixes for Solaris 2.6
+
+* moved almost all pioctl handling to arlad
+
+* fs {sa,lq,sq} now works
+
+* fixed pioctl handling in Linux (lookup of fid)
+
+* cred deletion added
+
+* updated getargs to handle options the transarc way
+
+* arlad now forks off per default
+
+* new debug levels to arlad
+
+* mkdir/rmdir in Linux added
+
+* Linux xfs access control fixed
+
+* df now produces something interesting in Linux
+
+* several new autoconf tests
+
+* arlad -t now works with cygwin32
+
+* time can now be mmaped to improve performance
+
+Changes in release 0.4:
+
+* bug that caused linux xfs module to loop fixed.
+
+* fix seek error on NetBSD
+
+* copy in arguments to xfs_mount which makes it not panic on some
+ NetBSD ports.
+
+* collect message statistics in arlad
+
+* fs getcrypt and fs setcrypt
+
+* set `d_type' in BSD directories which fixes lots of
+ directory-related problems.
+
+* some code reorganization.
+
+* fs getacl works
+
+* support for linking with the compatability libraries of krb 5.
+
+* support for reading cell information from /usr/vice/etc as a
+ fallback for /usr/arla/etc
+
+* now using the inconsistent interpretation of the unix mode bits on
+ directories to be compatible
+
+* some malloc/free related errors fixed
+
+Changes in release 0.3:
+
+* solaris port working
+
+* doc/ created with some introducing docs on Arla.
+
+* Local access checks introduced. (until now the rights were "shared" by
+ all users on the system)
+
+* arlad now reported to work on powerpc after a minimal fix.
+
+* xfs/Linux bugfixed and should work readonly
+
+Changes in release 0.2:
+
+* Improved directory handling code.
+
+* arlad now uses getarg for parsing arguments. New arguments:
+ --test (-t) test mode
+ --conffile (-c) configuration file
+ --log (-l) write log here
+ --device (-d) device used by xfs (default /dev/xfs0)
+ --rxkad-level (-r) minimum rxkad level
+ --version
+ --help
+
+* Fix reading from kernel space on Linux/i386.
+
+* Removed GCC-isms from the code.
+
+* More efficient.
+
+* arlad stores state between runs.
+
+* Only read new data when needed.
+
+* Handle volume callbacks.
+
+* arlad in test mode follows symlinks.
+
+* autoconf test for presence of `krb_principal'. This makes it much
+easier to build with other kerberos distributions than kth-krb.
+
+* Bug fixes.
+
+* More stuff that I have repressed.
+
+Changes in release 0.1:
+
+* I don't remember any longer. Try looking at the ChangeLog.
diff --git a/usr.sbin/afs/src/README b/usr.sbin/afs/src/README
new file mode 100644
index 00000000000..7249ed375ab
--- /dev/null
+++ b/usr.sbin/afs/src/README
@@ -0,0 +1,162 @@
+README for arla-0.9 ($Name: $)
+$Id: README,v 1.1.1.1 1998/09/14 21:52:51 art Exp $
+
+1. What is arla?
+
+Arla is a free AFS cache-manager/client implementation.
+
+2. Where do I find this file?
+
+This file is contained inside
+ftp://ftp.stacken.kth.se/pub/arla/arla-0.9.tar.gz
+(aka /afs/stacken.kth.se/ftp/pub/arla/arla-0.9.tar.gz).
+
+3. What is AFS?
+
+AFS is a world-wide distributed file system. See
+<http://www.transarc.com/afs/transarc.com/public/www/Product/AFS/FAQ/faq.html>
+for more information.
+
+4. What's included in arla?
+
+There is kernel support (with different level of functionality) for
+the following operating systems:
+
+- FreeBSD 2.2
+- OpenBSD 2.2 and 2.3
+- NetBSD 1.2 and 1.3
+- Linux 2.0.x and 2.1.x
+- SunOS 4
+- Solaris 2.5, 2.6 and 2.7 beta
+- AIX 4.x
+- IRIX 6.x
+- Digital Unix 4.0 (OSF/1)
+- Rhapsody DR2
+
+A cache manager (arlad) that works both in user-level mode and with
+the kernel module. The user-level mode is quite portable and has even
+been working under Windows NT (with the cygwin32 libraries).
+
+Some simple programs (fs, vos and pts).
+
+Programs for acquiring tokens (kauth, afslog) are not included but are
+part of the kth-krb distribution.
+
+5. What's the status or arla?
+
+This is a snapshot and pre-greek letters.
+
+Most of the functionality is there. You can read and write files and
+directories, with or without authentication. It's not as stable or
+high-performing as we would like, yet. It only does whole-file
+caching, but that's probably good enough.
+
+6. What do I need to run arla?
+
+If you have one of the systems listed above you will be able to mount
+afs as a file system (and probably to panic your kernel as well).
+
+The user-level programs should work and build on almost any other unix
+dialect.
+
+If you want to use authentication, you will also need a Kerberos v4
+implementation. We use and recommend the one at
+<http://www.pdc.kth.se/kth-krb/>.
+
+OpenBSD 2.3 already ships with kth-krb. However, you'll have to
+add the line 'AFS=yes' to /etc/mk.conf and rebuild libkafs and afslog.
+(can be found in /usr/src/kerberosIV/{kafs,afslog}).
+
+If you are using MIT-Kerberos or CNS Kerberos you can find a replacement
+for libkafs in http://andrew2.andrew.cmu.edu/dist/krbafs.html. Then you
+need to use the --with-krbafs=dir option when running configure.
+Thanks to Derrick J Brashear <shadow@dementia.org> for making this
+available for the american users.
+
+If you don't have Kerberos, you should still be able to test that it
+works, but there's not much point in running unauthenticated, and it's
+not very tested.
+
+7. How do I compile/install/start arla?
+
+See the file INSTALL
+
+8. What do I do when I find a bug?
+
+Report it with as much detail as possible (including patches) to
+<arla-drinkers@stacken.kth.se>.
+
+9. How do I adjust the amount of debug information?
+
+Both arlad and the xfs (the kernel module) has variables for
+controlling what type of debug messages should be printed.
+
+They are controlled by the `--debug' option to arlad and by setting
+the `xfsdeb' variable in xfs (see xfs/<system>/xfs_deb.c).
+
+10. How hard is it to port arla to a new operating system?
+
+It's not hard. The user-level code is quite portable and is not much
+different between different operating systems. The kernel module is
+system-specific but not that large and you can probably start with the
+one in `xfs/SYSTEM' that's most similar to your system. If you're
+interested in doing the port, send mail to
+<arla-drinkers@stacken.kth.se>.
+
+11. Known problems.
+
+OpenBSD 2.3 (current) and OpenBSD 2.2 on some architectures have
+serious problems with mmap. If arlad doesn't seem to work om your
+system run configure with `--disable-mmap'. This problem has only
+been noticed on sun4m platforms (probably just Microsparc 2).
+
+If you have problems with stale data cached or arlad is misbehaving a
+lot try zapping the entire cache directory (`/usr/arla/cache' per
+default) and restarting arlad.
+
+If you are using Digital's cc you should probably use the
+options -std1 (ie setting CC to "cc -std1" when runing configure).
+
+12. How can I help?
+
+With code. Send us bug-reports and/or patches.
+
+13. Are there any mailing lists for arla?
+
+arla-drinkers@stacken.kth.se general discussion
+arla-announce@stacken.kth.se only announcements
+
+Send mail to <LIST>-request@stacken.kth.se to subscribe.
+
+14. Is there a web page?
+
+Yes, http://www.stacken.kth.se/project/arla/
+
+15. Are there any copyrights on parts of arla?
+
+lwp and rx are copyrighted by IBM. We're grateful to Derrick J
+Brashear <shadow@dementia.org> and Jim Doyle <jrd@bu.edu> for making
+them available.
+
+the rxkad implementation was written by Björn Grönvall <bg@sics.se>
+and is also part of the kth-krb distribution.
+
+editline was written by Simmule Turner and Rich Salz.
+
+The code for gluing these together were written by ourselves.
+
+<arla-drinkers@stacken.kth.se>
+
+16. What has changed since *?
+
+See NEWS and ChangeLog.
+
+17. What does `arla' mean?
+
+- Arla in Swedish means `early'. Most of the code has been written
+early in the morning.
+
+- Arla is also the name of the largest producer of dairy products in
+Sweden. They produce, among others, a milk product called `fil'
+(filmjölk = sour milk) which also happens to be the swedish word for
+`file'.
diff --git a/usr.sbin/afs/src/THANKS b/usr.sbin/afs/src/THANKS
new file mode 100644
index 00000000000..0781bd93866
--- /dev/null
+++ b/usr.sbin/afs/src/THANKS
@@ -0,0 +1,23 @@
+The following persons have sent in bug reports, fixes, patches or
+contributed in some other way.
+
+If you have done something and are not mentioned here, please send
+mail to <arla-drinkers@stacken.kth.se>.
+
+If you are mentioned here and have not contributed, that's because we
+expect you to.
+
+Aaron M. Ucko <amu@MIT.EDU>
+Alec Wolman <wolman@cs.washington.edu>
+Alexandra Ellwood <lxs@MIT.EDU>
+Brad Keryan <keryan@andrew.cmu.edu>
+Chaskiel Grundman
+Constantine Sapuntzakis <csapuntz@openbsd.org>
+Dan Winship <danw@MIT.EDU>
+Derrick J Brashear <shadow@dementia.org>
+Jim Doyle <jrd@bu.edu>
+John Davison <davisoja@clarkson.edu>
+John Hawkinson <jhawk@MIT.EDU>
+Karl Ramm <kcr@MIT.EDU>
+Mark Eichin <eichin@kitten.gen.ma.us>
+Per Boussard T/ED <Per.Boussard@era-t.ericsson.se>
diff --git a/usr.sbin/afs/src/TODO b/usr.sbin/afs/src/TODO
new file mode 100644
index 00000000000..edb1cbfb5da
--- /dev/null
+++ b/usr.sbin/afs/src/TODO
@@ -0,0 +1,38 @@
+$Id: TODO,v 1.1.1.1 1998/09/14 21:52:52 art Exp $
+
+ TODO-list, in no particular order.
+
+Please mail arla-drinkers@stacken.kth.se if you want to work on
+any of these things so we don't do double work.
+
+arlad/xfs: More stable, bugfixes etc
+
+xfs/solaris: verify multithreadness
+
+xfs+arlad: implement advisory locking
+
+arlad: disconnected mode
+
+arlad: remove unused stuff from FCacheEntry
+
+arlad: fallback to disconnected mode if networking is not working
+(possibly per cell)
+
+arlad/xfs: return from open before fetching the whole file
+
+test suite
+
+OPTIMIZATIONS
+
+This is a list of posible optimizations that could be done to different parts
+of arla.
+
+ - Store cache files in inodes. Bypass the upper layer of VFS to read and
+ write cache.
+
+ - Delay reads and writes to cache and AFS-servers. Make the more operations
+ in one batch. (possible with rx?) Especially directories don't have to be
+ synced for every operation.
+
+ - send more messages to/from arlad in one sweep. (lookup on whole path in one
+ message, getattr+getdata, etc..)
diff --git a/usr.sbin/afs/src/appl/appl_locl.h b/usr.sbin/afs/src/appl/appl_locl.h
new file mode 100644
index 00000000000..bdbcd698c8c
--- /dev/null
+++ b/usr.sbin/afs/src/appl/appl_locl.h
@@ -0,0 +1,120 @@
+/* $OpenBSD: appl_locl.h,v 1.1.1.1 1998/09/14 21:52:52 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: appl_locl.h,v 1.24 1998/07/19 23:50:16 mattiasa Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <atypes.h>
+#include <roken.h>
+#include <getarg.h>
+#include <err.h>
+
+#include <cb.h>
+#include <time.h>
+#include <lock.h>
+#include <ip.h>
+#include <ctype.h>
+#ifdef KERBEROS
+#include <kerberosIV/krb.h>
+#include <des.h>
+#include <rxkad.h>
+#endif
+#ifdef HAVE_STDS_H
+#include <stds.h>
+#endif
+
+#include "arlalib.h"
+
+#include <service.h>
+#include <ports.h>
+#include <volumeserver.h>
+#include <volumeserver.cs.h>
+#include <vldb.h>
+#include <vldb.cs.h>
+#include <fs.h>
+#include <fs.cs.h>
+#include <ubik.h>
+#include <ubik.cs.h>
+
+#include <ko.h>
diff --git a/usr.sbin/afs/src/appl/arlalib.c b/usr.sbin/afs/src/appl/arlalib.c
new file mode 100644
index 00000000000..6b6c85f1535
--- /dev/null
+++ b/usr.sbin/afs/src/appl/arlalib.c
@@ -0,0 +1,248 @@
+/* $OpenBSD: arlalib.c,v 1.1.1.1 1998/09/14 21:52:52 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "appl_locl.h"
+
+RCSID("$KTH: arlalib.c,v 1.12 1998/07/19 23:58:58 mattiasa Exp $");
+
+
+static struct rx_securityClass *secureobj = NULL ;
+int secureindex = -1 ;
+int rx_initlizedp = 0;
+
+#ifdef KERBEROS
+static int
+arlalib_get_cred(const char *host, CREDENTIALS *c)
+{
+ char krealm[REALM_SZ];
+ char *rrealm;
+ char *princ = "afs";
+ char *inst = "" ;
+ KTEXT_ST foo;
+ int k_errno;
+
+ rrealm = krb_realmofhost(host);
+ strncpy(krealm, rrealm, REALM_SZ);
+ krealm[REALM_SZ-1] = '\0';
+
+
+ k_errno = krb_get_cred(princ, inst, krealm, c);
+
+ if(k_errno != KSUCCESS) {
+ k_errno = krb_mk_req(&foo, princ, inst, krealm, 0);
+ if (k_errno == KSUCCESS)
+ k_errno = krb_get_cred(princ, inst, krealm, c);
+ }
+
+
+ if (k_errno != KSUCCESS) {
+ fprintf(stderr, "Can't get a ticket for realm %s\n", krealm);
+ return -1;
+ }
+
+ return k_errno;
+}
+#endif /* KERBEROS */
+
+
+int
+arlalib_getservername(u_int32_t serverNumber, char **servername)
+{
+ struct hostent *he;
+
+ he = gethostbyaddr((char*) &serverNumber, sizeof(serverNumber), AF_INET);
+
+ if (he != NULL)
+ *servername = strdup(he->h_name);
+ else
+ *servername = strdup("");
+
+ return (*servername == NULL);
+}
+
+
+static struct rx_securityClass*
+arlalib_getsecurecontext(const char *host, int noauth)
+{
+#ifdef KERBEROS
+ CREDENTIALS c;
+#endif /* KERBEROS */
+ struct rx_securityClass* sec;
+
+ if (secureobj != NULL)
+ return secureobj;
+
+#ifdef KERBEROS
+
+ if (!noauth &&
+ arlalib_get_cred(host, &c) == KSUCCESS) {
+
+ sec = rxkad_NewClientSecurityObject(rxkad_auth,
+ &c.session,
+ c.kvno,
+ c.ticket_st.length,
+ c.ticket_st.dat);
+ secureindex = 2 ;
+ } else {
+#endif /* KERBEROS */
+
+ sec = rxnull_NewClientSecurityObject();
+ secureindex = 0;
+
+#ifdef KERBEROS
+ }
+#endif /* KERBEROS */
+
+ secureobj = sec;
+
+ return sec;
+
+}
+
+
+struct rx_connection *
+arlalib_getconnbyaddr(int32_t addr,
+ const char *host, int32_t port, int32_t servid,
+ int noauth)
+{
+ struct rx_connection *conn;
+ int allocedhost = 0;
+ char *serv;
+
+ if (rx_initlizedp ==0) {
+ rx_Init(0);
+ rx_initlizedp = 1;
+ }
+
+ if (host == NULL) {
+ arlalib_getservername(addr, &serv);
+ allocedhost= 1;
+ host = serv;
+ }
+
+ if (arlalib_getsecurecontext(host, noauth)== NULL)
+ return NULL;
+
+ conn = rx_NewConnection (addr,
+ htons (port),
+ servid,
+ secureobj,
+ secureindex);
+
+ if (conn == NULL)
+ fprintf (stderr, "Cannot start rx-connection, something is WRONG\n");
+
+ if (allocedhost)
+ free(serv);
+
+ return conn;
+}
+
+struct rx_connection *
+arlalib_getconnbyname(const char *host,
+ int32_t port, int32_t servid, int noauth)
+{
+ struct in_addr server;
+
+ if (ipgetaddr (host, &server) == NULL ) {
+ fprintf (stderr, "Cannot find host %s\n", host);
+ return NULL;
+ }
+
+ return arlalib_getconnbyaddr(server.s_addr, host, port, servid, noauth);
+
+}
+
+int
+arlalib_destroyconn(struct rx_connection *conn)
+{
+ if (conn == NULL)
+ return 0 ;
+
+ rx_DestroyConnection(conn);
+ return 0;
+}
+
+/*
+ * arlalib_getsyncsite
+ *
+ * if cell and host is NULL, local cell is assumed and a local dbserver is used
+ * if cell is NULL and host not, cell is figured out
+ * (if that fail, localcell is assumed)
+ * if cell is set but not host, host is found i CellServerDB or DNS
+ *
+ *
+ * RETURNS: 0 is ok, otherwise an error that should be handled to
+ * koerr_gettext()
+ */
+
+int
+arlalib_getsyncsite(const char *cell, const char *host, int32_t port,
+ u_int32_t *synchost, int noauth)
+{
+ struct rx_connection *conn;
+ ubik_debug db;
+ int error;
+
+ if (synchost == NULL)
+ return EINVAL;
+
+ if (cell == NULL && host != NULL)
+ cell = cell_getcellbyhost(host);
+ if (cell == NULL)
+ cell = cell_getthiscell();
+ if (host == NULL)
+ host = cell_findnamedbbyname (cell);
+
+ conn = arlalib_getconnbyname(host,
+ port,
+ VOTE_SERVICE_ID,
+ noauth);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ error = Ubik_Debug(conn, &db);
+ *synchost = htonl(db.syncHost);
+
+ arlalib_destroyconn(conn);
+
+ return error;
+}
+
diff --git a/usr.sbin/afs/src/appl/arlalib.h b/usr.sbin/afs/src/appl/arlalib.h
new file mode 100644
index 00000000000..b0b9e8430dc
--- /dev/null
+++ b/usr.sbin/afs/src/appl/arlalib.h
@@ -0,0 +1,90 @@
+/* $OpenBSD: arlalib.h,v 1.1.1.1 1998/09/14 21:52:52 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: arlalib.h,v 1.8 1998/07/24 19:55:48 lha Exp $ */
+
+#ifndef ARLALIB_H
+#define ARLALIB_H 1
+
+#ifdef KERBEROS
+int get_cred(char *host, CREDENTIALS *c);
+#endif /* KERBEROS */
+
+struct rx_connection *
+arlalib_getconnbyaddr(int32_t addr, const char *host,
+ int32_t port, int32_t servid, int noauth);
+
+struct rx_connection *
+arlalib_getconnbyname(const char *host, int32_t port, int32_t servid,
+ int noauth);
+
+int arlalib_destroyconn(struct rx_connection *conn);
+int arlalib_getservername(u_int32_t serverNumber, char **servername);
+int arlalib_getsyncsite(const char *cell, const char *host, int32_t port,
+ u_int32_t *synchost, int notauth);
+
+
+
+/*
+ * Wrappers around pioctl calls
+ */
+
+void fserr(char *progname, int error, char *realpath);
+
+int fs_getfid (char *path, VenusFid *fid);
+int fs_getfilecellname (char *path, char *cell, size_t len);
+int fs_nop(void);
+
+/* arla extensions */
+
+const char *fslib_version(void);
+
+int fs_setcrypt (u_int32_t level);
+int fs_getcrypt (u_int32_t *level);
+
+int fs_connect (int32_t type, int32_t *flags);
+
+int fs_setfprio(VenusFid fid, int16_t prio);
+int fs_getfprio(VenusFid fid, int16_t *prio);
+int fs_setmaxfprio(int16_t maxprio);
+int fs_getmaxfprio(int16_t *maxprio);
+
+
+
+#endif /* ARLALIB_H */
diff --git a/usr.sbin/afs/src/appl/fs.c b/usr.sbin/afs/src/appl/fs.c
new file mode 100644
index 00000000000..96cd25f8ff9
--- /dev/null
+++ b/usr.sbin/afs/src/appl/fs.c
@@ -0,0 +1,1637 @@
+/* $OpenBSD: fs.c,v 1.1.1.1 1998/09/14 21:52:52 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 <sl.h>
+#include "appl_locl.h"
+#include <kerberosIV/kafs.h>
+#include "fs_local.h"
+
+RCSID("$KTH: fs.c,v 1.41 1998/07/28 14:35:06 assar Exp $");
+
+static SL_cmd cmds[] = {
+ {"apropos", empty_cmd, "locate commands by keyword"},
+ {"checkservers", empty_cmd, "check servers in servers"},
+ {"checkvolumes", empty_cmd, "lookup mappings between volume-Id's and names"},
+ {"cleanacl", empty_cmd, "clear out numeric acl-entries"},
+ {"copyacl", empty_cmd, "copy acl"},
+ {"diskfree", diskfree_cmd, "show free partition space"},
+ {"examine", examine_cmd, "examine volume status"},
+ {"flush", flush_cmd, "remove file from cache"},
+ {"flushvolume", flushvolume_cmd, "remove volumedata (and files in volume) from cache"},
+ {"getcacheparms", empty_cmd, "get cache usage"},
+ {"getcrypt", getcrypt_cmd, "get encrypt status"},
+ {"getcellstatus", getcellstatus_cmd, "get suid cell status"},
+ {"getfid", getfid_cmd, "get fid"},
+ {"getserverprefs", empty_cmd, "show server rank"},
+ {"getpriority", getprio_cmd, "get priority of a file/dir"},
+ {"gp"},
+ {"getmaxpriority", getmaxprio_cmd, "get max priority for file gc"},
+ {"gmp"},
+ {"help", help_cmd, "help for commands"},
+ {"listacl", listacl_cmd, "show acl"},
+ {"la"},
+ {"listcells", listcells_cmd, "show cells configured"},
+ {"listquota", listquota_cmd, "show volume quota"},
+ {"lq"},
+ {"lsmount", lsmount_cmd, "show mount point"},
+ {"messages", empty_cmd, "change arlad logging"},
+ {"mkmount", mkmount_cmd, "create mount point"},
+ {"connect", connect_cmd, "connect mode"},
+ {"monitor", empty_cmd, "set remote logging host"},
+ {"newcell", empty_cmd, "add new cell"},
+ {"nop", nop_cmd, "do a picol-nop"},
+ {"quit", quit_cmd, "leave interactive mode"},
+ {"exit"},
+ {"quota", quota_cmd, "show quota"},
+ {"rmmount", rmmount_cmd, "delete mount point"},
+ {"removepriority", rmprio_cmd, "remove priority from file/directory"},
+ {"rmp"},
+ {"setacl", setacl_cmd, "set acl"},
+ {"sa"},
+ {"setcachesize", setcache_cmd, "change cache size"},
+ {"setcell", empty_cmd, "change cell status"},
+ {"setpriority", setprio_cmd, "set priority of a file/directory"},
+ {"sp"},
+ {"setmaxpriority", setmaxprio_cmd, "set upper limit of prio gc"},
+ {"smq"},
+ {"setquota", setquota_cmd, "change maxquota on volume"},
+ {"sq"},
+ {"setserverprefs", empty_cmd, "change server query order"},
+ {"setcrypt", setcrypt_cmd, "set encryption on/off"},
+ {"setvol", empty_cmd, "change status of volume"},
+/* {"storebehind", empty_cmd, ""}, */
+ {"sysname", sysname_cmd, "read/change sysname"},
+ {"version", fsversion_cmd, "get version of fs and fs_lib"},
+ {"venuslog", venuslog_cmd, "make arlad print status"},
+ {"whereis", whereis_cmd, "show server(s) of file"},
+ {"whichcell", whichcell_cmd, "show cell of file"},
+ {"wscell", wscell_cmd, "display cell of workstation"},
+ {NULL}
+};
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ if(!k_hasafs()) {
+ printf ("Error detecting AFS\n");
+ exit(1);
+ }
+
+ if (argc > 1) {
+ ret = sl_command(cmds, argc - 1, argv + 1);
+ if (ret == SL_BADCOMMAND)
+ printf ("%s: Unknown command\n", argv[1]);
+ }
+ else {
+ fs_interactive = 1;
+ printf("fs - an arla tool for administrating AFS files.\n");
+ printf("Type \"help\" to get a list of commands.\n");
+ ret = sl_loop(cmds, __progname": ");
+ }
+
+ return ret;
+}
+
+static int
+nop_cmd(int argc, char **argv)
+{
+ if (argc > 1)
+ fprintf(stderr, "extraneous arguments ignored\n");
+
+ printf("VIOCNOP returns %d\n", fs_nop());
+
+ return 0;
+}
+
+static int
+connect_usage(void)
+{
+ printf("connect [connected|fetch|disconnected]\n");
+ return 0;
+}
+
+static int
+connect_cmd(int argc, char **argv)
+{
+ int ret;
+ int32_t flags;
+
+ argc--;
+ argv++;
+
+ if (argc == 0) {
+ ret = fs_connect(CONNMODE_PROBE, &flags);
+ if (ret) {
+ fserr(PROGNAME, ret, NULL);
+ return 0;
+ }
+
+ switch(flags) {
+ case CONNMODE_CONN:
+ printf("Connected mode\n");
+ break;
+ case CONNMODE_FETCH:
+ printf("Fetch only mode\n");
+ break;
+ case CONNMODE_DISCONN:
+ printf("Disconnected mode\n");
+ break;
+ default:
+ printf("Unknown or error\n");
+ break;
+ }
+ return flags;
+ }
+
+ if (strncmp("dis", *argv, 3) == 0)
+ ret = fs_connect(CONNMODE_DISCONN, &flags);
+ else if (strncmp("fetch", *argv, 5) == 0)
+ ret = fs_connect(CONNMODE_FETCH, &flags);
+ else if (strncmp("conn", *argv, 4) == 0)
+ ret = fs_connect(CONNMODE_CONN, &flags);
+ else
+ return connect_usage();
+
+ if (ret)
+ fserr(PROGNAME, ret, NULL);
+
+ return 0;
+}
+
+
+static int
+diskfree_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ printf ("Volume Name kbytes used avail %%used\n");
+
+ if (argc == 0)
+ afs_diskfree (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_diskfree (argv[i]);
+
+ return 0;
+}
+
+static int
+empty_cmd (int argc, char **argv)
+{
+ printf ("%s%s not implemented yet!\n", PROGNAME, argv[0]);
+ return 0;
+}
+
+static int
+examine_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ afs_examine (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_examine (argv[i]);
+
+ return 0;
+}
+
+static int
+flushvolume_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ afs_flushvolume (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_flushvolume (argv[i]);
+
+ return 0;
+}
+
+static int
+flush_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ afs_flush (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_flush (argv[i]);
+
+ return 0;
+}
+
+static int
+getcellstatus_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ printf ("%s: Missing required parameter '-cell'\n", PROGNAME);
+ else
+ for (i = 0; i < argc; i++)
+ afs_getcellstatus (argv[i]);
+
+ return 0;
+}
+
+static int
+getcrypt_cmd (int argc, char **argv)
+{
+ u_int32_t n;
+ int ret;
+
+ argc--;
+ argv++;
+
+ if (argc != 0)
+ printf ("getcrypt: extraneous arguments ignored\n");
+
+ ret = fs_getcrypt (&n);
+ if (ret) {
+ fserr(PROGNAME, ret, NULL);
+ return 0;
+ }
+
+ switch (n) {
+ case 0 :
+ printf ("not encrypted\n");
+ break;
+ case 1 :
+ printf ("encrypted\n");
+ break;
+ default :
+ printf ("getcrypt: unknown reply %d\n", n);
+ }
+ return 0;
+}
+
+static int
+setcrypt_cmd (int argc, char **argv)
+{
+ u_int32_t n;
+ int ret ;
+
+ --argc;
+ ++argv;
+
+ if (argc != 1) {
+ printf ("setcrypt: Missing parameter on/off\n");
+ return 0;
+ }
+ if (strcasecmp(argv[0], "on") == 0)
+ n = 1;
+ else if(strcasecmp(argv[0], "off") == 0)
+ n = 0;
+ else {
+ printf ("setcrypt: Unknown parameter '%s'\n", argv[0]);
+ return 0;
+ }
+ ret = fs_setcrypt (n);
+ if (ret)
+ fserr(PROGNAME, ret, NULL);
+
+ return 0;
+}
+
+static int
+getfid_cmd(int argc, char **argv)
+{
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ printf("%s: Missing required parameter '-path'\n", PROGNAME);
+ else if (argc == 1)
+ afs_getfid(*argv);
+ else
+ while (argc) {
+ afs_getfid(*argv);
+ argc--;
+ argv++;
+ }
+ return 0;
+}
+
+static
+int setmaxprio_usage()
+{
+ fprintf(stderr, "usage: setmaxprio maxprio");
+ return 0;
+}
+
+static int
+setmaxprio_cmd (int argc, char **argv)
+{
+ int prio_tmp;
+ int16_t maxprio;
+ int ret;
+
+ if (argc != 1)
+ return setmaxprio_usage();
+
+ if (sscanf(argv[1], "%d", &prio_tmp) != 1)
+ return setmaxprio_usage();
+
+ maxprio = prio_tmp;
+
+ ret = fs_setmaxfprio(maxprio);
+ if (ret) {
+ fserr(PROGNAME, ret, argv[1]);
+ return 0;
+ }
+
+ return 0;
+
+}
+
+int
+setprio_usage(void)
+{
+ fprintf(stderr, "usage: file prio\n");
+ return 0;
+}
+
+static int
+setprio_cmd (int argc, char **argv)
+{
+ VenusFid fid;
+ int prio_tmp;
+ int16_t prio;
+ int ret;
+
+ if (argc != 2)
+ return setprio_usage();
+
+ if (sscanf(argv[2], "%d", &prio_tmp) != 1)
+ return setprio_usage();
+
+ prio = prio_tmp;
+
+ ret = fs_getfid(argv[1], &fid);
+ if (ret) {
+ fserr(PROGNAME, ret, argv[1]);
+ return 0;
+ }
+
+ ret = fs_setfprio(fid, prio);
+ if (ret) {
+ fserr(PROGNAME, ret, argv[1]);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+help_cmd (int argc, char **argv)
+{
+ SL_cmd *cmd = cmds;
+
+ while (cmd->name != NULL) {
+ if (cmd->usage != NULL)
+ printf ("%-20s%s\n", cmd->name, cmd->usage);
+ cmd++;
+ }
+
+ return 0;
+}
+
+static int
+mkmount_cmd (int argc, char **argv)
+{
+ char buf[MAXSIZE];
+
+ argc--;
+ argv++;
+
+ if (argc == 0) {
+ printf ("fs: Required parameter '-dir' missing\n");
+ return 0;
+ }
+ else if (argc == 1) {
+ printf ("fs: Required parameter '-vol' missing\n");
+ return 0;
+ }
+ else {
+ snprintf(buf, sizeof(buf), "#%s.", argv[1]);
+ if (symlink (buf, argv[0]) == -1) {
+ perror ("fs");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int
+listacl_cmd (int argc, char **argv)
+{
+ unsigned int i;
+
+ argc--;
+ argv++;
+
+ if(!argc)
+ afs_listacl(".");
+ else
+ for(i=0;i<argc;i++) {
+ if(i)
+ printf("\n");
+ afs_listacl(argv[i]);
+ }
+
+ return 0;
+}
+
+static int
+listcells_cmd (int argc, char **argv)
+{
+ afs_listcells ();
+
+ return 0;
+}
+
+static int
+listquota_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ printf("Volume Name Quota Used %% Used Partition\n");
+
+ if (argc == 0)
+ afs_listquota (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_listquota (argv[i]);
+
+ return 0;
+}
+
+static int
+getprio_usage(void)
+{
+ fprintf(stderr, "usage getprio file ...\n");
+ return 0;
+}
+
+static int
+getprio_cmd (int argc, char **argv)
+{
+ VenusFid fid;
+ int16_t prio;
+ int ret, i;
+ char *path;
+ char cell[MAXNAME];
+
+ if (argc == 0)
+ return getprio_usage();
+
+ for (i = 0; i < argc; i++) {
+ path = argv[i];
+
+ ret = fs_getfid(path, &fid);
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ continue;
+ }
+
+ ret = fs_getfprio(fid, &prio);
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ continue;
+ }
+
+ ret = fs_getfilecellname(path, cell, sizeof(cell));
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ continue;
+ }
+
+ printf("File %s(%s %d.%d.%d) have priority %d\n",
+ path, cell, fid.fid.Volume, fid.fid.Vnode,
+ fid.fid.Unique, prio);
+
+ }
+ return 0;
+}
+
+static int
+getmaxprio_cmd (int argc, char **argv)
+{
+ int16_t prio;
+ int ret;
+
+ if (argc != 0)
+ fprintf(stderr, "getmaxprio: extraneous argumets ignored\n");
+
+ ret = fs_getmaxfprio(&prio);
+ if (ret) {
+ fserr(PROGNAME, ret, NULL);
+ return ret;
+ }
+
+ return ret;
+}
+
+
+static int
+setquota_cmd (int argc, char **argv)
+{
+ if(argc!=3) {
+ printf("Usage: fs sq <path> <max quota in kbytes>\n");
+ return 0;
+ }
+
+ afs_setmaxquota(argv[1],(int32_t) atoi(argv[2]));
+
+ return 0;
+}
+
+static int
+lsmount_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0) {
+ printf ("fs: Required parameter '-dir' missing\n");
+ return 0;
+ }
+
+ for (i = 0; i < argc; i++)
+ afs_lsmount (argv[i]);
+
+ return 0;
+}
+
+static void
+setcache_usage()
+{
+ fprintf(stderr, "Usage: setcachesize <lowvnodes> [<highvnodes> "
+ "<lowbytes> <highbytes>]\n");
+
+}
+
+static int
+setcache_cmd (int argc, char **argv)
+{
+ int lv, hv, lb, hb;
+
+ argc--;
+ argv++;
+
+ if (argc != 1 && argc != 4) {
+ setcache_usage();
+ return 0;
+ }
+
+ if (argc == 4) {
+ if (sscanf(argv[0], "%d", &lv) &&
+ sscanf(argv[1], "%d", &hv) &&
+ sscanf(argv[2], "%d", &lb) &&
+ sscanf(argv[3], "%d", &hb))
+ return afs_setcache(lv, hv, lb, hb);
+ else
+ setcache_usage();
+ } else
+ if (sscanf(argv[0], "%d", &lv))
+ afs_setcache(lv, 0, 0, 0);
+ else
+ setcache_usage();
+
+ return 0;
+}
+
+static int
+quit_cmd (int argc, char **argv)
+{
+ printf ("Exiting...\n");
+ return 1;
+}
+
+static int
+quota_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0)
+ afs_quota (".");
+ else
+ for (i = 0; i < argc; i++)
+ afs_quota (argv[i]);
+
+ return 0;
+}
+
+static int
+rmmount_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0) {
+ printf ("fs: Required parameter '-dir' missing\n");
+ return 0;
+ }
+
+ for (i = 0; i < argc; i++)
+ afs_rmmount (argv[i]);
+
+ return 0;
+}
+
+static int
+rmprio_usage(void)
+{
+ printf("usage: rmpriority file ...\n");
+ return 0;
+}
+
+static int
+rmprio_cmd(int argc, char **argv)
+{
+ VenusFid fid;
+ int ret, i;
+ char *path;
+
+ if (argc == 0)
+ return rmprio_usage();
+
+ for (i = 0; i < argc; i++) {
+ path = argv[i];
+
+ ret = fs_getfid(path, &fid);
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ return 0;
+ }
+
+ ret = fs_setfprio(fid, 0);
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
+static int
+setacl_cmd (int argc, char **argv)
+{
+ argc--;
+ argv++;
+
+ if (argc != 3) {
+ printf ("fs: setacl: Too many or too few arguments\n");
+ return 0;
+ }
+
+ afs_setacl (argv[0], argv[1], argv[2]);
+
+ return 0;
+}
+
+static int
+sysname_cmd (int argc, char **argv)
+{
+ argc--;
+ argv++;
+ if (argc == 0)
+ afs_sysname (NULL);
+ else
+ afs_sysname (argv[0]);
+
+ return 0;
+}
+
+static int
+whereis_cmd (int argc, char **argv)
+{
+ argc--;
+ argv++;
+ if (argc == 0)
+ afs_whereis (".");
+ else
+ afs_whereis (argv[0]);
+
+ return 0;
+}
+
+static int
+whichcell_cmd (int argc, char **argv)
+{
+ int i;
+
+ argc--;
+ argv++;
+
+ if (argc == 0) {
+ afs_whichcell (".");
+ }
+
+ for (i = 0; i < argc; i++)
+ afs_whichcell (argv[i]);
+
+ return 0;
+}
+
+static int
+wscell_cmd (int argc, char **argv)
+{
+ argc--;
+ argv++;
+
+ afs_wscell ();
+
+ return 0;
+}
+
+static int
+venuslog_cmd (int argc, char **argv)
+{
+ afs_venuslog();
+
+ return 0;
+}
+
+static int
+fsversion_cmd(int argc, char **argv)
+{
+ if (argc != 0)
+ printf ("version: extraneous arguments ignored\n");
+
+ printf("fs: %s\nfs_lib: %s\n",
+ "$KTH: fs.c,v 1.41 1998/07/28 14:35:06 assar Exp $",
+ fslib_version());
+ return 0;
+}
+
+void afs_getfid(char *path)
+{
+ VenusFid fid;
+ int ret;
+ char cellname[MAXNAME];
+
+ ret = fs_getfid(path, &fid);
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ return;
+ }
+
+ ret = fs_getfilecellname(path, cellname, sizeof(cellname));
+ if (ret) {
+ fserr(PROGNAME, ret, path);
+ return;
+ }
+
+ printf("Fid: %u.%u.%u in %s (%u) \n", fid.fid.Volume,
+ fid.fid.Vnode, fid.fid.Unique, cellname, fid.Cell);
+}
+
+
+void afs_listacl(char *path)
+{
+ struct Acl *acl;
+ struct AclEntry *position;
+ int i;
+
+ if((acl=afs_getacl(path))==NULL)
+ exit(1);
+
+ printf("Access list for %s is\n", path);
+ if(acl->NumPositiveEntries) {
+ printf("Normal rights:\n");
+
+ position=acl->pos;
+ for(i=0;i<acl->NumPositiveEntries;i++) {
+ printf(" %s ", position->name);
+ if(position->RightsMask&PRSFS_READ)
+ printf("r");
+ if(position->RightsMask&PRSFS_LOOKUP)
+ printf("l");
+ if(position->RightsMask&PRSFS_INSERT)
+ printf("i");
+ if(position->RightsMask&PRSFS_DELETE)
+ printf("d");
+ if(position->RightsMask&PRSFS_WRITE)
+ printf("w");
+ if(position->RightsMask&PRSFS_LOCK)
+ printf("k");
+ if(position->RightsMask&PRSFS_ADMINISTER)
+ printf("a");
+ printf("\n");
+ position=position->next;
+ }
+ }
+ if(acl->NumNegativeEntries) {
+ printf("Negative rights:\n");
+
+ position=acl->neg;
+ for(i=0;i<acl->NumNegativeEntries;i++) {
+ printf(" %s ", position->name);
+ if(position->RightsMask&PRSFS_READ)
+ printf("r");
+ if(position->RightsMask&PRSFS_LOOKUP)
+ printf("l");
+ if(position->RightsMask&PRSFS_INSERT)
+ printf("i");
+ if(position->RightsMask&PRSFS_DELETE)
+ printf("d");
+ if(position->RightsMask&PRSFS_WRITE)
+ printf("w");
+ if(position->RightsMask&PRSFS_LOCK)
+ printf("k");
+ if(position->RightsMask&PRSFS_ADMINISTER)
+ printf("a");
+ printf("\n");
+ position=position->next;
+ }
+ }
+}
+
+void afs_setacl(char *path, char *user, char *rights)
+{
+ struct Acl *acl;
+ struct AclEntry *position;
+ struct ViceIoctl a_params;
+ int i;
+ int newrights=0;
+ int foundit=0;
+ char *ptr;
+ char acltext[MAXSIZE];
+ char tmpstr[MAXSIZE];
+
+ if((acl=afs_getacl(path))==NULL)
+ exit(1);
+
+ if(!strcmp(rights,"read"))
+ newrights=PRSFS_READ | PRSFS_LOOKUP;
+ else if(!strcmp(rights,"write"))
+ newrights=PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
+ PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK;
+ else if(!strcmp(rights,"mail"))
+ newrights=PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP;
+ else if(!strcmp(rights,"all"))
+ newrights=PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
+ PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
+ else {
+ ptr=rights;
+ while(*ptr!=0) {
+ if(*ptr=='r')
+ newrights|=PRSFS_READ;
+ if(*ptr=='l')
+ newrights|=PRSFS_LOOKUP;
+ if(*ptr=='i')
+ newrights|=PRSFS_INSERT;
+ if(*ptr=='d')
+ newrights|=PRSFS_DELETE;
+ if(*ptr=='w')
+ newrights|=PRSFS_WRITE;
+ if(*ptr=='k')
+ newrights|=PRSFS_LOCK;
+ if(*ptr=='a')
+ newrights|=PRSFS_ADMINISTER;
+ ptr++;
+ }
+ }
+
+ position=acl->pos;
+ for(i=0; i<acl->NumPositiveEntries; i++) {
+ if(!strncmp(user, position->name, 100)) {
+ position->RightsMask=newrights;
+ foundit=1;
+ }
+ if(position->next)
+ position=position->next;
+ }
+
+ if(!foundit) {
+ acl->NumPositiveEntries++;
+
+ /* We should already be at the last entry */
+ position->next=malloc(sizeof(struct AclEntry));
+ if(position->next==NULL) {
+ printf("fs: Out of memory\n");
+ exit(1);
+ }
+ position=position->next;
+ position->next=NULL;
+ strncpy(position->name, user, MAXNAME);
+ position->RightsMask=newrights;
+ }
+
+ sprintf(acltext,"%d\n%d\n", acl->NumPositiveEntries,
+ acl->NumNegativeEntries);
+ position=acl->pos;
+ for(i=0; i<acl->NumPositiveEntries; i++) {
+ sprintf(tmpstr, "%s %d\n", position->name, position->RightsMask);
+ strcat(acltext,tmpstr);
+ position=position->next;
+ }
+ position=acl->neg;
+ for(i=0; i<acl->NumNegativeEntries; i++) {
+ sprintf(tmpstr, "%s %d\n", position->name, position->RightsMask);
+ strcat(acltext,tmpstr);
+ position=position->next;
+ }
+
+ a_params.in_size=strlen(acltext);
+ a_params.out_size=0;
+ a_params.in=acltext;
+ a_params.out=0;
+
+
+ if(k_pioctl(path,VIOCSETAL,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ return;
+ }
+
+ /* free(oldacl); and its contents */
+}
+
+struct Acl *afs_getacl(char *path)
+{
+ struct Acl *oldacl;
+ struct ViceIoctl a_params;
+ struct AclEntry *pos=NULL;
+ struct AclEntry *neg=NULL;
+ char *curptr;
+ char tmpname[MAXNAME];
+ int tmprights;
+ int i;
+
+ oldacl=(struct Acl *) malloc(sizeof(struct Acl));
+ if(oldacl == NULL) {
+ printf("fs: Out of memory\n");
+ return NULL;
+ }
+
+ a_params.in_size=0;
+ a_params.out_size=MAXSIZE;
+ a_params.in=NULL;
+ a_params.out=malloc(MAXSIZE);
+
+ if(a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ free (oldacl);
+ return NULL;
+ }
+
+ if(k_pioctl(path,VIOCGETAL,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ free (oldacl);
+ free(a_params.out);
+ return NULL;
+ }
+
+ curptr=a_params.out;
+
+ /* Number of pos/neg entries parsing */
+ sscanf(curptr, "%d\n%d\n", &oldacl->NumPositiveEntries,
+ &oldacl->NumNegativeEntries);
+ skipline(&curptr);
+ skipline(&curptr);
+
+ if(oldacl->NumPositiveEntries)
+ for(i=0; i<oldacl->NumPositiveEntries; i++) {
+ sscanf(curptr, "%100s %d", tmpname, &tmprights);
+ skipline(&curptr);
+ if(!i) {
+ pos=malloc(sizeof(struct AclEntry));
+ oldacl->pos=pos;
+ }
+ else {
+ pos->next=malloc(sizeof(struct AclEntry));
+ pos=pos->next;
+ }
+ pos->RightsMask=tmprights;
+ strncpy(pos->name, tmpname, 100);
+ pos->next=NULL;
+ }
+
+ if(oldacl->NumNegativeEntries)
+ for(i=0; i<oldacl->NumNegativeEntries; i++) {
+ sscanf(curptr, "%100s %d", tmpname, &tmprights);
+ skipline(&curptr);
+ if(!i) {
+ neg=malloc(sizeof(struct AclEntry));
+ oldacl->neg=neg;
+ }
+ else {
+ neg->next=malloc(sizeof(struct AclEntry));
+ neg=neg->next;
+ }
+ neg->RightsMask=tmprights;
+ strncpy(neg->name, tmpname, 100);
+ neg->next=NULL;
+ }
+
+ free(a_params.out);
+ return oldacl;
+}
+
+void afs_sysname(char *name)
+{
+ struct ViceIoctl a_params;
+ int32_t get;
+ char *space=malloc(MAXSIZE);
+ char *curptr;
+
+ if(space == NULL) {
+ printf("fs: Out of memory\n");
+ return;
+ }
+
+ if(!name) {
+ get=0;
+ memcpy(space,&get,sizeof(int32_t));
+ a_params.in_size=sizeof(int32_t);
+ }
+ else {
+ char *ptr=space;
+ get=1;
+ memcpy(space,&get,sizeof(int32_t));
+ ptr+=sizeof(int32_t);
+ strncpy(ptr,name,100-sizeof(int32_t));
+ a_params.in_size=sizeof(int32_t)+strlen(ptr)+1;
+ }
+
+ a_params.out_size=MAXSIZE;
+ a_params.in=space;
+ a_params.out=space;
+
+ if(k_pioctl(NULL,VIOC_AFS_SYSNAME,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, NULL);
+ free(space);
+ return;
+ }
+
+ curptr=a_params.out;
+ if(!name) {
+ curptr+=sizeof(int32_t);
+ printf("Current sysname is '%s'\n",curptr);
+ }
+ else
+ printf("fs: new sysname set.\n");
+ free(space);
+}
+
+void afs_listquota(char *path)
+{
+ struct ViceIoctl a_params;
+ struct VolumeStatus *vs;
+ char *name;
+ double used_vol, used_part;
+
+ a_params.in_size=0;
+ a_params.out_size=MAXSIZE;
+ a_params.in=NULL;
+ a_params.out=malloc(MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if(k_pioctl(path,VIOCGETVOLSTAT,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ vs=(struct VolumeStatus *) a_params.out;
+ name=a_params.out+sizeof(struct VolumeStatus);
+
+ if (vs->MaxQuota)
+ used_vol = ((double) vs->BlocksInUse / vs->MaxQuota) * 100;
+ else
+ used_vol = 0.0;
+
+ if (vs->PartMaxBlocks)
+ used_part = (1.0 - (double) vs->PartBlocksAvail / vs->PartMaxBlocks)
+ * 100;
+ else
+ used_part = 0.0;
+
+ printf("%-20s%8d%8d%9.0f%%%s%9.0f%%%s%s\n",
+ name,
+ vs->MaxQuota,
+ vs->BlocksInUse,
+ used_vol,
+ used_vol > 90 ? "<<" : " ",
+ used_part,
+ used_part > 97 ? "<<" : " ",
+
+ /* Print a warning if more than 90% on home volume or 97% on */
+ /* the partion is being used */
+ (used_vol > 90 || used_part > 97) ? "\t<<WARNING" : "");
+
+ free(a_params.out);
+}
+
+void afs_setmaxquota(char *path, int32_t maxquota)
+{
+ struct ViceIoctl a_params;
+ struct VolumeStatus *vs;
+ int insize;
+
+ a_params.in_size=0;
+ a_params.out_size=MAXSIZE;
+ a_params.in=NULL;
+ a_params.out=malloc(MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ /* Read the old volume status */
+ if(k_pioctl(path,VIOCGETVOLSTAT,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ insize=sizeof(struct VolumeStatus)+strlen(path)+2;
+
+ a_params.in_size=MAXSIZE<insize?MAXSIZE:insize;
+ a_params.out_size=0;
+ a_params.in=a_params.out;
+ a_params.out=NULL;
+
+ vs=(struct VolumeStatus *) a_params.in;
+ vs->MaxQuota=maxquota;
+
+ if(k_pioctl(path,VIOCSETVOLSTAT,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.in);
+ return;
+ }
+
+ free(a_params.in);
+}
+
+void afs_whereis(char *path)
+{
+ struct ViceIoctl a_params;
+ struct in_addr addr;
+ int32_t *curptr;
+ int i=0;
+
+ a_params.in_size=0;
+ a_params.out_size=8*sizeof(int32_t);
+ a_params.in=NULL;
+ a_params.out=malloc(8*sizeof(int32_t));
+
+ if(a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if(k_pioctl(path,VIOCWHEREIS,&a_params,1)==-1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ curptr=(int32_t *) a_params.out;
+ printf("File %s is on host%s", path, curptr[0]&&curptr[1]?"s":"");
+
+ while(curptr[i] && i<8) {
+ struct hostent *h;
+ addr.s_addr=curptr[i];
+ h=gethostbyaddr((const char *) &addr, sizeof(addr), AF_INET);
+ if (h == NULL)
+ printf ("%s", inet_ntoa (addr));
+ else {
+ printf(" %s",h->h_name);
+ }
+ i++;
+ }
+ printf("\n");
+ free(a_params.out);
+}
+
+void afs_lsmount (char *path)
+{
+ struct ViceIoctl a_params;
+ char *last;
+ char *path_bkp;
+ int error;
+
+ path_bkp = strdup (path);
+ if (path_bkp == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ a_params.out = malloc (MAXSIZE);
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ free (path_bkp);
+ }
+
+ /* If path contains more than the filename alone - split it */
+
+ last = strrchr (path_bkp, '/');
+ if (last) {
+ *last = '\0';
+ a_params.in = last + 1;
+ }
+ else
+ a_params.in = path;
+
+ a_params.in_size = strlen (a_params.in) + 1;
+ a_params.out_size = MAXSIZE;
+
+ error = k_pioctl (last ? path_bkp : "." ,
+ VIOC_AFS_STAT_MT_PT, &a_params, 0);
+ if ((error == -1) && (errno != EINVAL)) {
+ fserr(PROGNAME, errno, path);
+ free (a_params.out);
+ free (path_bkp);
+ return;
+ } else if ((error == -1) && (errno == EINVAL)) {
+ printf ("'%s' is not a mount point.\n", path);
+ free (a_params.out);
+ free (path_bkp);
+ return;
+ }
+
+ printf ("'%s' is a mount point for volume '%s'\n", path, a_params.out);
+ free (a_params.out);
+ free (path_bkp);
+}
+
+void afs_rmmount (char *path)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = strlen (path) + 1;
+ a_params.out_size = 0;
+ a_params.in = path;
+ a_params.out = NULL;
+
+ if (k_pioctl (".", VIOC_AFS_DELETE_MT_PT, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, path);
+ return;
+ }
+}
+
+int
+afs_setcache(int lv, int hv, int lb, int hb)
+{
+ struct ViceIoctl a_params;
+ u_int32_t s[4];
+
+ s[0] = lv;
+ s[1] = hv;
+ s[2] = lb;
+ s[3] = hb;
+
+ a_params.in_size = ((hv == 0) ? 1 : 4) * sizeof(u_int32_t);
+ a_params.out_size = 0;
+ a_params.in = (void *)s;
+ a_params.out = NULL;
+
+ if (k_pioctl(NULL, VIOCSETCACHESIZE, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, ".");
+ return 0;
+ }
+ return 0;
+}
+
+void afs_examine (char *path)
+{
+ struct ViceIoctl a_params;
+ struct VolumeStatus *status;
+
+ a_params.in_size = 0;
+ a_params.out_size = MAXSIZE;
+ a_params.in = NULL;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if (k_pioctl (path, VIOCGETVOLSTAT, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ status = (struct VolumeStatus *) a_params.out;
+
+ printf ("Volume status for vid = %d named %s\n", status->Vid,
+ a_params.out + sizeof (struct VolumeStatus));
+ printf ("Current disk quota is %d\n", status->MaxQuota);
+ printf ("Current blocks used are %d\n", status->BlocksInUse);
+ printf ("The partition has %d blocks available out of %d\n\n", status->PartBlocksAvail, status->PartMaxBlocks);
+
+ free (a_params.out);
+}
+
+void
+afs_wscell (void)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = 0;
+ a_params.out_size = MAXSIZE;
+ a_params.in = NULL;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if (k_pioctl (NULL, VIOC_GET_WS_CELL, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, NULL);
+ free(a_params.out);
+ return;
+ }
+
+ printf ("This workstation belongs to cell '%s'\n", a_params.out);
+
+ free (a_params.out);
+}
+
+void afs_flushvolume (char *path)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = 0;
+ a_params.out_size = 0;
+ a_params.in = NULL;
+ a_params.out = NULL;
+
+ if (k_pioctl (path, VIOC_FLUSHVOLUME, &a_params, 0) == -1) {
+ perror ("fs");
+ exit (1);
+ }
+}
+
+void afs_flush (char *path)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = 0;
+ a_params.out_size = 0;
+ a_params.in = NULL;
+ a_params.out = NULL;
+
+ if (k_pioctl (path, VIOCFLUSH, &a_params, 0) == -1) {
+ perror ("fs");
+ exit (1);
+ }
+}
+
+void afs_venuslog (void)
+{
+ struct ViceIoctl a_params;
+ int32_t status = 0; /* XXX not really right, but anyway */
+
+ a_params.in_size = sizeof(int32_t);
+ a_params.out_size = 0;
+ a_params.in = (caddr_t) &status;
+ a_params.out = NULL;
+
+ if (k_pioctl (NULL, VIOC_VENUSLOG, &a_params, 0) == -1) {
+ perror ("fs");
+ exit (1);
+ }
+}
+
+void afs_whichcell (char *path)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = 0;
+ a_params.out_size = MAXSIZE;
+ a_params.in = NULL;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if (k_pioctl (path, VIOC_FILE_CELL_NAME, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ printf ("File %s lives in cell '%s'\n", path, a_params.out);
+ free (a_params.out);
+}
+
+void afs_diskfree (char *path)
+{
+ struct ViceIoctl a_params;
+ struct VolumeStatus *status;
+
+ a_params.in_size = 0;
+ a_params.out_size = MAXSIZE;
+ a_params.in = NULL;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if (k_pioctl (path, VIOCGETVOLSTAT, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ status = (struct VolumeStatus *) a_params.out;
+
+ printf ("%-20s%8d%8d%8d%9.0f%%\n",
+ a_params.out + sizeof (struct VolumeStatus),
+ status->PartMaxBlocks,
+ status->PartMaxBlocks - status->PartBlocksAvail,
+ status->PartBlocksAvail,
+ (float) (status->PartMaxBlocks - status->PartBlocksAvail) / status->PartMaxBlocks * 100);
+
+ free (a_params.out);
+}
+
+void afs_quota (char *path)
+{
+ struct ViceIoctl a_params;
+ struct VolumeStatus *status;
+
+ a_params.in_size = 0;
+ a_params.out_size = MAXSIZE;
+ a_params.in = NULL;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ if (k_pioctl (path, VIOCGETVOLSTAT, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, path);
+ free(a_params.out);
+ return;
+ }
+
+ status = (struct VolumeStatus *) a_params.out;
+
+ printf("%.0f%% of quota used.\n",
+ (1.0 - (float) status->BlocksInUse / status->MaxQuota) * 100);
+
+ free(a_params.out);
+}
+
+void afs_getcellstatus (char *cell)
+{
+ struct ViceIoctl a_params;
+ int32_t flags;
+
+ a_params.in_size = strlen (cell) + 1;
+ a_params.out_size = sizeof (int32_t);
+ a_params.in = cell;
+ a_params.out = (char *) &flags;
+
+ if (k_pioctl (NULL, VIOC_GETCELLSTATUS, &a_params, 0) == -1) {
+ fserr(PROGNAME, errno, cell);
+ return;
+ }
+
+ printf ("Cell %s status: %ssetuid allowed\n", cell, NO_SETUID_HONORED(flags) ? "no " : "");
+}
+
+void afs_listcells (void)
+{
+ struct ViceIoctl a_params;
+ struct in_addr addr;
+ int32_t *ip;
+ int32_t i, j;
+
+ a_params.in_size = sizeof (int32_t);
+ a_params.out_size = MAXSIZE;
+ a_params.in = (char *) &i;
+ a_params.out = malloc (MAXSIZE);
+
+ if (a_params.out == NULL) {
+ printf ("fs: Out of memory\n");
+ return;
+ }
+
+ i = 0;
+
+ while (k_pioctl (NULL, VIOCGETCELL, &a_params, 0) != -1) {
+ ip = (int32_t *) a_params.out;
+ printf ("Cell %s on hosts", a_params.out + 8 * sizeof (int32_t));
+
+ j = 0;
+
+ while (ip[j] && j<8) {
+ struct hostent *h;
+ addr.s_addr = ip[j];
+ h = gethostbyaddr ((const char *) &addr, sizeof(addr), AF_INET);
+ if (h == NULL) {
+ printf (" %s", inet_ntoa (addr));
+ }
+ else {
+ printf (" %s", h->h_name);
+ }
+ j++;
+ }
+ printf (".\n");
+ i++;
+ }
+
+ if (errno) {
+ fserr(PROGNAME, errno, NULL);
+ free(a_params.out);
+ return;
+ }
+
+ free (a_params.out);
+}
+
+void skipline(char **curptr)
+{
+ while(**curptr!='\n') (*curptr)++;
+ (*curptr)++;
+}
+
+
diff --git a/usr.sbin/afs/src/appl/fs_lib.c b/usr.sbin/afs/src/appl/fs_lib.c
new file mode 100644
index 00000000000..5658f07b332
--- /dev/null
+++ b/usr.sbin/afs/src/appl/fs_lib.c
@@ -0,0 +1,306 @@
+/* $OpenBSD: fs_lib.c,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "appl_locl.h"
+#include <kerberosIV/kafs.h>
+
+RCSID("$KTH: fs_lib.c,v 1.4 1998/07/24 19:55:51 lha Exp $");
+
+/*
+ *
+ */
+
+const char *
+fslib_version(void)
+{
+ return "$KTH: fs_lib.c,v 1.4 1998/07/24 19:55:51 lha Exp $";
+}
+
+/*
+ * fserr, try to implement a generic function for fs error messages
+ */
+
+void
+fserr(char *progname, int error, char *realpath)
+{
+ char *path = realpath ? realpath : "[unknown path]";
+
+ switch(error) {
+ case EACCES:
+ printf("%s: You don't have the required access rights on"
+ " '%s'\n",progname, path); return ;
+ break;
+ case EINVAL:
+ printf("%s: Invalid argument; it is possible that %s is"
+ " not in AFS.\n", progname, path); return ;
+ break;
+ case ENOENT:
+ printf("%s: '%s' doesn't exist\n",progname, path);
+ break;
+ case EPERM:
+ printf("%s: You do not have the required rights to do"
+ " this operation\n", progname);
+ break;
+ case ESRCH:
+ printf ("%s: Home cell information not available\n", progname);
+ break;
+ case EDOM:
+ break;
+ default:
+ printf("%s: error %s (%d) return from pioctl\n",
+ progname, koerr_gettext(error), error);
+ break;
+ }
+ return;
+}
+
+/*
+ * fs_getfid, the the `fid' that `path' points on.
+ */
+
+int
+fs_getfid(char *path, VenusFid *fid)
+{
+ struct ViceIoctl a_params;
+
+ if (path == NULL || fid == NULL)
+ return EINVAL;
+
+ a_params.in_size=0;
+ a_params.out_size=sizeof(*fid);
+ a_params.in=NULL;
+ a_params.out=(void*) fid;
+
+ if(k_pioctl(path,VIOCGETFID,&a_params,1) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ * Do nothing
+ */
+
+int
+fs_nop(void)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size=0;
+ a_params.out_size=0;
+ a_params.in=NULL;
+ a_params.out=NULL;
+
+ if (k_pioctl(NULL,VIOCNOP,&a_params,1) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ * Get the `cell' that the `path' ends up in
+ */
+
+int
+fs_getfilecellname(char *path, char *cell, size_t len)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size=0;
+ a_params.out_size=len;
+ a_params.in=NULL;
+ a_params.out=cell;
+
+ if (k_pioctl(path,VIOC_FILE_CELL_NAME,&a_params,1) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ * set the level of crypt
+ */
+
+int
+fs_setcrypt (u_int32_t n)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = sizeof(n);
+ a_params.out_size = 0;
+ a_params.in = (char *)&n;
+ a_params.out = NULL;
+
+ if (k_pioctl (NULL, VIOC_SETRXKCRYPT, &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ * get currernt level of crypt
+ */
+
+int
+fs_getcrypt (u_int32_t *level)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = 0;
+ a_params.out_size = sizeof(*level);
+ a_params.in = NULL;
+ a_params.out = (char *) level;
+
+ if (k_pioctl (NULL, VIOC_GETRXKCRYPT, &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ * get and set the connect-mode
+ */
+
+int
+fs_connect(int32_t type, int32_t *flags)
+{
+ struct ViceIoctl a_params;
+
+ a_params.in_size = sizeof(type);
+ a_params.out_size = sizeof (int32_t);
+ a_params.in = (char *) &type;
+ a_params.out = (char *) flags;
+
+ if (k_pioctl (NULL, VIOCCONNECTMODE, &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+int
+fs_setfprio(VenusFid fid, int16_t prio)
+{
+ struct ViceIoctl a_params;
+ struct vioc_fprio fprio;
+
+ fprio.cmd = FPRIO_SET;
+ fprio.Cell = fid.Cell;
+ fprio.Volume = fid.fid.Volume;
+ fprio.Vnode = fid.fid.Vnode;
+ fprio.Unique = fid.fid.Unique;
+ fprio.prio = prio;
+
+ a_params.in_size = sizeof(fprio);
+ a_params.out_size = 0;
+ a_params.in = (char *) &fprio;
+ a_params.out = NULL;
+
+ if (k_pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+int
+fs_getfprio(VenusFid fid, int16_t *prio)
+{
+ struct ViceIoctl a_params;
+ struct vioc_fprio fprio;
+
+ fprio.cmd = FPRIO_GET;
+ fprio.Cell = fid.Cell;
+ fprio.Volume = fid.fid.Volume;
+ fprio.Vnode = fid.fid.Vnode;
+ fprio.Unique = fid.fid.Unique;
+
+ a_params.in_size = sizeof(fprio);
+ a_params.out_size = sizeof(*prio);
+ a_params.in = (char *) &fprio;
+ a_params.out = (char *) prio;
+
+ if (k_pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+int
+fs_setmaxfprio(int16_t maxprio)
+{
+ struct ViceIoctl a_params;
+ struct vioc_fprio fprio;
+
+ fprio.cmd = FPRIO_SETMAX;
+ fprio.prio = maxprio;
+
+ a_params.in_size = sizeof(fprio);
+ a_params.out_size = 0;
+ a_params.in = (char *) &fprio;
+ a_params.out = NULL;
+
+ if (k_pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+int
+fs_getmaxfprio(int16_t *maxprio)
+{
+ struct ViceIoctl a_params;
+ struct vioc_fprio fprio;
+
+ fprio.cmd = FPRIO_GETMAX;
+
+ a_params.in_size = sizeof(fprio);
+ a_params.out_size = sizeof(*maxprio);
+ a_params.in = (char *) &fprio;
+ a_params.out = (char *) maxprio;
+
+ if (k_pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
+ return errno;
+
+ return 0;
+}
+
+
diff --git a/usr.sbin/afs/src/appl/fs_local.h b/usr.sbin/afs/src/appl/fs_local.h
new file mode 100644
index 00000000000..d5e2ba5bc95
--- /dev/null
+++ b/usr.sbin/afs/src/appl/fs_local.h
@@ -0,0 +1,148 @@
+/* $OpenBSD: fs_local.h,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * $KTH: fs_local.h,v 1.17 1998/07/24 19:55:52 lha Exp $
+ */
+
+#define MAXNAME 100
+#define MAXSIZE 2048
+
+struct Acl {
+ int NumPositiveEntries;
+ int NumNegativeEntries;
+ struct AclEntry *pos;
+ struct AclEntry *neg;
+};
+
+struct AclEntry {
+ struct AclEntry *next;
+ int32_t RightsMask;
+ char name[MAXNAME];
+};
+
+struct VolumeStatus {
+ int32_t Vid;
+ int32_t ParentId;
+ char Online;
+ char InService;
+ char Blessed;
+ char NeedsSalvage;
+ int32_t Type;
+ int32_t MinQuota;
+ int32_t MaxQuota;
+ int32_t BlocksInUse;
+ int32_t PartBlocksAvail;
+ int32_t PartMaxBlocks;
+};
+
+/* Flags for cell status */
+#define PRIMARY_CELL(flags) ((flags) & 0x1)
+#define NO_SETUID_HONORED(flags) ((flags) & 0x2)
+#define OBSOLETE_VERSION(flags) ((flags) & 0x4)
+
+void afs_listacl(char *path);
+void afs_setacl(char *path, char *user, char *rights);
+struct Acl *afs_getacl(char *path);
+void afs_sysname(char *name);
+void afs_listquota(char *path);
+void afs_setmaxquota(char *path, int32_t maxquota);
+void afs_whereis(char *path);
+void afs_lsmount(char *path);
+void afs_rmmount(char *path);
+void afs_examine(char *path);
+void afs_wscell(void);
+void afs_flushvolume(char *path);
+void afs_flush(char *path);
+void afs_venuslog(void);
+int afs_setcache(int, int, int, int);
+void afs_whichcell (char *path);
+void afs_diskfree (char *path);
+void afs_quota (char *path);
+void afs_getcellstatus (char *cell);
+void afs_getfid(char *path);
+void afs_listcells (void);
+int afs_connect(int32_t type);
+int afs_getcrypt (void);
+int afs_setcrypt (int n);
+
+void skipline(char **curptr);
+
+static int connect_cmd (int argc, char **argv);
+static int diskfree_cmd (int argc, char **argv);
+static int empty_cmd (int argc, char **argv);
+static int examine_cmd (int argc, char **argv);
+static int flushvolume_cmd (int argc, char **argv);
+static int flush_cmd (int argc, char **argv);
+static int getcellstatus_cmd (int argc, char **argv);
+static int getfid_cmd(int argc, char **argv);
+static int help_cmd (int argc, char **argv);
+static int mkmount_cmd (int argc, char **argv);
+static int listacl_cmd (int argc, char **argv);
+static int listcells_cmd (int argc, char **argv);
+static int listquota_cmd (int argc, char **argv);
+static int setquota_cmd (int argc, char **argv);
+static int lsmount_cmd (int argc, char **argv);
+static int quit_cmd (int argc, char **argv);
+static int quota_cmd (int argc, char **argv);
+static int rmmount_cmd (int argc, char **argv);
+static int setacl_cmd (int argc, char **argv);
+static int sysname_cmd (int argc, char **argv);
+static int whereis_cmd (int argc, char **argv);
+static int whichcell_cmd (int argc, char **argv);
+static int wscell_cmd (int argc, char **argv);
+static int venuslog_cmd (int argc, char **argv);
+static int setcache_cmd (int argc, char **argv);
+static int getcrypt_cmd (int argc, char **argv);
+static int setcrypt_cmd (int argc, char **argv);
+static int setprio_cmd (int argc, char **argv);
+static int getprio_cmd (int argc, char **argv);
+static int rmprio_cmd (int argc, char **argv);
+static int fsversion_cmd(int argc, char **argv);
+static int setmaxprio_cmd (int argc, char **argv);
+static int getmaxprio_cmd (int argc, char **argv);
+static int nop_cmd (int argc, char **argv);
+
+
+/* this program needs __progname defined as a macro */
+#define __progname "fs"
+#define PROGNAME (fs_interactive ? "" : __progname" ")
+
+/* if this is set the program runs in interactive mode */
+static int fs_interactive = 0;
diff --git a/usr.sbin/afs/src/appl/pts.c b/usr.sbin/afs/src/appl/pts.c
new file mode 100644
index 00000000000..7441a91d34d
--- /dev/null
+++ b/usr.sbin/afs/src/appl/pts.c
@@ -0,0 +1,723 @@
+/* $OpenBSD: pts.c,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Höskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 <sl.h>
+#include "appl_locl.h"
+#include <pts.h>
+#include <pts.cs.h>
+#include <err.h>
+#include <kerberosIV/kafs.h>
+#include <ctype.h>
+
+RCSID("$KTH: pts.c,v 1.6 1998/07/30 18:36:22 rb Exp $");
+
+
+static int empty_cmd(int, char **);
+static int help_cmd(int, char **);
+static int dump_cmd(int, char **);
+static int examine_cmd(int, char **);
+static int listmax_cmd(int, char **);
+static int member_cmd(int, char **);
+static int listowned_cmd(int, char **);
+
+static SL_cmd cmds[] = {
+ {"adduser", empty_cmd, "not yet implemented"},
+ {"chown", empty_cmd, "not yet implemented"},
+ {"creategroup", empty_cmd, "not yet implemented"},
+ {"cg"},
+ {"createuser", empty_cmd, "not yet implemented"},
+ {"dump", dump_cmd, "dump pts database"},
+ {"delete", empty_cmd, "not yet implemented"},
+ {"examine", examine_cmd, "examine a user or a group"},
+ {"help", help_cmd, "get help on pts"},
+ {"?"},
+ {"listmax", listmax_cmd, "print largest uid and gid"},
+ {"listowned", listowned_cmd, "list groups owned by a user or group, or orphaned groups"},
+ {"membership", member_cmd, "list group or user membership"},
+ {"groups"},
+ {"removeuser", empty_cmd, "not yet implemented"},
+ {"rename", empty_cmd, "not yet implemented"},
+ {"setfields", empty_cmd, "not yet implemented"},
+ {"setmax", empty_cmd, "not yet implemented"},
+ {NULL}
+};
+
+static int
+empty_cmd (int argc, char **argv)
+{
+ printf ("%s not implemented yet!\n", argv[0]);
+ return 0;
+}
+
+static int
+help_cmd (int argc, char **argv)
+{
+ SL_cmd *cmd = cmds;
+
+ while (cmd->name != NULL) {
+ if (cmd->usage != NULL)
+ printf ("%-20s%s\n", cmd->name, cmd->usage);
+ cmd++;
+ }
+
+ return 0;
+}
+
+void
+dump_usage ()
+{
+ printf("Usage: pts dump <vldb server>+ [-cell <cell>]\n");
+}
+
+static int
+dump_cmd (int argc, char **argv)
+{
+ struct rx_connection *connptdb = NULL;
+ struct prdebugentry entry;
+ struct prheader header;
+ char *host;
+ int noauth = 0;
+ unsigned int pos;
+ int error;
+
+ argc--;
+ argv++;
+
+ if (argc < 1) {
+ dump_usage ();
+ return -1;
+ }
+
+ host = argv[0];
+
+ connptdb = arlalib_getconnbyname(host,
+ afsprport,
+ PR_SERVICE_ID,
+ noauth);
+
+ if (connptdb == NULL)
+ return 0;
+
+ error = PR_DumpEntry(connptdb, 0, (struct prdebugentry *) &header);
+
+ if (error) {
+ printf("dump_cmd: DumpEntry failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return 0;
+ }
+
+ for (pos = header.headerSize; pos < header.eofPtr; pos += sizeof (struct prdebugentry)) {
+ error = PR_DumpEntry(connptdb, pos, &entry);
+ if (error) {
+ printf("dump_cmd: DumpEntry failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+/* return -1;*/
+ }
+ else {
+ printf("-----\n");
+ printf("Name: %s, id: %d, owner: %d, creator: %d,\n",
+ entry.name, entry.id, entry.owner, entry.creator);
+ printf(" membership: %d, flags:", entry.ngroups);
+ if ((entry.flags & PRTYPE) == PRFREE)
+ printf (" PRFREE");
+ if ((entry.flags & PRTYPE) == PRGRP)
+ printf (" PRGRP");
+ if ((entry.flags & PRTYPE) == PRCONT)
+ printf (" PRCONT");
+ if ((entry.flags & PRTYPE) == PRCELL)
+ printf (" PRCELL");
+ if ((entry.flags & PRTYPE) == PRFOREIGN)
+ printf (" PRFOREIGN");
+ if ((entry.flags & PRTYPE) == PRINST)
+ printf (" PRINST");
+ if ((entry.flags & PRTYPE) == PRUSER)
+ printf (" PRUSER");
+ if ((entry.flags & PRACCESS) == PRACCESS)
+ printf (" PRACCESS");
+ if ((entry.flags & PRQUOTA) == PRQUOTA)
+ printf (" PRQUOTA");
+
+ printf (" , group quota: %d.\n",
+ entry.ngroups);
+ }
+ }
+
+ arlalib_destroyconn(connptdb);
+ return 0;
+}
+
+void
+examine_usage ()
+{
+ printf("Usage: pts examine <name or id of a user/group>+ [-cell <cell>] [-noauth] [-help]\n");
+}
+
+
+int
+flags_to_string(int flags, char *string)
+{
+ strcpy(string, "-----");
+ if((flags & PRP_STATUS_ANY) != 0)
+ string[0]='S';
+ else if((flags & PRP_STATUS_MEM) != 0)
+ string[0]='s';
+ if((flags & PRP_OWNED_ANY) != 0)
+ string[1]='O';
+ if((flags & PRP_MEMBER_ANY) != 0)
+ string[2]='M';
+ else if((flags & PRP_MEMBER_MEM) != 0)
+ string[2]='m';
+ if((flags & PRP_ADD_ANY) != 0)
+ string[3]='A';
+ else if((flags & PRP_ADD_MEM) != 0)
+ string[3]='a';
+ if((flags & PRP_REMOVE_MEM) != 0)
+ string[4]='r';
+ return 0;
+}
+
+static int
+examine_id(struct rx_connection *conn, int32_t id, char *idname)
+{
+ prcheckentry ent;
+ int res;
+ namelist nlist;
+ idlist ilist;
+ char flags_str[6];
+
+ res = PR_ListEntry(conn, id, &ent);
+ if(res != 0) {
+ if(res == PRPERM)
+ errx(1, "No permissions");
+ else if(res == PRNOENT) {
+ errx(1, "User or group doesn't exist"
+ "; unable to find entry for %s", idname);
+ }
+ else if (res == PRDBBAD)
+ errx(1, "An error was found relating to the PDB");
+ else
+ errx(1, "PR_ListEntry returned errorcode %d", res);
+ }
+
+ nlist.len = 3;
+ nlist.val = malloc(sizeof(prname) * nlist.len);
+ if(nlist.val == NULL)
+ errx(1, "Out of memory");
+
+ ilist.len = 3;
+ ilist.val = malloc(sizeof(int32_t) * ilist.len);
+ if(ilist.val == NULL)
+ errx(1, "Out of memory");
+
+ ilist.val[0] = ent.id;
+ ilist.val[1] = ent.owner;
+ ilist.val[2] = ent.creator;
+
+ PR_IDToName(conn, &ilist, &nlist);
+
+ flags_to_string(ent.flags << 16, flags_str); /* XXX why do i have to shift by 16? seems strange */
+
+ printf("----- %x\n", ent.flags);
+ printf("Name: %s, id: %d, owner: %s, creator: %s,\n",
+ nlist.val[0], ent.id, nlist.val[1], nlist.val[2]);
+ printf(" membership: %d, flags: %s, group quota: %d.\n",
+ ent.count, flags_str, ent.ngroups);
+ free(ilist.val);
+ free(nlist.val);
+ return 0;
+}
+
+static int
+examine_cmd (int argc, char **argv)
+{
+ const char *host = NULL;
+ const char *cell = NULL;
+ struct rx_connection *connptdb = NULL;
+ namelist nlist;
+ idlist ilist;
+ int i = 0;
+ int switches = 0;
+ int noauth = 1;
+
+ argc--; argv++; /* Get rid of command name */
+
+ /* pts examine needs at least one argument */
+ if(argc < 1) {
+ examine_usage();
+ return 0;
+ }
+
+ /* get rid of -nameorid that is allowed in front of usernames */
+ if(strcmp(argv[0], "-nameorid") == 0) {
+ argv++;
+ argc--;
+ }
+
+ /* scan for switches */
+ for(i = 0; i < argc; i++) {
+ if(strncmp(argv[i], "-cell", 2) == 0) {
+ if(cell != NULL || (argc - 1 <= i) ) {
+ examine_usage();
+ return 0;
+ }
+ switches+=2;
+ cell = argv[i+1];
+ argv[i] = NULL; /* don't examine "-cell" as a user/group */
+ argv[i+1] = NULL; /* don't examine cell name as a user/group */
+ i+=1;
+ } else if(strncmp(argv[i], "-noauth", 2) == 0) {
+ noauth = 1;
+ switches++;
+ }
+ }
+
+ if (cell == NULL)
+ cell = cell_getthiscell();
+
+ host = cell_findnamedbbyname (cell);
+
+ if(host == NULL)
+ errx(1, "Can't find cell %s", cell);
+
+ connptdb = arlalib_getconnbyname(host,
+ 7002,
+ PR_SERVICE_ID,
+ noauth);
+ if (connptdb == NULL)
+ errx(1, "Could not connect to ptserver");
+
+ nlist.len = argc - switches;
+ nlist.val = malloc(sizeof(prname) * nlist.len);
+ if(nlist.val == NULL)
+ errx(1, "Out of memory.");
+
+ ilist.len = nlist.len;
+ ilist.val = malloc(sizeof(int32_t)*ilist.len);
+ if(ilist.val == NULL)
+ errx(1, "Out of memory.");
+
+ for(i = 0; i < argc - switches; i++) {
+ while(strcmp(argv[0], "") == 0)
+ argv++;
+ strncpy(nlist.val[i], argv[0], sizeof(prname));
+ argv++;
+ }
+
+ PR_NameToID(connptdb, &nlist, &ilist);
+
+ for(i = 0; i < nlist.len; i++) {
+ if(ilist.val[i] == ANONYMOUSID) {
+ ilist.val[i] = atoi(nlist.val[i]);
+ }
+ }
+
+
+ for(i = 0; i < nlist.len; i++) {
+ examine_id(connptdb, ilist.val[i], nlist.val[i]);
+ }
+
+ free(nlist.val);
+ free(ilist.val);
+
+ arlalib_destroyconn(connptdb);
+ return 0;
+
+}
+
+void
+listmax_usage()
+{
+ printf("Usage: pts listmax [-cell <cell>] [-help]\n");
+}
+
+static int
+listmax_cmd (int argc, char **argv)
+{
+ int32_t uid = 0;
+ int32_t gid = 0;
+ int32_t res = 0;
+ const char *host = NULL;
+ const char *cell = NULL;
+ struct rx_connection *connptdb = NULL;
+
+ argc--; argv++; /* Get rid of command name */
+
+ while(argc) {
+ if(strcmp(argv[0], "-cell") == 0 && argc > 0) {
+ cell = argv[1];
+ argv++;
+ argc--;
+ } else {
+ listmax_usage();
+ return 0;
+ }
+ argv++;
+ argc--;
+ }
+
+ if (cell == NULL)
+ cell = cell_getthiscell();
+
+ host = cell_findnamedbbyname (cell);
+
+ connptdb = arlalib_getconnbyname(host,
+ 7002,
+ PR_SERVICE_ID,
+ 1); /* XXX this means no auth */
+ if (connptdb == NULL)
+ errx(1, "Could not connect to ptserver");
+
+ res = PR_ListMax(connptdb, &uid, &gid);
+
+ if (res == 0)
+ printf("Max user id is %d and max group id is %d.\n", uid, gid);
+ else {
+ errx(1, "PR_ListMax failed with errorcode %d", res);
+ }
+
+ arlalib_destroyconn(connptdb);
+ return 0;
+}
+
+int
+pts_id_to_name(struct rx_connection *conn, int id, prname *pr)
+{
+ int32_t res = 0;
+ namelist nlist;
+ idlist ilist;
+ nlist.len = 1;
+ nlist.val = malloc(sizeof(prname) * nlist.len);
+ ilist.len = 1;
+ ilist.val = malloc(sizeof(int32_t) * ilist.len);
+ if((ilist.val == NULL) || (nlist.val == NULL))
+ errx(1, "Out of memory");
+ ilist.val[0]=id;
+ res = PR_IDToName(conn, &ilist, &nlist);
+ if(res == 0)
+ strncpy((char *)pr, (char *)nlist.val[0], PR_MAXNAMELEN);
+ free(ilist.val);
+ free(nlist.val);
+ return res;
+}
+
+int
+pts_name_to_id(struct rx_connection *conn, char *name, int *id)
+{
+ int32_t res = 0;
+ namelist nlist;
+ idlist ilist;
+ int isdig = 1;
+ char *ptr = name;
+ while(*ptr && isdig) {
+ if(!isdigit(*ptr))
+ isdig = 0;
+ ptr++;
+ }
+ if(isdig) {
+ *id = atoi(name);
+ return 0;
+ }
+
+ nlist.len = 1;
+ nlist.val = malloc(sizeof(prname) * nlist.len);
+ ilist.len = 1;
+ ilist.val = malloc(sizeof(int32_t) * ilist.len);
+ if((nlist.val == NULL) || (ilist.val == NULL))
+ errx(1, "Out of memory");
+ strncpy(nlist.val[0], name, sizeof(prname));
+ res = PR_NameToID(conn, &nlist, &ilist);
+ *id = ilist.val[0];
+ free(ilist.val);
+ free(nlist.val);
+ return res;
+}
+
+void
+listmembershipbyname(struct rx_connection *conn, char *name)
+{
+ int32_t res = 0;
+ int32_t id = 0;
+ res = pts_name_to_id(conn, name, &id);
+ if(res != 0) {
+ if(res == PRPERM) {
+ errx(1, "pts: Permission denied ; unable to get membership "
+ "of %s (id: %d)", name, id);
+ }
+ else if(res == PRNOENT)
+ errx(1, "pts: User or group doesn't exist so couldn't look up"
+ "id for %s (id: %d)", name, id);
+ else
+ errx(1, "pts: pts_name_to_id(..) returned %d", res); /* shouldnt happen */
+ }
+ else {
+ int32_t over;
+ int i;
+ prlist elist;
+ elist.len = PR_MAXGROUPS; /* XXX this will allocate 5000 ints, should
+ check how many groups first. That will take
+ a lot of code though. */
+ elist.val = malloc(sizeof(int32_t) * elist.len);
+ if(elist.val == NULL)
+ errx(1, "Out of memory");
+ res = PR_ListElements(conn, id, &elist, &over);
+ if(res != 0) {
+ if(res == PRPERM) {
+ if(id == ANONYMOUSID) /* this sucks */
+ errx(1, "pts: User or group doesn't exist so couldn't"
+ "look up id for %s (id: %d)", name, id);
+ else
+ errx(1, "pts: Permission denied ; unable to get "
+ "membership of %s (id: %d)", name, id);
+ }
+ else if(res == PRNOENT)
+ errx(1, "pts: User or group doesn't exist so couldn't look up"
+ "id for %s (id: %d)", name, id);
+ else
+ errx(1, "pts: PR_ListElements(..) returned %d", res);
+ }
+ else {
+ if(id>=0)
+ printf("Groups %s (id: %d) is a member of:\n", name, id);
+ else
+ printf("Members of %s (id: %d) are:\n", name, id);
+ for(i = 0; i < elist.len; i++) {
+ prname pr;
+ res = pts_id_to_name(conn, elist.val[i], &pr);
+ printf(" %s\n", (char *)&pr);
+ }
+ free(elist.val);
+ }
+ }
+ return;
+}
+
+void
+member_usage()
+{
+ printf("Usage: pts membership [-nameorid] <users and groups>+ "
+ "[-cell <cell>] [-noauth] [-help]\n");
+}
+
+static int
+member_cmd (int argc, char **argv)
+{
+ const char *host = NULL;
+ const char *cell = NULL;
+ struct rx_connection *connptdb = NULL;
+ int32_t noauth = 0;
+ int i = 0;
+ int switches = 0;
+
+ if(argc <= 1) {
+ member_usage();
+ return 0;
+ }
+
+ argc--; argv++; /* Get rid of command name */
+
+ /* get rid of -nameorid that is allowed on commandline */
+ if(strcmp("-nameorid", argv[0]) == 0) {
+ argv++;
+ argc--;
+ }
+
+ /* scan for switches */
+ for(i = 0; i < argc; i++) {
+ if(strncmp(argv[i], "-cell", 2) == 0) {
+ if(cell != NULL || (argc - 1 <= i) ) {
+ member_usage();
+ return 0;
+ }
+ switches+=2;
+ cell = argv[i+1];
+ argv[i] = NULL;
+ argv[i+1] = NULL;
+ i+=1;
+ } else if(strncmp(argv[i], "-noauth", 2) == 0) {
+ noauth = 1;
+ switches++;
+ }
+ }
+
+ if (cell == NULL)
+ cell = cell_getthiscell();
+
+ host = cell_findnamedbbyname (cell);
+
+ connptdb = arlalib_getconnbyname(host,
+ 7002,
+ PR_SERVICE_ID,
+ noauth);
+ if (connptdb == NULL)
+ errx(1, "Could not connect to ptserver");
+
+ for(i = 0; i < argc - switches; i++) {
+ if(argv[0] != NULL)
+ listmembershipbyname(connptdb, argv[0]);
+ argv++;
+ }
+
+ arlalib_destroyconn(connptdb);
+ return 0;
+}
+
+void
+listowned_usage()
+{
+ printf("Usage: pts [-id] <user or group> [-cell <cell>] [-noauth] [-help]\n");
+}
+
+static char *listowned_id;
+static char *listowned_cell;
+static int listowned_noauth;
+static int listowned_help;
+
+static struct getargs listowned_args[] = {
+ {"id", 0, arg_string, &listowned_id, "id of user/group", NULL, arg_mandatory},
+ {"cell", 0, arg_string, &listowned_cell, "what cell to use", NULL},
+ {"noauth", 0, arg_flag, &listowned_noauth, "don't authenticate", NULL},
+ {"help", 0, arg_flag, &listowned_help, NULL, NULL},
+ {NULL, 0, arg_end, NULL}
+};
+
+int
+listowned_cmd(int argc, char **argv)
+{
+ int optind = 0;
+ int i;
+ const char *host = NULL;
+ struct rx_connection *connptdb = NULL;
+ prlist pr;
+ int32_t over;
+ int32_t res;
+ int32_t id;
+ prname *name;
+
+ listowned_noauth = listowned_help = 0;
+ listowned_id = listowned_cell = NULL;
+
+ if (getarg (listowned_args, argc, argv, &optind, ARG_AFSSTYLE)) {
+ listowned_usage();
+ return 0;
+ }
+
+ if(listowned_help) {
+ listowned_usage();
+ return 0;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (listowned_cell == NULL)
+ listowned_cell = (char *) cell_getthiscell();
+
+ host = cell_findnamedbbyname (listowned_cell);
+
+ connptdb = arlalib_getconnbyname(host,
+ 7002,
+ PR_SERVICE_ID,
+ listowned_noauth);
+ if (connptdb == NULL)
+ errx(1, "Could not connect to ptserver");
+
+ res = pts_name_to_id(connptdb, listowned_id, &id);
+ if(res != 0) {
+ if(res == PRPERM) {
+ errx(1, "pts: Permission denied ; unable to get owner list "
+ "for %s (id: %d)", listowned_id, id);
+ }
+ else if(res == PRNOENT)
+ errx(1, "pts: User or group doesn't exist so couldn't look up"
+ "id for %s (id: %d)", listowned_id, id);
+ else
+ errx(1, "pts: pts_name_to_id(..) returned %d", res); /* shouldnt happen */
+ }
+
+ pr.len = PR_MAXGROUPS;
+ pr.val = malloc(sizeof(int32_t) * pr.len);
+ if(pr.val == NULL)
+ errx(1, "Out of memory");
+
+ res = PR_ListOwned(connptdb, id, &pr, &over);
+ if(res != 0)
+ errx(1, "PR_ListOwned() returned %d", res);
+
+ printf("id = %d\n", id);
+ printf("pr.len = %d\n", pr.len);
+
+ i = 0;
+ name = malloc(PR_MAXNAMELEN);
+ if(name == NULL)
+ errx(1, "Out of memory");
+
+ printf("Groups owned by %s (id: %d) are:\n", listowned_id, id);
+
+ while(pr.val[i] != 0 && i < pr.len) {
+ pts_id_to_name(connptdb, pr.val[i++], name);
+ printf(" %s\n", (char *) name);
+ }
+
+ free(pr.val);
+ arlalib_destroyconn(connptdb);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ initports();
+ cell_init(0); /* XXX */
+
+ if(argc > 1) {
+ ret = sl_command(cmds, argc - 1, argv + 1);
+ if (ret == -1)
+ printf("%s: Unknown command\n", argv[1]);
+ }
+ else {
+ printf("pts - an arla tool for administrating AFS users"
+ " and groups.\n");
+ printf("Type \"pts help\" to get a list of commands.\n");
+ }
+ return ret;
+}
diff --git a/usr.sbin/afs/src/appl/udebug.c b/usr.sbin/afs/src/appl/udebug.c
new file mode 100644
index 00000000000..206dadf18d9
--- /dev/null
+++ b/usr.sbin/afs/src/appl/udebug.c
@@ -0,0 +1,263 @@
+/* $OpenBSD: udebug.c,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "appl_locl.h"
+RCSID("$KTH: udebug.c,v 1.3 1998/07/16 00:19:40 assar Exp $");
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "udebug: Version $KTH: udebug.c,v 1.3 1998/07/16 00:19:40 assar Exp $\n"
+ "usage: udebug -servers server ... -port port -noauth\n");
+ exit(1);
+}
+
+
+static void
+newhost(u_int32_t **hosts, int *len, char *host)
+{
+ struct in_addr server;
+ u_int32_t *ptr;
+
+ if (host == NULL)
+ return;
+
+ if (ipgetaddr (host, &server) == NULL) {
+ warnx("cant find addr for '%s'.", host);
+ return;
+ }
+
+ ptr = realloc(*hosts, sizeof(u_int32_t) * ++*len);
+ if (ptr == NULL)
+ err(1, "realloc");
+
+ *hosts = ptr;
+
+ ptr[*len-1] = server.s_addr;
+}
+
+/*
+ * XXX reentrerant, no thanks, use this twice in a printf and
+ * you are a rosted bunny.
+ */
+
+char *myctime(time_t time)
+{
+ static char str[30]; /* Man page say 26 */
+
+ strncpy(str, ctime(&time), 29);
+ str[29] = '\0';
+ strtok(str, "\n");
+ return str;
+}
+
+static void
+ProbeHost(u_int32_t host, u_int16_t port, int noauth)
+{
+ struct rx_connection *conn;
+ ubik_debug db;
+ int error;
+ struct in_addr server;
+
+ server.s_addr = host;
+
+ conn = arlalib_getconnbyaddr(host,
+ NULL,
+ port,
+ VOTE_SERVICE_ID,
+ noauth);
+
+ if (conn == NULL) {
+ warnx("Could not contact host %s", inet_ntoa(server));
+ return;
+ }
+
+ error = Ubik_Debug(conn, &db);
+ if (error) {
+ fprintf(stderr, "ProbeHost: Ubik_Debug: %s (%d)\n",
+ koerr_gettext(error), error);
+
+ return;
+ }
+
+#define ABS_COMP_DB(dbname,field) (abs(db.now - dbname##.##field))
+
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ printf("Host %s time is %s\n",
+ inet_ntoa(server),
+ myctime((time_t) db.now));
+ printf("Localtime is %s, differ %d seconds\n",
+ myctime((time_t) tv.tv_sec),
+ abs(db.now - tv.tv_sec));
+ server.s_addr = db.syncHost;
+ printf("Last yes vote for %s secs was %d ago (at %s)\n",
+ inet_ntoa(server),
+ ABS_COMP_DB(db,lastYesTime),
+ myctime(db.lastYesTime));
+ printf("Last vote started %d secs ago (at %s)\n",
+ ABS_COMP_DB(db,syncTime),
+ myctime(db.lastYesTime));
+ printf("Local db version is %u.%u\n",
+ db.localVersion.epoch,
+ db.localVersion.counter);
+ printf("Syncsite db version is %u.%u\n",
+ db.syncVersion.epoch,
+ db.syncVersion.counter);
+ printf("%d locked pages, %d of them for write\n",
+ db.anyReadLocks + db.anyWriteLocks, db.anyWriteLocks);
+
+ if (db.amSyncSite) {
+ int i;
+ ubik_sdebug sdb;
+
+ printf("I'm the synchost for %d seconds more (%s)\n",
+ db.syncSiteUntil - db.now,
+ myctime(db.syncSiteUntil));
+
+ printf("Recover state is 0x%x\n", db.recoveryState);
+ printf("Last time a new db version was laballed was:\n"
+ "\t\t%d secs ago (at %s)\n\n",
+ ABS_COMP_DB(db,epochTime),
+ myctime((time_t) db.epochTime));
+
+
+ for (i = 0; i < db.nServers - 1; i++) {
+
+ error = Ubik_SDebug(conn, i, &sdb);
+ if (error) {
+ printf("Problem with host %d\n\n", i);
+ continue;
+ }
+
+ server.s_addr = sdb.addr;
+ printf("Server %s: (db %u.%u)\n",
+ inet_ntoa(server),
+ sdb.remoteVersion.epoch,
+ sdb.remoteVersion.counter);
+ printf("\tlast vote recived %d secs ago (at %s)\n",
+ ABS_COMP_DB(sdb,lastVoteTime),
+ myctime((time_t) sdb.lastVoteTime));
+ printf("\tlast beacon sent %d secs ago (at %s)\n",
+ ABS_COMP_DB(sdb,lastBeaconSent),
+ myctime((time_t) sdb.lastBeaconSent));
+ printf("\tdbcurrent=%d, up=%d, beaconSince=%u\n",
+ sdb.currentDB,
+ sdb.up,
+ sdb.beaconSinceDown);
+
+ printf("\n");
+
+ }
+ } else {
+ server.s_addr = db.syncHost;
+ printf("I'm not the synchost, but %s is.\n",
+ inet_ntoa(server));
+ }
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ u_int32_t *hosts = NULL;
+ int len = 0;
+ u_int16_t port = 0;
+ enum { START, NOWHERE, HOST, PORT } state = START;
+
+ if (argc < 2)
+ usage();
+
+ argv++;
+ argc--;
+
+ while (argc) {
+ if (*argv[0] == '-') {
+ if (strcmp(*argv, "-server") == 0)
+ state = HOST;
+ else if (strcmp(*argv, "-port") == 0)
+ state = PORT;
+ else
+ usage();
+ } else {
+ switch (state) {
+ case START:
+ if (argc != 2)
+ usage();
+ newhost(&hosts, &len, *argv);
+ argv++;
+ argc--;
+ port = atoi(*argv);
+ break;
+ case HOST:
+ newhost(&hosts, &len, *argv);
+ break;
+ case PORT:
+ port = atoi(*argv);
+ state = NOWHERE;
+ break;
+ case NOWHERE:
+ usage();
+ default:
+ abort();
+ }
+ }
+ argc--;
+ argv++;
+ }
+
+ if (hosts == NULL)
+ errx(1, "No hosts found !");
+
+ if (port == 0)
+ errx(1, "No port given");
+
+ while (len) {
+ ProbeHost(*hosts, port, 1 /* noauth */);
+ hosts++;
+ len--;
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/afs/src/appl/vos.c b/usr.sbin/afs/src/appl/vos.c
new file mode 100644
index 00000000000..87e499daaf0
--- /dev/null
+++ b/usr.sbin/afs/src/appl/vos.c
@@ -0,0 +1,915 @@
+/* $OpenBSD: vos.c,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "appl_locl.h"
+#include <sl.h>
+#include "vos_local.h"
+
+RCSID("$KTH: vos.c,v 1.46 1998/08/23 22:50:21 assar Exp $");
+
+static int empty_cmd (int, char **);
+static int exa_cmd (int, char **);
+static int help_cmd (int, char **);
+static int quit_cmd (int, char **);
+static int listp_cmd (int, char **);
+static int livol_cmd (int, char **);
+static int parti_cmd (int, char **);
+static int stat_cmd (int, char **);
+static int syncsite_cmd (int, char **);
+
+static SL_cmd cmds[] = {
+ {"addsite", empty_cmd, "not yet implemented"},
+ {"apropos", empty_cmd, "not yet implemented"},
+ {"backup", empty_cmd, "not yet implemented"},
+ {"backupsys", empty_cmd, "not yet implemented"},
+ {"changeaddr", empty_cmd, "not yet implemented"},
+ {"create", empty_cmd, "not yet implemented"},
+ {"delentry", empty_cmd, "not yet implemented"},
+ {"dump", empty_cmd, "not yet implemented"},
+ {"examine", exa_cmd, "print information about a volume"},
+ {"volinfo"},
+ {"help", help_cmd, "print help"},
+ {"?"},
+ {"listpart", listp_cmd, "list partitions on a server"},
+ {"listvldb", empty_cmd, "not yet implemented"},
+ {"listvol", livol_cmd, "list volumes on a server"},
+ {"lock", empty_cmd, "not yet implemented"},
+ {"move", empty_cmd, "not yet implemented"},
+ {"partinfo", parti_cmd, "print partition information on a server"},
+ {"release", empty_cmd, "not yet implemented"},
+ {"remove", empty_cmd, "not yet implemented"},
+ {"remsite", empty_cmd, "not yet implemented"},
+ {"rename", empty_cmd, "not yet implemented"},
+ {"restore", empty_cmd, "not yet implemented"},
+ {"status", stat_cmd, "Show volume server transactions"},
+ {"syncserv", empty_cmd, "not yet implemented"},
+ {"syncvldb", empty_cmd, "not yet implemented"},
+ {"syncsite", syncsite_cmd, "print the syncsite"},
+ {"unlock", empty_cmd, "not yet implemented"},
+ {"unlockvldb", empty_cmd, "not yet implemented"},
+ {"zap", empty_cmd, "not yet implemented"},
+ {"quit", quit_cmd, "exit interactive mode"},
+ {NULL}
+};
+
+
+
+int printlistparts(char *server);
+int printvolstat(char *volname,
+ const char *cell, const char *host, int noauth);
+
+#define LISTVOL_PART 0x1
+#define LISTVOL_NOAUTH 0x2
+#define LISTVOL_LOCALAUTH 0x4
+
+int printlistvol(char *server, int part, int flags);
+int printpartinfo(char *server, char *partition);
+int printstatus(char *server);
+
+static int
+empty_cmd(int argc, char **argv)
+{
+ printf("%s%s has not been implemented yet!\n", PROGNAME, argv[0]);
+ return 0;
+}
+
+static int
+quit_cmd(int argc, char **argv)
+{
+ printf("exiting\n");
+ return 1;
+}
+
+static int
+help_cmd(int argc, char **argv)
+{
+ sl_help(cmds, argc, argv);
+ return 0;
+}
+
+/*
+ * volume_name2num
+ * convert a char string that might be a partition to a
+ * number.
+ *
+ * returns -1 is there is an error
+ *
+ */
+
+int
+volume_name2num(char *name)
+{
+ int ret;
+
+ if (strncmp(name, "/vicep", 6) == 0)
+ name += 6;
+ else if (strncmp(name, "vicep", 5) == 0)
+ name += 5;
+
+ if (*name == '\0')
+ return -1;
+
+ if(*(name+1) == '\0') {
+ if(isalpha(*name)) {
+ ret = tolower(*name) - 'a';
+ } else
+ return -1;
+ } else if (*(name+2) == '\0') {
+ if (isalpha(*name) && isalpha(*name+1)) {
+ ret = 26 * (tolower(*(name)) - 'a' + 1) + tolower(*(name+1)) - 'a';
+ } else
+ return -1;
+ } else
+ return -1;
+
+ if(ret > 255)
+ return -1;
+
+ return ret;
+
+}
+
+
+static int exa_helpflag;
+static char *exa_host;
+static char *exa_cell;
+static char *exa_vol;
+static int exa_noauth;
+static int exa_localauth;
+
+static struct getargs exa_args[] = {
+ {"id", 0, arg_string, &exa_vol, "id of volume", NULL, arg_mandatory},
+ {"host", 0, arg_string, &exa_host, "what host to use", NULL},
+ {"cell", 0, arg_string, &exa_cell, "what cell to use", NULL},
+ {"noauth", 0, arg_flag, &exa_noauth, "what cell to use", NULL},
+ {"localauth",0,arg_flag, &exa_localauth, "localauth", NULL},
+ {"help", 0, arg_flag, &exa_helpflag, NULL, NULL},
+ {NULL, 0, arg_end, NULL}
+};
+
+
+int
+exa_usage()
+{
+ arg_printusage(exa_args, NULL, "examine");
+ return 0;
+}
+
+
+static int
+exa_cmd(int argc, char **argv)
+{
+ int optind = 0;
+ exa_noauth = exa_helpflag = 0;
+ exa_vol = NULL;
+
+ exa_cell = NULL;
+ exa_host = NULL;
+ exa_noauth = 0;
+
+ if (getarg (exa_args, argc, argv, &optind, ARG_AFSSTYLE))
+ return exa_usage();
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc) {
+ printf("unknown option %s\n", *argv);
+ return 0;
+ }
+
+ /* don't allow any bogus volname */
+ if (exa_vol == NULL || exa_vol[0] == '\0')
+ return exa_usage();
+
+ printvolstat(exa_vol, exa_cell, exa_host, exa_noauth);
+ return 0;
+}
+
+static int listp_helpflag;
+static char *listp_server;
+static int listp_noauth;
+
+static struct getargs listp_args[] = {
+ {"server", 0, arg_string, &listp_server, "server", NULL, arg_mandatory},
+ {"noauth", 0, arg_flag, &listp_noauth, "what cell to use", NULL},
+ {"help", 0, arg_flag, &listp_helpflag, NULL, NULL}
+};
+
+int
+listp_usage()
+{
+ arg_printusage(listp_args, NULL, "listpart");
+ return 0;
+}
+
+
+static int
+listp_cmd(int argc, char **argv)
+{
+ int optind = 0;
+ exa_noauth = exa_helpflag = 0;
+ exa_vol = NULL;
+
+
+ if (getarg (listp_args,argc, argv, &optind, ARG_AFSSTYLE))
+ return listp_usage();
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc) {
+ printf("unknown option %s\n", *argv);
+ return 0;
+ }
+
+ if (listp_server == NULL || listp_server[0] == '\0')
+ return listp_usage();
+
+ printlistparts(listp_server);
+ return 0;
+}
+
+/*
+ * list volume on a afs-server
+ */
+
+char *listvol_server;
+char *listvol_partition;
+int listvol_machine;
+char *listvol_cell;
+char *listvol_noauth;
+char *listvol_localauth;
+char *listvol_help;
+
+static struct getargs listvol_args[] = {
+ {"server", 0, arg_string, &listvol_server,
+ "server to probe", NULL, arg_mandatory},
+ {"partition", 0, arg_string, &listvol_partition,
+ "partition to probe", NULL},
+ {"machine", 'm', arg_flag, &listvol_machine,
+ "machineparseableform", NULL},
+ {"cell", 0, arg_string, &listvol_cell,
+ "what cell to use", NULL},
+ {"noauth", 0, arg_flag, &listvol_noauth,
+ "don't authenticate", NULL},
+ {"localauth", 0, arg_flag, &listvol_localauth,
+ "use local authentication", NULL},
+ {"help", 0, arg_flag, &listvol_help,
+ NULL, NULL},
+ {NULL, 0, arg_end, NULL}
+};
+
+void
+listvol_usage()
+{
+ printf("Usage: %slistvol [-server] servername [[-partition] part ] [[-cell] cell] [-noauth] [-localauth] [-machine] [-help]\n", PROGNAME);
+}
+
+static int
+livol_cmd(int argc, char **argv)
+{
+ int optind = 0;
+ int flags = 0;
+ int part;
+
+ if (getarg (listvol_args, argc, argv, &optind, ARG_AFSSTYLE)) {
+ listvol_usage();
+ return 0;
+ }
+
+ if(listvol_help) {
+ listvol_usage();
+ return 0;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (listvol_server == NULL) {
+ listvol_usage();
+ return 0;
+ }
+
+ if (listvol_partition == NULL) {
+ part = -1;
+ } else {
+ part = volume_name2num(listvol_partition);
+ if (part == -1) {
+ listvol_usage();
+ return 0;
+ }
+ }
+
+ if (listvol_machine)
+ flags |= LISTVOL_PART;
+ if (listvol_noauth)
+ flags |= LISTVOL_NOAUTH;
+ if (listvol_localauth)
+ flags |= LISTVOL_LOCALAUTH;
+
+ printlistvol(listvol_server, part, flags );
+ return 0;
+}
+
+void
+parti_usage()
+{
+ printf("Usage: %spartinfo <server name> [partition name]\n", PROGNAME);
+}
+
+static int
+parti_cmd(int argc, char **argv)
+{
+ char *server;
+ char *partition = NULL;
+
+ /* remove command name */
+ argc--;
+ argv++;
+
+ if (argc < 1) {
+ parti_usage();
+ return 0;
+ }
+
+ /* dinosaur protection */
+ if (strcmp(argv[0], "-server") == 0) {
+ argc--;
+ argv++;
+ }
+
+ server = argv[0];
+
+ argc--;
+ argv++;
+
+ /* sanity check (assumes that argv[argc] == NULL)*/
+ if (server == NULL || server[0] == '-' || server[0] == '\0') {
+ parti_usage();
+ return 0;
+ }
+
+ /* there could be a partition specified */
+ if (argc > 0) {
+ /* dinosaur protection */
+ if (strcmp(argv[0], "-partition") == 0) {
+ argc--;
+ argv++;
+ partition = argv[0];
+ argc--;
+ argv++;
+ } else
+ /* this could be the partition */
+ if (argv[0][0] != '-') {
+ partition = argv[0];
+ argc--;
+ argv++;
+ }
+ }
+
+ printpartinfo(server, partition);
+ return 0;
+}
+
+void
+stat_usage()
+{
+ printf("Usage: %sstatus <server name>\n", PROGNAME);
+}
+
+static int
+stat_cmd(int argc, char **argv)
+{
+ char *server;
+
+ /* remove command name */
+ argc--;
+ argv++;
+
+ if (argc < 1) {
+ stat_usage();
+ return 0;
+ }
+
+ /* dinosaur protection */
+ if (strcmp(argv[0], "-server") == 0) {
+ argc--;
+ argv++;
+ }
+
+ server = argv[0];
+
+ argc--;
+ argv++;
+
+ if (server == NULL || server[0] == '-' || server[0] == '\0') {
+ stat_usage();
+ return 0;
+ }
+
+ printstatus(server);
+ return 0;
+}
+
+static int
+syncsite_cmd (int argc, char **argv)
+{
+ struct in_addr saddr;
+ int error;
+
+ error = arlalib_getsyncsite(NULL, NULL, afsvldbport, &saddr.s_addr, 0);
+ if (error) {
+ fprintf(stderr, "syncsite: %s (%d)\n", koerr_gettext(error), error);
+ return 0;
+ }
+
+ printf("Our vldb syncsite is %s.\n", inet_ntoa(saddr));
+
+ return 0;
+}
+
+static char*
+getvolumetype(int32_t flag)
+{
+ char *str ;
+ if (flag & VLSF_RWVOL)
+ str = "RW";
+ else if (flag & VLSF_ROVOL)
+ str = "RO";
+ else if (flag & VLSF_BACKVOL)
+ str = "BACKUP";
+ else
+ str = "FOO!";
+
+ return str;
+}
+
+static char*
+getvolumetype2(int32_t type)
+{
+ char *str = NULL;
+ switch (type) {
+ case RWVOL:
+ str = "RW";
+ break;
+ case ROVOL:
+ str = "RO";
+ break;
+ case BACKVOL:
+ str = "BK";
+ break;
+ default:
+ str = "FOO!";
+ }
+ return str;
+}
+
+int
+printvolstat(char *volname, const char *cell, const char *host, int noauth)
+{
+ struct rx_connection *connvolser = NULL;
+ struct rx_connection *connvldb = NULL;
+ int error;
+ int i;
+ char *servername;
+ char timestr[30];
+ volEntries volint ;
+ vldbentry vlentry;
+
+ if (cell == NULL && host != NULL)
+ cell = cell_getcellbyhost(host);
+ if (cell == NULL)
+ cell = cell_getthiscell();
+ if (host == NULL)
+ host = cell_findnamedbbyname (cell);
+
+
+ connvldb = arlalib_getconnbyname(host,
+ afsvldbport,
+ VLDB_SERVICE_ID,
+ noauth);
+ if (connvldb == NULL)
+ return -1;
+
+
+ error = VL_GetEntryByName(connvldb, volname, &vlentry);
+ if (error) {
+ fprintf(stderr, "VLDB: no such entry\n");
+ return -1;
+ }
+
+ connvolser = arlalib_getconnbyaddr(htonl(vlentry.serverNumber[0]),
+ NULL,
+ afsvolport,
+ VOLSERVICE_ID,
+ noauth);
+ if (connvolser == NULL)
+ return -1 ;
+
+ volint.val = NULL;
+ if ((error = VOLSER_AFSVolListOneVolume(connvolser,
+ vlentry.serverPartition[0],
+ vlentry.volumeId[0],
+ &volint)) != 0) {
+ printf("ListOneVolume failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return -1;
+ }
+
+ printf("%s\t\t\t%10u %s %8d K %s\n",
+ vlentry.name,
+ vlentry.volumeId[0],
+ getvolumetype(vlentry.serverFlags[0]),
+ volint.val->size,
+ volint.val->status == VOK ? "On-line" : "Busy");
+
+ if (volint.val->status == VOK) {
+
+ arlalib_getservername(htonl(vlentry.serverNumber[0]), &servername);
+ printf(" %s /vicep%c\n", servername,
+ 'a' + vlentry.serverPartition[0]);
+ printf(" ");
+ free(servername);
+
+ if (vlentry.flags & VLF_RWEXISTS)
+ printf("RWrite %u\t", vlentry.volumeId[RWVOL]);
+
+ if (vlentry.flags & VLF_ROEXISTS )
+ printf("ROnly %u\t", vlentry.volumeId[ROVOL]);
+
+ if (vlentry.flags & VLF_BACKEXISTS)
+ printf("Backup %u\t", vlentry.volumeId[BACKVOL]);
+
+ printf("\n MaxQuota %10d K\n", volint.val->maxquota);
+
+ /* Get and format date */
+ strncpy(timestr,
+ ctime( (time_t*) &volint.val->creationDate),
+ sizeof(timestr));
+ timestr[strlen(timestr)-1] = '\0';
+ printf(" Creation %s\n", timestr);
+
+ /* Get and format date */
+ strncpy(timestr,
+ ctime((time_t *) &volint.val->updateDate),
+ sizeof(timestr));
+ timestr[strlen(timestr)-1] = '\0';
+ printf(" Last Update %s\n", timestr);
+
+ printf(" %d accesses in the past day (i.e., vnode references)\n\n",
+ volint.val->dayUse);
+
+ }
+
+ /* Print volume stats */
+ printf(" ");
+ printf("RWrite: %u\t", vlentry.flags & VLF_RWEXISTS ? vlentry.volumeId[RWVOL] : 0);
+ printf("ROnly: %u\t", vlentry.flags & VLF_ROEXISTS ? vlentry.volumeId[ROVOL] : 0);
+ printf("Backup: %u\t", vlentry.flags & VLF_BACKEXISTS ? vlentry.volumeId[BACKVOL] : 0);
+
+ printf("\n number of sites -> %d\n", vlentry.nServers );
+
+ for ( i = 0 ; i < vlentry.nServers ; i++) {
+ printf(" ");
+
+ if (vlentry.serverNumber[i] != 0)
+ arlalib_getservername(htonl(vlentry.serverNumber[i]), &servername);
+ else
+ servername = strdup("error");
+
+ printf("server %s partition /vicep%c %s Site\n",
+ servername,
+ 'a' + vlentry.serverPartition[i],
+ getvolumetype(vlentry.serverFlags[i]));
+ free(servername);
+
+ }
+
+ free(volint.val);
+ arlalib_destroyconn(connvolser);
+ arlalib_destroyconn(connvldb);
+ return 0;
+}
+
+
+int
+getlistparts(char *host, struct pIDs *partIDs)
+{
+ struct rx_connection *connvolser = NULL;
+ int error ;
+
+ connvolser = arlalib_getconnbyname(host,
+ afsvolport,
+ VOLSERVICE_ID,
+ 0); /* XXX this means try auth */
+ if (connvolser == NULL)
+ return -1 ;
+
+ if ((error = VOLSER_AFSVolListPartitions(connvolser,
+ partIDs)) != 0) {
+ printf("getlistparts: ListPartitions failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return -1;
+ }
+
+ arlalib_destroyconn(connvolser);
+ return 0;
+}
+
+int
+printlistparts(char *host)
+{
+ struct pIDs partIDs;
+ int i,j ;
+
+ if ((i = getlistparts(host, &partIDs)) != 0)
+ return i;
+
+ j = 0 ;
+
+ printf("The partitions on the server are:\n ");
+ for (i = 0 ; i < 26 ; i++) {
+ if (partIDs.partIds[i] != -1) {
+ j++;
+ printf(" /vicep%c%c", i + 'a', j % 6 == 0 ? '\n':' ');
+ }
+ }
+
+ printf("\nTotal: %d\n", j);
+ return 0;
+}
+
+
+int
+printlistvol(char *host, int part, int flags)
+{
+ struct rx_connection *connvolser = NULL;
+ volEntries volint ;
+ struct pIDs partIDs;
+ volintInfo *vi;
+ int32_t partnum = 0;
+ int32_t vol;
+ int online, busy, offline;
+ int error ;
+
+ connvolser = arlalib_getconnbyname(host,
+ afsvolport,
+ VOLSERVICE_ID,
+ flags & LISTVOL_NOAUTH);
+ if (connvolser == NULL)
+ return -1 ;
+
+ if (part == -1) {
+ if ((error = getlistparts(host, &partIDs)) != 0)
+ return -1;
+ } else {
+ for (partnum = 0 ; partnum < 26 ; partnum++)
+ partIDs.partIds[partnum] = -1 ;
+ partIDs.partIds[0] = part ;
+ }
+
+ partnum = 0;
+ while(1) {
+ while(partIDs.partIds[partnum] == -1 && partnum < 26 ) partnum++;
+ if (partnum >= 26)
+ break;
+
+ volint.val = NULL;
+ if ((error = VOLSER_AFSVolListVolumes(connvolser,
+ partIDs.partIds[partnum],
+ 1, /* We want full info */
+ &volint)) != 0) {
+ printf("printlistvol: PartitionInfo failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return -1;
+ }
+ online = busy = offline = 0;
+
+ printf("Total number of volumes on server %s partition /vicep%c: %d\n",
+ host,
+ partIDs.partIds[partnum] + 'a',
+ volint.len);
+
+ for (vol = 0 ; vol < volint.len ; vol ++) {
+ vi = &volint.val[vol];
+
+ if (vi->status == VBUSY)
+ busy++;
+ else if (vi->inUse)
+ online++;
+ else
+ offline++;
+
+ if(vi->status == VOK) {
+ printf("%-38s %10u %s %10u K %s %s%c\n",
+ vi->name,
+ vi->volid,
+ getvolumetype2(vi->type),
+ vi->size,
+ vi->inUse ? "On-line" : "Off-line",
+ flags&LISTVOL_PART?"/vicep":"",
+ flags&LISTVOL_PART?partIDs.partIds[partnum] + 'a':' ');
+
+ }
+ }
+
+ for (vol = 0 ; vol < volint.len ; vol ++) {
+ vi = &volint.val[vol];
+
+ if(vi->status == VBUSY)
+ printf("Volume with id number %u is currently busy\n",
+ vi->volid);
+ }
+
+ printf("\nTotal volumes onLine %d ; Total volumes offLine %d " \
+ "; Total busy %d\n\n",
+ online, offline, busy);
+
+ free(volint.val);
+ partnum++;
+ }
+
+ arlalib_destroyconn(connvolser);
+ return 0;
+}
+
+int
+printpartinfo(char *host, char *part)
+{
+ struct rx_connection *connvolser = NULL;
+ struct diskPartition partinfo ;
+ struct pIDs partIDs;
+ int iter = 0;
+ int partnum = 0;
+ char name[30];
+ int error ;
+
+ connvolser = arlalib_getconnbyname(host,
+ afsvolport,
+ VOLSERVICE_ID,
+ 0); /* XXX This means try auth */
+ if (connvolser == NULL)
+ return -1 ;
+
+ if (part == NULL) {
+ iter = 1;
+ if ((error = getlistparts(host, &partIDs)) != 0)
+ return error;
+ } else {
+ if (strlen(part) <= 2) {
+ snprintf(name, sizeof(name), "/vicep%s", part);
+ part = name;
+ }
+ }
+
+ while(part != NULL || iter) {
+
+ if (iter) {
+ while(partIDs.partIds[partnum] == -1 && partnum < 26 ) partnum++;
+ if (partnum < 26) {
+ snprintf(name, sizeof(name), "/vicep%c", 'a' + partnum);
+ part = name;
+ partnum++;
+ } else {
+ iter = 0 ;
+ continue;
+ }
+ }
+
+ if ((error = VOLSER_AFSVolPartitionInfo(connvolser,
+ part,
+ &partinfo)) != 0) {
+ printf("printpartinfo: PartitionInfo failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return -1;
+ }
+ printf("Free space on partition %s %d K blocks out of total %d\n",
+ partinfo.name,
+ partinfo.free,
+ partinfo.minFree
+/* XXX - partinfo.totalUsable */
+ );
+ part = NULL;
+ }
+
+ arlalib_destroyconn(connvolser);
+ return 0;
+}
+
+int
+printstatus(char *host)
+{
+ struct rx_connection *connvolser = NULL;
+ struct transDebugInfo *entries;
+ transDebugEntries info;
+ unsigned int entries_len, i;
+ int error;
+
+ connvolser = arlalib_getconnbyname(host,
+ afsvolport,
+ VOLSERVICE_ID,
+ 0);
+
+ if (connvolser == NULL)
+ return -1;
+
+ if ((error = VOLSER_AFSVolMonitor(connvolser,
+ &info)) != 0) {
+ printf("printstatus: GetStat failed with: %s (%d)\n",
+ koerr_gettext(error),
+ error);
+ return -1;
+ }
+
+ entries_len = info.len;
+ entries = info.val;
+
+ if (entries_len == 0)
+ printf ("No active transactions on %s\n", host);
+ else {
+ for (i = 0; i < entries_len; i--) {
+ printf("--------------------------------------\n");
+ printf("transaction: %d created: %s", entries->tid, ctime((time_t *) &entries->creationTime));
+ printf("attachFlags: ");
+
+ if ((entries->iflags & ITOffline) == ITOffline)
+ printf(" offline");
+ if ((entries->iflags & ITBusy) == ITBusy)
+ printf(" busy");
+ if ((entries->iflags & ITReadOnly) == ITReadOnly)
+ printf("read-only");
+ if ((entries->iflags & ITCreate) == ITCreate)
+ printf("create");
+ if ((entries->iflags & ITCreateVolID) == ITCreateVolID)
+ printf("create-VolID");
+
+ printf("\nvolume: %d partition: <insert partition name here> procedure: %s\n", entries->volid, entries->lastProcName);
+ printf("packetRead: %d lastReceiveTime: %d packetSend: %d lastSendTime: %d\n", entries->readNext, entries->lastReceiveTime, entries->transmitNext, entries->lastSendTime);
+ entries++;
+ }
+ printf("--------------------------------------\n");
+ }
+
+ arlalib_destroyconn(connvolser);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ cell_init(0);
+ initports();
+
+ if (argc > 1)
+ ret = sl_command(cmds, argc - 1, argv + 1);
+ else {
+ vos_interactive = 1;
+ printf("vos - an arla tool for administrating AFS volumes.\n");
+ printf("Type \"help\" to get a list of commands.\n");
+ ret = sl_loop(cmds, __progname": ");
+ }
+ return ret;
+}
diff --git a/usr.sbin/afs/src/appl/vos_local.h b/usr.sbin/afs/src/appl/vos_local.h
new file mode 100644
index 00000000000..9732153919a
--- /dev/null
+++ b/usr.sbin/afs/src/appl/vos_local.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: vos_local.h,v 1.1.1.1 1998/09/14 21:52:53 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * RCSID("$KTH: vos_local.h,v 1.1 1998/04/06 18:41:09 mikeee Exp $");
+ */
+
+/* Iflags returned by AFSVolMonitor */
+
+#define ITOffline 0x1
+#define ITBusy 0x2
+#define ITReadOnly 0x8
+#define ITCreate 0x10
+#define ITCreateVolID 0x1000
+
+/* this program needs __progname defined as a macro */
+#define __progname "vos"
+#define PROGNAME (vos_interactive ? "" : __progname" ")
+
+/* if this is set the program runs in interactive mode */
+static int vos_interactive = 0;
diff --git a/usr.sbin/afs/src/arlad/adir.c b/usr.sbin/afs/src/arlad/adir.c
new file mode 100644
index 00000000000..48c4b439626
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/adir.c
@@ -0,0 +1,635 @@
+/* $OpenBSD: adir.c,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Routines for reading an AFS directory
+ */
+
+#include "arla_local.h"
+
+RCSID("$KTH: adir.c,v 1.33 1998/07/29 14:38:51 assar Exp $") ;
+
+/*
+ * Hash the filename of one entry.
+ */
+
+static unsigned
+hashentry (const char *entry)
+{
+ int s = 0, h;
+
+ while (*entry)
+ s = s * 173 + *entry++;
+ h = s & (ADIRHASHSIZE - 1);
+ if (h == 0)
+ return h;
+ else if( s < 0 )
+ h = ADIRHASHSIZE - h;
+ return h;
+}
+
+/*
+ * Return the entry in the directory given the number.
+ * The directory must be contiounsly in memory after page0.
+ */
+
+static DirEntry *
+getentry (DirPage0 *page0,
+ unsigned short num)
+{
+ DirPage1 *page;
+
+ page = (DirPage1 *)((char *)page0 +
+ AFSDIR_PAGESIZE * (num / ENTRIESPERPAGE));
+ assert (page->header.pg_tag == htons(AFSDIRMAGIC));
+ return &page->entry[num % ENTRIESPERPAGE];
+}
+
+/*
+ *
+ */
+
+static unsigned
+find_by_name (DirPage0 *page0,
+ const char *name,
+ VenusFid *fid,
+ const VenusFid *dir)
+{
+ unsigned i;
+
+ i = ntohs(page0->dheader.hash[hashentry (name)]);
+ while (i != 0) {
+ const DirEntry *entry = getentry (page0, i - 1);
+
+ if (strcmp (entry->name, name) == 0) {
+ fid->Cell = dir->Cell;
+ fid->fid.Volume = dir->fid.Volume;
+ fid->fid.Vnode = ntohl (entry->fid.Vnode);
+ fid->fid.Unique = ntohl (entry->fid.Unique);
+ return i;
+ }
+ i = ntohs(entry->next);
+ }
+ return i;
+}
+
+
+/*
+ * Lookup `name' in the AFS directory identified by `dir' and return
+ * the Fid in `file'. All operations are done as `cred' and return
+ * value is 0 or error code.
+ */
+
+int
+adir_lookup (VenusFid dir,
+ const char *name,
+ VenusFid *file,
+ CredCacheEntry *ce)
+{
+ int fd;
+ DirPage0 *page0;
+ FCacheEntry *centry;
+ unsigned ind;
+ unsigned len;
+ int ret;
+ fbuf the_fbuf;
+ struct stat sb;
+
+ ret = fcache_get (&centry, dir, ce);
+ if (ret) {
+ ReleaseWriteLock (&centry->lock);
+ return ret;
+ }
+
+ ret = fcache_get_data (centry, ce);
+ if (ret) {
+ ReleaseWriteLock (&centry->lock);
+ return ret;
+ }
+
+ if (centry->status.FileType != TYPE_DIR) {
+ ReleaseWriteLock (&centry->lock);
+ return ENOTDIR;
+ }
+
+#if 0
+ len = centry->status.Length;
+#endif
+
+ fd = fcache_open_file (centry, O_RDONLY, 0);
+ if (fd < 0) {
+ ReleaseWriteLock (&centry->lock);
+ return errno;
+ }
+
+ if (fstat (fd, &sb)) {
+ close (fd);
+ ReleaseWriteLock (&centry->lock);
+ return errno;
+ }
+
+ len = sb.st_size;
+
+ ret = fbuf_create (&the_fbuf, fd, len, FBUF_READ);
+ if (ret) {
+ close (fd);
+ ReleaseWriteLock (&centry->lock);
+ return ret;
+ }
+
+ page0 = (DirPage0 *)(the_fbuf.buf);
+ ind = find_by_name (page0, name, file, &dir);
+
+ fbuf_end (&the_fbuf);
+ ReleaseWriteLock (&centry->lock);
+ if (ind != 0)
+ return 0;
+ else
+ return ENOENT;
+}
+
+/*
+ * Read all entries in the AFS directory identified by `dir' and call
+ * `func' on each entry with the fid, the name, and `arg'.
+ */
+
+int
+adir_readdir (VenusFid dir,
+ void (*func)(VenusFid *, const char *, void *),
+ void *arg,
+ CredCacheEntry *ce)
+{
+ int fd;
+ fbuf the_fbuf;
+ DirPage0 *page0;
+ unsigned i;
+ FCacheEntry *centry;
+ int ret;
+ unsigned ind, dotind, dotdotind;
+ VenusFid fid;
+ unsigned len;
+ struct stat sb;
+
+ ret = fcache_get (&centry, dir, ce);
+ if (ret)
+ return ret;
+
+ ret = fcache_get_data (centry, ce);
+ if (ret) {
+ ReleaseWriteLock (&centry->lock);
+ return ret;
+ }
+
+ if (centry->status.FileType != TYPE_DIR) {
+ ReleaseWriteLock (&centry->lock);
+ return ENOTDIR;
+ }
+
+ fd = fcache_open_file (centry, O_RDONLY, 0);
+ if (fd < 0) {
+ ReleaseWriteLock (&centry->lock);
+ return errno;
+ }
+
+ if (fstat (fd, &sb)) {
+ ReleaseWriteLock (&centry->lock);
+ close (fd);
+ return errno;
+ }
+
+ len = sb.st_size;
+
+ ret = fbuf_create (&the_fbuf, fd, len, FBUF_READ);
+ if (ret) {
+ ReleaseWriteLock (&centry->lock);
+ close (fd);
+ return ret;
+ }
+ page0 = (DirPage0 *)(the_fbuf.buf);
+
+ /*
+ * Begin with placing `.' and `..' first. (some system seem to need that)
+ */
+
+ dotind = find_by_name (page0, ".", &fid, &dir);
+ assert (dotind != 0);
+ (*func)(&fid, ".", arg);
+
+ dotdotind = find_by_name (page0, "..", &fid, &dir);
+ assert (dotind != 0);
+ (*func)(&fid, "..", arg);
+
+ for (i = 0; i < ADIRHASHSIZE; ++i) {
+ const DirEntry *entry;
+
+ for(ind = ntohs(page0->dheader.hash[i]);
+ ind;
+ ind = ntohs(entry->next)) {
+
+ entry = getentry (page0, ind - 1);
+
+ fid.Cell = dir.Cell;
+ fid.fid.Volume = dir.fid.Volume;
+ fid.fid.Vnode = ntohl (entry->fid.Vnode);
+ fid.fid.Unique = ntohl (entry->fid.Unique);
+ if (ind != dotind && ind != dotdotind) /* already did them */
+ (*func)(&fid, entry->name, arg);
+ }
+ }
+ fbuf_end (&the_fbuf);
+ ReleaseWriteLock (&centry->lock);
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+used_slot (DirPage1 *page, int off)
+{
+ return page->header.pg_bitmap[off / 8] & (1 << (off % 8));
+}
+
+/*
+ *
+ */
+
+static void
+set_used (DirPage1 *page, int off)
+{
+ page->header.pg_bitmap[off / 8] |= 1 << (off % 8);
+}
+
+/*
+ * Add a new page to a directory.
+ */
+
+static int
+create_new_page (DirPage1 **ret_page,
+ fbuf *the_fbuf)
+{
+ int ret;
+ DirPage1 *page1;
+ size_t len = the_fbuf->len;
+
+ ret = fbuf_truncate (the_fbuf, len + AFSDIR_PAGESIZE);
+ if (ret)
+ return ret;
+
+ page1 = (DirPage1 *)((char *)(the_fbuf->buf) + len);
+ page1->header.pg_pgcount = htons(0);
+ page1->header.pg_tag = htons(AFSDIRMAGIC);
+ page1->header.pg_freecount = ENTRIESPERPAGE - 1;
+ memset (page1->header.pg_bitmap, 0, sizeof(page1->header.pg_bitmap));
+ set_used (page1, 0);
+ *ret_page = page1;
+
+ return 0;
+}
+
+/*
+ * return index into `page'
+ */
+
+static int
+add_to_page (DirPage0 *page0,
+ DirPage1 *page,
+ unsigned pageno,
+ const char *filename,
+ AFSFid fid,
+ unsigned next)
+{
+ int len = strlen (filename);
+ int i, j;
+ unsigned n = 1;
+
+ for (len = strlen(filename), n = 1;
+ len > 15;
+ len -= sizeof(DirEntry), ++n)
+ ;
+
+ if (page0->dheader.map[pageno] < n)
+ return -1;
+
+ for (i = 0; i < ENTRIESPERPAGE - n;) {
+ for (j = 0; j < n && !used_slot (page, i + j + 1); ++j)
+ ;
+ if (j == n) {
+ int k;
+
+ for (k = i + 1; k < i + j + 1; ++k)
+ page->header.pg_bitmap[k / 8] |= (1 << (k % 8));
+
+ page->entry[i].flag = 0;
+ page->entry[i].length = 0;
+ page->entry[i].next = next;
+ page->entry[i].fid.Vnode = htonl(fid.Vnode);
+ page->entry[i].fid.Unique = htonl(fid.Unique);
+ strcpy (page->entry[i].name, filename);
+ memset(page->entry[i + j - 1].fill, 0, 4);
+ page0->dheader.map[pageno] -= n;
+ return i;
+ }
+ i += j + 1;
+ }
+ return -1;
+}
+
+/*
+ *
+ */
+
+static int
+remove_from_page (DirPage0 *page0,
+ DirPage1 *page,
+ unsigned pageno,
+ unsigned off)
+{
+ DirEntry *entry = &page->entry[off];
+ int len;
+ unsigned n = 1, i;
+
+ for (len = strlen(entry->name), n = 1;
+ len > 15;
+ len -= sizeof(DirEntry), ++n)
+ ;
+
+ page0->dheader.map[pageno] += n;
+
+ entry->next = 0;
+ entry->fid.Vnode = 0;
+ entry->fid.Unique = 0;
+
+ for (i = off + 1; i < off + n + 1; ++i)
+ page->header.pg_bitmap[i / 8] &= ~(1 << (i % 8));
+ return 0;
+}
+
+/*
+ * Create a new directory with only . and ..
+ */
+
+int
+adir_mkdir (FCacheEntry *dir,
+ AFSFid dot,
+ AFSFid dot_dot)
+{
+ fbuf the_fbuf;
+ int ret;
+ int fd;
+ DirPage0 *page0;
+ DirPage1 *page;
+ int ind;
+ int i;
+ int tmp;
+
+ assert (CheckLock(&dir->lock) == -1);
+
+ fd = fcache_open_file (dir, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ return errno;
+
+ ret = fbuf_create (&the_fbuf, fd, 0, FBUF_WRITE);
+ if (ret)
+ return ret;
+
+ ret = create_new_page (&page, &the_fbuf);
+ if (ret)
+ goto out;
+
+ page0 = (DirPage0 *)(the_fbuf.buf);
+ memset (&page0->dheader, 0, sizeof(page0->dheader));
+ tmp = ENTRIESPERPAGE
+ - (sizeof(PageHeader) + sizeof(DirHeader)) / sizeof(DirEntry);
+ page0->header.pg_freecount = tmp;
+ page0->dheader.map[0] = tmp;
+ page0->header.pg_pgcount = htons(1);
+
+ for (i = 0; i < 13; ++i)
+ set_used (page, i);
+
+ assert (page0->dheader.hash[hashentry(".")] == 0);
+
+ ind = add_to_page (page0, page, 0, ".", dot, 0);
+
+ assert (ind >= 0);
+
+ page0->dheader.hash[hashentry(".")] = htons(ind + 1);
+
+ assert (page0->dheader.hash[hashentry("..")] == 0);
+
+ ind = add_to_page (page0, page, 0, "..", dot_dot, 0);
+
+ assert (ind >= 0);
+
+ page0->dheader.hash[hashentry("..")] = htons(ind + 1);
+
+out:
+ assert (dir->status.Length == the_fbuf.len);
+ fbuf_end (&the_fbuf);
+ return ret;
+}
+
+/*
+ * Create a new entry with name `filename' and contents `fid' in `dir.
+ */
+
+int
+adir_creat (FCacheEntry *dir,
+ const char *name,
+ AFSFid fid)
+{
+ fbuf the_fbuf;
+ int ret;
+ int fd;
+ int i;
+ size_t len;
+ unsigned npages;
+ DirPage0 *page0;
+ DirPage1 *page;
+ int ind = 0;
+ unsigned hash_value, next;
+ struct stat statbuf;
+
+ assert (CheckLock(&dir->lock) == -1);
+
+ assert (dir->flags.datap);
+
+ fd = fcache_open_file (dir, O_RDWR, 0);
+ if (fd < 0)
+ return errno;
+
+ if(fstat (fd, &statbuf) < 0) {
+ close (fd);
+ return errno;
+ }
+
+ len = statbuf.st_size;
+
+ ret = fbuf_create (&the_fbuf, fd, len, FBUF_WRITE);
+ if (ret)
+ return ret;
+
+ page0 = (DirPage0 *)(the_fbuf.buf);
+ npages = ntohs(page0->header.pg_pgcount);
+
+ assert (npages == the_fbuf.len / AFSDIR_PAGESIZE);
+
+ hash_value = hashentry (name);
+ next = page0->dheader.hash[hash_value];
+
+ for (i = 0; i < npages; ++i)
+ if (page0->dheader.map[i]) {
+ page = (DirPage1 *)((char *)page0 + i * AFSDIR_PAGESIZE);
+ ind = add_to_page (page0, page, i, name, fid, next);
+ if (ind >= 0)
+ break;
+ }
+ if (i == npages) {
+ ret = create_new_page (&page, &the_fbuf);
+ if (ret)
+ goto out;
+ page0 = (DirPage0 *)(the_fbuf.buf);
+ page0->header.pg_pgcount = htons(npages + 1);
+ page0->dheader.map[i] = ENTRIESPERPAGE - 1;
+ ind = add_to_page (page0, page, i, name, fid, next);
+ assert (ind >= 0);
+ }
+ ind += i * ENTRIESPERPAGE;
+
+ page0->dheader.hash[hash_value] = htons(ind + 1);
+
+out:
+ /* assert (dir->status.Length == the_fbuf.len); */
+ fbuf_end (&the_fbuf);
+ return ret;
+}
+
+/*
+ * Remove the entry named `name' in dir.
+ */
+
+int
+adir_remove (FCacheEntry *dir,
+ const char *name)
+{
+ fbuf the_fbuf;
+ int ret;
+ int fd;
+ int i;
+ unsigned len;
+ DirPage0 *page0;
+ DirPage1 *page;
+ unsigned hash_value;
+ DirEntry *entry = NULL;
+ DirEntry *prev_entry;
+ unsigned pageno;
+ int found;
+ struct stat sb;
+ unsigned npages;
+
+ assert (CheckLock(&dir->lock) == -1);
+
+ assert (dir->flags.datap);
+
+ fd = fcache_open_file (dir, O_RDWR, 0);
+ if (fd < 0)
+ return errno;
+
+#if 0
+ len = dir->status.Length;
+#endif
+ if (fstat (fd, &sb)) {
+ close (fd);
+ return errno;
+ }
+
+ len = sb.st_size;
+
+ ret = fbuf_create (&the_fbuf, fd, len, FBUF_WRITE);
+ if (ret) {
+ close (fd);
+ return ret;
+ }
+
+ page0 = (DirPage0 *)(the_fbuf.buf);
+ npages = ntohs(page0->header.pg_pgcount);
+ hash_value = hashentry (name);
+ i = ntohs(page0->dheader.hash[hash_value]);
+ found = i == 0;
+ prev_entry = NULL;
+ while (!found) {
+ entry = getentry (page0, i - 1);
+
+ if (strcmp (entry->name, name) == 0) {
+ found = TRUE;
+ } else {
+ i = ntohs(entry->next);
+ if (i == 0)
+ found = TRUE;
+ prev_entry = entry;
+ }
+ }
+ if (i == 0) {
+ fbuf_end (&the_fbuf);
+ return ENOENT;
+ } else {
+ if (prev_entry == NULL)
+ page0->dheader.hash[hash_value] = entry->next;
+ else
+ prev_entry->next = entry->next;
+
+ pageno = (i - 1) / ENTRIESPERPAGE;
+ page = (DirPage1 *)((char *)page0 + pageno * AFSDIR_PAGESIZE);
+ remove_from_page (page0, page, pageno, (i - 1) % ENTRIESPERPAGE);
+ if (pageno == npages - 1
+ && page0->dheader.map[pageno] == ENTRIESPERPAGE - 1) {
+ do {
+ len -= AFSDIR_PAGESIZE;
+ --pageno;
+ --npages;
+ } while(page0->dheader.map[pageno] == ENTRIESPERPAGE - 1);
+ page0->header.pg_pgcount = htons(npages);
+ fbuf_truncate (&the_fbuf, len);
+ }
+ fbuf_end (&the_fbuf);
+ return 0;
+ }
+}
diff --git a/usr.sbin/afs/src/arlad/adir.h b/usr.sbin/afs/src/arlad/adir.h
new file mode 100644
index 00000000000..bb4e7b3751e
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/adir.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: adir.h,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Interface to directory handling routines
+ */
+
+/* $KTH: adir.h,v 1.8 1998/03/18 14:14:17 assar Exp $ */
+
+#ifndef _ADIR_H_
+#define _ADIR_H_
+
+#include "fs.h"
+#include "cred.h"
+#include "fcache.h"
+
+int adir_lookup (VenusFid dir, const char *name, VenusFid *file,
+ CredCacheEntry *ce);
+
+int adir_readdir (VenusFid dir,
+ void (*)(VenusFid *, const char *name, void *),
+ void *arg,
+ CredCacheEntry *ce);
+
+int
+adir_creat (FCacheEntry *dir,
+ const char *filename,
+ AFSFid fid);
+
+int
+adir_remove (FCacheEntry *dir,
+ const char *name);
+
+int
+adir_mkdir (FCacheEntry *dir,
+ AFSFid dot,
+ AFSFid dot_dot);
+
+#endif /* _ADIR_H_ */
diff --git a/usr.sbin/afs/src/arlad/afs_dir.h b/usr.sbin/afs/src/arlad/afs_dir.h
new file mode 100644
index 00000000000..8ba3b201fbd
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/afs_dir.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: afs_dir.h,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 directory structure used by AFS.
+ */
+
+/* $KTH: afs_dir.h,v 1.4 1998/02/21 17:19:59 assar Exp $ */
+
+#ifndef _AFS_DIR_
+#define _AFS_DIR_
+
+#define AFSDIR_PAGESIZE 2048
+#define ADIRHASHSIZE 128
+#define ENTRIESPERPAGE 64
+
+#define MAXPAGES 128
+
+/* Is this really so? */
+
+/*
+ * We only save vnode and unique in the directory. Everything else is
+ * the same as in the parent directory.
+ */
+
+typedef struct {
+ u_int32_t Vnode;
+ u_int32_t Unique;
+} DirFid;
+
+typedef struct {
+ union {
+ struct {
+ u_int16_t pgcount;
+ u_int16_t tag; /* Should be 1234 in net-order */
+ u_int8_t freecount;
+ u_int8_t bitmap[ENTRIESPERPAGE / 8];
+ } s;
+ u_int8_t pad[32];
+ } u;
+} PageHeader;
+
+#define AFSDIRMAGIC 1234
+
+#define pg_tag u.s.tag
+#define pg_freecount u.s.freecount
+#define pg_pgcount u.s.pgcount
+#define pg_bitmap u.s.bitmap
+
+typedef struct {
+ u_int8_t map[MAXPAGES];
+ u_int16_t hash[ADIRHASHSIZE];
+} DirHeader;
+
+typedef struct {
+ u_int8_t flag;
+ u_int8_t length;
+ u_int16_t next;
+ DirFid fid;
+ char name[16]; /* If name overflows into fill, then we */
+ char fill[4]; /* should use next entry too. */
+} DirEntry;
+
+typedef struct {
+ PageHeader header;
+ DirHeader dheader;
+ DirEntry entry[1];
+} DirPage0;
+
+typedef struct {
+ PageHeader header;
+ DirEntry entry[1];
+} DirPage1;
+
+#endif /* _AFS_DIR_ */
diff --git a/usr.sbin/afs/src/arlad/afsdir_check.c b/usr.sbin/afs/src/arlad/afsdir_check.c
new file mode 100644
index 00000000000..2d37ce641b6
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/afsdir_check.c
@@ -0,0 +1,281 @@
+/* $OpenBSD: afsdir_check.c,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Check a directory in afs format.
+ */
+
+#include "arla_local.h"
+
+RCSID("$KTH: afsdir_check.c,v 1.7 1998/04/05 03:33:09 assar Exp $");
+
+/*
+ * Hash the filename of one entry.
+ */
+
+static unsigned
+hashentry (const char *entry)
+{
+ int s = 0, h;
+
+ while (*entry)
+ s = s * 173 + *entry++;
+ h = s & (ADIRHASHSIZE - 1);
+ if (h == 0)
+ return h;
+ else if( s < 0 )
+ h = ADIRHASHSIZE - h;
+ return h;
+}
+
+/*
+ * Return the entry in the directory given the number.
+ * The directory must be contiounsly in memory after page0.
+ */
+
+static const DirEntry *
+getentry (DirPage0 *page0,
+ unsigned short num)
+{
+ DirPage1 *page;
+
+ page = (DirPage1 *)((char *)page0 +
+ AFSDIR_PAGESIZE * (num / ENTRIESPERPAGE));
+ assert (page->header.pg_tag == htons(AFSDIRMAGIC));
+ return &page->entry[num % ENTRIESPERPAGE];
+}
+
+int
+check (const char *filename)
+{
+ struct stat statbuf;
+ int fd;
+ fbuf the_fbuf;
+ DirPage0 *page0;
+ unsigned i, j;
+ unsigned ind;
+ unsigned len;
+ int ret = 0;
+ unsigned npages;
+ unsigned page_entry_count;
+ unsigned hash_entry_count;
+ unsigned noverfill;
+ u_int8_t my_bitmaps[MAXPAGES][ENTRIESPERPAGE / 8];
+
+ fd = open (filename, O_RDONLY | O_BINARY, 0);
+ if (fd < 0)
+ err (1, "open %s", filename);
+
+ if (fstat (fd, &statbuf) < 0)
+ err (1, "stat %s", filename);
+
+ len = statbuf.st_size;
+
+ ret = fbuf_create (&the_fbuf, fd, len, FBUF_READ);
+ if (ret)
+ return ret;
+
+ page0 = (DirPage0 *)(the_fbuf.buf);
+
+ printf ("size = %u, pages = %u, pgcount = %u\n",
+ len, len / AFSDIR_PAGESIZE,
+ ntohs(page0->header.pg_pgcount));
+
+ if (len / AFSDIR_PAGESIZE != ntohs(page0->header.pg_pgcount)) {
+ ret = 1;
+ goto out;
+ }
+
+ npages = len / AFSDIR_PAGESIZE;
+
+ printf ("map: ");
+ for (i = 0; i < npages; ++i) {
+ printf ("%u ", page0->dheader.map[i]);
+ }
+ printf ("\n");
+
+ page_entry_count = 0;
+
+ for (i = 0; i < npages; ++i) {
+ PageHeader *ph = (PageHeader *)((char *)page0 + i * AFSDIR_PAGESIZE);
+ int start;
+
+ if (ph->pg_tag != htons(AFSDIRMAGIC)) {
+ printf ("page %d: wrong tag: %u\n", i, htons(ph->pg_tag));
+ ret = 1;
+ goto out;
+ }
+ printf ("page %d: count = %u, tag = %u, freecount = %u\n",
+ i, ntohs(ph->pg_pgcount), htons(ph->pg_tag), ph->pg_freecount);
+ if (i == 0) {
+ if (ph->pg_freecount != 51) {
+ printf ("freecount should be 51!\n");
+ ret = 1;
+ goto out;
+ }
+ if (ntohs(ph->pg_pgcount) != npages) {
+ printf ("pgcount should be %u!\n", npages);
+ ret = 1;
+ goto out;
+ }
+ } else {
+ if (ph->pg_freecount != 63) {
+ printf ("freecount should be 63!\n");
+ ret = 1;
+ goto out;
+ }
+ if (ntohs(ph->pg_pgcount) != 0) {
+ printf ("pgcount should be 0!\n");
+ ret = 1;
+ goto out;
+ }
+ }
+
+ if (i == 0)
+ start = 13;
+ else
+ start = 1;
+
+ for (j = start; j < ENTRIESPERPAGE; ++j) {
+ if (ph->pg_bitmap[j / 8] & (1 << (j % 8)))
+ ++page_entry_count;
+ }
+ }
+
+ printf ("page entry count = %u\n", page_entry_count);
+
+ hash_entry_count = 0;
+ noverfill = 0;
+
+ memset (my_bitmaps, 0, sizeof(my_bitmaps));
+
+ for (i = 0; i < ADIRHASHSIZE; ++i) {
+ const DirEntry *entry;
+
+ for(ind = ntohs(page0->dheader.hash[i]);
+ ind;
+ ind = ntohs(entry->next)) {
+ DirPage1 *page_n;
+ int len;
+ unsigned off;
+ unsigned pageno;
+
+ entry = getentry (page0, ind - 1);
+
+ if (hashentry (entry->name) != i)
+ printf ("wrong name here? hash = %u, name = *%s*\n",
+ i, entry->name);
+
+ pageno = (ind) / ENTRIESPERPAGE;
+ off = (ind) % ENTRIESPERPAGE;
+
+ page_n = (DirPage1 *)((char *)page0
+ + AFSDIR_PAGESIZE * pageno);
+
+ if (!(page_n->header.pg_bitmap[off / 8] & (1 << (off % 8)))) {
+ printf ("page %d: off %u not set\n",
+ (ind - 1) / ENTRIESPERPAGE, off);
+ }
+
+ my_bitmaps[pageno][off / 8] |= (1 << (off % 8));
+
+ len = strlen(entry->name);
+ while (len > 15) {
+ len -= sizeof(DirEntry);
+ ++noverfill;
+ ++off;
+ my_bitmaps[pageno][off / 8] |= (1 << (off % 8));
+ }
+
+ ++hash_entry_count;
+ }
+ }
+
+ for (i = 0; i < npages; ++i) {
+ DirPage1 *page_n;
+ int j;
+ unsigned unused;
+
+ if (i == 0)
+ unused = 13;
+ else
+ unused = 1;
+
+ for (j = 0; j < unused; ++j)
+ my_bitmaps[i][j / 8] |= (1 << (j % 8));
+
+ page_n = (DirPage1 *)((char *)page0 + AFSDIR_PAGESIZE * i);
+
+ if (memcmp (my_bitmaps[i],
+ page_n->header.pg_bitmap, sizeof(my_bitmaps[i])) != 0) {
+ printf ("page %i: bitmaps differ\n"
+ "actual: ", i);
+ for (j = 0; j < ENTRIESPERPAGE / 8; ++j)
+ printf ("%02x ", page_n->header.pg_bitmap[j]);
+ printf ("\n"
+ "calculated: ");
+ for (j = 0; j < ENTRIESPERPAGE / 8; ++j)
+ printf ("%02x ", my_bitmaps[i][j]);
+ printf ("\n");
+ }
+ }
+
+
+ printf ("hash entry count = %u, noverfill = %u, sum = %u\n",
+ hash_entry_count, noverfill, hash_entry_count + noverfill);
+
+ if (hash_entry_count + noverfill != page_entry_count)
+ ret = 1;
+
+out:
+ fbuf_end (&the_fbuf);
+ return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+ if (argc != 2)
+ return 1;
+
+ arla_loginit ("/dev/stderr");
+ arla_log_set_level ("all");
+
+ return check (argv[1]);
+}
diff --git a/usr.sbin/afs/src/arlad/arla.c b/usr.sbin/afs/src/arlad/arla.c
new file mode 100644
index 00000000000..8ea5439f9e7
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/arla.c
@@ -0,0 +1,870 @@
+/* $OpenBSD: arla.c,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/* $OpenBSD: arla.c,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Test to talk with FS
+ */
+
+#include "arla_local.h"
+#include <sl.h>
+#include <parse_units.h>
+#include <getarg.h>
+
+#include <version.h>
+
+RCSID("$KTH: arla.c,v 1.87 1998/08/23 22:50:22 assar Exp $") ;
+
+enum connected_mode connected_mode = CONNECTED;
+
+static CredCacheEntry *tmpce;
+
+static VenusFid cwd;
+static VenusFid rootcwd;
+
+static int arla_chdir(int, char **);
+static int arla_ls(int, char **);
+static int arla_cat(int, char **);
+static int help(int, char **);
+static int arla_quit(int, char **);
+static int arla_conn_status(int, char **);
+static int arla_vol_status(int, char **);
+static int arla_cred_status(int, char **);
+static int arla_fcache_status(int, char **);
+static int arla_sysname(int, char**);
+static int arla_rx_status(int argc, char **argv);
+static int arla_flushfid(int argc, char **argv);
+
+static SL_cmd cmds[] = {
+ {"chdir", arla_chdir, "chdir directory"},
+ {"cd"},
+ {"ls", arla_ls, "ls"},
+ {"cat", arla_cat, "cat file"},
+ {"help", help, "help"},
+ {"?"},
+ {"conn-status", arla_conn_status, "connection status"},
+ {"vol-status", arla_vol_status, "volume cache status"},
+ {"cred-status", arla_cred_status, "credentials status"},
+ {"fcache-status", arla_fcache_status, "file cache status"},
+ {"rx-status", arla_rx_status, "rx connection status"},
+ {"flushfid", arla_flushfid, "flush a fid from the cache"},
+ {"quit", arla_quit, "quit"},
+ {"exit"},
+ {"sysname", arla_sysname, "sysname"},
+ { NULL }
+};
+
+static void
+print_dir (VenusFid *fid, const char *name, void *v)
+{
+ printf("(%d, %d, %d, %d): %s\n", fid->Cell,
+ fid->fid.Volume,
+ fid->fid.Vnode,
+ fid->fid.Unique, name);
+}
+
+/*
+ * Return 0 iff OK.
+ */
+
+static int
+newwalk (VenusFid *startdir, char *fname)
+{
+ VenusFid cwd = *startdir;
+ char *base;
+ VenusFid file;
+ Result ret;
+ FCacheEntry *entry;
+ int error;
+ char symlink[MAXPATHLEN];
+ char store_name[MAXPATHLEN];
+
+ strcpy(store_name, fname);
+ fname = store_name;
+
+ do {
+ /* set things up so that fname points to the remainder of the path,
+ * whereas base points to the whatever preceeds the first /
+ */
+ base = fname;
+ fname = strchr(fname, '/');
+ if (fname) {
+ /* deal with repeated adjacent / chars by eliminating the
+ * duplicates.
+ */
+ while (*fname == '/') {
+ *fname = '\0';
+ fname++;
+ }
+ }
+
+ /* deal with absolute pathnames first. */
+ if (*base == '\0') {
+ cwd = rootcwd;
+ if (fname) {
+ if (strncmp("afs",fname,3) == 0) {
+ fname += 3;
+ }
+ continue;
+ } else {
+ break;
+ }
+ }
+ ret = cm_lookup (cwd, base, &file, &tmpce);
+ if (ret.res) {
+ arla_warn (ADEBWARN, ret.error, "lookup(%s)", base);
+ return -1;
+ }
+ error = fcache_get (&entry, file, tmpce);
+ if (error) {
+ arla_warn (ADEBWARN, error, "fcache_get");
+ return -1;
+ }
+ error = fcache_get_data (entry, tmpce);
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+
+ arla_warn (ADEBWARN, error, "fcache_get_data");
+ return -1;
+ }
+ /* handle symlinks here */
+ if (entry->status.FileType == TYPE_LINK) {
+ int len;
+ int fd;
+
+ fd = fcache_open_file (entry, O_RDONLY, 0);
+ /* read the symlink and null-terminate it */
+ if (fd < 0) {
+ ReleaseWriteLock(&entry->lock);
+ arla_warn (ADEBWARN, errno, "fcache_open_file");
+ return -1;
+ }
+ len = read (fd, symlink, sizeof(symlink));
+ close (fd);
+ if (len <= 0) {
+ ReleaseWriteLock(&entry->lock);
+ arla_warnx (ADEBWARN, "cannot read symlink");
+ return -1;
+ }
+ symlink[len] = '\0';
+ /* if we're not at the end (i.e. fname is not null), take
+ * the expansion of the symlink and append fname to it.
+ */
+ if (fname != NULL) {
+ strcat (symlink, "/");
+ strcat (symlink, fname);
+ }
+ strcpy(store_name,symlink);
+ fname = store_name;
+ } else {
+ /* if not a symlink, just update cwd */
+ cwd = file;
+ }
+ ReleaseWriteLock (&entry->lock);
+
+ /* the *fname condition below deals with a trailing / in a
+ * path-name */
+ } while (fname != NULL && *fname);
+ *startdir = cwd;
+ return 0;
+}
+
+static int
+arla_quit (int argc, char **argv)
+{
+ printf("Thank you for using arla\n");
+ return 1;
+}
+
+static int
+arla_flushfid(int argc, char **argv)
+{
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+ VenusFid fid;
+
+ if (argc != 2) {
+ fprintf(stderr, "flushfid fid\n");
+ return 0;
+ }
+
+ if ((sscanf(argv[1], "%d.%d.%d.%d", &fid.Cell, &fid.fid.Volume,
+ &fid.fid.Vnode, &fid.fid.Unique)) == 4) {
+ ;
+ } else if ((sscanf(argv[1], "%d.%d.%d", &fid.fid.Volume,
+ &fid.fid.Vnode, &fid.fid.Unique)) == 3) {
+ fid.Cell = cwd.Cell;
+ } else {
+ fprintf(stderr, "flushfid fid\n");
+ return 0;
+ }
+
+ fcache_stale_entry(fid, broken_callback);
+
+ return 0;
+}
+
+
+static int
+arla_chdir (int argc, char **argv)
+{
+ if (argc != 2) {
+ printf ("usage: %s dir\n", argv[0]);
+ return 0;
+ }
+
+ newwalk (&cwd, argv[1]);
+ return 0;
+}
+
+static int
+arla_ls (int argc, char **argv)
+{
+ int error;
+
+ error = adir_readdir (cwd, print_dir, NULL, tmpce);
+ if (error) {
+ printf ("adir_readdir failed: %s\n", koerr_gettext(error));
+ }
+ return 0;
+}
+
+static int
+arla_sysname (int argc, char **argv)
+{
+ switch (argc) {
+ case 1:
+ printf("sysname: %s\n", arlasysname);
+ break;
+ case 2:
+ strncpy(arlasysname, argv[1], SYSNAMEMAXLEN);
+ arlasysname[SYSNAMEMAXLEN-1] = '\0';
+ printf("setting sysname to: %s\n", arlasysname);
+ break;
+ default:
+ printf("syntax: sysname <sysname>\n");
+ break;
+ }
+ return 0;
+}
+
+
+
+static int
+arla_cat (int argc, char **argv)
+{
+ VenusFid fid;
+ int fd;
+ char buf[8192];
+ int ret;
+ FCacheEntry *e;
+
+ if (argc != 2) {
+ printf ("usage: %s file\n", argv[0]);
+ return 0;
+ }
+ fid = cwd;
+ if( newwalk (&fid, argv[1]) == 0) {
+
+ ret = fcache_get (&e, fid, tmpce);
+ if (ret) {
+ printf ("fcache_get failed: %d\n", ret);
+ return 0;
+ }
+ ret = fcache_get_data (e, tmpce);
+ if (ret) {
+ ReleaseWriteLock (&e->lock);
+ printf ("fcache_get_data failed: %d\n", ret);
+ return 0;
+ }
+
+ fd = fcache_open_file (e, O_RDONLY, 0);
+
+ if (fd < 0) {
+ ReleaseWriteLock (&e->lock);
+ printf ("fcache_open_file failed: %d\n", errno);
+ return 0;
+ }
+ while ((ret = read (fd, buf, sizeof(buf))) > 0) {
+ write (STDOUT_FILENO, buf, ret);
+ }
+ close (fd);
+ ReleaseWriteLock (&e->lock);
+ }
+ return 0;
+}
+
+static int
+help (int argc, char **argv)
+{
+ sl_help(cmds, argc, argv);
+ return 0;
+}
+
+static int
+arla_conn_status (int argc, char **argv)
+{
+ conn_status (stderr);
+ return 0;
+}
+
+static int
+arla_vol_status (int argc, char **argv)
+{
+ volcache_status (stderr);
+ return 0;
+}
+
+static int
+arla_cred_status (int argc, char **argv)
+{
+ cred_status (stderr);
+ return 0;
+}
+
+static int
+arla_fcache_status (int argc, char **argv)
+{
+ fcache_status (stderr);
+ return 0;
+}
+
+static int
+arla_rx_status(int argc, char **argv)
+{
+ rx_PrintStats(stderr);
+ return 0;
+}
+
+
+static void
+initrx (int port)
+{
+ int error;
+
+ error = rx_Init (htons(port));
+ if (error)
+ arla_err (1, ADEBERROR, error, "rx_init");
+}
+
+#ifdef KERBEROS
+
+static int
+get_cred(const char *princ, const char *inst, const char *krealm,
+ CREDENTIALS *c)
+{
+ KTEXT_ST foo;
+ int k_errno;
+
+ k_errno = krb_get_cred((char*)princ, (char*)inst, (char*)krealm, c);
+
+ if(k_errno != KSUCCESS) {
+ k_errno = krb_mk_req(&foo, (char*)princ, (char*)inst, (char*)krealm, 0);
+ if (k_errno == KSUCCESS)
+ k_errno = krb_get_cred((char*)princ, (char*)inst, (char*)krealm, c);
+ }
+ return k_errno;
+}
+
+
+#endif /* KERBEROS */
+
+#define KERNEL_STACKSIZE (16*1024)
+
+static void
+store_state (void)
+{
+ arla_warnx (ADEBMISC, "storing state");
+ fcache_store_state ();
+ volcache_store_state ();
+ cm_store_state ();
+}
+
+/*
+ * signal handlers...
+ */
+
+static void
+sigint (int foo)
+{
+ arla_warnx (ADEBMISC, "fatal signal received");
+ store_state ();
+ exit (0);
+}
+
+static void
+sighup (int foo)
+{
+ store_state ();
+}
+
+static void
+daemonify (void)
+{
+ pid_t pid;
+ int fd;
+
+ pid = fork ();
+ if (pid < 0)
+ arla_err (1, ADEBERROR, errno, "fork");
+ else if (pid > 0)
+ exit(0);
+ if (setsid() == -1)
+ arla_err (1, ADEBERROR, errno, "setsid");
+ fd = open(_PATH_DEVNULL, O_RDWR, 0);
+ if (fd < 0)
+ arla_err (1, ADEBERROR, errno, "open " _PATH_DEVNULL);
+ dup2 (fd, STDIN_FILENO);
+ dup2 (fd, STDOUT_FILENO);
+ dup2 (fd, STDERR_FILENO);
+ close (fd);
+}
+
+struct conf_param {
+ const char *name;
+ unsigned *val;
+ unsigned default_val;
+};
+
+/*
+ * Reads in a configuration file, and sets some defaults.
+ */
+
+static struct units size_units[] = {
+ { "M", 1024 * 1024 },
+ { "k", 1024 },
+ { NULL, 0 }
+};
+
+static void
+read_conffile(char *fname,
+ struct conf_param *params)
+{
+ FILE *fp;
+ char buf[256];
+ int lineno;
+ struct conf_param *p;
+
+ for (p = params; p->name; ++p)
+ *(p->val) = p->default_val;
+
+ arla_warnx (ADEBINIT, "read_conffile: %s", fname);
+
+ fp = fopen(fname, "r");
+ if (fp == NULL) {
+ arla_warn (ADEBINIT, errno, "open %s", fname);
+ return;
+ }
+
+ lineno = 0;
+
+ while (fgets (buf, sizeof(buf), fp) != NULL) {
+ struct conf_param *partial_param = NULL;
+ int partial_match = 0;
+ char *save = NULL;
+ char *n;
+ char *v;
+ unsigned val;
+ char *endptr;
+
+ ++lineno;
+ if (buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ if (buf[0] == '#')
+ continue;
+
+ n = strtok_r (buf, " \t", &save);
+ if (n == NULL) {
+ fprintf (stderr, "%s:%d: no parameter?\n", fname, lineno);
+ continue;
+ }
+
+ v = strtok_r (NULL, " \t", &save);
+ if (v == NULL) {
+ fprintf (stderr, "%s:%d: no value?\n", fname, lineno);
+ continue;
+ }
+
+ val = parse_units(v, size_units, NULL);
+ if(val == (unsigned)-1) {
+ val = strtol(v, &endptr, 0);
+ if (endptr == v)
+ fprintf (stderr, "%s:%d: bad value `%s'\n",
+ fname, lineno, v);
+ }
+
+ for (p = params; p->name; ++p) {
+ if (strcmp(n, p->name) == 0) {
+ partial_match = 1;
+ partial_param = p;
+ break;
+ } else if(strncmp(n, p->name, strlen(n)) == 0) {
+ ++partial_match;
+ partial_param = p;
+ }
+ }
+ if (partial_match == 1)
+ *(partial_param->val) = val;
+ else if (partial_match == 0)
+ fprintf (stderr, "%s:%d: unknown parameter `%s'\n",
+ fname, lineno, n);
+ else
+ fprintf (stderr, "%s:%d: ambiguous parameter `%s'\n",
+ fname, lineno, n);
+ }
+ fclose(fp);
+}
+
+static unsigned low_vnodes, high_vnodes, low_bytes, high_bytes;
+static unsigned numcreds, numconns, numvols;
+
+static struct conf_param conf_params[] = {
+ {"low_vnodes", &low_vnodes, ARLA_LOW_VNODES},
+ {"high_vnodes", &high_vnodes, ARLA_HIGH_VNODES},
+ {"low_bytes", &low_bytes, ARLA_LOW_BYTES},
+ {"high_bytes", &high_bytes, ARLA_HIGH_BYTES},
+ {"numcreds", &numcreds, ARLA_NUMCREDS},
+ {"numconns", &numconns, ARLA_NUMCREDS},
+ {"numvols", &numvols, ARLA_NUMVOLS},
+ {"fpriority", &fprioritylevel, FPRIO_DEFAULT},
+ {NULL, NULL, 0}};
+
+static int test_flag;
+static char *conf_file = ARLACONFFILE;
+static char *log_file = NULL;
+static char *device_file = "/dev/xfs0";
+static char *debug_levels = NULL;
+static char *connected_mode_string = NULL;
+#ifdef KERBEROS
+static char *rxkad_level_string = "auth";
+#endif
+static const char *temp_sysname = NULL;
+static char *root_volume;
+static char *cache_dir;
+static int version_flag;
+static int help_flag;
+static int no_fork;
+static int client_port = 4711;
+static int recover = 1;
+
+static struct getargs args[] = {
+ {"test", 't', arg_flag, &test_flag,
+ "run in test mode", NULL},
+ {"conffile", 'c', arg_string, &conf_file,
+ "path to configuration file", NULL},
+ {"log", 'l', arg_string, &log_file,
+ "where to write log (stderr (default), syslog, or path to file)", NULL},
+ {"debug", 0, arg_string, &debug_levels,
+ "what to write in the log", NULL},
+ {"device", 'd', arg_string, &device_file,
+ "the XFS device to use [/dev/xfs0]", NULL},
+ {"connected-mode", 0, arg_string, &connected_mode_string,
+ "initial connected mode [conncted|fetch-only|disconnected]", NULL},
+ {"no-fork", 'n', arg_flag, &no_fork,
+ "don't fork and demonize", NULL},
+#ifdef KERBEROS
+ {"rxkad-level", 'r', arg_string, &rxkad_level_string,
+ "the rxkad level to use (clear, auth or crypt)", NULL},
+#endif
+ {"sysname", 's', arg_string, &temp_sysname,
+ "set the sysname of this system", NULL},
+ {"root-volume",0, arg_string, &root_volume},
+ {"port", 0, arg_integer, &client_port,
+ "port number to use", NULL},
+ {"recover", 'z', arg_negative_flag, &recover,
+ "don't recover state", NULL},
+ {"cache-dir", 0, arg_string, &cache_dir,
+ "cache directory", NULL},
+ {"version", 0, arg_flag, &version_flag,
+ NULL, NULL},
+ {"help", 0, arg_flag, &help_flag,
+ NULL, NULL},
+ {NULL, 0, arg_end, NULL, NULL, NULL}
+};
+
+static int
+parse_string_list (const char *s, const char **units)
+{
+ const char **p;
+ int partial_val = 0;
+ int partial_match = 0;
+
+ for (p = units; *p; ++p) {
+ if (strcmp (s, *p) == 0)
+ return p - units;
+ if (strncmp (s, *p, strlen(s)) == 0) {
+ partial_match++;
+ partial_val = p - units;
+ }
+ }
+ if (partial_match == 1)
+ return partial_val;
+ else
+ return -1;
+}
+
+#ifdef KERBEROS
+static const char *rxkad_level_units[] = {
+"clear", /* 0 */
+"auth", /* 1 */
+"crypt", /* 2 */
+NULL
+};
+
+static int
+parse_rxkad_level (const char *s)
+{
+ return parse_string_list (s, rxkad_level_units);
+}
+#endif
+
+static const char *connected_levels[] = {
+"connected", /* CONNECTED = 0 */
+"fetch-only", /* FETCH_ONLY = 1 */
+"disconnected", /* DISCONNCTED = 2 */
+NULL
+};
+
+static int
+set_connected_mode (const char *s)
+{
+ return parse_string_list (s, connected_levels);
+}
+
+static void
+usage (int ret)
+{
+ arg_printusage (args,
+ NULL,
+ "[device]");
+ exit (ret);
+}
+
+
+/*
+ *
+ */
+
+int
+main (int argc, char **argv)
+{
+ PROCESS kernelpid;
+ int error;
+ int optind = 0;
+ char *default_log_file;
+ char fpriofile[MAXPATHLEN];
+
+ set_progname (argv[0]);
+
+ if (getarg (args, argc, argv, &optind, ARG_GNUSTYLE))
+ usage (1);
+
+ argc -= optind;
+ argv += optind;
+
+ if (help_flag)
+ usage (0);
+
+ if (version_flag)
+ errx (1, "%s", arla_version);
+
+ if (argc > 0) {
+ device_file = *argv;
+ argc--;
+ argv++;
+ }
+
+ if (argc != 0)
+ usage (1);
+
+ if (temp_sysname == NULL)
+ temp_sysname = arla_getsysname ();
+
+ if (temp_sysname != NULL) {
+ strncpy(arlasysname, temp_sysname, SYSNAMEMAXLEN - 1);
+ arlasysname[SYSNAMEMAXLEN - 1] = '\0';
+ }
+
+#ifdef KERBEROS
+ rxkad_min_level = parse_rxkad_level (rxkad_level_string);
+ if (rxkad_min_level < 0)
+ errx (1, "bad rxkad level `%s'", rxkad_level_string);
+#endif
+
+ signal (SIGINT, sigint);
+ signal (SIGTERM, sigint);
+ signal (SIGHUP, sighup);
+ umask (S_IRWXG|S_IRWXO); /* 077 */
+
+ if (!test_flag && !no_fork) {
+ default_log_file = "syslog";
+ } else {
+ default_log_file = "/dev/stderr";
+ }
+
+ if (log_file == NULL)
+ log_file = default_log_file;
+
+ arla_loginit(log_file);
+
+ if (debug_levels != NULL) {
+ if (arla_log_set_level (debug_levels) < 0) {
+ warnx ("bad debug levels: `%s'", debug_levels);
+ arla_log_print_levels (stderr);
+ exit (1);
+ }
+ }
+
+ if (connected_mode_string != NULL) {
+ int tmp = set_connected_mode (connected_mode_string);
+
+ if (tmp < 0)
+ errx (1, "bad connected mode: `%s'", connected_mode_string);
+ connected_mode = tmp;
+ }
+
+ read_conffile(conf_file, conf_params);
+
+ if (!test_flag && !no_fork)
+ daemonify ();
+
+ if (cache_dir == NULL)
+ cache_dir = ARLACACHEDIR;
+
+ mkdir (cache_dir, 0777);
+ if (chdir (cache_dir) < 0)
+ arla_err (1, ADEBERROR, errno, "chdir %s", cache_dir);
+
+
+ snprintf(fpriofile, sizeof(fpriofile), "%s/%s", cache_dir, "fprio");
+
+ /*
+ * Init
+ */
+
+ arla_warnx (ADEBINIT,"Arlad booting sequence:");
+ arla_warnx (ADEBINIT, "connected mode: %s",
+ connected_levels[connected_mode]);
+ arla_warnx (ADEBINIT, "initports");
+ initports ();
+ arla_warnx (ADEBINIT, "conn_init numconns = %u", numconns);
+ conn_init (numconns);
+ arla_warnx (ADEBINIT, "cellcache");
+ cell_init (0);
+ arla_warnx (ADEBINIT, "fprio");
+ fprio_init(fpriofile);
+ arla_warnx (ADEBINIT, "volcache numvols = %u", numvols);
+ volcache_init (numvols, recover);
+ if (root_volume != NULL)
+ volcache_set_rootvolume (root_volume);
+ arla_warnx (ADEBINIT, "rx");
+ initrx (client_port);
+#ifdef KERBEROS
+ arla_warnx (ADEBINIT, "using rxkad level %s",
+ rxkad_level_units[rxkad_min_level]);
+#endif
+
+ /*
+ * Credential cache
+ */
+ arla_warnx (ADEBINIT, "credcache numcreds = %u", numcreds);
+ cred_init (numcreds);
+
+ arla_warnx (ADEBINIT,
+ "fcache low_vnodes = %u, high_vnodes = %u"
+ "low_bytes = %u, high_bytes = %u",
+ low_vnodes, high_vnodes,
+ low_bytes, high_bytes);
+ fcache_init (low_vnodes, high_vnodes,
+ low_bytes, high_bytes, recover);
+
+ arla_warnx (ADEBINIT, "cmcb");
+ cmcb_init ();
+
+ arla_warnx(ADEBINIT, "cm");
+ cm_init ();
+
+ arla_warnx(ADEBINIT, "arla init done.");
+
+ if (test_flag) {
+#ifdef KERBEROS
+ {
+ krbstruct krbdata;
+ int ret;
+ const char *this_cell = cell_getthiscell ();
+ const char *db_server = cell_findnamedbbyname (this_cell);
+ char *realm = krb_realmofhost (db_server);
+
+ ret = get_cred("afs", this_cell, realm, &krbdata.c);
+ if (ret)
+ ret = get_cred("afs", "", realm, &krbdata.c);
+
+ if (ret) {
+ arla_warnx (ADEBWARN,
+ "getting ticket for %s: %s",
+ this_cell,
+ krb_get_err_text (ret));
+ } else if (cred_add_krb4(getuid(), &krbdata.c) == NULL) {
+ arla_warnx (ADEBWARN, "Could not insert tokens to arla");
+ }
+ }
+#endif
+
+ tmpce = cred_get (0, getuid(), CRED_ANY);
+
+ arla_warnx (ADEBINIT, "Getting root...");
+ error = getroot (&rootcwd, tmpce);
+ if (error)
+ arla_err (1, ADEBERROR, error, "getroot");
+ cwd = rootcwd;
+ arla_warnx(ADEBINIT, "arla loop started");
+ sl_loop(cmds, "arla> ");
+ store_state ();
+ } else {
+ xfs_message_init ();
+
+ if (LWP_CreateProcess (kernel_interface, KERNEL_STACKSIZE, 1,
+ device_file, "Kernel-interface", &kernelpid))
+ arla_errx (1, ADEBERROR,
+ "Cannot create kernel-interface process");
+ LWP_WaitProcess ((char *)main);
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/afs/src/arlad/arla_local.h b/usr.sbin/afs/src/arlad/arla_local.h
new file mode 100644
index 00000000000..86a87661f1f
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/arla_local.h
@@ -0,0 +1,161 @@
+/* $OpenBSD: arla_local.h,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 file for whole arlad
+ * $KTH: arla_local.h,v 1.32 1998/07/03 12:38:19 assar Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef USE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <err.h>
+#include <parse_units.h>
+#include <roken.h>
+
+#include <lwp.h>
+#include <lock.h>
+
+#include <rx/rx.h>
+#include <rx/rx_null.h>
+
+#ifdef KERBEROS
+#include <des.h>
+#include <kerberosIV/krb.h>
+#include <rxkad.h>
+#endif
+
+#ifdef USE_MMAPTIME
+#include <mmaptime.h>
+#endif
+
+#include <kerberosIV/kafs.h>
+
+#include "log.h"
+
+#include "fs.h"
+#include "cmcb.h"
+#include "fs.cs.h"
+#include "list.h"
+#include "vldb.h"
+#include "vldb.cs.h"
+#include "volcache.h"
+#include "fbuf.h"
+#include "fcache.h"
+#include "hash.h"
+#include "afs_dir.h"
+#include "ip.h"
+#include "service.h"
+#include "ports.h"
+#include "fcache.h"
+#include "conn.h"
+#include "inter.h"
+#include "cred.h"
+#include "adir.h"
+#include "service.h"
+#include "subr.h"
+#include "fprio.h"
+#include "bool.h"
+#include "minmax.h"
+#include "kernel.h"
+#include "messages.h"
+#include "strutil.h"
+#include "arladeb.h"
+#include "ko.h"
+
+#define SYSNAMEMAXLEN 2048
+extern char arlasysname[SYSNAMEMAXLEN];
+
+enum connected_mode { CONNECTED = 0,
+ FETCH_ONLY = 1,
+ DISCONNECTED = 2,
+ CONNECTEDLOG = 4};
+
+extern enum connected_mode connected_mode;
+
+#define ARLA_NUMCONNS 200
+#define ARLA_HIGH_VNODES 4000
+#define ARLA_LOW_VNODES 3000
+#define ARLA_HIGH_BYTES 40000000
+#define ARLA_LOW_BYTES 30000000
+#define ARLA_NUMCREDS 200
+#define ARLA_NUMVOLS 100
+
+/*
+ * This should be a not used uid in the system,
+ * XFS_ANONYMOUSID may be good
+ */
+#define ARLA_NO_AUTH_CRED 4
+
+
diff --git a/usr.sbin/afs/src/arlad/arladeb.c b/usr.sbin/afs/src/arlad/arladeb.c
new file mode 100644
index 00000000000..0af13d7297e
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/arladeb.c
@@ -0,0 +1,201 @@
+/* $OpenBSD: arladeb.c,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "arla_local.h"
+
+RCSID("$KTH: arladeb.c,v 1.12 1998/04/03 03:30:17 assar Exp $");
+
+static Log_method* arla_log_method = NULL;
+
+struct units arla_deb_units[] = {
+ { "all", (unsigned)(~0) >> 1 },
+ { "miscellaneous", ADEBMISC },
+ { "connection", ADEBCONN },
+ { "initialization", ADEBINIT },
+ { "file-cache", ADEBFCACHE },
+ { "volume-cache", ADEBVOLCACHE },
+ { "cache-manager", ADEBCM },
+ { "callbacks", ADEBCALLBACK },
+ { "cleaner", ADEBCLEANER },
+ { "kernel", ADEBKERNEL },
+ { "messages", ADEBMSG },
+ { "fbuf", ADEBFBUF },
+ { "warnings", ADEBWARN },
+ { "errors", ADEBERROR },
+ { "none", 0 },
+ { NULL }
+};
+
+#define DEFAULT_LOG (ADEBWARN | ADEBERROR)
+
+void
+arla_log(unsigned level, char *fmt, ...)
+{
+ va_list args;
+
+ assert (arla_log_method);
+
+ va_start(args, fmt);
+ log_vlog(arla_log_method, level, fmt, args);
+ va_end(args);
+}
+
+void
+arla_loginit(char *log)
+{
+ assert (log);
+
+ arla_log_method = log_open("arla", log);
+ log_set_mask(arla_log_method, DEFAULT_LOG);
+}
+
+int
+arla_log_set_level (const char *s)
+{
+ int ret;
+
+ ret = parse_flags (s, arla_deb_units, log_get_mask(arla_log_method));
+ if (ret < 0)
+ return ret;
+ else {
+ log_set_mask (arla_log_method, ret);
+ return 0;
+ }
+}
+
+void
+arla_log_get_level (char *s, size_t len)
+{
+ unparse_flags (log_get_mask (arla_log_method),
+ arla_deb_units, s, len);
+}
+
+void
+arla_log_print_levels (FILE *f)
+{
+ print_flags_table (arla_deb_units, f);
+}
+
+/*
+ *
+ */
+
+void
+arla_err (int eval, unsigned level, int error, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ arla_verr (eval, level, error, fmt, args);
+ va_end (args);
+}
+
+void
+arla_verr (int eval, unsigned level, int error, const char *fmt, va_list args)
+{
+ char *s;
+
+ vasprintf (&s, fmt, args);
+ if (s == NULL) {
+ log_log (arla_log_method, level,
+ "Sorry, no memory to print `%s'...", fmt);
+ exit (eval);
+ }
+ log_log (arla_log_method, level, "%s: %s", s, koerr_gettext (error));
+ free (s);
+ exit (eval);
+}
+
+void
+arla_errx (int eval, unsigned level, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ arla_verrx (eval, level, fmt, args);
+ va_end (args);
+}
+
+void
+arla_verrx (int eval, unsigned level, const char *fmt, va_list args)
+{
+ log_vlog (arla_log_method, level, fmt, args);
+ exit (eval);
+}
+
+void
+arla_warn (unsigned level, int error, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ arla_vwarn (level, error, fmt, args);
+ va_end (args);
+}
+
+void
+arla_vwarn (unsigned level, int error, const char *fmt, va_list args)
+{
+ char *s;
+
+ vasprintf (&s, fmt, args);
+ if (s == NULL) {
+ log_log (arla_log_method, level,
+ "Sorry, no memory to print `%s'...", fmt);
+ return;
+ }
+ log_log (arla_log_method, level, "%s: %s", s, koerr_gettext (error));
+ free (s);
+}
+
+void
+arla_warnx (unsigned level, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ arla_vwarnx (level, fmt, args);
+ va_end (args);
+}
+
+void
+arla_vwarnx (unsigned level, const char *fmt, va_list args)
+{
+ log_vlog (arla_log_method, level, fmt, args);
+}
diff --git a/usr.sbin/afs/src/arlad/arladeb.h b/usr.sbin/afs/src/arlad/arladeb.h
new file mode 100644
index 00000000000..36c3d9e9f14
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/arladeb.h
@@ -0,0 +1,118 @@
+/* $OpenBSD: arladeb.h,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * $KTH: arladeb.h,v 1.16 1998/05/23 05:25:47 assar Exp $
+ */
+
+#ifndef _arladeb_h
+#define _arladeb_h
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <roken.h>
+
+/* masks */
+#define ADEBANY 0xffffffff
+#define ADEBMISC 0x00000001 /* misc debugging */
+#define ADEBCONN 0x00000002 /* conncache */
+#define ADEBINIT 0x00000004 /* initialization debug */
+#define ADEBFCACHE 0x00000008 /* file cache */
+#define ADEBVOLCACHE 0x00000010 /* volume cache */
+#define ADEBCM 0x00000020 /* cache manager */
+#define ADEBCALLBACK 0x00000040 /* callbacks */
+#define ADEBCLEANER 0x00000080 /* cleaner */
+#define ADEBKERNEL 0x00000100 /* kernel interface */
+#define ADEBMSG 0x00000200 /* messages */
+#define ADEBFBUF 0x00000400 /* fbuf */
+#define ADEBWARN 0x08000000 /* don't ignore warning */
+#define ADEBERROR 0x10000000 /* don't ignore error */
+
+void arla_log(unsigned level, char *fmt, ...);
+void arla_loginit(char *log);
+int arla_log_set_level (const char *s);
+void arla_log_get_level (char *s, size_t len);
+void arla_log_print_levels (FILE *f);
+
+void
+arla_err (int eval, unsigned level, int error, const char *fmt, ...)
+__attribute__ ((noreturn))
+__attribute__ ((format (printf, 4, 5)))
+;
+
+void
+arla_verr (int eval, unsigned level, int error, const char *fmt, va_list args)
+__attribute__ ((noreturn))
+__attribute__ ((format (printf, 4, 0)))
+;
+
+void
+arla_errx (int eval, unsigned level, const char *fmt, ...)
+__attribute__ ((noreturn))
+__attribute__ ((format (printf, 3, 4)))
+;
+
+void
+arla_verrx (int eval, unsigned level, const char *fmt, va_list args)
+__attribute__ ((noreturn))
+__attribute__ ((format (printf, 3, 0)))
+;
+
+void
+arla_warn (unsigned level, int error, const char *fmt, ...)
+__attribute__ ((format (printf, 3, 4)))
+;
+
+void
+arla_vwarn (unsigned level, int error, const char *fmt, va_list args)
+__attribute__ ((format (printf, 3, 0)))
+;
+
+void
+arla_warnx (unsigned level, const char *fmt, ...)
+__attribute__ ((format (printf, 2, 3)))
+;
+
+void
+arla_vwarnx (unsigned level, const char *fmt, va_list args)
+__attribute__ ((format (printf, 2, 0)))
+;
+
+#endif /* _arladeb_h */
diff --git a/usr.sbin/afs/src/arlad/bsd-subr.c b/usr.sbin/afs/src/arlad/bsd-subr.c
new file mode 100644
index 00000000000..a41669f1d70
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/bsd-subr.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: bsd-subr.c,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* XXX need this to get dirent and DIRSIZ */
+#ifdef __osf__
+#define _OSF_SOURCE
+#define _BSD
+#endif
+#include "arla_local.h"
+RCSID("$KTH: bsd-subr.c,v 1.24 1998/05/02 02:28:46 assar Exp $");
+
+static long blocksize = 1024; /* XXX */
+
+struct args {
+ int fd;
+ off_t off;
+ char *buf;
+ char *ptr;
+ struct dirent *last;
+ FCacheEntry *e;
+};
+
+static void
+flushbuf (struct args *args)
+{
+ unsigned inc = blocksize - (args->ptr - args->buf);
+
+ args->last->d_reclen += inc;
+#if 0
+ args->last->d_off += inc;
+#endif
+ if (write (args->fd, args->buf, blocksize) != blocksize)
+ arla_warn (ADEBWARN, errno, "write");
+ args->ptr = args->buf;
+ args->last = NULL;
+}
+
+static void
+write_dirent(VenusFid *fid, const char *name, void *arg)
+{
+ struct dirent dirent, *real;
+ struct args *args = (struct args *)arg;
+
+ dirent.d_namlen = strlen (name);
+ dirent.d_reclen = DIRSIZ(&dirent);
+
+ if (args->ptr + dirent.d_reclen > args->buf + blocksize)
+ flushbuf (args);
+ real = (struct dirent *)args->ptr;
+
+ real->d_namlen = dirent.d_namlen;
+ real->d_reclen = dirent.d_reclen;
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ real->d_type = DT_UNKNOWN;
+#endif
+
+ if (dirent.d_namlen == 2
+ && strcmp(name, "..") == 0
+ && args->e->flags.mountp) {
+ real->d_fileno = afsfid2inode (&args->e->parent);
+ } else if (dirent.d_namlen == 1 &&
+ strcmp(name, ".") == 0 &&
+ args->e->flags.mountp) {
+ real->d_fileno = afsfid2inode (&args->e->realfid);
+ } else
+ real->d_fileno = afsfid2inode (fid);
+ strcpy (real->d_name, name);
+ args->ptr += real->d_reclen;
+ args->off += real->d_reclen;
+#if 0
+ real->d_off = args->off;
+#endif
+ args->last = real;
+}
+
+/*
+ *
+ */
+
+Result
+conv_dir (FCacheEntry *e, char *handle, size_t handle_size,
+ CredCacheEntry *ce, u_int tokens)
+{
+ struct args args;
+ Result res;
+
+ e->flags.extradirp = TRUE;
+ fcache_extra_file_name (e, handle, handle_size);
+ res.tokens = e->tokens |= XFS_DATA_R | XFS_OPEN_NR;
+
+ args.fd = open (handle, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (args.fd == -1) {
+ res.res = -1;
+ res.error = errno;
+ arla_warn (ADEBWARN, errno, "open %s", handle);
+ return res;
+ }
+ args.off = 0;
+ args.buf = (char *)malloc (blocksize);
+ if (args.buf == NULL) {
+ arla_warn (ADEBWARN, errno, "malloc %u", (unsigned)blocksize);
+ res.res = -1;
+ res.error = errno;
+ close (args.fd);
+ return res;
+ }
+ args.ptr = args.buf;
+ args.last = NULL;
+ args.e = e;
+ ReleaseWriteLock (&e->lock);
+ adir_readdir (e->fid, write_dirent, (void *)&args, ce);
+ ObtainWriteLock (&e->lock);
+ if (args.last)
+ flushbuf (&args);
+ free (args.buf);
+ res.res = close (args.fd);
+ if (res.res)
+ res.error = errno;
+ return res;
+}
diff --git a/usr.sbin/afs/src/arlad/cmcb.c b/usr.sbin/afs/src/arlad/cmcb.c
new file mode 100644
index 00000000000..4894e150a8f
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/cmcb.c
@@ -0,0 +1,153 @@
+/* $OpenBSD: cmcb.c,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 callback interface to the cache manager.
+ */
+
+#include "arla_local.h"
+RCSID("$KTH: cmcb.c,v 1.19 1998/04/03 03:32:38 assar Exp $") ;
+
+#include "cb.ss.h"
+
+/*
+ * Create an instance of the callback service and start a server.
+ */
+
+void
+cmcb_init (void)
+{
+ static struct rx_securityClass *nullSecObjP;
+ static struct rx_securityClass *(securityObjects[1]);
+
+ nullSecObjP = rxnull_NewClientSecurityObject ();
+ if (nullSecObjP == NULL) {
+ arla_warnx (ADEBWARN, "Cannot create null security object.");
+ return;
+ }
+
+ securityObjects[0] = nullSecObjP;
+
+ if (rx_NewService (0, CM_SERVICE_ID, "cm", securityObjects,
+ sizeof(securityObjects) / sizeof(*securityObjects),
+ (long (*)())RXAFSCB_ExecuteRequest) == NULL ) {
+ arla_warnx (ADEBWARN, "Cannot install callback service");
+ return;
+ }
+ rx_StartServer (0);
+}
+
+/*
+ * Just tell the host that we're still alive.
+ */
+
+int
+RXAFSCB_Probe (struct rx_call *a_rxCallP)
+{
+ u_long host = rx_HostOf (rx_PeerOf (rx_ConnectionOf (a_rxCallP)));
+ struct in_addr in_addr;
+
+ in_addr.s_addr = host;
+ arla_warnx (ADEBCALLBACK, "probe (%s)", inet_ntoa(in_addr));
+ return 0;
+}
+
+/*
+ * Throw away all callbacks from the host in `a_rxCallP'.
+ */
+
+int
+RXAFSCB_InitCallBackState (struct rx_call *a_rxCallP)
+{
+ u_long host = rx_HostOf (rx_PeerOf (rx_ConnectionOf (a_rxCallP)));
+ struct in_addr in_addr;
+
+ in_addr.s_addr = host;
+ arla_warnx (ADEBCALLBACK, "InitCallBackState (%s)", inet_ntoa(in_addr));
+ fcache_purge_host (host);
+ return 0;
+}
+
+/*
+ * Handle the callbacks in `a_fidArrayP' and `a_callBackArrayP' (this
+ * array can be shorter).
+ * There are two types of callbacks:
+ * - (volume-id, 0, 0) is a volume callback.
+ * - (volume-id, x, y) is a callback on a file.
+ */
+
+int
+RXAFSCB_CallBack (struct rx_call *a_rxCallP,
+ const AFSCBFids *a_fidArrayP,
+ const AFSCBs *a_callBackArrayP)
+{
+ int i;
+ long cell;
+ u_long host = rx_HostOf (rx_PeerOf (rx_ConnectionOf (a_rxCallP)));
+ struct in_addr in_addr;
+
+ in_addr.s_addr = host;
+ arla_warnx (ADEBCALLBACK, "callback (%s)", inet_ntoa(in_addr));
+ cell = conn_host2cell(host, afsport, FS_SERVICE_ID);
+ for (i = 0; i < a_fidArrayP->len; ++i) {
+ VenusFid fid;
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ fid.fid = a_fidArrayP->val[i];
+ fid.Cell = cell;
+ arla_warnx (ADEBCALLBACK, "%d: (%u, %u, %u)", fid.Cell,
+ fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+
+ /*
+ * Check if it's a volume callback.
+ */
+
+ if (fid.fid.Vnode == 0 && fid.fid.Unique == 0) {
+ fcache_purge_volume (fid);
+ volcache_invalidate (fid.fid.Volume, fid.Cell);
+ } else if (i < a_callBackArrayP->len)
+ fcache_stale_entry (fid,
+ a_callBackArrayP->val[i]);
+ else
+ fcache_stale_entry (fid,
+ broken_callback);
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/afs/src/arlad/cmcb.h b/usr.sbin/afs/src/arlad/cmcb.h
new file mode 100644
index 00000000000..05037f76b7b
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/cmcb.h
@@ -0,0 +1,47 @@
+/* $OpenBSD: cmcb.h,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: cmcb.h,v 1.2 1998/02/19 05:36:58 assar Exp $ */
+
+#ifndef _CMCB_H_
+#define _CMCB_H_
+
+void cmcb_init (void);
+
+#endif /* _CMCB_H_ */
diff --git a/usr.sbin/afs/src/arlad/conn.c b/usr.sbin/afs/src/arlad/conn.c
new file mode 100644
index 00000000000..467aefc0a67
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/conn.c
@@ -0,0 +1,468 @@
+/* $OpenBSD: conn.c,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Cache of connections
+ */
+
+
+#include "arla_local.h"
+#ifdef RCSID
+RCSID("$KTH: conn.c,v 1.39 1998/07/13 19:16:55 assar Exp $") ;
+#endif
+
+#define CONNCACHESIZE 101
+
+#define CONNFREELISTINC 17
+
+/* Hashtable of connections */
+static Hashtab *connhtab;
+
+/* A list with free connections */
+static List *connfreelist;
+
+/* # of connections */
+static unsigned nconnections;
+
+/* # of active connections */
+static unsigned nactive_connections;
+
+/*
+ * Functions for handling entries into the connection cache.
+ */
+
+static int
+conncmp (void *a, void *b)
+{
+ ConnCacheEntry *c1 = (ConnCacheEntry*)a;
+ ConnCacheEntry *c2 = (ConnCacheEntry*)b;
+
+ return c1->cred != c2->cred
+ || c1->host != c2->host
+ || c1->service != c2->service
+ || c1->port != c2->port
+ || c1->securityindex != c2->securityindex;
+}
+
+static unsigned int
+connhash (void *a)
+{
+ ConnCacheEntry *c = (ConnCacheEntry*)a;
+
+ return c->cred + c->host + c->service + c->port + c->securityindex;
+}
+
+
+/*
+ * Create `n' ConnCacheEntry's and add them to `connfreelist'
+ */
+
+static void
+create_new_connections (unsigned n)
+{
+ unsigned i;
+ ConnCacheEntry *entries;
+
+ entries = (ConnCacheEntry*)calloc (n, sizeof (ConnCacheEntry));
+ if (entries == NULL)
+ arla_errx (1, ADEBERROR, "conncache: calloc failed");
+ for (i = 0; i < n; ++i) {
+ entries[i].connection = NULL;
+ entries[i].refcount = 0 ;
+ listaddhead (connfreelist, &entries[i]);
+ }
+ nconnections += n;
+}
+
+/*
+ * Initialize the connection cache.
+ */
+
+void
+conn_init (unsigned nentries)
+{
+ arla_warnx (ADEBCONN, "initconncache");
+
+ connhtab = hashtabnew (CONNCACHESIZE, conncmp, connhash);
+ if (connhtab == NULL)
+ arla_errx (1, ADEBERROR, "conn_init: hashtabnew failed");
+ connfreelist = listnew ();
+ if (connfreelist == NULL)
+ arla_errx (1, ADEBERROR, "conn_init: listnew failed");
+ nconnections = 0;
+ create_new_connections (nentries);
+}
+
+/*
+ * Re-cycle an entry:
+ * remove it from the hashtab, clear it out and place it on the freelist.
+ */
+
+static void
+recycle_conn (ConnCacheEntry *e)
+{
+ hashtabdel (connhtab, e);
+ rx_DestroyConnection (e->connection);
+ memset (e, 0, sizeof(*e));
+ listaddhead (connfreelist, e);
+ --nactive_connections;
+}
+
+/*
+ * Remove this connection from the hashtab and add it to the freelist
+ * iff refcount == 0.
+ */
+
+static Bool
+clear_conn (void *ptr, void *arg)
+{
+ ConnCacheEntry *e = (ConnCacheEntry *)ptr;
+
+ if (e->refcount == 0)
+ recycle_conn (e);
+ return FALSE;
+}
+
+/*
+ * Get a free connection to use. Try to pick it from `connfreelist'.
+ * If there are no there, it's time to go through `connhtab' and GC
+ * unused connections. If that fails, allocate some more.
+ * And if that fails, give up.
+ */
+
+static ConnCacheEntry *
+get_free_connection (void)
+{
+ ConnCacheEntry *e;
+
+ e = (ConnCacheEntry *)listdelhead (connfreelist);
+ if (e != NULL)
+ return e;
+
+ hashtabforeach (connhtab, clear_conn, NULL);
+
+ e = (ConnCacheEntry *)listdelhead (connfreelist);
+ if (e != NULL)
+ return e;
+
+ create_new_connections (CONNFREELISTINC);
+
+ e = (ConnCacheEntry *)listdelhead (connfreelist);
+ if (e != NULL)
+ return e;
+
+ arla_errx (1, ADEBERROR,
+ "conncache: there was no way of getting a connection");
+}
+
+/*
+ * Get a free connection, fill in all parameters and create a
+ * rx_connection.
+ */
+
+static ConnCacheEntry *
+new_connection (int32_t cell,
+ u_int32_t host,
+ u_int16_t port,
+ u_int16_t service,
+ pag_t cred,
+ int securityindex,
+ struct rx_securityClass *securityobject)
+{
+ ConnCacheEntry *e;
+
+ e = get_free_connection ();
+
+ e->cell = cell;
+ e->host = host;
+ e->port = port;
+ e->service = service;
+ e->flags.alivep = TRUE;
+ e->refcount = 0;
+ e->cred = cred;
+ e->securityindex = securityindex;
+
+ e->connection = rx_NewConnection (host,
+ htons (port),
+ service,
+ securityobject,
+ securityindex);
+ if (e->connection == NULL)
+ arla_errx (1, ADEBERROR, "rx_NewConnection failed");
+ return e;
+}
+
+/*
+ * Create a new connection and add it to `connhtab'.
+ */
+
+static ConnCacheEntry *
+add_connection(int32_t cell,
+ u_int32_t host,
+ u_int16_t port,
+ u_int16_t service,
+ CredCacheEntry *ce)
+{
+ ConnCacheEntry *e;
+ struct rx_securityClass *securityobj;
+ int securityindex;
+ pag_t cred;
+
+ if (ce) {
+ securityindex = ce->securityindex;
+ cred = ce->cred;
+
+ switch (ce->type) {
+#ifdef KERBEROS
+ case CRED_KRB4 :
+ case CRED_KRB5 : {
+ krbstruct *krbdata = (krbstruct *)ce->cred_data;
+
+ securityobj = rxkad_NewClientSecurityObject(
+ rxkad_auth,
+ &krbdata->c.session,
+ krbdata->c.kvno,
+ krbdata->c.ticket_st.length,
+ krbdata->c.ticket_st.dat);
+ break;
+ }
+#endif
+ case CRED_NONE :
+ securityobj = rxnull_NewClientSecurityObject ();
+ break;
+ default :
+ abort();
+ }
+ } else {
+ securityobj = rxnull_NewClientSecurityObject ();
+ securityindex = 0;
+ cred = 0;
+ }
+
+ e = new_connection (cell, host, port, service,
+ cred, securityindex, securityobj);
+
+ hashtabadd (connhtab, (void *)e);
+ ++nactive_connections;
+
+ return e;
+}
+
+
+/*
+ * Find a connection from the cache given:
+ * (cell, host, port, service, cred).
+ * If there's no connection at all, create one.
+ */
+
+ConnCacheEntry *
+conn_get (int32_t cell,
+ u_int32_t host,
+ u_int16_t port,
+ u_int16_t service,
+ CredCacheEntry *ce)
+{
+ ConnCacheEntry *e;
+ ConnCacheEntry key;
+
+ if (connected_mode == DISCONNECTED)
+ return NULL;
+
+ key.host = host;
+ key.port = port;
+ key.service = service;
+ key.cred = ce->cred;
+ key.securityindex = ce->securityindex;
+
+ e = (ConnCacheEntry *)hashtabsearch (connhtab, (void *)&key);
+
+ if (e == NULL) {
+ if (ce->securityindex || ce->cred) {
+ key.cred = 0;
+ key.securityindex = 0;
+ e = (ConnCacheEntry *)hashtabsearch (connhtab, (void *)&key);
+ if (e == NULL)
+ add_connection (cell, host, port, service, NULL);
+ }
+
+ e = add_connection (cell, host, port, service, ce);
+ }
+
+ ++e->refcount;
+ return e;
+}
+
+/*
+ * Free a reference to a ConnCacheEntry.
+ * If refcount drops to zero, it makes it eligible for re-use.
+ */
+
+void
+conn_free (ConnCacheEntry *e)
+{
+ if (e == NULL) /* When in disconnected mode conn sets to NULL */
+ return;
+
+ --e->refcount;
+ if (e->refcount == 0 && e->flags.killme)
+ recycle_conn (e);
+}
+
+/*
+ * Given a host try to figure out what cell it's in.
+ */
+
+int32_t
+conn_host2cell (u_int32_t host, u_int16_t port, u_int16_t service)
+{
+ ConnCacheEntry *e;
+ ConnCacheEntry key;
+
+ key.host = host;
+ key.port = port;
+ key.service = service;
+ key.cred = 0;
+ key.securityindex = 0;
+
+ e = (ConnCacheEntry *)hashtabsearch(connhtab, (void *)&key);
+ if (e == NULL)
+ return -1;
+ else
+ return e->cell;
+}
+
+/*
+ * Is the service at (cell, host, port, service) up?
+ */
+
+Bool
+conn_serverupp (u_int32_t host, u_int16_t port, u_int16_t service)
+{
+ ConnCacheEntry *e;
+ ConnCacheEntry key;
+
+ key.host = host;
+ key.port = port;
+ key.service = service;
+ key.cred = 0;
+ key.securityindex = 0;
+
+ e = (ConnCacheEntry *)hashtabsearch (connhtab, (void *)&key);
+ if (e != NULL)
+ return e->flags.alivep;
+ else
+ return TRUE;
+}
+
+/*
+ * Print an entry.
+ */
+
+static Bool
+print_conn (void *ptr, void *arg)
+{
+ ConnCacheEntry *e = (ConnCacheEntry *)ptr;
+ FILE *f = (FILE *)arg;
+ struct in_addr tmp;
+
+ tmp.s_addr = e->host;
+
+ fprintf (f, "host = %s, port = %d, service = %d, "
+ "cell = %d (%s), "
+ "securityindex = %d, cred = %u, "
+ "conn = %p, alive = %d, "
+ "killme = %d, refcount = %d\n\n",
+ inet_ntoa(tmp), e->port, e->service, e->cell,
+ cell_num2name (e->cell),
+ e->securityindex, e->cred, e->connection,
+ e->flags.alivep, e->flags.killme, e->refcount);
+
+ return FALSE;
+}
+
+/*
+ * Print the status of the connection cache.
+ */
+
+void
+conn_status (FILE *f)
+{
+ fprintf (f, "%u(%u) connections\n",
+ nactive_connections, nconnections);
+ hashtabforeach (connhtab, print_conn, f);
+}
+
+struct clear_state {
+ int32_t cell;
+ pag_t cred;
+ int securityindex;
+};
+
+static Bool
+clear_cred (void *ptr, void *arg)
+{
+ ConnCacheEntry *e = (ConnCacheEntry *)ptr;
+ struct clear_state *s = (struct clear_state *)arg;
+
+ if (e->cred == s->cred
+ && (s->cell == 0 || e->cell == s->cell)
+ && e->securityindex == s->securityindex) {
+ if (e->refcount > 0)
+ e->flags.killme = 1;
+ else
+ recycle_conn (e);
+ }
+ return FALSE;
+}
+
+/*
+ * Remove all connections matching (cell, cred, securityindex).
+ */
+
+void
+conn_clearcred(int32_t cell, pag_t cred, int securityindex)
+{
+ struct clear_state s;
+
+ s.cell = cell;
+ s.cred = cred;
+ s.securityindex = securityindex;
+
+ hashtabforeach (connhtab, clear_cred, (void *)&s);
+}
diff --git a/usr.sbin/afs/src/arlad/conn.h b/usr.sbin/afs/src/arlad/conn.h
new file mode 100644
index 00000000000..42fbf2c7e55
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/conn.h
@@ -0,0 +1,90 @@
+/* $OpenBSD: conn.h,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 for connection cache
+ */
+
+/* $KTH: conn.h,v 1.11 1998/02/19 05:39:03 assar Exp $ */
+
+#ifndef _CONN_H_
+#define _CONN_H_
+
+#include <stdio.h>
+#include <xfs/xfs_message.h>
+#include <cred.h>
+
+typedef struct {
+ u_int32_t host; /* IP address of host */
+ u_int16_t port; /* port number at host */
+ u_int16_t service; /* RX service # */
+ int32_t cell; /* cell of host */
+ int securityindex;
+ pag_t cred;
+ struct rx_connection *connection;
+ struct {
+ unsigned alivep : 1;
+ unsigned killme : 1;
+ } flags;
+ unsigned refcount;
+} ConnCacheEntry;
+
+void
+conn_init (unsigned nentries);
+
+ConnCacheEntry *
+conn_get (int32_t cell, u_int32_t host, u_int16_t port, u_int16_t service,
+ CredCacheEntry *ce);
+
+void
+conn_free (ConnCacheEntry *e);
+
+int32_t
+conn_host2cell (u_int32_t host, u_int16_t port, u_int16_t service);
+
+Bool
+conn_serverupp (u_int32_t host, u_int16_t port, u_int16_t service);
+
+void
+conn_status (FILE *);
+
+void
+conn_clearcred (int32_t cell, pag_t cred, int securityindex);
+
+#endif /* _CONN_H_ */
diff --git a/usr.sbin/afs/src/arlad/cred.c b/usr.sbin/afs/src/arlad/cred.c
new file mode 100644
index 00000000000..51f2568d395
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/cred.c
@@ -0,0 +1,317 @@
+/* $OpenBSD: cred.c,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Cache of credentials
+ */
+
+#include "arla_local.h"
+RCSID("$KTH: cred.c,v 1.22 1998/06/08 22:26:59 map Exp $");
+
+#define CREDCACHESIZE 101
+
+#define CREDFREEINC 10
+
+/* a hashtable of all credentials */
+static Hashtab *credhtab;
+
+/* list of all free entries */
+static List *freelist;
+
+/* # of credentials */
+static unsigned ncredentials;
+
+/* # of active credentials */
+static unsigned nactive_credentials;
+
+/*
+ * Functions for handling entries into the credentials cache.
+ */
+
+static int
+credcmp (void *a, void *b)
+{
+ CredCacheEntry *c1 = (CredCacheEntry*)a;
+ CredCacheEntry *c2 = (CredCacheEntry*)b;
+
+ return c1->cred != c2->cred
+ || c1->type != c2->type
+ || c1->cell != c2->cell;
+}
+
+static unsigned
+credhash (void *a)
+{
+ CredCacheEntry *c = (CredCacheEntry*)a;
+
+ return c->cred + c->type + c->cell;
+}
+
+
+/*
+ * Create `n' credentials and add them to `freelist'
+ */
+
+static void
+create_new_credentials (unsigned n)
+{
+ unsigned i;
+ CredCacheEntry *entries;
+
+ entries = (CredCacheEntry*)calloc (n, sizeof (CredCacheEntry));
+ if (entries == NULL)
+ arla_errx (1, ADEBERROR, "credcache: calloc failed");
+ for (i = 0; i < n; ++i) {
+ entries[i].cred_data = NULL;
+ listaddhead (freelist, &entries[i]);
+ }
+ ncredentials += n;
+}
+
+/*
+ * Initialize the cred cache.
+ */
+
+void
+cred_init (unsigned nentries)
+{
+ credhtab = hashtabnew (CREDCACHESIZE, credcmp, credhash);
+ if (credhtab == NULL)
+ arla_errx (1, ADEBERROR, "cred_init: hashtabnew failed");
+ freelist = listnew ();
+ if (freelist == NULL)
+ arla_errx (1, ADEBERROR, "cred_init: listnew failed");
+ ncredentials = 0;
+ create_new_credentials (nentries);
+}
+
+static CredCacheEntry *
+internal_get (long cell, pag_t cred, int type)
+{
+ CredCacheEntry *e;
+ CredCacheEntry key;
+
+ key.cell = cell;
+ key.type = type;
+ key.cred = cred;
+
+ e = (CredCacheEntry *)hashtabsearch (credhtab, (void *)&key);
+
+ if (e == NULL && type == CRED_NONE) {
+ e = cred_add (cred, type, 0, cell, 0, NULL, 0);
+ }
+
+ if (e != NULL)
+ ++e->refcount;
+
+ return e;
+}
+
+CredCacheEntry *
+cred_get (long cell, pag_t cred, int type)
+{
+ if (type == CRED_ANY) {
+ CredCacheEntry *e;
+ int i;
+
+ for (i = CRED_MAX; i > CRED_NONE; --i) {
+ e = internal_get (cell, cred, i);
+ if (e != NULL)
+ return e;
+ }
+
+ return internal_get (cell, cred, CRED_NONE);
+ } else
+ return internal_get (cell, cred, type);
+}
+
+static void
+recycle_entry (CredCacheEntry *ce)
+{
+ hashtabdel (credhtab, ce);
+ if (ce->cred_data != NULL)
+ free (ce->cred_data);
+ memset (ce, 0, sizeof(*ce));
+ listaddhead (freelist, ce);
+ --nactive_credentials;
+}
+
+void
+cred_free (CredCacheEntry *ce)
+{
+ --ce->refcount;
+ if (ce->flags.killme && ce->refcount == 0)
+ recycle_entry (ce);
+}
+
+static CredCacheEntry *
+get_free_cred (void)
+{
+ CredCacheEntry *e;
+
+ e = (CredCacheEntry *)listdelhead (freelist);
+ if (e != NULL)
+ return e;
+
+ create_new_credentials (CREDFREEINC);
+
+ e = (CredCacheEntry *)listdelhead (freelist);
+ if (e != NULL)
+ return e;
+
+ arla_errx (1, ADEBERROR,
+ "credcache: there was no way of getting a cred");
+}
+
+CredCacheEntry *
+cred_add (pag_t cred, int type, int securityindex, long cell,
+ time_t expire, void *cred_data, size_t cred_data_sz)
+{
+ void *data;
+ CredCacheEntry *e;
+ CredCacheEntry *old;
+
+ if (cred_data != NULL) {
+ data = malloc (cred_data_sz);
+ if (data == NULL)
+ return NULL;
+ memcpy (data, cred_data, cred_data_sz);
+ } else
+ data = NULL;
+
+ e = get_free_cred ();
+
+ e->cred = cred;
+ e->type = type;
+ e->securityindex = securityindex;
+ e->cell = cell;
+ e->expire = expire;
+ e->cred_data = data;
+
+ old = hashtabsearch (credhtab, e);
+ if (old != NULL)
+ recycle_entry (old);
+
+ hashtabadd (credhtab, e);
+ ++nactive_credentials;
+ return e;
+}
+
+#if KERBEROS
+CredCacheEntry *
+cred_add_krb4 (pag_t cred, CREDENTIALS *c)
+{
+ CredCacheEntry *ce;
+ char *cellname;
+ int cellnum;
+
+ if (*c->instance == '\0')
+ cellname = strdup (c->realm);
+ else
+ cellname = strdup (c->instance);
+ strlwr (cellname);
+ cellnum = cell_name2num(cellname);
+ free (cellname);
+ assert (cellnum != -1);
+
+ ce = cred_add (cred, CRED_KRB4, 2, cellnum, -1, c, sizeof(*c));
+ return ce;
+}
+#endif
+
+/*
+ *
+ */
+
+void
+cred_delete (CredCacheEntry *ce)
+{
+ if (ce->refcount > 0)
+ ce->flags.killme = 1;
+ else
+ recycle_entry (ce);
+}
+
+/*
+ *
+ */
+
+void
+cred_expire (CredCacheEntry *ce)
+{
+ cred_delete (ce);
+}
+
+static Bool
+remove_entry (void *ptr, void *arg)
+{
+ CredCacheEntry *ce = (CredCacheEntry *)ptr;
+ pag_t *cred = (pag_t *)arg;
+
+ if (ce->cred == *cred)
+ cred_delete (ce);
+ return FALSE;
+}
+
+void
+cred_remove (pag_t cred)
+{
+ hashtabforeach (credhtab, remove_entry, &cred);
+}
+
+static Bool
+print_cred (void *ptr, void *arg)
+{
+ CredCacheEntry *e = (CredCacheEntry *)ptr;
+ FILE *f = (FILE *)arg;
+
+ fprintf (f, "cred = %u, type = %d, securityindex = %d\n"
+ "cell = %ld, refcount = %u, killme = %d\n\n",
+ e->cred, e->type, e->securityindex, e->cell, e->refcount,
+ e->flags.killme);
+ return FALSE;
+}
+
+void
+cred_status (FILE *f)
+{
+ fprintf (f, "%u(%u) credentials\n",
+ nactive_credentials, ncredentials);
+ hashtabforeach (credhtab, print_cred, f);
+}
diff --git a/usr.sbin/afs/src/arlad/cred.h b/usr.sbin/afs/src/arlad/cred.h
new file mode 100644
index 00000000000..2faa6f91aa4
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/cred.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: cred.h,v 1.1.1.1 1998/09/14 21:52:55 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 for credetial cache
+ */
+
+/* $KTH: cred.h,v 1.18 1998/05/02 01:03:25 assar Exp $ */
+
+#ifndef _CRED_H_
+#define _CRED_H_
+
+#include <sys/types.h>
+#include <time.h>
+#include <lock.h>
+#ifdef KERBEROS
+#include <des.h>
+#include <kerberosIV/krb.h>
+#endif /* KERBEROS */
+#include "bool.h"
+#include <xfs/xfs_message.h>
+
+/* The cred-types we support */
+#define CRED_NONE 0
+#define CRED_KRB4 1
+#define CRED_KRB5 2
+#define CRED_MAX CRED_KRB5
+#define CRED_ANY (-1)
+
+#ifdef KERBEROS
+typedef struct {
+ CREDENTIALS c;
+} krbstruct;
+#endif
+
+typedef struct {
+ pag_t cred;
+ int type;
+ int securityindex;
+ long cell;
+ time_t expire;
+ void *cred_data;
+ struct {
+ unsigned killme : 1;
+ } flags;
+ unsigned refcount;
+} CredCacheEntry;
+
+void cred_init (unsigned nentries);
+
+CredCacheEntry *
+cred_get (long cell, pag_t cred, int type);
+
+void
+cred_free (CredCacheEntry *ce);
+
+CredCacheEntry *
+cred_add (pag_t cred, int type, int securityindex, long cell,
+ time_t expire, void *cred_data, size_t cred_data_sz);
+
+void
+cred_delete (CredCacheEntry *ce);
+
+void
+cred_expire (CredCacheEntry *ce);
+
+#ifdef KERBEROS
+CredCacheEntry * cred_add_krb4 (pag_t cred, CREDENTIALS *c);
+#endif
+
+void cred_status (FILE *f);
+
+void cred_remove (pag_t cred);
+
+#endif /* _CRED_H_ */
diff --git a/usr.sbin/afs/src/arlad/fbuf.c b/usr.sbin/afs/src/arlad/fbuf.c
new file mode 100644
index 00000000000..c7994a0417d
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fbuf.c
@@ -0,0 +1,377 @@
+/* $OpenBSD: fbuf.c,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "arla_local.h"
+RCSID("$KTH: fbuf.c,v 1.16 1998/07/29 13:37:29 assar Exp $") ;
+
+#ifdef BROKEN_MMAP
+#undef HAVE_MMAP
+#endif
+
+#if defined(HAVE_MMAP) && !defined(MAP_FAILED)
+#define MAP_FAILED ((void *)(-1))
+#endif
+
+#ifdef HAVE_MMAP
+
+static int
+mmap_flags (fbuf_flags flags)
+{
+ int ret = 0;
+
+ if (flags & FBUF_READ)
+ ret = MAP_PRIVATE;
+ if (flags & FBUF_WRITE)
+ ret = MAP_SHARED;
+ return ret;
+}
+
+static int
+mmap_create (fbuf *f, int fd, size_t len, fbuf_flags flags)
+{
+ void *buf;
+
+ if (len != 0) {
+ buf = mmap (0, len, PROT_READ | PROT_WRITE, mmap_flags(flags), fd, 0);
+ if (buf == (void *) MAP_FAILED) {
+ close (fd);
+ return errno;
+ }
+ } else
+ buf = NULL;
+
+ f->buf = buf;
+ f->fd = fd;
+ f->len = len;
+ f->flags = flags;
+ return 0;
+}
+
+static int
+mmap_truncate (fbuf *f, size_t new_len)
+{
+ int ret;
+
+ if (f->buf != NULL) {
+ ret = munmap (f->buf, f->len);
+ if (ret < 0) {
+ close (f->fd);
+ return errno;
+ }
+ }
+ ret = ftruncate (f->fd, new_len);
+ if (ret < 0) {
+ close (f->fd);
+ return errno;
+ }
+ return mmap_create (f, f->fd, new_len, f->flags);
+}
+
+static int
+mmap_end (fbuf *f)
+{
+ int ret;
+
+ ret = munmap (f->buf, f->len);
+ if (ret < 0)
+ ret = errno;
+ close (f->fd);
+ return ret;
+}
+
+static int
+mmap_copyrx2fd (struct rx_call *call, int fd, size_t len)
+{
+ void *buf;
+ int r_len;
+ int save_errno;
+
+ if(ftruncate (fd, len) < 0)
+ return errno;
+ buf = mmap (0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (buf == (void *) MAP_FAILED)
+ return errno;
+ r_len = rx_Read (call, buf, len);
+ save_errno = errno;
+ munmap (buf, len);
+ ftruncate (fd, len);
+ close (fd);
+ if (r_len != len) {
+ return save_errno;
+ } else {
+ return 0;
+ }
+}
+
+static int
+mmap_copyfd2rx (int fd, struct rx_call *call, size_t len)
+{
+ void *buf;
+ int r_write;
+ int save_errno;
+
+ buf = mmap (0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (buf == (void *) MAP_FAILED)
+ return errno;
+ r_write = rx_Write (call, buf, len);
+ save_errno = errno;
+ munmap (buf, len);
+ close (fd);
+ if (r_write != len)
+ return save_errno;
+ else
+ return 0;
+}
+
+#else /* !HAVE_MMAP */
+
+static int
+malloc_create (fbuf *f, int fd, size_t len, fbuf_flags flags)
+{
+ void *buf;
+
+ buf = malloc (len);
+ if (buf == NULL) {
+ close(fd);
+ return ENOMEM;
+ }
+ if (read (fd, buf, len) != len) {
+ free(buf);
+ close(fd);
+ return errno;
+ }
+ f->buf = buf;
+ f->fd = fd;
+ f->len = len;
+ f->flags = flags;
+ return 0;
+}
+
+static int
+malloc_flush (fbuf *f)
+{
+ if (f->flags & FBUF_WRITE) {
+ lseek (f->fd, SEEK_SET, 0);
+ if (write (f->fd, f->buf, f->len) != f->len)
+ return errno;
+ }
+ return 0;
+}
+
+static int
+malloc_end (fbuf *f)
+{
+ int ret;
+
+ ret = malloc_flush (f);
+ free (f->buf);
+ close (f->fd);
+ return ret;
+}
+
+static int
+malloc_truncate (fbuf *f, size_t new_len)
+{
+ void *buf;
+ int ret;
+
+ ret = malloc_flush (f);
+ if (ret)
+ goto fail;
+
+ ret = ftruncate (f->fd, new_len);
+ if (ret < 0) {
+ ret = errno;
+ goto fail;
+ }
+
+ buf = realloc (f->buf, new_len);
+ if (buf == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ f->buf = buf;
+ f->len = new_len;
+ return 0;
+
+fail:
+ free (f->buf);
+ close (f->fd);
+ return ret;
+}
+
+static int
+malloc_copyrx2fd (struct rx_call *call, int fd, size_t len)
+{
+ void *buf;
+ struct stat statbuf;
+ u_long bufsize;
+ u_long nread;
+ size_t reallen = len;
+ int ret = 0;
+
+ if (fstat (fd, &statbuf)) {
+ arla_warn (ADEBFBUF, errno, "fstat");
+ bufsize = 1024;
+ } else
+ bufsize = statbuf.st_blksize;
+
+ buf = malloc (bufsize);
+ if (buf == NULL)
+ return ENOMEM;
+
+ while ( len && (nread = rx_Read (call, buf, min(bufsize,
+ len))) > 0) {
+ if (write (fd, buf, nread) != nread) {
+ ret = errno;
+ break;
+ }
+ len -= nread;
+ }
+ if (ftruncate (fd, reallen) < 0)
+ ret = errno;
+ close (fd);
+ free (buf);
+ return ret;
+}
+
+static int
+malloc_copyfd2rx (int fd, struct rx_call *call, size_t len)
+{
+ void *buf;
+ struct stat statbuf;
+ u_long bufsize;
+ u_long nread;
+ int ret = 0;
+
+ if (fstat (fd, &statbuf)) {
+ arla_warn (ADEBFBUF, errno, "fstat");
+ bufsize = 1024;
+ } else
+ bufsize = statbuf.st_blksize;
+
+ buf = malloc (bufsize);
+ if (buf == NULL)
+ return ENOMEM;
+
+ while (len
+ && (nread = read (fd, buf, min(bufsize, len))) > 0) {
+ if (rx_Write (call, buf, nread) != nread) {
+ ret = errno;
+ break;
+ }
+ len -= nread;
+ }
+ close (fd);
+ free (buf);
+ return ret;
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Return a pointer to a copy of this file contents. If we have mmap,
+ * we use that, otherwise we have to allocate some memory and read it.
+ */
+
+int
+fbuf_create (fbuf *f, int fd, size_t len, fbuf_flags flags)
+{
+#ifdef HAVE_MMAP
+ return mmap_create (f, fd, len, flags);
+#else
+ return malloc_create (f, fd, len, flags);
+#endif
+}
+
+/*
+ * Undo everything we did in fbuf_create.
+ */
+
+int
+fbuf_end (fbuf *f)
+{
+#ifdef HAVE_MMAP
+ return mmap_end (f);
+#else
+ return malloc_end (f);
+#endif
+}
+
+/*
+ * Make the file (and the buffer) be `new_len' bytes.
+ */
+
+int
+fbuf_truncate (fbuf *f, size_t new_len)
+{
+#ifdef HAVE_MMAP
+ return mmap_truncate (f, new_len);
+#else
+ return malloc_truncate (f, new_len);
+#endif
+}
+
+/*
+ * Copy from a RX_call to a fd.
+ */
+
+int
+copyrx2fd (struct rx_call *call, int fd, size_t len)
+{
+#ifdef HAVE_MMAP
+ return mmap_copyrx2fd (call, fd, len);
+#else
+ return malloc_copyrx2fd (call, fd, len);
+#endif
+}
+
+/*
+ * Copy from a file descriptor to a RX call.
+ */
+
+int
+copyfd2rx (int fd, struct rx_call *call, size_t len)
+{
+#ifdef HAVE_MMAP
+ return mmap_copyfd2rx (fd, call, len);
+#else
+ return malloc_copyfd2rx (fd, call, len);
+#endif
+}
diff --git a/usr.sbin/afs/src/arlad/fbuf.h b/usr.sbin/afs/src/arlad/fbuf.h
new file mode 100644
index 00000000000..9e20d00dfca
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fbuf.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: fbuf.h,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: fbuf.h,v 1.5 1998/02/22 08:09:09 assar Exp $ */
+
+#ifndef _FBUF_H_
+#define _FBUF_H_
+
+typedef enum { FBUF_READ = 1, FBUF_WRITE = 2 } fbuf_flags;
+
+struct fbuf {
+ void *buf;
+ int fd;
+ size_t len;
+ fbuf_flags flags;
+};
+
+typedef struct fbuf fbuf;
+
+int fbuf_create (fbuf *fbuf, int fd, size_t len, fbuf_flags flags);
+int fbuf_truncate (fbuf *fbuf, size_t new_len);
+int fbuf_end (fbuf *fbuf);
+
+int copyrx2fd (struct rx_call *call, int fd, size_t len);
+int copyfd2rx (int fd, struct rx_call *call, size_t len);
+
+#endif /* _FBUF_H_ */
diff --git a/usr.sbin/afs/src/arlad/fcache.c b/usr.sbin/afs/src/arlad/fcache.c
new file mode 100644
index 00000000000..0517c17ef78
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fcache.c
@@ -0,0 +1,2457 @@
+/* $OpenBSD: fcache.c,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 is the cache for files.
+ * The hash-table is keyed with (cell, volume, fid).
+ */
+
+#include "arla_local.h"
+RCSID("$KTH: fcache.c,v 1.114 1998/08/13 21:32:38 assar Exp $") ;
+
+/*
+ * Local data for this module.
+ */
+
+/*
+ * Hash table for all the vnodes known by the cache manager keyed by
+ * (cell, volume, vnode, unique).
+ */
+
+static Hashtab *hashtab;
+
+/*
+ * List of all hash table entries. This list is sorted in LRU-order.
+ * The head is the MRU and the tail the LRU, which is from where we
+ * take entries when we need to add new ones.
+ */
+
+static List *lrulist;
+
+/*
+ * List of entries to be invalidated.
+ */
+
+static List *invalid_list;
+
+/* low and high-water marks for vnodes and space */
+
+static u_long lowvnodes, highvnodes, lowbytes, highbytes;
+
+/* current values */
+
+static u_long usedbytes, usedvnodes;
+
+/*
+ * This is how far the cleaner will go to clean out entries.
+ * The higher this is, the higher is the risk that you will
+ * lose any file that you feel is important to disconnected
+ * operation.
+ */
+
+unsigned fprioritylevel;
+
+/* This is just temporary for allocating "inode"-numbers. */
+
+static int inode_count; /* XXX */
+
+#define FCHASHSIZE 997
+
+/*
+ * The cleaner
+ */
+
+#define CLEANER_STACKSIZE (16*1024)
+#define CLEANER_SLEEP 10
+
+static PROCESS cleaner_pid;
+
+/*
+ * The creator of nodes.
+ */
+
+#define CREATE_NODES_STACKSIZE (16*1024)
+
+static PROCESS create_nodes_pid;
+
+/*
+ * The invalidator
+ */
+
+#define INVALIDATOR_STACKSIZE (16*1024)
+
+static PROCESS invalidator_pid;
+
+/*
+ * Compare two entries. Return 0 if and only if the same.
+ */
+
+static int
+fcachecmp (void *a, void *b)
+{
+ FCacheEntry *f1 = (FCacheEntry*)a;
+ FCacheEntry *f2 = (FCacheEntry*)b;
+
+ return f1->fid.Cell != f2->fid.Cell
+ || f1->fid.fid.Volume != f2->fid.fid.Volume
+ || f1->fid.fid.Vnode != f2->fid.fid.Vnode
+ || f1->fid.fid.Unique != f2->fid.fid.Unique;
+}
+
+/*
+ * Hash the value of an entry.
+ */
+
+static unsigned
+fcachehash (void *e)
+{
+ FCacheEntry *f = (FCacheEntry*)e;
+
+ return f->fid.Cell + f->fid.fid.Volume + f->fid.fid.Vnode
+ + f->fid.fid.Unique;
+}
+
+/*
+ * Globalnames
+ */
+
+char arlasysname[SYSNAMEMAXLEN];
+
+/*
+ * Create `n' new entries
+ */
+
+static void
+create_new_entries (unsigned n)
+{
+ FCacheEntry *entries;
+ unsigned int i, j;
+
+ entries = calloc (n, sizeof(FCacheEntry));
+ if (entries == NULL)
+ arla_errx (1, ADEBERROR, "fcache: calloc failed");
+
+ for (i = 0; i < n; ++i) {
+ entries[i].lru_le = listaddhead (lrulist, &entries[i]);
+ entries[i].invalid_le = NULL;
+ entries[i].volume = NULL;
+ entries[i].refcount = 0;
+ entries[i].anonaccess = 0;
+ for (j = 0; j < NACCESS; j++) {
+ entries[i].acccache[j].cred = ARLA_NO_AUTH_CRED;
+ entries[i].acccache[j].access = 0;
+ }
+ Lock_Init(&entries[i].lock);
+ }
+}
+
+
+/*
+ * Discard the data cached for `entry'.
+ */
+
+static void
+throw_data (FCacheEntry *entry)
+{
+ int fd;
+
+ assert (entry->flags.datap && entry->flags.usedp
+ && CheckLock(&entry->lock) == -1);
+
+ fd = fcache_open_file (entry, O_WRONLY | O_TRUNC, 0);
+ if (fd < 0) {
+ arla_warn (ADEBFCACHE, errno, "fcache_open_file");
+ return;
+ }
+ close (fd);
+ if (entry->flags.extradirp) {
+ char fname[MAXPATHLEN];
+
+ fcache_extra_file_name (entry, fname, sizeof(fname));
+ unlink (fname);
+ }
+ assert(usedbytes >= entry->status.Length);
+ usedbytes -= entry->status.Length;
+ entry->flags.datap = FALSE;
+ entry->flags.extradirp = FALSE;
+}
+
+/*
+ *
+ */
+
+static void
+throw_entry (FCacheEntry *entry)
+{
+ CredCacheEntry *ce;
+ ConnCacheEntry *conn;
+ AFSCBFids fids;
+ AFSCBs cbs;
+ int ret;
+
+ assert (entry->flags.usedp && entry->volume != NULL
+ && CheckLock(&entry->lock) == -1);
+
+ hashtabdel (hashtab, entry);
+
+ if (entry->flags.datap)
+ throw_data (entry);
+
+ if (entry->invalid_le != NULL) {
+ listdel (invalid_list, entry->invalid_le);
+ entry->invalid_le = NULL;
+ }
+
+ if (entry->flags.attrp && entry->host) {
+ ce = cred_get (entry->fid.Cell, 0, CRED_NONE);
+ assert (ce != NULL);
+
+ conn = conn_get (entry->fid.Cell, entry->host, afsport,
+ FS_SERVICE_ID, ce);
+ cred_free (ce);
+
+ fids.len = cbs.len = 1;
+ fids.val = &entry->fid.fid;
+ cbs.val = &entry->callback;
+ ret = RXAFS_GiveUpCallBacks (conn->connection, &fids, &cbs);
+ conn_free (conn);
+ if (ret)
+ arla_warn (ADEBFCACHE, ret, "RXAFS_GiveUpCallBacks");
+ }
+ volcache_free (entry->volume);
+ entry->volume = NULL;
+/* entry->inode = 0;*/
+ entry->flags.attrp = FALSE;
+ entry->flags.usedp = FALSE;
+ --usedvnodes;
+}
+
+/*
+ * Return the next inode-number.
+ */
+
+static ino_t
+nextinode (void)
+{
+ return inode_count++;
+}
+
+/*
+ *
+ */
+
+static void
+create_nodes (char *arg)
+{
+ Listitem *item;
+ FCacheEntry *entry;
+ int fd;
+ unsigned count = 0;
+
+ arla_warnx (ADEBFCACHE,
+ "pre-creating nodes");
+
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+
+ entry = (FCacheEntry *)listdata (item);
+ assert (entry->lru_le == item);
+ if (!entry->flags.usedp
+ && CheckLock(&entry->lock) == 0
+ && entry->inode == 0) {
+ struct timeval tv;
+
+ ObtainWriteLock (&entry->lock);
+ entry->inode = nextinode ();
+ fd = fcache_open_file (entry, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ close (fd);
+ ReleaseWriteLock (&entry->lock);
+ ++count;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ IOMGR_Select(0, NULL, NULL, NULL, &tv);
+ }
+ }
+
+ arla_warnx (ADEBFCACHE,
+ "pre-created %u nodes", count);
+}
+
+/*
+ *
+ */
+
+static void
+cleaner (char *arg)
+{
+ for (;;) {
+ Listitem *item, *prev;
+ FCacheEntry *entry;
+ int prio;
+
+ arla_warnx(ADEBCLEANER,
+ "running cleaner: "
+ "%lu (%lu-%lu) files, "
+ "%lu (%lu-%lu) bytes",
+ usedvnodes, lowvnodes, highvnodes,
+ usedbytes, lowbytes, highbytes);
+
+ for (prio = 0 ; prio <= fprioritylevel ; prio += 10) {
+
+ while (usedvnodes > lowvnodes) {
+
+ for (item = listtail (lrulist);
+ item && usedvnodes > lowvnodes;
+ item = prev) {
+ prev = listprev (lrulist, item);
+ entry = (FCacheEntry *)listdata (item);
+ assert (entry->lru_le == item);
+ if (entry->flags.usedp
+ && !entry->flags.attrusedp
+ && !entry->flags.datausedp
+ && entry->priority < prio
+ && entry->refcount == 0
+ && CheckLock(&entry->lock) == 0) {
+ listdel (lrulist, item);
+ ObtainWriteLock (&entry->lock);
+ throw_entry (entry);
+ ReleaseWriteLock (&entry->lock);
+ entry->lru_le = listaddtail (lrulist, entry);
+ break;
+ }
+ }
+ if (item == NULL)
+ break;
+ }
+
+ for (item = listtail (lrulist);
+ item && usedbytes > lowbytes;
+ item = listprev (lrulist, item)) {
+ entry = (FCacheEntry *)listdata (item);
+ assert (entry->lru_le == item);
+ if (entry->flags.datap
+ && !entry->flags.datausedp
+ && entry->priority < prio
+ && entry->refcount == 0
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ throw_data (entry);
+ ReleaseWriteLock (&entry->lock);
+ }
+ }
+ }
+
+ arla_warnx(ADEBCLEANER,
+ "cleaner done: "
+ "%lu (%lu-%lu) files, "
+ "%lu (%lu-%lu) bytes",
+ usedvnodes, lowvnodes, highvnodes,
+ usedbytes, lowbytes, highbytes);
+
+ IOMGR_Sleep (CLEANER_SLEEP);
+ }
+}
+
+/*
+ *
+ */
+
+static void
+invalidator (char *arg)
+{
+ for (;;) {
+ Listitem *item, *next;
+ struct timeval tv;
+
+ while (listemptyp (invalid_list))
+ LWP_WaitProcess (invalid_list);
+
+ gettimeofday (&tv, NULL);
+
+ for (item = listhead (invalid_list);
+ item;
+ item = next) {
+ FCacheEntry *entry = (FCacheEntry *)listdata(item);
+
+ assert (entry->invalid_le == item);
+
+ next = listnext (invalid_list, item);
+ if (tv.tv_sec < entry->callback.ExpirationTime) {
+ IOMGR_Sleep (entry->callback.ExpirationTime - tv.tv_sec);
+ break;
+ }
+
+ ObtainWriteLock (&entry->lock);
+ listdel (invalid_list, item);
+ entry->invalid_le = NULL;
+ if (entry->flags.kernelp)
+ break_callback (entry->fid);
+ ReleaseWriteLock (&entry->lock);
+ }
+ }
+}
+
+/*
+ * Add `entry' to the list of to invalidate when its time is up.
+ */
+
+static void
+add_to_invalidate (FCacheEntry *e)
+{
+ Listitem *item;
+
+ if (e->invalid_le != NULL) {
+ listdel (invalid_list, e->invalid_le);
+ e->invalid_le = NULL;
+ }
+
+ for (item = listhead (invalid_list);
+ item;
+ item = listnext (invalid_list, item)) {
+ FCacheEntry *this_entry = (FCacheEntry *)listdata (item);
+
+ if (e->callback.ExpirationTime < this_entry->callback.ExpirationTime) {
+ e->invalid_le = listaddbefore (invalid_list,
+ item,
+ e);
+ return;
+ }
+ }
+ e->invalid_le = listaddhead (invalid_list, e);
+ LWP_NoYieldSignal (invalid_list);
+}
+
+/*
+ * Remove the entry least-recently used and return it or NULL if none
+ * is found.
+ */
+
+static FCacheEntry *
+unlink_lru_entry (void)
+{
+ FCacheEntry *entry = NULL;
+ Listitem *item;
+
+ assert (!listemptyp (lrulist));
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+
+ entry = (FCacheEntry *)listdata (item);
+ if (!entry->flags.usedp
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ listdel (lrulist, entry->lru_le);
+ entry->lru_le = NULL;
+ return entry;
+ }
+ }
+
+ assert (!listemptyp (lrulist));
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+
+ entry = (FCacheEntry *)listdata (item);
+ if (entry->flags.usedp
+ && !entry->flags.attrusedp
+ && entry->refcount == 0
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ listdel (lrulist, entry->lru_le);
+ entry->lru_le = NULL;
+ throw_entry (entry);
+ return entry;
+ }
+ }
+
+ assert (!listemptyp (lrulist));
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+
+ entry = (FCacheEntry *)listdata (item);
+ if (entry->flags.usedp
+ && entry->refcount == 0
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ listdel (lrulist, entry->lru_le);
+ entry->lru_le = NULL;
+ if (entry->flags.kernelp)
+ break_callback (entry->fid);
+ throw_entry (entry);
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ *
+ */
+
+static void
+emergency_remove_data (size_t sz)
+{
+ FCacheEntry *entry = NULL;
+ Listitem *item;
+ int prio;
+
+ for (prio = 0 ; prio <= fprioritylevel ; prio += 10) {
+
+ for (item = listtail (lrulist);
+ item && usedbytes + sz > highbytes;
+ item = listprev (lrulist, item)) {
+ entry = (FCacheEntry *)listdata (item);
+ if (entry->flags.datap
+ && !entry->flags.datausedp
+ && entry->priority < prio
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ throw_data (entry);
+ ReleaseWriteLock (&entry->lock);
+ }
+ }
+
+ for (item = listtail (lrulist);
+ item && usedbytes + sz > highbytes;
+ item = listprev (lrulist, item)) {
+ entry = (FCacheEntry *)listdata (item);
+ if (entry->flags.datap
+ && entry->priority < prio
+ && CheckLock(&entry->lock) == 0) {
+ ObtainWriteLock (&entry->lock);
+ throw_data (entry);
+ ReleaseWriteLock (&entry->lock);
+ }
+ }
+ }
+
+}
+
+/*
+ * Return a usable entry.
+ */
+
+static FCacheEntry *
+find_free_entry (void)
+{
+ FCacheEntry *entry;
+
+ entry = unlink_lru_entry ();
+ if (entry == NULL)
+ arla_warnx (ADEBFCACHE, "All vnode entries in use");
+ else {
+ assert (CheckLock(&entry->lock) == -1);
+ ++usedvnodes;
+ }
+ return entry;
+}
+
+/*
+ *
+ */
+
+int
+fcache_store_state (void)
+{
+ Listitem *item;
+ int fd;
+ unsigned n;
+
+ fd = open ("fcache.new", O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (fd < 0)
+ return errno;
+ n = 0;
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+ FCacheEntry *entry = (FCacheEntry *)listdata (item);
+
+ if (!entry->flags.usedp)
+ continue;
+ if (write (fd, entry, sizeof(*entry)) != sizeof(*entry)) {
+ close (fd);
+ return errno;
+ }
+ ++n;
+ }
+
+ if(close (fd))
+ return errno;
+ if (rename ("fcache.new", "fcache"))
+ return errno;
+
+ arla_warnx (ADEBFCACHE, "wrote %u entries to fcache", n);
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+static void
+fcache_recover_state (void)
+{
+ int fd;
+ FCacheEntry tmp;
+ unsigned n;
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ fd = open ("fcache", O_RDONLY | O_BINARY, 0);
+ if (fd < 0)
+ return;
+ n = 0;
+ while (read (fd, &tmp, sizeof(tmp)) == sizeof(tmp)) {
+ CredCacheEntry *ce;
+ FCacheEntry *e;
+ int i;
+ VolCacheEntry *vol;
+
+ ce = cred_get (tmp.fid.Cell, 0, 0);
+ assert (ce != NULL);
+
+ vol = volcache_getbyid (tmp.fid.fid.Volume, tmp.fid.Cell, ce);
+ cred_free (ce);
+ if (vol == NULL)
+ continue;
+
+ e = find_free_entry ();
+
+ ++n;
+
+ e->fid = tmp.fid;
+ e->host = 0;
+ e->status = tmp.status;
+ e->callback = broken_callback;
+ e->volsync = tmp.volsync;
+ e->refcount = tmp.refcount;
+
+ /* Better not restore the rights. pags don't have to be the same */
+ for (i = 0; i < NACCESS; ++i) {
+ e->acccache[i].cred = ARLA_NO_AUTH_CRED;
+ e->acccache[i].access = ANONE;
+ }
+
+ e->anonaccess = tmp.anonaccess;
+ e->inode = tmp.inode;
+ inode_count = max(inode_count, tmp.inode + 1);
+ e->flags.usedp = TRUE;
+ e->flags.attrp = tmp.flags.attrp;
+ e->flags.datap = tmp.flags.datap;
+ e->flags.attrusedp = FALSE;
+ e->flags.datausedp = FALSE;
+ e->flags.kernelp = FALSE;
+ e->flags.extradirp = tmp.flags.extradirp;
+ e->flags.mountp = tmp.flags.mountp;
+ e->tokens = tmp.tokens;
+ e->parent = tmp.parent;
+ e->realfid = tmp.realfid;
+ e->priority = tmp.priority;
+ e->lru_le = listaddhead (lrulist, e);
+ e->volume = vol;
+ hashtabadd (hashtab, e);
+ if (e->flags.datap)
+ usedbytes += e->status.Length;
+ ReleaseWriteLock (&e->lock);
+ }
+ close (fd);
+ arla_warnx (ADEBFCACHE, "recovered %u entries to fcache", n);
+}
+
+/*
+ * Search for `cred' in `ae' and return a pointer in `pos'. If it
+ * already exists return TRUE, else return FALSE and set pos to a
+ * random slot.
+ */
+
+Bool
+findaccess (pag_t cred, AccessEntry *ae, AccessEntry **pos)
+{
+ int i;
+
+ for(i = 0; i < NACCESS ; ++i)
+ if(ae[i].cred == cred) {
+ *pos = &ae[i];
+ return TRUE;
+ }
+
+ assert (i == NACCESS);
+ i = rand() % NACCESS;
+ *pos = &ae[i];
+
+ return FALSE;
+}
+
+/*
+ * Find the file server we should be talking to for a given fid and
+ * user and return the connection.
+ */
+
+static ConnCacheEntry *
+findconn (FCacheEntry *e, CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ VolCacheEntry *ve = e->volume;
+ int i;
+ u_long addr = 0;
+ int type = -1, bit;
+
+ for (i = RWVOL; i <= BACKVOL; ++i)
+ if (ve->entry.volumeId[i] == e->fid.fid.Volume) {
+ type = i;
+ break;
+ }
+
+ switch (type) {
+ case RWVOL :
+ bit = VLSF_RWVOL;
+ break;
+ case ROVOL :
+ bit = VLSF_ROVOL;
+ break;
+ case BACKVOL :
+ bit = VLSF_BACKVOL;
+ break;
+ default :
+ abort ();
+ }
+
+ for (i = 0; i < MAXNSERVERS; ++i)
+ if (ve->entry.serverFlags[i] & bit) {
+ addr = htonl(ve->entry.serverNumber[i]);
+ break;
+ }
+
+ assert (addr != 0);
+
+ conn = conn_get (e->fid.Cell, addr, afsport, FS_SERVICE_ID, ce);
+ if (conn == NULL) {
+ arla_warnx (ADEBFCACHE, "Cannot connect to FS");
+ return NULL;
+ }
+ return conn;
+}
+
+/*
+ * Initialize the file cache in `cachedir', with these values for high
+ * and low-water marks.
+ */
+
+void
+fcache_init (u_long alowvnodes,
+ u_long ahighvnodes,
+ u_long alowbytes,
+ u_long ahighbytes,
+ Bool recover)
+{
+ /*
+ * Initialize all variables.
+ */
+
+ inode_count = 1; /* XXX */
+ lowvnodes = alowvnodes;
+ highvnodes = ahighvnodes;
+ lowbytes = alowbytes;
+ highbytes = ahighbytes;
+ fprioritylevel = FPRIO_DEFAULT;
+
+ hashtab = hashtabnew (FCHASHSIZE, fcachecmp, fcachehash);
+ if (hashtab == NULL)
+ arla_errx (1, ADEBERROR, "fcache: hashtabnew failed");
+
+ lrulist = listnew ();
+ if (lrulist == NULL)
+ arla_errx (1, ADEBERROR, "fcache: listnew failed");
+
+ invalid_list = listnew ();
+ if (invalid_list == NULL)
+ arla_errx (1, ADEBERROR, "fcache: listnew failed");
+
+ create_new_entries (highvnodes);
+
+ if (recover)
+ fcache_recover_state ();
+
+ if (LWP_CreateProcess (create_nodes, CREATE_NODES_STACKSIZE, 1,
+ NULL, "fcache-create-nodes",
+ &create_nodes_pid))
+ arla_errx (1, ADEBERROR,
+ "fcache: cannot create create-nodes thread");
+
+ if (LWP_CreateProcess (cleaner, CLEANER_STACKSIZE, 1,
+ NULL, "fcache-cleaner", &cleaner_pid))
+ arla_errx (1, ADEBERROR,
+ "fcache: cannot create cleaner thread");
+
+ if (LWP_CreateProcess (invalidator, CLEANER_STACKSIZE, 1,
+ NULL, "fcache-invalidator", &invalidator_pid))
+ arla_errx (1, ADEBERROR,
+ "fcache: cannot create invalidator thread");
+}
+
+/*
+ *
+ */
+
+int
+fcache_reinit(u_long alowvnodes,
+ u_long ahighvnodes,
+ u_long alowbytes,
+ u_long ahighbytes)
+{
+ arla_warnx (ADEBFCACHE, "fcache_reinit");
+
+ if (ahighvnodes > highvnodes) {
+ create_new_entries(ahighvnodes - highvnodes);
+ highvnodes = ahighvnodes;
+ } else
+ return EINVAL;
+
+ if (alowvnodes != 0)
+ lowvnodes = alowvnodes;
+
+ if (alowbytes != 0)
+ lowbytes = alowbytes;
+
+ if (ahighbytes != 0)
+ highbytes = ahighbytes;
+
+ return 0;
+}
+
+/*
+ * Find the entry for `fid' in the hash table.
+ * If it's found, move it to the front of the lrulist as well.
+ */
+
+static FCacheEntry *
+find_entry (VenusFid fid)
+{
+ FCacheEntry key;
+ FCacheEntry *e;
+
+ key.fid = fid;
+ e = (FCacheEntry *)hashtabsearch (hashtab, (void *)&key);
+ if (e != NULL) {
+ ObtainWriteLock (&e->lock);
+ listdel (lrulist, e->lru_le);
+ e->lru_le = listaddhead (lrulist, e);
+ }
+ return e;
+}
+
+/*
+ * Mark `e' as having `callback' and notify the kernel.
+ */
+
+static void
+stale (FCacheEntry *e, AFSCallBack callback)
+{
+ if (callback.CallBackType == CBDROPPED &&
+ e->callback.CallBackType == CBDROPPED)
+ return;
+
+ assert (CheckLock (&e->lock) == 0);
+
+ ObtainWriteLock (&e->lock);
+ e->callback = callback;
+ e->tokens = 0;
+ if (e->flags.kernelp)
+ break_callback (e->fid);
+ e->flags.kernelp = FALSE;
+ ReleaseWriteLock (&e->lock);
+}
+
+/*
+ * Call stale on the entry corresponding to `fid', if any.
+ */
+
+void
+fcache_stale_entry (VenusFid fid, AFSCallBack callback)
+{
+ FCacheEntry *e;
+
+ e = find_entry (fid);
+ if (e == NULL) {
+ arla_warnx (ADEBFCACHE,
+ "callback for non-existing file (%d, %u, %u, %u)",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+ return;
+ }
+
+ ReleaseWriteLock(&e->lock);
+ stale (e, callback);
+}
+
+
+typedef struct {
+ pag_t pag;
+ int32_t cell;
+} fc_purgecred;
+
+
+/*
+ * If ptr has cred arg, set it invalid
+ */
+
+static Bool
+purge_cred (void *ptr, void *arg)
+{
+ FCacheEntry *e = (FCacheEntry *)ptr;
+ fc_purgecred *cred = (fc_purgecred *) arg;
+ AccessEntry *ae = e->acccache;
+ int i;
+
+ if (e->fid.Cell == cred->cell || cred->cell == -1) {
+
+ for(i = 0; i < NACCESS ; ++i)
+ if(ae[i].cred == cred->pag) {
+ ae[i].cred = ARLA_NO_AUTH_CRED;
+ ae[i].access = ANONE;
+ stale(e, e->callback);
+ break;
+ }
+ }
+ return FALSE;
+}
+
+
+/*
+ * Mark as cred as stale in kernel and all fcache-entries,
+ * When cell == -1, flush all creds in this pag.
+ */
+
+void
+fcache_purge_cred (pag_t pag, int32_t cell)
+{
+ fc_purgecred cred;
+
+ cred.pag = pag;
+ cred.cell = cell;
+
+ hashtabforeach(hashtab, purge_cred, &cred);
+}
+
+/*
+ * If ptr was retrieved from cell - volume , try to mark stale
+ */
+
+static Bool
+purge_volume (void *ptr, void *arg)
+{
+ FCacheEntry *e = (FCacheEntry *)ptr;
+ VenusFid *fid = (VenusFid *) arg;
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ if (e->fid.Cell == fid->Cell &&
+ e->fid.fid.Volume == fid->fid.Volume) {
+ stale (e, broken_callback);
+ }
+ return FALSE;
+}
+
+/*
+ * Mark as stale all entries from cell.volume
+ */
+
+void
+fcache_purge_volume (VenusFid fid)
+{
+ hashtabforeach(hashtab, purge_volume, &fid);
+}
+
+/*
+ * If `ptr' was retrieved from `host', mark it as stale.
+ */
+
+static Bool
+purge_host (void *ptr, void *arg)
+{
+ FCacheEntry *e = (FCacheEntry *)ptr;
+ u_long *host = (u_long *)arg;
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ assert (*host);
+ if (e->host == *host) {
+ if (CheckLock (&e->lock) == 0)
+ stale (e, broken_callback);
+ }
+ return FALSE;
+}
+
+/*
+ * Mark as stale all entries from the host `host'.
+ */
+
+void
+fcache_purge_host (u_long host)
+{
+ hashtabforeach (hashtab, purge_host, &host);
+}
+
+/*
+ * return the file name of the cached file for `entry'.
+ */
+
+int
+fcache_file_name (FCacheEntry *entry, char *s, size_t len)
+{
+ return snprintf (s, len, "%04X", (unsigned)entry->inode);
+}
+
+/*
+ * return the file name of the converted directory for `entry'.
+ */
+
+int
+fcache_extra_file_name (FCacheEntry *entry, char *s, size_t len)
+{
+ int ret;
+
+ assert (entry->flags.datap &&
+ entry->flags.extradirp &&
+ entry->status.FileType == TYPE_DIR);
+
+ ret = fcache_file_name (entry, s, len);
+ *s += 0x10;
+ return ret;
+}
+
+/*
+ * return a fd to the cache file of `entry'
+ */
+
+int
+fcache_open_file (FCacheEntry *entry, int flag, mode_t mode)
+{
+ char fname[MAXPATHLEN];
+
+ fcache_file_name (entry, fname, sizeof(fname));
+ return open (fname, flag | O_BINARY, mode);
+}
+
+/*
+ * return a fd to the converted directory for `entry'
+ */
+
+int
+fcache_open_extra_dir (FCacheEntry *entry, int flag, mode_t mode)
+{
+ char fname[MAXPATHLEN];
+
+ assert (entry->flags.datap && entry->flags.extradirp &&
+ entry->status.FileType == TYPE_DIR);
+
+ fcache_extra_file_name (entry, fname, sizeof(fname));
+ return open (fname, flag | O_BINARY, mode);
+}
+
+/*
+ * Update all the relevant parts of `entry' after having received new
+ * data from the file server.
+ */
+
+static void
+update_entry (FCacheEntry *entry,
+ AFSFetchStatus *status,
+ AFSCallBack *callback,
+ AFSVolSync *volsync,
+ u_int32_t host,
+ pag_t cred)
+{
+ struct timeval tv;
+ AccessEntry *ae;
+
+ gettimeofday (&tv, NULL);
+
+ entry->status = *status;
+ if (callback) {
+ entry->callback = *callback;
+ entry->callback.ExpirationTime += tv.tv_sec;
+ add_to_invalidate (entry);
+ }
+ if (volsync) {
+ entry->volsync = *volsync;
+ volcache_update_volsync (entry->volume, *volsync);
+ }
+ entry->host = host;
+
+ entry->anonaccess = status->AnonymousAccess;
+ findaccess (cred, entry->acccache, &ae);
+ ae->cred = cred;
+ ae->access = status->CallerAccess;
+}
+
+/*
+ * Fetch the attributes for the file in `entry' from the file_server,
+ * using the credentials in `ce' and returning the connection in
+ * `ret_conn' */
+
+static int
+do_read_attr (FCacheEntry *entry,
+ CredCacheEntry *ce,
+ ConnCacheEntry **ret_conn)
+{
+ int ret;
+ ConnCacheEntry *conn;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ if (connected_mode == DISCONNECTED) {
+ *ret_conn = NULL;
+ if (entry->flags.attrp == TRUE)
+ return 0;
+ return ENETDOWN;
+ }
+
+ conn = findconn (entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_FetchStatus (conn->connection,
+ &entry->fid.fid,
+ &status,
+ &callback,
+ &volsync);
+ if (ret) {
+ if (ret == -1)
+ ret = ENETDOWN;
+ conn_free(conn);
+ arla_warn (ADEBFCACHE, ret, "fetch-status");
+ return ret;
+ }
+
+ if (entry->flags.datap
+ && entry->status.DataVersion != status.DataVersion) {
+ throw_data (entry);
+ entry->tokens &= ~(XFS_DATA_R|XFS_DATA_W);
+ }
+
+ update_entry (entry, &status, &callback, &volsync,
+ rx_HostOf (rx_PeerOf (conn->connection)),
+ ce->cred);
+
+ entry->tokens |= XFS_ATTR_R;
+ entry->flags.attrp = TRUE;
+
+ *ret_conn = conn;
+ return 0;
+}
+
+
+/*
+ * Read the attributes of `entry' from the file server and store them.
+ */
+
+int
+read_attr (FCacheEntry *entry, CredCacheEntry *ce)
+{
+ int ret;
+ ConnCacheEntry *conn;
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ ret = do_read_attr (entry, ce, &conn);
+ if (ret)
+ return ret;
+ conn_free (conn);
+ return 0;
+}
+
+/*
+ * Read the contents of `entry' from the file server and store it.
+ */
+
+static int
+read_data (FCacheEntry *entry, ConnCacheEntry *conn, CredCacheEntry *ce)
+{
+ struct rx_call *call;
+ int ret = 0;
+ u_int32_t sizefs;
+ int fd;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+
+ arla_warnx (ADEBMISC, "read_data");
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ if (connected_mode == DISCONNECTED)
+ return ENETDOWN;
+
+ if (usedbytes + entry->status.Length > highbytes)
+ emergency_remove_data (entry->status.Length);
+
+ if (usedbytes + entry->status.Length > highbytes) {
+ ret = ENOSPC;
+ goto out;
+ }
+
+ call = rx_NewCall (conn->connection);
+ if (call == NULL) {
+ arla_warnx (ADEBMISC, "rx_NewCall failed");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ ret = StartRXAFS_FetchData (call, &entry->fid.fid,
+ 0, entry->status.Length);
+ if(ret) {
+ arla_warn (ADEBFCACHE, ret, "fetch-data");
+ goto out;
+ }
+
+ ret = rx_Read (call, &sizefs, sizeof(sizefs));
+ if (ret != sizeof(sizefs)) {
+ ret = rx_Error(call);
+ arla_warn (ADEBFCACHE, ret, "Error reading length");
+ rx_EndCall(call, 0);
+ goto out;
+ }
+ sizefs = ntohl (sizefs);
+
+ assert (sizefs == entry->status.Length);
+
+ fd = fcache_open_file (entry, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "open cache file %u",
+ (unsigned)entry->inode);
+ rx_EndCall(call, 0);
+ goto out;
+ }
+
+ if (copyrx2fd (call, fd, sizefs)) {
+ ret = errno;
+ rx_EndCall(call, ret);
+ arla_warn (ADEBFCACHE, ret, "copyrx2fd");
+ }
+
+ usedbytes += sizefs; /* XXX - sync */
+
+ ret = rx_EndCall (call, EndRXAFS_FetchData (call,
+ &status,
+ &callback,
+ &volsync));
+ if(ret) {
+ arla_warn (ADEBFCACHE, ret, "rx_EndCall");
+ goto out;
+ }
+
+ update_entry (entry, &status, &callback, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ entry->flags.datap = TRUE;
+ entry->tokens |= XFS_DATA_R | XFS_DATA_W | XFS_OPEN_NR | XFS_OPEN_NW;
+
+out:
+ return ret;
+}
+
+/*
+ * Write the contents of the cache file back to the file server.
+ */
+
+int
+write_data (FCacheEntry *entry, CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ struct rx_call *call;
+ int ret = 0;
+ u_int32_t sizefs;
+ int fd;
+ struct stat statinfo;
+ AFSStoreStatus storestatus;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ conn = findconn (entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ fd = fcache_open_file (entry, O_RDONLY, 0666);
+ if (fd < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "open cache file %u",
+ (unsigned)entry->inode);
+ goto out;
+ }
+
+ if (fstat (fd, &statinfo) < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "stat cache file %u",
+ (unsigned)entry->inode);
+ goto out;
+ }
+
+ sizefs = statinfo.st_size;
+
+ usedbytes = usedbytes - entry->status.Length + sizefs;
+
+ call = rx_NewCall (conn->connection);
+ if (call == NULL) {
+ arla_warnx (ADEBMISC, "rx_NewCall failed");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ storestatus.Mask = 0; /* Dont save anything */
+ ret = StartRXAFS_StoreData (call, &entry->fid.fid,
+ &storestatus,
+ 0,
+ sizefs,
+ sizefs);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "store-data");
+ rx_EndCall(call, 0);
+ goto out;
+ }
+
+ if (copyfd2rx (fd, call, sizefs)) {
+ ret = errno;
+ rx_EndCall(call, ret);
+ arla_warnx (ADEBFCACHE, "copyfd2rx");
+ goto out;
+ }
+
+ ret = rx_EndCall (call, EndRXAFS_StoreData (call,
+ &status,
+ &callback,
+ &volsync));
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "rx_EndCall");
+ goto out;
+ }
+
+ update_entry (entry, &status, &callback, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ close (fd);
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Truncate the file in `entry' to `size' bytes.
+ */
+
+int
+truncate_file (FCacheEntry *entry, off_t size, CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ struct rx_call *call;
+ int ret = 0;
+ AFSStoreStatus storestatus;
+ u_int32_t sizefs = sizeof(entry->status.Length);
+ int fd;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ conn = findconn (entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ fd = fcache_open_file (entry, O_RDWR | O_CREAT, 0);
+ if (fd < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "open fache file %u",
+ (unsigned)entry->inode);
+ goto out;
+ }
+
+ if(ftruncate (fd, size) < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "ftruncate %ld", (long)size);
+ close (fd);
+ goto out;
+ }
+
+ close (fd);
+
+ if (entry->flags.datap) {
+ assert (usedbytes >= entry->status.Length);
+ usedbytes -= entry->status.Length;
+ }
+ usedbytes += size;
+
+ entry->status.Length = size;
+
+ call = rx_NewCall (conn->connection);
+ if (call == NULL) {
+ arla_warnx (ADEBMISC, "rx_NewCall failed");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ storestatus.Mask = 0;
+ ret = StartRXAFS_StoreData (call,
+ &entry->fid.fid,
+ &storestatus,
+ 0, 0, entry->status.Length);
+ if(ret) {
+ arla_warn (ADEBFCACHE, ret, "store-data");
+ rx_EndCall(call, 0);
+ goto out;
+ }
+
+ sizefs = htonl (sizefs);
+ if (rx_Write (call, &sizefs, sizeof(sizefs)) != sizeof(sizefs)) {
+ ret = rx_Error(call);
+ arla_warn (ADEBFCACHE, ret, "writing length");
+ rx_EndCall(call, 0);
+ goto out;
+ }
+
+ if (rx_Write (call, 0, 0) != 0) {
+ ret = rx_Error(call);
+ arla_warn (ADEBFCACHE, ret, "writing length");
+ rx_EndCall(call, 0);
+ goto out;
+ }
+
+ ret = rx_EndCall (call, EndRXAFS_StoreData (call,
+ &status,
+ &callback,
+ &volsync));
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "rx_EndCall");
+ goto out;
+ }
+
+ update_entry (entry, &status, &callback, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ conn_free(conn);
+ return ret;
+}
+
+/*
+ * Set the attributes of the file in `entry' to `status'.
+ */
+
+int
+write_attr (FCacheEntry *entry,
+ const AFSStoreStatus *store_status,
+ CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ int ret = 0;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&entry->lock) == -1);
+
+ conn = findconn (entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_StoreStatus (conn->connection,
+ &entry->fid.fid,
+ store_status,
+ &status,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "store-status");
+ goto out;
+ }
+
+ update_entry (entry, &status, NULL, &volsync,
+ rx_HostOf (rx_PeerOf (conn->connection)),
+ ce->cred);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Create a file.
+ */
+
+int
+create_file (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFid OutFid;
+ FCacheEntry *child_entry;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+ int fd;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_CreateFile (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ store_attr,
+ &OutFid,
+ fetch_attr,
+ &status,
+ &callback,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "CreateFile");
+ goto out;
+ }
+
+ update_entry (dir_entry, &status, &callback, &volsync,
+ rx_HostOf (rx_PeerOf (conn->connection)),
+ ce->cred);
+
+ child_fid->Cell = dir_entry->fid.Cell;
+ child_fid->fid = OutFid;
+
+ ret = fcache_get (&child_entry, *child_fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ goto out;
+ }
+
+ update_entry (child_entry, fetch_attr, NULL, NULL,
+ rx_HostOf (rx_PeerOf (conn->connection)),
+ ce->cred);
+
+ child_entry->flags.attrp = TRUE;
+ child_entry->flags.kernelp = TRUE;
+
+ fd = fcache_open_file (child_entry, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ ret = errno;
+ arla_warn (ADEBFCACHE, ret, "open cache file %u",
+ (unsigned)child_entry->inode);
+ ReleaseWriteLock (&child_entry->lock);
+ goto out;
+ }
+ close (fd);
+
+ child_entry->flags.datap = TRUE;
+ child_entry->tokens |= XFS_ATTR_R | XFS_DATA_R | XFS_DATA_W;
+
+ ReleaseWriteLock (&child_entry->lock);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Create a directory.
+ */
+
+int
+create_directory (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFid OutFid;
+ FCacheEntry *child_entry;
+ AFSFetchStatus status;
+ AFSCallBack callback;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_MakeDir (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ store_attr,
+ &OutFid,
+ fetch_attr,
+ &status,
+ &callback,
+ &volsync);
+
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "MakeDir");
+ goto out;
+ }
+
+ update_entry (dir_entry, &status, &callback, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ child_fid->Cell = dir_entry->fid.Cell;
+ child_fid->fid = OutFid;
+
+ ret = fcache_get (&child_entry, *child_fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ goto out;
+ }
+
+ update_entry (child_entry, fetch_attr, NULL, NULL,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ child_entry->flags.attrp = TRUE;
+ child_entry->flags.kernelp = TRUE;
+
+ ret = adir_mkdir (child_entry, child_fid->fid, dir_entry->fid.fid);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "adir_mkdir");
+ ReleaseWriteLock (&child_entry->lock);
+ goto out;
+ }
+
+ usedbytes += child_entry->status.Length;
+
+ child_entry->flags.datap = TRUE;
+ child_entry->tokens |= XFS_ATTR_R | XFS_DATA_R | XFS_DATA_W;
+
+ ReleaseWriteLock (&child_entry->lock);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Create a symbolic link.
+ */
+
+int
+create_symlink (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ const char *contents,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFid OutFid;
+ FCacheEntry *child_entry;
+ AFSVolSync volsync;
+ AFSFetchStatus new_status;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_Symlink (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ contents,
+ store_attr,
+ &OutFid,
+ fetch_attr,
+ &new_status,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "Symlink");
+ goto out;
+ }
+
+ usedbytes = usedbytes - dir_entry->status.Length + new_status.Length;
+
+ update_entry (dir_entry, &new_status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ child_fid->Cell = dir_entry->fid.Cell;
+ child_fid->fid = OutFid;
+
+ ret = fcache_get (&child_entry, *child_fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ goto out;
+ }
+
+ update_entry (child_entry, fetch_attr, NULL, NULL,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ child_entry->flags.attrp = TRUE;
+ child_entry->flags.kernelp = TRUE;
+ child_entry->tokens |= XFS_ATTR_R;
+
+ ReleaseWriteLock (&child_entry->lock);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Create a hard link.
+ */
+
+int
+create_link (FCacheEntry *dir_entry,
+ const char *name,
+ FCacheEntry *existing_entry,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFetchStatus new_status;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_Link (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ &existing_entry->fid.fid,
+ &new_status,
+ &status,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "Link");
+ goto out;
+ }
+
+ usedbytes = usedbytes - dir_entry->status.Length + status.Length;
+
+ update_entry (dir_entry, &status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ update_entry (existing_entry, &new_status, NULL, NULL,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Remove a file from a directory.
+ */
+
+int
+remove_file (FCacheEntry *dir_entry, const char *name, CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_RemoveFile (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ &status,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "RemoveFile");
+ goto out;
+ }
+
+ usedbytes = usedbytes - dir_entry->status.Length + status.Length;
+
+ update_entry (dir_entry, &status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Remove a file from a directory.
+ */
+
+int
+remove_directory (FCacheEntry *dir_entry,
+ const char *name,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&dir_entry->lock) == -1);
+
+ conn = findconn (dir_entry, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_RemoveDir (conn->connection,
+ &dir_entry->fid.fid,
+ name,
+ &status,
+ &volsync);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "RemoveDir");
+ goto out;
+ }
+
+ usedbytes = usedbytes - dir_entry->status.Length + status.Length;
+
+ update_entry (dir_entry, &status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Rename a file
+ */
+
+int
+rename_file (FCacheEntry *old_dir,
+ const char *old_name,
+ FCacheEntry *new_dir,
+ const char *new_name,
+ CredCacheEntry *ce)
+{
+ int ret = 0;
+ ConnCacheEntry *conn;
+ AFSFetchStatus orig_status, new_status;
+ AFSVolSync volsync;
+
+ assert (CheckLock(&old_dir->lock) == -1
+ && CheckLock(&new_dir->lock) == -1);
+
+ conn = findconn (old_dir, ce);
+
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_Rename (conn->connection,
+ &old_dir->fid.fid,
+ old_name,
+ &new_dir->fid.fid,
+ new_name,
+ &orig_status,
+ &new_status,
+ &volsync);
+
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "Rename");
+ goto out;
+ }
+
+ usedbytes = usedbytes - old_dir->status.Length + orig_status.Length;
+
+ usedbytes = usedbytes - new_dir->status.Length + new_status.Length;
+
+ update_entry (old_dir, &orig_status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+ update_entry (new_dir, &new_status, NULL, &volsync,
+ rx_HostOf(rx_PeerOf(conn->connection)),
+ ce->cred);
+
+out:
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * Return the fid to the root.
+ */
+
+int
+getroot (VenusFid *res, CredCacheEntry *ce)
+{
+ VolCacheEntry *ve;
+ VenusFid fid;
+ const char *root_volume = volcache_get_rootvolume ();
+
+ ve = volcache_getbyname (root_volume, 0, ce);
+ if (ve == NULL) {
+ arla_warnx (ADEBFCACHE, "Cannot find the root volume");
+ return ENODEV;
+ }
+
+ fid.Cell = 0;
+ if (ve->entry.flags & VLF_ROEXISTS) {
+ fid.fid.Volume = ve->entry.volumeId[ROVOL];
+ } else if (ve->entry.flags & VLF_RWEXISTS) {
+ arla_warnx(ADEBERROR,
+ "getroot: %s is missing a RO clone, not good",
+ root_volume);
+ fid.fid.Volume = ve->entry.volumeId[RWVOL];
+ } else {
+ arla_errx(1, ADEBERROR,
+ "getroot: %s has no RW or RO clone?",
+ root_volume);
+ }
+ fid.fid.Vnode = fid.fid.Unique = 1;
+
+ volcache_free (ve);
+
+ *res = fid;
+ return 0;
+}
+
+/*
+ * Return the type for this volume.
+ */
+
+static long
+gettype (int32_t volid, VolCacheEntry *ve)
+{
+ int i;
+
+ for (i = RWVOL; i <= BACKVOL; ++i)
+ if (ve->entry.volumeId[i] == volid)
+ return i;
+ assert (FALSE);
+ return -1; /* NOT REACHED */
+}
+
+/*
+ * Return the entry for `fid' or NULL.
+ */
+
+int
+fcache_find (FCacheEntry **res, VenusFid fid)
+{
+ *res = find_entry (fid);
+ if (*res != NULL)
+ return 0;
+ else
+ return -1;
+}
+
+/*
+ * Return the entry for `fid'. If it's not cached, add it.
+ */
+
+int
+fcache_get (FCacheEntry **res, VenusFid fid, CredCacheEntry *ce)
+{
+ FCacheEntry *e;
+ VolCacheEntry *vol;
+
+ e = find_entry (fid);
+ if (e) {
+ assert (e->flags.usedp);
+ *res = e;
+ return 0;
+ }
+
+ if (connected_mode == DISCONNECTED) {
+ *res = NULL;
+ return ENETDOWN;
+ }
+
+ vol = volcache_getbyid (fid.fid.Volume, fid.Cell, ce);
+ if (vol == NULL)
+ return ENODEV;
+
+ e = find_free_entry ();
+ e->fid = fid;
+ if (e->inode == 0)
+ e->inode = nextinode ();
+ e->anonaccess = 0;
+ e->tokens = 0;
+ e->flags.usedp = TRUE;
+ e->flags.datap = FALSE;
+ e->flags.attrp = FALSE;
+ e->flags.attrusedp = FALSE;
+ e->flags.datausedp = FALSE;
+ e->flags.extradirp = FALSE;
+ e->flags.mountp = FALSE;
+ e->flags.kernelp = FALSE;
+ e->host = 0;
+ e->priority = fprio_get(fid);
+ e->volume = vol;
+
+ e->lru_le = listaddhead (lrulist, e);
+ hashtabadd (hashtab, e);
+
+ *res = e;
+ return 0;
+}
+
+/*
+ *
+ */
+
+static Bool
+uptodatep (FCacheEntry *e)
+{
+ struct timeval tv;
+ assert (e->flags.usedp);
+
+ if (connected_mode != CONNECTED &&
+ connected_mode != CONNECTEDLOG)
+ return TRUE;
+
+ gettimeofday(&tv, NULL);
+
+ if (tv.tv_sec < e->callback.ExpirationTime &&
+ e->callback.CallBackType != CBDROPPED &&
+ (e->callback.CallBackType != 0
+ || e->volume->volsync.spare1 != e->volsync.spare1))
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Make sure that `e' has attributes and that they are up-to-date.
+ */
+
+int
+fcache_get_attr (FCacheEntry *e, CredCacheEntry *ce)
+{
+ AccessEntry *ae;
+ assert (e->flags.usedp);
+
+ assert (CheckLock(&e->lock) == -1);
+
+ if (e->flags.attrp && uptodatep(e) &&
+ findaccess(ce->cred, e->acccache, &ae) != FALSE)
+ return 0;
+
+ return read_attr (e, ce);
+}
+
+/*
+ * Make sure that `e' has file data and is up-to-date.
+ */
+
+int
+fcache_get_data (FCacheEntry *e, CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ int ret;
+
+ assert (e->flags.usedp);
+
+ assert (CheckLock(&e->lock) == -1);
+
+ if (e->flags.attrp && uptodatep(e)) {
+ if (e->flags.datap)
+ return 0;
+ else {
+ conn = findconn (e, ce);
+ if (conn == NULL)
+ return ENETDOWN;
+ }
+ } else {
+ ret = do_read_attr (e, ce, &conn);
+ if (ret)
+ return ret;
+ if (e->flags.datap) {
+ conn_free (conn);
+ return 0;
+ }
+ }
+ ret = read_data (e, conn, ce);
+ conn_free (conn);
+ return ret;
+}
+
+/*
+ * If this entry is a mount point, set the fid data to
+ * the root directory of the volume it's pointing at,
+ * otherwise just leave it.
+ */
+
+int
+followmountpoint (VenusFid *fid, VenusFid *parent, CredCacheEntry **ce)
+{
+ int fd;
+ fbuf the_fbuf;
+ char *buf;
+ long cell;
+ long type;
+ FCacheEntry *e;
+ VenusFid oldfid = *fid;
+ int res;
+ u_int32_t length;
+
+ res = fcache_get (&e, *fid, *ce);
+ if (res)
+ return res;
+
+ res = fcache_get_attr (e, *ce);
+ if (res) {
+ ReleaseWriteLock (&e->lock);
+ return res;
+ }
+
+ if (e->status.FileType != TYPE_LINK) {
+ ReleaseWriteLock (&e->lock);
+ return 0;
+ }
+
+ res = fcache_get_data (e, *ce);
+ if (res) {
+ ReleaseWriteLock (&e->lock);
+ return res;
+ }
+
+ fd = fcache_open_file (e, O_RDONLY, 0);
+ if (fd < 0) {
+ ReleaseWriteLock (&e->lock);
+ return errno;
+ }
+
+ length = e->status.Length;
+ res = fbuf_create (&the_fbuf, fd, length, FBUF_READ);
+ if (res) {
+ close (fd);
+ ReleaseWriteLock (&e->lock);
+ return res;
+ }
+ buf = (char *)(the_fbuf.buf);
+ switch (*buf) {
+ case '#' :
+ case '%' : {
+ int founderr;
+ char *dot;
+
+ dot = buf + e->status.Length - 1;
+ *dot = '\0';
+ dot = strchr (buf, ':');
+ if (dot) {
+ *dot++ = '\0';
+ cell = cell_name2num (buf + 1);
+ } else {
+ cell = fid->Cell;
+ dot = buf + 1;
+ }
+ if (*buf == '%')
+ type = RWVOL;
+ else
+ type = gettype (fid->fid.Volume, e->volume);
+
+ founderr = 0;
+
+ /*
+ * If this is a cross-cell mountpoint we need new credentials.
+ */
+
+ if ((*ce)->cell != cell) {
+ CredCacheEntry *new_ce;
+
+ new_ce = cred_get (cell, (*ce)->cred, (*ce)->type);
+ if (new_ce == NULL) {
+ new_ce = cred_get(cell, (*ce)->cred, CRED_ANY);
+ }
+ if (new_ce == NULL) {
+ ReleaseWriteLock (&e->lock);
+ return ENOMEM;
+ }
+ cred_free (*ce);
+ *ce = new_ce;
+ }
+
+ /* is the cell is invalid the rest should be bougs too */
+ if (cell== -1)
+ founderr = -1;
+ else {
+ VolCacheEntry *ve;
+
+ ve = volcache_getbyname (dot, cell, *ce);
+ if (ve == NULL)
+ founderr = -1;
+ else {
+ switch (type) {
+ case ROVOL :
+ if (ve->entry.flags & VLF_ROEXISTS) {
+ fid->fid.Volume = ve->entry.volumeId[ROVOL];
+ break;
+ }
+ /* fall through */
+ case RWVOL :
+ if (ve->entry.flags & VLF_RWEXISTS)
+ fid->fid.Volume = ve->entry.volumeId[RWVOL];
+ else
+ founderr = -1;
+ break;
+ case BACKVOL :
+ if (ve->entry.flags & VLF_BOEXISTS)
+ fid->fid.Volume = ve->entry.volumeId[BACKVOL];
+ else
+ founderr = -1;
+ break;
+ default :
+ abort ();
+ }
+ volcache_free (ve);
+ }
+ }
+ if (founderr) {
+ res = ENODEV;
+ break;
+ }
+ fid->Cell = cell;
+ fid->fid.Vnode = fid->fid.Unique = 1;
+
+ ReleaseWriteLock (&e->lock);
+ res = fcache_get (&e, *fid, *ce);
+ if (res)
+ break;
+ ++e->refcount;
+ e->flags.mountp = TRUE;
+ e->realfid = oldfid;
+ e->parent = *parent;
+ }
+ }
+ ReleaseWriteLock (&e->lock);
+ fbuf_end (&the_fbuf);
+ return res;
+}
+
+/*
+ *
+ */
+
+static Bool
+print_entry (void *ptr, void *arg)
+{
+ FCacheEntry *e = (FCacheEntry *)ptr;
+ FILE *f = (FILE *)arg;
+
+ fprintf (f, "(%d, %u, %u, %u)\n",
+ e->fid.Cell,
+ e->fid.fid.Volume, e->fid.fid.Vnode, e->fid.fid.Unique);
+ return FALSE;
+}
+
+
+/*
+ *
+ */
+
+void
+fcache_status (FILE *f)
+{
+ fprintf (f, "%lu (%lu-%lu) files\n"
+ "%lu (%lu-%lu) bytes\n",
+ usedvnodes, lowvnodes, highvnodes,
+ usedbytes, lowbytes, highbytes);
+ hashtabforeach (hashtab, print_entry, f);
+}
+
+/*
+ * Request an ACL and put it in opaque
+ */
+
+int
+getacl(VenusFid fid,
+ CredCacheEntry *ce,
+ AFSOpaque *opaque)
+{
+ FCacheEntry *dire;
+ ConnCacheEntry *conn;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+ int ret;
+
+ ret = fcache_get (&dire, fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ return ret;
+ }
+
+ conn = findconn (dire, ce);
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_FetchACL (conn->connection, &fid.fid,
+ opaque, &status, &volsync);
+ conn_free (conn);
+ throw_entry (dire);
+
+ return ret;
+}
+
+/*
+ * Store the ACL read from opaque
+ */
+
+int
+setacl(VenusFid fid,
+ CredCacheEntry *ce,
+ AFSOpaque *opaque)
+{
+ FCacheEntry *dire;
+ ConnCacheEntry *conn;
+ AFSFetchStatus status;
+ AFSVolSync volsync;
+ int ret;
+
+ ret = fcache_get (&dire, fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ return EINVAL;
+ }
+
+ conn = findconn (dire, ce);
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_StoreACL (conn->connection, &fid.fid,
+ opaque, &status, &volsync);
+
+ conn_free (conn);
+ throw_entry (dire);
+
+ return ret;
+}
+
+/*
+ * Request volume status
+ */
+
+int
+getvolstat(VenusFid fid, CredCacheEntry *ce,
+ AFSFetchVolumeStatus *volstat,
+ char *volumename,
+ char *offlinemsg,
+ char *motd)
+{
+ FCacheEntry *dire;
+ ConnCacheEntry *conn;
+ int ret;
+
+ ret = fcache_get (&dire, fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ return EINVAL;
+ }
+
+ conn = findconn (dire, ce);
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_GetVolumeStatus (conn->connection, fid.fid.Volume,
+ volstat, volumename, offlinemsg,
+ motd);
+ conn_free (conn);
+ throw_entry (dire);
+
+ return ret;
+}
+
+/*
+ * Store volume status
+ */
+
+int
+setvolstat(VenusFid fid, CredCacheEntry *ce,
+ AFSStoreVolumeStatus *volstat,
+ char *volumename,
+ char *offlinemsg,
+ char *motd)
+{
+ FCacheEntry *dire;
+ ConnCacheEntry *conn;
+ int ret;
+
+ ret = fcache_get (&dire, fid, ce);
+ if (ret) {
+ arla_warn (ADEBFCACHE, ret, "fcache_get");
+ return EINVAL;
+ }
+
+ conn = findconn (dire, ce);
+ if (conn == NULL)
+ return ENETDOWN;
+
+ ret = RXAFS_SetVolumeStatus (conn->connection, fid.fid.Volume,
+ volstat, volumename, offlinemsg,
+ motd);
+ conn_free (conn);
+ throw_entry (dire);
+
+ return ret;
+}
diff --git a/usr.sbin/afs/src/arlad/fcache.h b/usr.sbin/afs/src/arlad/fcache.h
new file mode 100644
index 00000000000..6838ce9b7ae
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fcache.h
@@ -0,0 +1,252 @@
+/* $OpenBSD: fcache.h,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 interface for the file-cache.
+ */
+
+/* $KTH: fcache.h,v 1.37 1998/07/22 07:02:04 assar Exp $ */
+
+#ifndef _FCACHE_H_
+#define _FCACHE_H_
+
+#include <xfs/xfs_message.h>
+#include <fcntl.h>
+#include <cred.h>
+
+/*
+ * For each entry in the filecache we save the rights of NACCESS users.
+ * The value should be the same as MAXRIGHTS from xfs_message.h
+ * If it isn't you can get some very strange behavior from xfs, so don't
+ * even try. XXX
+ */
+
+#define NACCESS MAXRIGHTS
+
+typedef struct {
+ pag_t cred;
+ u_long access;
+} AccessEntry;
+
+enum Access { ANONE = 0x0,
+ AREAD = 0x01,
+ AWRITE = 0x02,
+ AINSERT = 0x04,
+ ALIST = 0x08,
+ ADELETE = 0x10,
+ ALOCK = 0x20,
+ AADMIN = 0x40 };
+
+typedef struct {
+ struct Lock lock; /* locking information for this entry */
+ VenusFid fid; /* The fid of the file for this entry */
+ unsigned refcount; /* reference count */
+ u_long host; /* the source of this entry */
+ AFSFetchStatus status; /* Removed unused stuff later */
+ AFSCallBack callback; /* Callback to the AFS-server */
+ AFSVolSync volsync; /* Sync info for ro-volumes */
+ AccessEntry acccache[NACCESS]; /* cache for the access rights */
+ u_long anonaccess; /* the access mask for system:anyuser */
+ ino_t inode; /* right now only an index */
+ struct {
+ unsigned usedp : 1; /* Is this entry used? */
+ unsigned attrp : 1; /* Are the attributes in status valid? */
+ unsigned datap : 1; /* Is the cache-file valid? */
+ unsigned attrusedp : 1; /* Attr is used in the kernel */
+ unsigned datausedp : 1; /* Data is used in the kernel */
+ unsigned extradirp : 1; /* Has this directory been "converted"? */
+ unsigned mountp : 1; /* Is this an AFS mount point? */
+ unsigned kernelp : 1; /* Does this entry exist in the kernel? */
+ } flags;
+ u_int tokens; /* read/write tokens for the kernel */
+ VenusFid parent; /* fid of the parent */
+ VenusFid realfid; /* Real fid (mountpoints) */
+ Listitem *lru_le; /* lru */
+ Listitem *invalid_le; /* invalidation list */
+ VolCacheEntry *volume; /* pointer to the volume entry */
+ unsigned priority; /* the priority of keeping the file 0-100 */
+} FCacheEntry;
+
+
+/*
+ * How far the cleaner will go went cleaning things up.
+ */
+
+extern unsigned fprioritylevel;
+
+void
+fcache_init (u_long alowvnodes,
+ u_long ahighvnodes,
+ u_long alowbytes,
+ u_long ahighbytes,
+ Bool recover);
+
+int
+fcache_reinit(u_long alowvnodes,
+ u_long ahighvnodes,
+ u_long alowbytes,
+ u_long ahighbytes);
+
+void
+fcache_purge_volume (VenusFid fid);
+
+void
+fcache_purge_host (u_long host);
+
+void
+fcache_purge_cred (pag_t cred, int32_t cell);
+
+void
+fcache_stale_entry (VenusFid fid, AFSCallBack callback);
+
+int
+fcache_file_name (FCacheEntry *entry, char *s, size_t len);
+
+int
+fcache_extra_file_name (FCacheEntry *entry, char *s, size_t len);
+
+int
+fcache_open_file (FCacheEntry *entry, int flag, mode_t mode);
+
+int
+fcache_open_extra_dir (FCacheEntry *entry, int flag, mode_t mode);
+
+int
+write_data (FCacheEntry *entry, CredCacheEntry *ce);
+
+int
+truncate_file (FCacheEntry *entry, off_t size, CredCacheEntry *ce);
+
+int
+write_attr (FCacheEntry *entry, const AFSStoreStatus *status,
+ CredCacheEntry *ce);
+
+int
+create_file (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ CredCacheEntry *ce);
+
+int
+create_directory (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ CredCacheEntry *ce);
+
+int
+create_symlink (FCacheEntry *dir_entry,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *child_fid, AFSFetchStatus *fetch_attr,
+ const char *contents,
+ CredCacheEntry *ce);
+
+int
+create_link (FCacheEntry *dir_entry,
+ const char *name,
+ FCacheEntry *existing_entry,
+ CredCacheEntry *ce);
+
+int
+remove_file (FCacheEntry *dire, const char *name, CredCacheEntry *ce);
+
+int
+remove_directory (FCacheEntry *dire, const char *name, CredCacheEntry *ce);
+
+int
+rename_file (FCacheEntry *old_dir,
+ const char *old_name,
+ FCacheEntry *new_dir,
+ const char *new_name,
+ CredCacheEntry *ce);
+
+int
+getroot (VenusFid *res, CredCacheEntry *ce);
+
+int
+fcache_get (FCacheEntry **res, VenusFid fid, CredCacheEntry *ce);
+
+int
+fcache_find (FCacheEntry **res, VenusFid fid);
+
+int
+fcache_get_attr (FCacheEntry *e, CredCacheEntry *ce);
+
+int
+fcache_get_data (FCacheEntry *e, CredCacheEntry *ce);
+
+int
+followmountpoint (VenusFid *fid, VenusFid *parent, CredCacheEntry **ce);
+
+void
+fcache_status (FILE *f);
+
+int
+fcache_store_state (void);
+
+int
+getacl(VenusFid fid, CredCacheEntry *ce,
+ AFSOpaque *opaque);
+
+int
+setacl(VenusFid fid, CredCacheEntry *ce,
+ AFSOpaque *opaque);
+
+int
+getvolstat(VenusFid fid, CredCacheEntry *ce,
+ AFSFetchVolumeStatus *volstat,
+ char *volumename,
+ char *offlinemsg,
+ char *motd);
+
+int
+setvolstat(VenusFid fid, CredCacheEntry *ce,
+ AFSStoreVolumeStatus *volstat,
+ char *volumename,
+ char *offlinemsg,
+ char *motd);
+
+
+/* XXX - this shouldn't be public, but getrights in inter.c needs it */
+int
+read_attr (FCacheEntry *, CredCacheEntry *);
+
+Bool
+findaccess (pag_t cred, AccessEntry *ae, AccessEntry **pos);
+
+#endif /* _FCACHE_H_ */
diff --git a/usr.sbin/afs/src/arlad/fprio.c b/usr.sbin/afs/src/arlad/fprio.c
new file mode 100644
index 00000000000..7e4aabe3ab2
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fprio.c
@@ -0,0 +1,300 @@
+/* $OpenBSD: fprio.c,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Manage the priority of the files
+ */
+
+#include "arla_local.h"
+#include <kerberosIV/kafs.h>
+RCSID("$KTH: fprio.c,v 1.3 1998/06/08 18:55:13 lha Exp $");
+
+/* Hashtable of entries by name */
+static Hashtab *fpriohashtab;
+
+/*
+ * fprio - hash help functions
+ */
+
+static int
+fpriocmp (void *a, void *b)
+{
+ struct fpriorityentry *n1 = (struct fpriorityentry *)a;
+ struct fpriorityentry *n2 = (struct fpriorityentry *)b;
+
+ return n1->fid.Cell != n2->fid.Cell ||
+ n1->fid.fid.Volume != n2->fid.fid.Volume ||
+ n1->fid.fid.Vnode != n2->fid.fid.Vnode ||
+ n1->fid.fid.Unique != n2->fid.fid.Unique;
+}
+
+static unsigned
+fpriohash (void *a)
+{
+ struct fpriorityentry *n = (struct fpriorityentry *)a;
+
+ return n->fid.Cell ^ n->fid.fid.Volume ^
+ n->fid.fid.Vnode ^ n->fid.fid.Unique;
+}
+
+/*
+ * fprio_init
+ *
+ * Just create the hashtab. Leave the smartness to the user.
+ */
+
+void
+fprio_init (char *file)
+{
+ fpriohashtab = hashtabnew (FPRIOCACHE_SIZE, fpriocmp, fpriohash);
+ if (fpriohashtab == NULL)
+ arla_errx (1, ADEBERROR, "fprio_init: hashtabnew failed");
+
+ if (file)
+ fprio_readin(file);
+}
+
+/*
+ * Cleanout unwanted enteries
+ */
+
+static Bool
+cleanupfpriohash(void *ptr, void *arg)
+{
+ struct fpriorityentry *n = (struct fpriorityentry *)ptr;
+ struct fpriorityentry *a = (struct fpriorityentry *)arg;
+
+ /* Clean out if
+ *
+ * NULL cleanout argument
+ * cleanout argument is in the same Cell and
+ * Volume == Vnode == 0 (ie, when whole cell), or
+ * Volume == the victim entry's Volume
+ * && Vnode == 0 (ie, whole volume), or
+ * the Vnode and Unique also match (ie the file/direntry)
+ *
+ * This means that memset(&myarg, 0, sizeof(stuct fprioentry))
+ * is probably not what you want. (Cleaning out the localcell's
+ * all entries)
+ */
+
+ if (a == NULL ||
+ (a->fid.Cell == n->fid.Cell &&
+ ((a->fid.fid.Volume == 0 && a->fid.fid.Vnode ==0) ||
+ (a->fid.fid.Volume == n->fid.fid.Volume &&
+ (a->fid.fid.Vnode == 0 ||
+ (a->fid.fid.Vnode == n->fid.fid.Vnode &&
+ a->fid.fid.Unique == n->fid.fid.Unique)))))) {
+
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ fcache_stale_entry (n->fid, broken_callback);
+ free(n);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+int
+fprio_clear(void)
+{
+ hashtabcleantab(fpriohashtab, cleanupfpriohash, NULL);
+ return 0;
+}
+
+/*
+ * zapp the `fid'
+ */
+
+void
+fprio_remove(VenusFid fid)
+{
+ struct fpriorityentry key;
+
+ key.fid = fid;
+ hashtabfree(fpriohashtab, &key);
+ return;
+}
+
+/*
+ * set a `fid' with `prio' to the hashtab
+ */
+
+void
+fprio_set(VenusFid fid, unsigned prio)
+{
+ struct fpriorityentry *e;
+ struct fpriorityentry key;
+
+ key.fid = fid;
+
+ e = hashtabsearch(fpriohashtab, &key);
+ if (e) {
+ e->priority = prio;
+ return;
+ }
+
+ e = calloc(1, sizeof(*e));
+ if (e == NULL) {
+ arla_warn(ADEBFCACHE, 1, "fprio_set: Out of memory");
+ return;
+ }
+ e->fid = fid;
+ e->priority = prio;
+
+ hashtabadd(fpriohashtab, e);
+}
+
+/*
+ * Read in new data from the file
+ */
+
+#define MAXFPRIOLINE 1024
+
+int
+fprio_readin(char *file)
+{
+ FILE *f;
+ char line[MAXFPRIOLINE];
+ unsigned prio;
+ char cell[MAXFPRIOLINE];
+ int32_t cellnum;
+ VenusFid fid;
+ int lineno = 0 ;
+
+ f = fopen(file, "r");
+ if (f == NULL) {
+ arla_warn(ADEBFCACHE, 1, "fprio_readin: cant open file %s", file);
+ return -1;
+ }
+
+ while(fgets(line, sizeof(line)-1, f) != NULL) {
+ lineno++;
+
+ if (line[0] == '#')
+ continue;
+
+ if (sscanf(line, "%d:%s:%u:%u:%u", &prio,
+ cell,
+ &fid.fid.Volume,
+ &fid.fid.Vnode,
+ &fid.fid.Unique) != 5) {
+ arla_warn(ADEBFCACHE, 1,
+ "fprio_readin: %s:%d contain error(s)",
+ file, lineno);
+ continue;
+ }
+
+ cellnum = cell_name2num(cell);
+ if (cellnum == -1) {
+ arla_warn(ADEBFCACHE, 1,
+ "fprio_readin: the cell %s does not exist", cell);
+ continue;
+ }
+
+ fid.Cell = cellnum;
+ fprio_set(fid, prio);
+ }
+ return 0;
+}
+
+/*
+ * Find the priority of a fid
+ */
+
+int
+fprio_get(VenusFid fid)
+{
+ struct fpriorityentry a;
+ struct fpriorityentry *b;
+
+ a.fid = fid;
+
+ b = hashtabsearch(fpriohashtab, &a);
+ if (b)
+ return b->priority;
+ return 0;
+}
+
+/*
+ * Print the entry `ptr' to the FILE `arg'
+ */
+
+static Bool
+fprio_print_entry (void *ptr, void *arg)
+{
+ struct fpriorityentry *n = (struct fpriorityentry *)ptr;
+ FILE *f = (FILE *) ptr;
+ const char *cell = cell_num2name(n->fid.Cell);
+ char *comment;
+
+ if (cell == NULL) /* If we cant find the cell comment it out */
+ comment = "#";
+ else
+ comment = "";
+
+ fprintf(f, "%s%d:%s:%d:%d:%d",
+ comment, n->priority, cell?cell:"unknowncell", n->fid.fid.Volume,
+ n->fid.fid.Vnode, n->fid.fid.Unique);
+
+ return FALSE;
+}
+
+/*
+ * Print the status of the fprio module in some strange format...
+ */
+
+void
+fprio_status (FILE *f)
+{
+ time_t the_time = time(NULL);
+
+ fprintf (f, "#fprio entries\n#\n# Date: %s\n#\n"
+ "#priority range from %d to %d\n#\n"
+ "#Syntax: (# means comment)\n"
+ "#priority:cell:volume:vnode:unique\n",
+ ctime(&the_time), FPRIO_MIN, FPRIO_MAX);
+ hashtabforeach (fpriohashtab, fprio_print_entry, f);
+}
+
+
+
diff --git a/usr.sbin/afs/src/arlad/fprio.h b/usr.sbin/afs/src/arlad/fprio.h
new file mode 100644
index 00000000000..b8a7d123c8e
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/fprio.h
@@ -0,0 +1,70 @@
+/* $OpenBSD: fprio.h,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Our cache of volume information.
+ */
+
+/* $KTH: fprio.h,v 1.3 1998/06/08 18:55:13 lha Exp $ */
+
+#ifndef _FPRIO_
+#define _FPRIO_
+
+
+struct fpriorityentry {
+ VenusFid fid; /* The VenusFid, not stored */
+ unsigned priority; /* The assigned priority */
+} ;
+
+#define FPRIOCACHE_SIZE 2048
+#define MAXFPRIOLINE 1024
+
+void fprio_init (char *file);
+int fprio_clear(void);
+void fprio_remove(VenusFid fid);
+void fprio_set(VenusFid fid, unsigned prio);
+int fprio_readin(char *file);
+int fprio_get(VenusFid fid);
+void fprio_status (FILE *f);
+
+#endif /* _FPRIO_ */
+
+
+
+
diff --git a/usr.sbin/afs/src/arlad/inter.c b/usr.sbin/afs/src/arlad/inter.c
new file mode 100644
index 00000000000..0205beebc4e
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/inter.c
@@ -0,0 +1,1034 @@
+/* $OpenBSD: inter.c,v 1.1.1.1 1998/09/14 21:52:56 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Interface to the cache manager.
+ */
+
+#include "arla_local.h"
+RCSID("$KTH: inter.c,v 1.55 1998/07/29 21:31:59 assar Exp $") ;
+
+#include <xfs/xfs_message.h>
+
+/*
+ * Return the rights for user cred and entry e.
+ * If the rights are not existant fill in the entry.
+ * The locking of e is up to the caller.
+ */
+
+u_long
+getrights (FCacheEntry *e, CredCacheEntry *ce)
+{
+ AccessEntry *ae;
+ int error;
+
+ while (findaccess (ce->cred, e->acccache, &ae) == FALSE) {
+ if ((error = read_attr(e, ce)) != 0)
+ return 0; /* XXXX we want to return errno */
+ }
+ return ae->access;
+}
+
+/*
+ * Check to see if the operation(s) mask are allowed to user cred on
+ * file e
+ */
+
+static Bool
+checkright (FCacheEntry *e, u_long mask, CredCacheEntry *ce)
+{
+ u_long rights;
+
+ if (e->status.FileType == TYPE_LINK &&
+ e->anonaccess & ALIST)
+ return TRUE;
+ if ((e->anonaccess & mask) == mask)
+ return TRUE;
+ rights = getrights (e, ce);
+ if (e->status.FileType == TYPE_LINK &&
+ rights & ALIST)
+ return TRUE;
+ if ((rights & mask) == mask)
+ return TRUE;
+ return FALSE;
+}
+
+static int log_fd;
+static FILE *log_fp;
+
+/*
+ *
+ */
+
+void
+cm_init (void)
+{
+ log_fd = open ("log", O_WRONLY | O_APPEND | O_CREAT | O_BINARY, 0666);
+ if (log_fd < 0)
+ arla_err (1, ADEBERROR, errno, "open log");
+ log_fp = fdopen (log_fd, "a");
+ if (log_fp == NULL)
+ arla_err (1, ADEBERROR, errno, "fdopen");
+}
+
+/*
+ *
+ */
+
+void
+cm_store_state (void)
+{
+ fclose (log_fp);
+}
+
+static void
+log_operation (const char *fmt, ...)
+{
+ va_list args;
+ struct timeval now;
+
+ if(connected_mode == CONNECTED)
+ return;
+
+ va_start (args, fmt);
+#ifdef USE_MMAPTIME
+ mmaptime_gettimeofday (&now, NULL);
+#else
+ gettimeofday (&now, NULL);
+#endif
+ fprintf (log_fp, "%lu.%lu ",
+ (unsigned long)now.tv_sec,
+ (unsigned long)now.tv_usec);
+ vfprintf (log_fp, fmt, args);
+ va_end (args);
+}
+
+
+/*
+ * These functions often take a FID as an argument to be general, but
+ * they are intended to be called from a vnode-type of layer.
+ */
+
+/*
+ * The interface to the open-routine.
+ * This means that the file should be in the local cache and that the
+ * cache manager should recall that some process has this file opened
+ * for reading and/or writing.
+ * We do no checking here. Should we?
+ */
+
+Result
+cm_open (VenusFid fid, CredCacheEntry* ce, u_int tokens)
+{
+ FCacheEntry *entry;
+ Result ret;
+ u_long mask;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ assert (CheckLock (&entry->lock) == -1);
+
+ error = fcache_get_data (entry, ce);
+ if(error) {
+ ReleaseWriteLock (&entry->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ switch(tokens) {
+ case XFS_DATA_R:
+ /* case XFS_OPEN_NR:
+ case XFS_OPEN_SR: */
+ mask = AREAD;
+ break;
+ case XFS_DATA_W:
+ mask = AWRITE;
+ break;
+ case XFS_OPEN_NW:
+ mask = AREAD | AWRITE;
+ break;
+ default:
+ arla_warnx (ADEBCM, "cm_open(): unknown token: %d, assuming AREAD",
+ tokens);
+ mask = AREAD;
+/* assert(FALSE); */
+ }
+
+ if (checkright (entry, mask, ce)) {
+ ret.res = entry->inode;
+ entry->flags.datausedp = TRUE;
+ entry->tokens |= tokens;
+
+ ret.res = entry->inode;
+ ret.tokens = entry->tokens;
+
+ log_operation ("open (%ld,%lu,%lu,%lu) %u\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique,
+ mask);
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ ReleaseWriteLock (&entry->lock);
+
+ return ret;
+}
+
+/*
+ * close. Set flags and if we opened the file for writing, write it
+ * back to the server.
+ */
+
+Result
+cm_close (VenusFid fid, int flag, CredCacheEntry* ce)
+{
+ FCacheEntry *entry;
+ Result ret;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ if (flag & XFS_WRITE) {
+ error = write_data (entry, ce);
+
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+ arla_warn (ADEBCM, error, "writing back file");
+ ret.res = -1 ;
+ ret.error = EPERM ;
+ return ret;
+ }
+ }
+
+ log_operation ("close (%ld,%lu,%lu,%lu) %d\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique,
+ flag);
+
+ ReleaseWriteLock (&entry->lock);
+ ret.res = 0;
+ return ret;
+}
+
+/*
+ * getattr - read the attributes from this file.
+ */
+
+Result
+cm_getattr (VenusFid fid,
+ AFSFetchStatus *attr,
+ VenusFid *realfid,
+ CredCacheEntry* ce,
+ AccessEntry **ae)
+{
+ FCacheEntry *entry;
+ Result ret;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (entry, ce);
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ if (checkright (entry,
+ entry->status.FileType == TYPE_FILE ? AREAD : ALIST,
+ ce)) {
+ *attr = entry->status;
+ ret.res = 0;
+ entry->flags.attrusedp = TRUE;
+ entry->flags.kernelp = TRUE;
+ entry->tokens |= XFS_ATTR_R;
+ if (ae != NULL)
+ *ae = entry->acccache;
+
+ log_operation ("getattr (%ld,%lu,%lu,%lu)\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ if(entry->flags.mountp)
+ *realfid = entry->realfid;
+ else
+ *realfid = fid;
+
+ ReleaseWriteLock (&entry->lock);
+ ret.tokens = entry->tokens;
+ return ret;
+}
+
+/*
+ * setattr - set the attributes of this file. These are immediately
+ * sent to the FS.
+ */
+
+Result
+cm_setattr (VenusFid fid, AFSStoreStatus *attr, CredCacheEntry* ce)
+{
+ FCacheEntry *entry;
+ Result ret;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (entry, ce);
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+ if (checkright (entry, AWRITE, ce)) {
+ arla_warnx (ADEBCM, "cm_setattr: Writing status");
+ ret.res = write_attr (entry, attr, ce);
+ if (ret.res != 0)
+ ret.error = ret.res;
+
+ log_operation ("setattr (%ld,%lu,%lu,%lu)\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ ReleaseWriteLock (&entry->lock);
+ return ret;
+}
+
+/*
+ * ftruncate - make the specified file have a specified size
+ */
+
+Result
+cm_ftruncate (VenusFid fid, off_t size, CredCacheEntry* ce)
+{
+ FCacheEntry *entry;
+ Result ret;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (entry, ce);
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ if (checkright (entry, AWRITE, ce)) {
+ ret.res = truncate_file (entry, size, ce);
+
+ log_operation ("ftruncate (%ld,%lu,%lu,%lu) %lu\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique,
+ (unsigned long)size);
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ ReleaseWriteLock (&entry->lock);
+ return ret;
+}
+
+/*
+ * access - check if user is allowed to perform operation.
+ */
+
+Result
+cm_access (VenusFid fid, int mode, CredCacheEntry* ce)
+{
+ FCacheEntry *entry;
+ Result ret;
+ int error;
+
+ error = fcache_get (&entry, fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (entry, ce);
+ if (error) {
+ ReleaseWriteLock (&entry->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ if (checkright (entry, AWRITE, ce)) {
+ ret.res = 0; /**/
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+
+ log_operation ("access (%ld,%lu,%lu,%lu)\n",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+
+ ReleaseWriteLock (&entry->lock);
+ return ret;
+}
+
+/*
+ * Expand `src' into `dest' (of size `dst_sz'), expanding `str' to
+ * `replacement'. Return number of characters written to `dest'
+ * (excluding terminating zero) or `dst_sz' if there's not enough
+ * room.
+ */
+
+static int
+expand_sys (char *dest, size_t dst_sz, const char *src,
+ const char *str, const char *rep)
+{
+ char *destp = dest;
+ const char *srcp = src;
+ char *s;
+ int n = 0;
+ int len;
+ size_t str_len = strlen(str);
+ size_t rep_len = strlen(rep);
+ size_t src_len = strlen(src);
+
+ while ((s = strstr (srcp, str)) != NULL) {
+ len = s - srcp;
+
+ if (dst_sz <= n + len + rep_len)
+ return dst_sz;
+
+ memcpy (destp, srcp, len);
+ memcpy (destp + len, rep, rep_len);
+ n += len + rep_len;
+ destp += len + rep_len;
+ srcp = s + str_len;
+ }
+ len = src_len - (srcp - src);
+ if (dst_sz <= n + len)
+ return dst_sz;
+ memcpy (destp, srcp, len);
+ n += len;
+ destp[len] = '\0';
+ return n;
+}
+
+/*
+ * Find this entry in the directory. If the entry happens to point to
+ * a mount point, then we follow that and return the root directory of
+ * the volume. Hopefully this is the only place where we need to think
+ * about mount points.
+ */
+
+Result
+cm_lookup (VenusFid dir_fid,
+ const char *name,
+ VenusFid *res,
+ CredCacheEntry** ce)
+{
+ char tmp_name[MAXPATHLEN];
+ Result ret;
+ int error;
+
+ if (strstr (name, "@sys") != NULL) {
+ if (expand_sys (tmp_name, sizeof(tmp_name), name,
+ "@sys", arlasysname) >= sizeof(tmp_name)) {
+ ret.res = -1;
+ ret.error = ENAMETOOLONG;
+ return ret;
+ }
+ name = tmp_name;
+ }
+
+ error = adir_lookup (dir_fid, name, res, *ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+ error = followmountpoint (res, &dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ ret.tokens = 0;
+ }
+
+ /* Assume that this means a bad .. */
+ if ( strcmp("..", name) == 0
+ && dir_fid.Cell == res->Cell
+ && dir_fid.fid.Volume == res->fid.Volume
+ && dir_fid.fid.Vnode == res->fid.Vnode
+ && dir_fid.fid.Unique == res->fid.Unique) {
+ FCacheEntry *e;
+ int error;
+
+ error = fcache_get (&e, dir_fid, *ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (e, *ce);
+ if (error) {
+ ReleaseWriteLock (&e->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ assert (e->flags.mountp);
+
+ *res = e->parent;
+ ret.res = 0;
+ ret.tokens = e->tokens;
+ ReleaseWriteLock (&e->lock);
+ }
+
+ log_operation ("lookup (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name);
+
+ return ret;
+}
+
+/*
+ * Create this file and more.
+ */
+
+Result
+cm_create (VenusFid dir_fid, const char *name, AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ CredCacheEntry* ce)
+{
+ FCacheEntry *dire;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, AINSERT, ce)) {
+ error = create_file (dire, name, store_attr,
+ res, fetch_attr, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_creat (dire, name, res->fid);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+out:
+ log_operation ("create (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name);
+
+ ReleaseWriteLock (&dire->lock);
+ return ret;
+}
+
+/*
+ * Create a new directory
+ */
+
+Result
+cm_mkdir (VenusFid dir_fid, const char *name,
+ AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ CredCacheEntry* ce)
+{
+ FCacheEntry *dire;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, AINSERT, ce)) {
+ error = create_directory (dire, name, store_attr,
+ res, fetch_attr, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_creat (dire, name, res->fid);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+
+ log_operation ("mkdir (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name);
+
+out:
+ ReleaseSharedLock (&dire->lock);
+ return ret;
+}
+
+/*
+ * Create a symlink
+ */
+
+Result
+cm_symlink (VenusFid dir_fid,
+ const char *name, AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ const char *contents,
+ CredCacheEntry* ce)
+{
+ FCacheEntry *dire;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, AINSERT, ce)) {
+ error = create_symlink (dire, name, store_attr,
+ res, fetch_attr,
+ contents, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_creat (dire, name, res->fid);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ log_operation ("symlink (%ld,%lu,%lu,%lu) %s %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name,
+ contents);
+
+out:
+ ReleaseWriteLock (&dire->lock);
+ return ret;
+}
+
+/*
+ * Create a hard link.
+ */
+
+Result
+cm_link (VenusFid dir_fid,
+ const char *name,
+ VenusFid existing_fid,
+ AFSFetchStatus *existing_status,
+ CredCacheEntry* ce)
+{
+ FCacheEntry *dire, *file;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ReleaseWriteLock (&dire->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get (&file, existing_fid, ce);
+ if (error) {
+ ReleaseWriteLock (&dire->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_attr (file, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, AINSERT, ce)) {
+ error = create_link (dire, name,
+ file, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_creat (dire, name, existing_fid.fid);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ *existing_status = file->status;
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ log_operation ("link (%ld,%lu,%lu,%lu) (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ existing_fid.Cell,
+ existing_fid.fid.Volume,
+ existing_fid.fid.Vnode,
+ existing_fid.fid.Unique,
+ name);
+
+out:
+ ReleaseWriteLock (&dire->lock);
+ ReleaseWriteLock (&file->lock);
+ return ret;
+}
+/*
+ *
+ */
+
+Result
+cm_remove(VenusFid dir_fid,
+ const char *name, CredCacheEntry* ce)
+{
+ FCacheEntry *dire;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, ADELETE, ce)) {
+ error = remove_file (dire, name, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_remove (dire, name);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+ log_operation ("remove (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name);
+
+out:
+ ReleaseWriteLock (&dire->lock);
+ return ret;
+}
+
+/*
+ *
+ */
+
+Result
+cm_rmdir(VenusFid dir_fid,
+ const char *name, CredCacheEntry* ce)
+{
+ FCacheEntry *dire;
+ Result ret;
+ int error;
+
+ error = fcache_get (&dire, dir_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (dire, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ if (checkright (dire, ADELETE, ce)) {
+ error = remove_directory (dire, name, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ error = adir_remove (dire, name);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+
+ log_operation ("rmdir (%ld,%lu,%lu,%lu) %s\n",
+ dir_fid.Cell,
+ dir_fid.fid.Volume, dir_fid.fid.Vnode, dir_fid.fid.Unique,
+ name);
+
+out:
+ ReleaseWriteLock (&dire->lock);
+ return ret;
+}
+
+/*
+ *
+ */
+
+Result
+cm_rename(VenusFid old_parent_fid, const char *old_name,
+ VenusFid new_parent_fid, const char *new_name,
+ CredCacheEntry* ce)
+{
+ FCacheEntry *old_dir;
+ FCacheEntry *new_dir;
+ Result ret;
+ int error;
+
+ /* old parent dir */
+
+ error = fcache_get (&old_dir, old_parent_fid, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (old_dir, ce);
+ if (error) {
+ ReleaseWriteLock (&old_dir->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ /* new parent dir */
+
+ if (old_parent_fid.fid.Vnode != new_parent_fid.fid.Vnode
+ || old_parent_fid.fid.Unique != new_parent_fid.fid.Unique) {
+
+ error = fcache_get (&new_dir, new_parent_fid, ce);
+ if (error) {
+ ReleaseWriteLock (&old_dir->lock);
+ ret.res = -1;
+ ret.error = error;
+ return ret;
+ }
+
+ error = fcache_get_data (new_dir, ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+
+ } else {
+ new_dir = old_dir;
+ }
+
+ if (checkright (old_dir, ADELETE, ce)
+ && checkright (new_dir, AINSERT, ce)) {
+
+ error = rename_file (old_dir, old_name,
+ new_dir, new_name,
+ ce);
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ VenusFid foo_fid;
+
+ ReleaseWriteLock (&old_dir->lock);
+ error = adir_lookup (old_dir->fid, old_name, &foo_fid, ce);
+ ObtainWriteLock (&old_dir->lock);
+
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ goto out;
+ }
+ error = adir_remove (old_dir, old_name)
+ || adir_creat (new_dir, new_name, foo_fid.fid);
+
+ if (error) {
+ ret.res = -1;
+ ret.error = error;
+ } else {
+ ret.res = 0;
+ }
+ }
+ } else {
+ ret.res = -1;
+ ret.error = EACCES;
+ }
+
+ log_operation ("rename (%ld,%lu,%lu,%lu) (%ld,%lu,%lu,%lu) %s %s\n",
+ old_parent_fid.Cell,
+ old_parent_fid.fid.Volume,
+ old_parent_fid.fid.Vnode,
+ old_parent_fid.fid.Unique,
+ new_parent_fid.Cell,
+ new_parent_fid.fid.Volume,
+ new_parent_fid.fid.Vnode,
+ new_parent_fid.fid.Unique,
+ old_name, new_name);
+
+out:
+ ReleaseWriteLock (&old_dir->lock);
+ if (old_parent_fid.fid.Vnode != new_parent_fid.fid.Vnode
+ || old_parent_fid.fid.Unique != new_parent_fid.fid.Unique)
+ ReleaseWriteLock (&new_dir->lock);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/arlad/inter.h b/usr.sbin/afs/src/arlad/inter.h
new file mode 100644
index 00000000000..96296728f82
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/inter.h
@@ -0,0 +1,129 @@
+/* $OpenBSD: inter.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 interface to the cache manager.
+ */
+
+/* $KTH: inter.h,v 1.14 1998/07/22 07:04:06 assar Exp $ */
+
+#ifndef _INTER_H_
+#define _INTER_H_
+
+#include <cred.h>
+
+/*
+ * This is the return value of all these operations.
+ * Iff res == -1, the error reason should be errno.
+ */
+
+typedef struct {
+ int res;
+ int error;
+ u_int tokens;
+} Result;
+
+void
+cm_init (void);
+
+void
+cm_store_state (void);
+
+Result
+cm_open (VenusFid fid, CredCacheEntry *ce, u_int tokens);
+
+Result
+cm_close (VenusFid fid, int flag, CredCacheEntry *ce);
+
+Result
+cm_getattr (VenusFid fid,
+ AFSFetchStatus *attr,
+ VenusFid *real_fid,
+ CredCacheEntry *ce,
+ AccessEntry **ae);
+
+Result
+cm_setattr (VenusFid fid, AFSStoreStatus *attr, CredCacheEntry *ce);
+
+Result
+cm_ftruncate (VenusFid fid, off_t size, CredCacheEntry *ce);
+
+Result
+cm_access (VenusFid fid, int mode, CredCacheEntry *ce);
+
+Result
+cm_lookup (VenusFid dir_fid, const char *name, VenusFid *res,
+ CredCacheEntry **ce);
+Result
+cm_create (VenusFid dir_fid, const char *name, AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ CredCacheEntry* ce);
+Result
+cm_mkdir (VenusFid dir_fid, const char *name, AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ CredCacheEntry* ce);
+
+Result
+cm_remove (VenusFid dir_fid, const char *name, CredCacheEntry *ce);
+
+Result
+cm_rmdir (VenusFid dir_fid, const char *name, CredCacheEntry *ce);
+
+Result
+cm_readdir (VenusFid fid);
+
+Result
+cm_link (VenusFid dir_fid, const char *name,
+ VenusFid existing_fid,
+ AFSFetchStatus *existing_status,
+ CredCacheEntry* ce);
+
+Result
+cm_symlink (VenusFid dir_fid, const char *name,
+ AFSStoreStatus *store_attr,
+ VenusFid *res, AFSFetchStatus *fetch_attr,
+ const char *contents,
+ CredCacheEntry* ce);
+
+Result
+cm_rename(VenusFid old_parent_fid, const char *old_name,
+ VenusFid new_parent_fid, const char *new_name,
+ CredCacheEntry* ce);
+
+#endif /* _INTER_H_ */
diff --git a/usr.sbin/afs/src/arlad/kernel.c b/usr.sbin/afs/src/arlad/kernel.c
new file mode 100644
index 00000000000..de6a0229c9a
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/kernel.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: kernel.c,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "arla_local.h"
+RCSID("$KTH: kernel.c,v 1.12 1998/07/13 19:19:02 assar Exp $");
+
+/*
+ * The fd we use to talk with the kernel on.
+ */
+
+int kernel_fd;
+
+/* count of the number of messages in a read */
+
+static unsigned recv_count[20];
+
+/* for more than above... */
+
+static unsigned recv_count_overflow;
+
+static int
+process_message (int fd)
+{
+ static char data[MAX_XMSG_SIZE];
+ int res;
+ struct xfs_message_header *header;
+ char *p;
+ int cnt;
+
+ res = read (fd, data, sizeof (data));
+
+ if (res < 0) {
+ arla_warn (ADEBWARN, errno, "read");
+ /* XXX process the errno? Are we supposed to exit on every error?*/
+ return -1;
+ }
+ cnt = 0;
+ for (p = data; res > 0; p += header->size, res -= header->size) {
+ header = (struct xfs_message_header *)p;
+ xfs_message_receive (fd, header, header->size);
+ ++cnt;
+ }
+ if (cnt < sizeof(recv_count)/sizeof(recv_count[0]))
+ ++recv_count[cnt];
+ else
+ ++recv_count_overflow;
+
+ return 0;
+}
+
+void
+kernel_interface (char *device)
+{
+ int fd;
+
+ fd = open (device, O_RDWR);
+ if (fd < 0)
+ arla_err (1, ADEBERROR, errno, "open %s", device);
+ kernel_fd = fd;
+
+ arla_warnx(ADEBKERNEL, "Arla: selecting on fd: %d", fd);
+
+ for (;;) {
+ fd_set readset;
+ int ret;
+
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+
+ ret = IOMGR_Select (fd + 1, &readset, NULL, NULL, NULL);
+
+ if (ret < 0)
+ arla_warn (ADEBKERNEL, errno, "select");
+ else if (ret == 0)
+ arla_warnx (ADEBKERNEL,
+ "Arla: select returned with 0. strange.");
+ else if (FD_ISSET(fd, &readset)) {
+
+ if (process_message (fd))
+ arla_errx (1, ADEBKERNEL, "error processing message");
+ }
+ }
+}
diff --git a/usr.sbin/afs/src/arlad/kernel.h b/usr.sbin/afs/src/arlad/kernel.h
new file mode 100644
index 00000000000..97de7190d50
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/kernel.h
@@ -0,0 +1,49 @@
+/* $OpenBSD: kernel.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: kernel.h,v 1.2 1998/02/19 05:48:20 assar Exp $ */
+
+#ifndef _KERNEL_H_
+#define _KERNEL_H_
+
+void kernel_interface (char *device);
+
+extern int kernel_fd;
+
+#endif /* _KERNEL_H_ */
diff --git a/usr.sbin/afs/src/arlad/messages.c b/usr.sbin/afs/src/arlad/messages.c
new file mode 100644
index 00000000000..9c185ed8b8b
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/messages.c
@@ -0,0 +1,2452 @@
+/* $OpenBSD: messages.c,v 1.1.1.1 1998/09/14 21:52:54 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "arla_local.h"
+RCSID("$KTH: messages.c,v 1.79 1998/08/17 21:03:20 art Exp $");
+
+#include <xfs/xfs_message.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <kerberosIV/kafs.h>
+
+#include "messages.h"
+
+static int
+xfs_message_wakeup (int, struct xfs_message_wakeup*, u_int);
+
+static int
+xfs_message_getroot (int, struct xfs_message_getroot*, u_int);
+
+static int
+xfs_message_getnode (int, struct xfs_message_getnode*, u_int);
+
+static int
+xfs_message_getattr (int, struct xfs_message_getattr*, u_int);
+
+static int
+xfs_message_getdata (int, struct xfs_message_getdata*, u_int);
+
+static int
+xfs_message_inactivenode (int,struct xfs_message_inactivenode*,u_int);
+
+static int
+xfs_message_putdata (int fd, struct xfs_message_putdata *h, u_int size);
+
+static int
+xfs_message_putattr (int fd, struct xfs_message_putattr *h, u_int size);
+
+static int
+xfs_message_create (int fd, struct xfs_message_create *h, u_int size);
+
+static int
+xfs_message_mkdir (int fd, struct xfs_message_mkdir *h, u_int size);
+
+static int
+xfs_message_link (int fd, struct xfs_message_link *h, u_int size);
+
+static int
+xfs_message_symlink (int fd, struct xfs_message_symlink *h, u_int size);
+
+static int
+xfs_message_remove (int fd, struct xfs_message_remove *h, u_int size);
+
+static int
+xfs_message_rmdir (int fd, struct xfs_message_rmdir *h, u_int size);
+
+static int
+xfs_message_rename (int fd, struct xfs_message_rename *h, u_int size);
+
+static int
+xfs_message_pioctl (int fd, struct xfs_message_pioctl *h, u_int size) ;
+
+typedef int
+(*xfs_message_function) (int, struct xfs_message_header*, u_int);
+
+static xfs_message_function rcvfuncs[] = {
+NULL, /* version */
+(xfs_message_function)xfs_message_wakeup, /* wakeup */
+(xfs_message_function)xfs_message_getroot, /* getroot */
+NULL, /* installroot */
+(xfs_message_function)xfs_message_getnode, /* getnode */
+NULL, /* installnode */
+(xfs_message_function)xfs_message_getattr, /* getattr */
+NULL, /* installattr */
+(xfs_message_function)xfs_message_getdata, /* getdata */
+NULL, /* installdata */
+(xfs_message_function)xfs_message_inactivenode, /* inactivenode */
+NULL, /* invalidnode */
+(xfs_message_function)xfs_message_getdata, /* open */
+(xfs_message_function)xfs_message_putdata, /* put_data */
+(xfs_message_function)xfs_message_putattr, /* put attr */
+(xfs_message_function)xfs_message_create, /* create */
+(xfs_message_function)xfs_message_mkdir, /* mkdir */
+(xfs_message_function)xfs_message_link, /* link */
+(xfs_message_function)xfs_message_symlink, /* symlink */
+(xfs_message_function)xfs_message_remove, /* remove */
+(xfs_message_function)xfs_message_rmdir, /* rmdir */
+(xfs_message_function)xfs_message_rename, /* rename */
+(xfs_message_function)xfs_message_pioctl, /* pioctl */
+NULL /* wakeup_data */
+};
+
+static u_int *seqnums;
+
+static List *sleepers;
+
+/* number of times each type of message has been sent */
+
+static unsigned sent_stat[XFS_MSG_COUNT];
+
+/* number of times each type of message has been received */
+
+static unsigned recv_stat[XFS_MSG_COUNT];
+
+/* count of the number of messages in a write */
+
+static unsigned send_count[9]; /* 8 is the max the multiple stuff handles */
+
+static char *rcvfuncs_name[] =
+{
+ "version",
+ "wakeup",
+ "getroot",
+ "installroot",
+ "getnode",
+ "installnode",
+ "getattr",
+ "installattr",
+ "getdata",
+ "installdata",
+ "inactivenode",
+ "invalidnode",
+ "open",
+ "put_data",
+ "put_attr",
+ "create",
+ "mkdir",
+ "link",
+ "symlink",
+ "remove",
+ "rmdir",
+ "rename",
+ "pioctl",
+ "wakeup_data",
+};
+
+long
+afsfid2inode (VenusFid *fid)
+{
+ return ((fid->fid.Volume & 0x7FFF) << 16 | (fid->fid.Vnode & 0xFFFFFFFF));
+}
+
+/*
+ * AFSFetchStatus -> xfs_attr
+ */
+
+static void
+afsstatus2xfs_attr (AFSFetchStatus *status,
+ VenusFid *fid,
+ struct xfs_attr *attr)
+{
+ attr->valid = XA_V_NONE;
+ switch (status->FileType) {
+ case TYPE_FILE :
+ XA_SET_MODE(attr, S_IFREG);
+ XA_SET_TYPE(attr, XFS_FILE_REG);
+ break;
+ case TYPE_DIR :
+ XA_SET_MODE(attr, S_IFDIR);
+ XA_SET_TYPE(attr, XFS_FILE_DIR);
+ break;
+ case TYPE_LINK :
+ XA_SET_MODE(attr, S_IFLNK);
+ XA_SET_TYPE(attr, XFS_FILE_LNK);
+ break;
+ default :
+ arla_warnx (ADEBMSG, "afsstatus2xfs_attr: default");
+ abort ();
+ }
+ XA_SET_NLINK(attr, status->LinkCount);
+ XA_SET_SIZE(attr, status->Length);
+ XA_SET_UID(attr,status->Owner);
+ XA_SET_GID(attr, status->Group);
+ attr->xa_mode |= status->UnixModeBits;
+ XA_SET_ATIME(attr, status->ServerModTime);
+ XA_SET_MTIME(attr, status->ServerModTime);
+ XA_SET_CTIME(attr, status->ServerModTime);
+ XA_SET_FILEID(attr, afsfid2inode(fid));
+}
+
+/*
+ * Transform `access', `FileType' and `UnixModeBits' into rights.
+ *
+ * There are different transformations for directories and files to be
+ * compatible with the Transarc client.
+ */
+
+static u_char
+afsrights2xfsrights(u_long ar, u_int32_t FileType, u_int32_t UnixModeBits)
+{
+ u_char ret = 0;
+
+ if (FileType == TYPE_DIR) {
+ if (ar & ALIST)
+ ret |= XFS_RIGHT_R | XFS_RIGHT_X;
+ if (ar & (AINSERT | ADELETE))
+ ret |= XFS_RIGHT_W;
+ } else {
+ if (FileType == TYPE_LINK && (ar & ALIST))
+ ret |= XFS_RIGHT_R;
+ if ((ar & AREAD) && (UnixModeBits & S_IRUSR))
+ ret |= XFS_RIGHT_R;
+ if ((ar & AWRITE) && (UnixModeBits & S_IWUSR))
+ ret |= XFS_RIGHT_W;
+ if ((ar & AREAD) && (UnixModeBits & S_IXUSR))
+ ret |= XFS_RIGHT_X;
+ }
+
+ return ret;
+}
+
+static void
+fcacheentry2xfsnode (VenusFid *fid,
+ VenusFid *statfid,
+ AFSFetchStatus *status,
+ struct xfs_msg_node *node,
+ AccessEntry *ae)
+{
+ int i;
+
+ afsstatus2xfs_attr (status, statfid, &node->attr);
+ memcpy (&node->handle, fid, sizeof(*fid));
+ node->anonrights = afsrights2xfsrights(status->AnonymousAccess,
+ status->FileType,
+ status->UnixModeBits);
+ for (i = 0; i < NACCESS; i++) {
+ node->id[i] = ae[i].cred;
+ node->rights[i] = afsrights2xfsrights(ae[i].access,
+ status->FileType,
+ status->UnixModeBits);
+ }
+}
+
+static int
+xfs_attr2afsstorestatus(struct xfs_attr *xa,
+ AFSStoreStatus *storestatus)
+{
+ int mask = 0;
+
+ if (XA_VALID_MODE(xa)) {
+ storestatus->UnixModeBits = xa->xa_mode;
+ mask |= SS_MODEBITS;
+ }
+ if (XA_VALID_UID(xa)) {
+ storestatus->Owner = xa->xa_uid;
+ mask |= SS_OWNER;
+ }
+ if (XA_VALID_GID(xa)) {
+ storestatus->Group = xa->xa_gid;
+ mask |= SS_GROUP;
+ }
+ if (XA_VALID_MTIME(xa)) {
+ storestatus->ClientModTime = xa->xa_mtime;
+ mask |= SS_MODTIME;
+ }
+ storestatus->Mask = mask ;
+
+ /* SS_SegSize */
+ storestatus->SegSize = 0 ;
+ return 0;
+}
+
+/*
+ *
+ */
+
+void
+xfs_message_init (void)
+{
+ unsigned i;
+
+ seqnums = (u_int *)malloc (sizeof (*seqnums) * getdtablesize ());
+ if (seqnums == NULL)
+ arla_err (1, ADEBERROR, errno, "xfs_message_init: malloc");
+ for (i = 0; i < getdtablesize (); ++i)
+ seqnums[i] = 0;
+ sleepers = listnew ();
+ if (sleepers == NULL)
+ arla_err (1, ADEBERROR, errno, "xfs_message_init: listnew");
+ assert (sizeof(rcvfuncs) / sizeof(*rcvfuncs) == XFS_MSG_COUNT);
+ assert (sizeof(rcvfuncs_name) / sizeof(*rcvfuncs_name) == XFS_MSG_COUNT);
+}
+
+/*
+ *
+ */
+
+int
+xfs_message_receive (int fd, struct xfs_message_header *h, u_int size)
+{
+ unsigned opcode = h->opcode;
+
+ if (opcode >= XFS_MSG_COUNT || rcvfuncs[opcode] == NULL ) {
+ arla_warnx (ADEBMSG, "Bad message opcode = %u", opcode);
+ return -1;
+ }
+
+ ++recv_stat[opcode];
+
+ arla_warnx (ADEBMSG, "Rec message: opcode = %u (%s), size = %u",
+ opcode, rcvfuncs_name[opcode], h->size);
+
+ return (*rcvfuncs[opcode])(fd, h, size);
+}
+
+static int
+xfs_message_send (int fd, struct xfs_message_header *h, u_int size)
+{
+ int res;
+ unsigned opcode = h->opcode;
+
+ h->size = size;
+ h->sequence_num = seqnums[fd]++;
+
+ if (opcode >= XFS_MSG_COUNT) {
+ arla_warnx (ADEBMSG, "Bad message opcode = %u", opcode);
+ return -1;
+ }
+
+ ++sent_stat[opcode];
+ ++send_count[1];
+
+ arla_warnx (ADEBMSG, "Send message: opcode = %u (%s), size = %u",
+ opcode, rcvfuncs_name[opcode], h->size);
+
+ if ((res = write (fd, h, size)) < 0) {
+ arla_warn (ADEBMSG, errno, "xfs_message_send: write");
+ return -1;
+ } else
+ return 0;
+}
+
+static int
+xfs_message_wakeup (int fd, struct xfs_message_wakeup *h, u_int size)
+{
+ Listitem *i;
+ struct xfs_message_header *w;
+
+ for (i = listhead (sleepers); i; i = listnext (sleepers, i)) {
+ w = (struct xfs_message_header *)listdata(i);
+ if (w->sequence_num == h->sleepers_sequence_num) {
+ listdel (sleepers, i);
+ memcpy (w, h, size);
+ LWP_SignalProcess ((char *)w);
+ }
+ }
+ return 0;
+}
+
+#ifdef notyet
+static int
+xfs_message_sleep (struct xfs_message_header *h)
+{
+ listaddtail (sleepers, h);
+ LWP_WaitProcess ((char *)h);
+ return ((struct xfs_message_wakeup *)h)->error;
+}
+
+static int
+xfs_message_rpc (int fd, struct xfs_message_header *h, u_int size)
+{
+ if (size < sizeof (struct xfs_message_wakeup)) {
+ arla_warnx (ADEBMSG, "xfs_message_rpc: Too small packet for rpc");
+ return -1;
+ }
+ return xfs_message_send (fd, h, size) || xfs_message_sleep (h);
+}
+#endif
+
+static int
+xfs_send_message_wakeup (int fd, u_int seqnum, int error)
+{
+ struct xfs_message_wakeup msg;
+
+ msg.header.opcode = XFS_MSG_WAKEUP;
+ msg.sleepers_sequence_num = seqnum;
+ msg.error = error;
+ arla_warnx (ADEBMSG, "sending wakeup: seq = %u, error = %d",
+ seqnum, error);
+ return xfs_message_send (fd, (struct xfs_message_header *)&msg,
+ sizeof(msg));
+}
+
+/*
+ *
+ */
+
+static int
+xfs_send_message_wakeup_vmultiple (int fd,
+ u_int seqnum,
+ int error,
+ va_list args)
+{
+ struct iovec iovec[8];
+ struct xfs_message_header *h;
+ struct xfs_message_wakeup msg;
+ size_t size;
+ int i = 0;
+ int ret;
+
+ h = va_arg (args, struct xfs_message_header *);
+ size = va_arg (args, size_t);
+ while (h != NULL) {
+ h->size = size;
+ h->sequence_num = seqnums[fd]++;
+ assert (h->opcode >= 0 && h->opcode < XFS_MSG_COUNT);
+ assert (i < 8);
+ iovec[i].iov_base = (char *)h;
+ iovec[i].iov_len = size;
+
+ ++sent_stat[h->opcode];
+
+ arla_warnx (ADEBMSG, "Multi-send: opcode = %u (%s), size = %u",
+ h->opcode, rcvfuncs_name[h->opcode], h->size);
+
+ h = va_arg (args, struct xfs_message_header *);
+ size = va_arg (args, size_t);
+ ++i;
+ }
+ msg.header.opcode = XFS_MSG_WAKEUP;
+ msg.header.size = sizeof(msg);
+ msg.header.sequence_num = seqnums[fd]++;
+ msg.sleepers_sequence_num = seqnum;
+ msg.error = error;
+ iovec[i].iov_base = (char *)&msg;
+ iovec[i].iov_len = sizeof(msg);
+
+ ++sent_stat[XFS_MSG_WAKEUP];
+
+ arla_warnx (ADEBMSG, "multi-sending wakeup: seq = %u, error = %d",
+ seqnum, error);
+
+ ++i;
+
+ ++send_count[i];
+
+ ret = writev (fd, iovec, i);
+ if (ret < 0) {
+ arla_warn (ADEBMSG, errno,
+ "xfs_send_message_wakeup_vmultiple: writev");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+xfs_send_message_wakeup_multiple (int fd,
+ u_int seqnum,
+ int error,
+ ...)
+{
+ va_list args;
+ int ret;
+
+ va_start (args, error);
+ ret = xfs_send_message_wakeup_vmultiple (fd, seqnum, error, args);
+ va_end (args);
+ return ret;
+}
+
+static int
+xfs_send_message_wakeup_data (int fd, u_int seqnum, int error,
+ void *data, int size)
+{
+ struct xfs_message_wakeup_data msg;
+
+ msg.header.opcode = XFS_MSG_WAKEUP_DATA;
+ msg.sleepers_sequence_num = seqnum;
+ msg.error = error;
+ arla_warnx (ADEBMSG,
+ "sending wakeup: seq = %u, error = %d", seqnum, error);
+
+ if (sizeof(msg) >= size && size != 0) {
+ memcpy(msg.msg, data, size);
+ }
+
+ msg.len = size;
+
+ return xfs_message_send (fd, (struct xfs_message_header *)&msg,
+ sizeof(msg));
+}
+
+static int
+xfs_message_getroot (int fd, struct xfs_message_getroot *h, u_int size)
+{
+ struct xfs_message_installroot msg;
+ int ret = 0;
+ VenusFid root_fid;
+ VenusFid real_fid;
+ AFSFetchStatus status;
+ Result result;
+ CredCacheEntry *ce;
+ AccessEntry *ae;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ ce = cred_get (0, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ ret = getroot (&root_fid, ce);
+ if (ret)
+ goto out;
+
+ result = cm_getattr(root_fid, &status, &real_fid, ce, &ae);
+ if (result.res == -1) {
+ ret = result.error;
+ goto out;
+ }
+
+ fcacheentry2xfsnode (&root_fid, &real_fid,
+ &status, &msg.node, ae);
+
+ msg.header.opcode = XFS_MSG_INSTALLROOT;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+
+out:
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_getroot (fd, h, size);
+ }
+
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ NULL, 0);
+ return ret;
+}
+
+static int
+xfs_message_getnode (int fd, struct xfs_message_getnode *h, u_int size)
+{
+ struct xfs_message_installnode msg;
+ VenusFid *dirfid = (VenusFid *)&h->parent_handle;
+ VenusFid fid;
+ VenusFid real_fid;
+ Result res;
+ AFSFetchStatus status;
+ CredCacheEntry *ce;
+ AccessEntry *ae;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ ce = cred_get (dirfid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_lookup (*dirfid, h->name, &fid, &ce);
+ if (res.res == 0) {
+ res = cm_getattr (fid, &status, &real_fid, ce, &ae);
+ if (res.res == 0) {
+ fcacheentry2xfsnode (&fid, &real_fid,
+ &status, &msg.node, ae);
+
+ msg.node.tokens = res.tokens & ~XFS_DATA_MASK;
+ msg.parent_handle = h->parent_handle;
+ strcpy (msg.name, h->name);
+
+ msg.header.opcode = XFS_MSG_INSTALLNODE;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+ }
+ }
+
+ if (res.res != 0 && res.error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_getnode (fd, h, size);
+ }
+
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ res.res == -1 ? res.error : res.res,
+ h0, h0_len,
+ NULL, 0);
+ return 0;
+}
+
+static int
+xfs_message_getattr (int fd, struct xfs_message_getattr *h, u_int size)
+{
+ struct xfs_message_installattr msg;
+ VenusFid *fid;
+ VenusFid real_fid;
+ AFSFetchStatus status;
+ Result res;
+ CredCacheEntry *ce;
+ AccessEntry *ae;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ fid = (VenusFid *)&h->handle;
+
+ ce = cred_get (fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_getattr (*fid, &status, &real_fid, ce, &ae);
+ if (res.res == 0) {
+ fcacheentry2xfsnode (fid, &real_fid,
+ &status, &msg.node, ae);
+
+ msg.node.tokens = res.tokens & ~XFS_DATA_MASK;
+ msg.header.opcode = XFS_MSG_INSTALLATTR;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+ }
+
+ if (res.res != 0 && res.error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_getattr (fd, h, size);
+ }
+
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ res.res ? res.error : res.res,
+ h0, h0_len,
+ NULL, 0);
+
+ return 0;
+}
+
+
+static int
+xfs_message_putattr (int fd, struct xfs_message_putattr *h, u_int size)
+{
+ VenusFid *fid;
+ AFSStoreStatus status;
+ Result res;
+ CredCacheEntry *ce;
+
+ fid = (VenusFid *)&h->handle;
+
+ ce = cred_get (fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ xfs_attr2afsstorestatus(&h->attr, &status);
+ res.res = 0;
+ if (XA_VALID_SIZE(&h->attr))
+ res = cm_ftruncate (*fid, h->attr.xa_size, ce);
+
+ if (res.res == 0)
+ res = cm_setattr(*fid, &status, ce);
+
+ if (res.res != 0 && res.error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_putattr (fd, h, size);
+ }
+
+ cred_free (ce);
+ xfs_send_message_wakeup (fd, h->header.sequence_num,
+ res.res ? res.error : res.res);
+ return 0;
+}
+
+static int
+xfs_message_create (int fd, struct xfs_message_create *h, u_int size)
+{
+ VenusFid *parent_fid, child_fid;
+ AFSStoreStatus store_status;
+ AFSFetchStatus fetch_status;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg1;
+ struct xfs_message_installnode msg2;
+ struct xfs_message_installdata msg3;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+ struct xfs_message_header *h1 = NULL;
+ size_t h1_len = 0;
+ struct xfs_message_header *h2 = NULL;
+ size_t h2_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ xfs_attr2afsstorestatus(&h->attr, &store_status);
+ res = cm_create(*parent_fid, h->name, &store_status,
+ &child_fid, &fetch_status, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ FCacheEntry *child_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg1.cache_handle, tmp, 4);
+ msg1.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status,
+ &msg1.node,
+ dir_entry->acccache);
+ ReleaseWriteLock (&dir_entry->lock);
+
+ ret = fcache_get (&child_entry, child_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (child_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&child_entry->lock);
+ goto out;
+ }
+
+ sprintf (tmp, "%04X", (unsigned)child_entry->inode); /* XXX */
+ ReleaseWriteLock (&child_entry->lock);
+
+ msg1.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg1;
+ h0_len = sizeof(msg1);
+
+ fcacheentry2xfsnode (&child_fid, &child_fid,
+ &fetch_status, &msg2.node, dir_entry->acccache);
+
+ msg2.node.tokens = XFS_ATTR_R | XFS_OPEN_NW | XFS_OPEN_NR; /* XXX */
+ msg2.parent_handle = h->parent_handle;
+ strcpy (msg2.name, h->name);
+
+ msg2.header.opcode = XFS_MSG_INSTALLNODE;
+ h1 = (struct xfs_message_header *)&msg2;
+ h1_len = sizeof(msg2);
+
+ msg3.node = msg2.node;
+ msg3.header.opcode = XFS_MSG_INSTALLDATA;
+ strncpy((char *)&msg3.cache_handle, tmp, 4); /* XXX */
+ h2 = (struct xfs_message_header *)&msg3;
+ h2_len = sizeof(msg3);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_create (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ h1, h1_len,
+ h2, h2_len,
+ NULL, 0);
+
+ return ret;
+}
+
+static int
+xfs_message_mkdir (int fd, struct xfs_message_mkdir *h, u_int size)
+{
+ VenusFid *parent_fid, child_fid;
+ AFSStoreStatus store_status;
+ AFSFetchStatus fetch_status;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg1;
+ struct xfs_message_installnode msg2;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+ struct xfs_message_header *h1 = NULL;
+ size_t h1_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ xfs_attr2afsstorestatus(&h->attr, &store_status);
+ res = cm_mkdir(*parent_fid, h->name, &store_status,
+ &child_fid, &fetch_status, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg1.cache_handle, tmp, 4);
+ msg1.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status, &msg1.node,
+ dir_entry->acccache);
+
+ msg1.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg1;
+ h0_len = sizeof(msg1);
+ ReleaseWriteLock (&dir_entry->lock);
+
+ fcacheentry2xfsnode (&child_fid, &child_fid,
+ &fetch_status, &msg2.node,
+ dir_entry->acccache);
+
+ msg2.node.tokens = XFS_ATTR_R; /* XXX */
+ msg2.parent_handle = h->parent_handle;
+ strcpy (msg2.name, h->name);
+
+ msg2.header.opcode = XFS_MSG_INSTALLNODE;
+ h1 = (struct xfs_message_header *)&msg2;
+ h1_len = sizeof(msg2);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_mkdir (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ h1, h1_len,
+ NULL, 0);
+
+ return ret;
+}
+
+static int
+xfs_message_link (int fd, struct xfs_message_link *h, u_int size)
+{
+ VenusFid *parent_fid, *existing_fid;
+ AFSFetchStatus fetch_status;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg1;
+ struct xfs_message_installnode msg2;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+ struct xfs_message_header *h1 = NULL;
+ size_t h1_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+ existing_fid = (VenusFid *)&h->from_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_link (*parent_fid, h->name, *existing_fid,
+ &fetch_status, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg1.cache_handle, tmp, 4);
+ msg1.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status, &msg1.node,
+ dir_entry->acccache);
+
+ msg1.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg1;
+ h0_len = sizeof(msg1);
+ ReleaseWriteLock (&dir_entry->lock);
+
+ fcacheentry2xfsnode (existing_fid, existing_fid,
+ &fetch_status, &msg2.node,
+ dir_entry->acccache);
+
+ msg2.node.tokens = XFS_ATTR_R; /* XXX */
+ msg2.parent_handle = h->parent_handle;
+ strcpy (msg2.name, h->name);
+
+ msg2.header.opcode = XFS_MSG_INSTALLNODE;
+ h1 = (struct xfs_message_header *)&msg2;
+ h1_len = sizeof(msg2);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_link (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ h1, h1_len,
+ NULL, 0);
+
+ return ret;
+}
+
+static int
+xfs_message_symlink (int fd, struct xfs_message_symlink *h, u_int size)
+{
+ VenusFid *parent_fid, child_fid;
+ AFSStoreStatus store_status;
+ AFSFetchStatus fetch_status;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg1;
+ struct xfs_message_installnode msg2;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+ struct xfs_message_header *h1 = NULL;
+ size_t h1_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ xfs_attr2afsstorestatus(&h->attr, &store_status);
+ res = cm_symlink(*parent_fid, h->name, &store_status,
+ &child_fid, &fetch_status,
+ h->contents, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg1.cache_handle, tmp, 4);
+ msg1.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status, &msg1.node,
+ dir_entry->acccache);
+
+ msg1.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg1;
+ h0_len = sizeof(msg1);
+ ReleaseWriteLock (&dir_entry->lock);
+
+ fcacheentry2xfsnode (&child_fid, &child_fid,
+ &fetch_status, &msg2.node,
+ dir_entry->acccache);
+
+ msg2.node.tokens = XFS_ATTR_R; /* XXX */
+ msg2.parent_handle = h->parent_handle;
+ strcpy (msg2.name, h->name);
+
+ msg2.header.opcode = XFS_MSG_INSTALLNODE;
+ h1 = (struct xfs_message_header *)&msg2;
+ h1_len = sizeof(msg2);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_symlink (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ h1, h1_len,
+ NULL, 0);
+ return ret;
+}
+
+static int
+xfs_message_remove (int fd, struct xfs_message_remove *h, u_int size)
+{
+ VenusFid *parent_fid;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_remove(*parent_fid, h->name, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg.cache_handle, tmp, 4);
+ msg.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status, &msg.node,
+ dir_entry->acccache);
+
+ msg.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+ ReleaseWriteLock (&dir_entry->lock);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_remove (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ NULL, 0);
+ return ret;
+}
+
+static int
+xfs_message_rmdir (int fd, struct xfs_message_rmdir *h, u_int size)
+{
+ VenusFid *parent_fid;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ parent_fid = (VenusFid *)&h->parent_handle;
+
+ ce = cred_get (parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_rmdir(*parent_fid, h->name, ce);
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg.cache_handle, tmp, 4);
+ msg.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *parent_fid;
+
+ fcacheentry2xfsnode (parent_fid, &realfid,
+ &dir_entry->status, &msg.node,
+ dir_entry->acccache);
+
+ msg.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+ ReleaseWriteLock (&dir_entry->lock);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_rmdir (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ NULL, 0);
+ return ret;
+}
+
+static int
+xfs_message_rename (int fd, struct xfs_message_rename *h, u_int size)
+{
+ VenusFid *old_parent_fid;
+ VenusFid *new_parent_fid;
+ Result res;
+ CredCacheEntry *ce;
+ int ret;
+ struct xfs_message_installdata msg1;
+ struct xfs_message_installdata msg2;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+ struct xfs_message_header *h1 = NULL;
+ size_t h1_len = 0;
+
+ old_parent_fid = (VenusFid *)&h->old_parent_handle;
+ new_parent_fid = (VenusFid *)&h->new_parent_handle;
+
+ ce = cred_get (old_parent_fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_rename(*old_parent_fid, h->old_name,
+ *new_parent_fid, h->new_name,
+ ce);
+
+ if (res.res == 0) {
+ FCacheEntry *dir_entry;
+ char tmp[5];
+ VenusFid realfid;
+
+ ret = fcache_get (&dir_entry, *old_parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg1.cache_handle, tmp, 4);
+ msg1.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *old_parent_fid;
+
+ fcacheentry2xfsnode (old_parent_fid, &realfid,
+ &dir_entry->status, &msg1.node,
+ dir_entry->acccache);
+
+ msg1.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg1;
+ h0_len = sizeof(msg1);
+ ReleaseWriteLock (&dir_entry->lock);
+
+ /* new parent */
+
+ ret = fcache_get (&dir_entry, *new_parent_fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (dir_entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&dir_entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (dir_entry, tmp, sizeof(tmp), ce, 0); /* XXX */
+ if (res.res == -1) {
+ ReleaseWriteLock (&dir_entry->lock);
+ ret = res.error;
+ goto out;
+ }
+ strncpy((char *)&msg2.cache_handle, tmp, 4);
+ msg2.node.tokens = res.tokens;
+
+ if (dir_entry->flags.mountp)
+ realfid = dir_entry->realfid;
+ else
+ realfid = *new_parent_fid;
+
+ fcacheentry2xfsnode (new_parent_fid, &realfid,
+ &dir_entry->status, &msg2.node,
+ dir_entry->acccache);
+
+ msg2.header.opcode = XFS_MSG_INSTALLDATA;
+ h1 = (struct xfs_message_header *)&msg2;
+ h1_len = sizeof(msg2);
+ ReleaseWriteLock (&dir_entry->lock);
+ }
+
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_rename (fd, h, size);
+ }
+ } else
+ ret = 0;
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ h1, h1_len,
+ NULL, 0);
+
+ return ret;
+}
+
+static int
+xfs_message_putdata (int fd, struct xfs_message_putdata *h, u_int size)
+{
+ VenusFid *fid;
+ Result res;
+ CredCacheEntry *ce;
+
+ fid = (VenusFid *)&h->handle;
+
+ ce = cred_get (fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_close(*fid, h->flag, ce);
+ if (res.res != 0)
+ arla_warn (ADEBMSG, res.error, "xfs_message_putdata: cm_close");
+
+ if (res.res != 0 && res.error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_putdata (fd, h, size);
+ }
+
+
+ cred_free (ce);
+ xfs_send_message_wakeup (fd, h->header.sequence_num,
+ res.res ? res.error : res.res);
+ return 0;
+}
+
+static int
+xfs_message_getdata (int fd, struct xfs_message_getdata *h, u_int size)
+{
+ struct xfs_message_installdata msg;
+ VenusFid *fid;
+ VenusFid real_fid;
+ Result res;
+ AFSFetchStatus status;
+ char tmp[5];
+ CredCacheEntry *ce;
+ int ret;
+ AccessEntry *ae;
+ struct xfs_message_header *h0 = NULL;
+ size_t h0_len = 0;
+
+ fid = (VenusFid *)&h->handle;
+
+ ce = cred_get (fid->Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ res = cm_getattr (*fid, &status, &real_fid, ce, &ae);
+ if (res.res == 0) {
+ fcacheentry2xfsnode (fid, &real_fid, &status, &msg.node, ae);
+ if (status.FileType == TYPE_DIR) {
+ FCacheEntry *entry;
+
+ ret = fcache_get (&entry, *fid, ce);
+ if (ret)
+ goto out;
+
+ ret = fcache_get_data (entry, ce);
+ if (ret) {
+ ReleaseWriteLock (&entry->lock);
+ goto out;
+ }
+
+ res = conv_dir (entry, tmp, sizeof(tmp), ce, h->tokens);
+ if (res.res != -1) {
+ strncpy ((char *)&msg.cache_handle, tmp, 4); /* XXX */
+ msg.node.tokens = res.tokens;
+ }
+ ReleaseWriteLock(&entry->lock);
+ } else {
+ res = cm_open (*fid, ce, h->tokens);
+ if (res.res != -1) {
+ sprintf (tmp, "%04X", res.res); /* XXX */
+ strncpy ((char *)&msg.cache_handle, tmp, 4); /* XXX */
+ msg.node.tokens = res.tokens;
+ }
+ }
+ }
+
+ if (res.res != -1) {
+ msg.header.opcode = XFS_MSG_INSTALLDATA;
+ h0 = (struct xfs_message_header *)&msg;
+ h0_len = sizeof(msg);
+ }
+ if (res.res == -1) {
+ ret = res.error;
+ if (ret == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return xfs_message_getdata (fd, h, size);
+ }
+ } else
+ ret = 0;
+
+out:
+ cred_free (ce);
+ xfs_send_message_wakeup_multiple (fd,
+ h->header.sequence_num,
+ ret,
+ h0, h0_len,
+ NULL, 0);
+
+ return ret;
+}
+
+void
+break_callback (VenusFid fid)
+{
+ struct xfs_message_invalidnode msg;
+
+ msg.header.opcode = XFS_MSG_INVALIDNODE;
+ memcpy (&msg.handle, &fid, sizeof(fid));
+ xfs_message_send (kernel_fd , (struct xfs_message_header *)&msg,
+ sizeof(msg));
+}
+
+static int
+xfs_message_inactivenode (int fd, struct xfs_message_inactivenode *h,
+ u_int size)
+{
+ FCacheEntry *entry;
+ VenusFid *fid;
+ int ret;
+ CredCacheEntry *ce;
+
+ fid = (VenusFid *)&h->handle;
+
+ ce = cred_get (fid->Cell, 0, CRED_NONE);
+ assert (ce != NULL);
+
+ ret = fcache_get (&entry, *fid, ce);
+ cred_free (ce);
+
+ if (ret) {
+ arla_warnx (ADEBMSG, "xfs_message_inactivenode: node not found");
+ return 0;
+ }
+ if (h->flag & XFS_NOREFS)
+ entry->flags.datausedp = entry->flags.attrusedp = FALSE;
+ if (h->flag & XFS_DELETE)
+ entry->flags.kernelp = FALSE;
+ ReleaseWriteLock (&entry->lock);
+ return 0;
+}
+
+
+
+static int
+viocflushvolume (int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid ;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = 0;
+ fid.fid.Unique = 0;
+
+ arla_warnx(ADEBMSG,
+ "flushing volume (%d, %u)",
+ fid.Cell, fid.fid.Volume);
+
+ fcache_purge_volume(fid);
+ return 0 ;
+}
+
+/*
+ * Get an ACL for a directory
+ */
+
+static int
+viocgetacl(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ AFSOpaque opaque;
+ CredCacheEntry *ce;
+ int error;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = h->handle.c;
+ fid.fid.Unique = h->handle.d;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ error = getacl (fid, ce, &opaque);
+
+ if (error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return viocgetacl (fd, h, size);
+ } else if (error != 0 && error != EACCES)
+ error = EINVAL;
+
+ cred_free (ce);
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ opaque.val, opaque.len);
+ free (opaque.val);
+ return 0;
+}
+
+/*
+ * Set an ACL for a directory
+ */
+
+static int
+viocsetacl(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ AFSOpaque opaque;
+ CredCacheEntry *ce;
+ int error;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ if (h->insize > AFSOPAQUEMAX)
+ return EINVAL;
+
+ if((opaque.val=malloc(AFSOPAQUEMAX))==NULL)
+ return ENOMEM;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = h->handle.c;
+ fid.fid.Unique = h->handle.d;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ opaque.len=h->insize;
+ memcpy(opaque.val, h->msg, h->insize);
+
+ error = setacl (fid, ce, &opaque);
+
+ if (error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return viocsetacl (fd, h, size);
+ } else if (error != 0 && error != EACCES)
+ error = EINVAL;
+
+ cred_free (ce);
+ free (opaque.val);
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ NULL, 0);
+ return 0;
+}
+
+/*
+ * Get volume status
+ */
+
+static int
+viocgetvolstat(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ CredCacheEntry *ce;
+ AFSFetchVolumeStatus volstat;
+ char volumename[AFSNAMEMAX];
+ char offlinemsg[AFSOPAQUEMAX];
+ char motd[AFSOPAQUEMAX];
+ char out[SYSNAMEMAXLEN];
+ int32_t outsize;
+ int error;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = 0;
+ fid.fid.Unique = 0;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ memset (volumename, 0, AFSNAMEMAX);
+ memset (offlinemsg, 0, AFSOPAQUEMAX);
+ memset (motd, 0, AFSOPAQUEMAX);
+ memset (out, 0, SYSNAMEMAXLEN);
+
+ error = getvolstat (fid, ce, &volstat, volumename,
+ offlinemsg, motd);
+
+ cred_free (ce);
+
+ if (error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return viocgetvolstat (fd, h, size);
+ } else if (error != 0 && error != EACCES)
+ error = EINVAL;
+
+ memcpy (out, (char *) &volstat, sizeof (AFSFetchVolumeStatus));
+ outsize = sizeof (AFSFetchVolumeStatus);
+
+ if (volumename[0]) {
+ strncpy (out+outsize, volumename, AFSNAMEMAX);
+ outsize += strlen (volumename);
+ }
+ else {
+ out[outsize] = 0;
+ outsize++;
+ }
+
+ if (offlinemsg[0]) {
+ strncpy (out+outsize, offlinemsg, AFSOPAQUEMAX);
+ outsize += strlen (offlinemsg);
+ }
+ else {
+ out[outsize] = 0;
+ outsize++;
+ }
+
+ if (motd[0]) {
+ strncpy (out+outsize, motd, AFSOPAQUEMAX);
+ outsize += strlen (motd);
+ }
+ else {
+ out[outsize] = 0;
+ outsize++;
+ }
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ out, outsize);
+ return 0;
+}
+
+/*
+ * Set volume status
+ */
+
+static int
+viocsetvolstat(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ CredCacheEntry *ce;
+ AFSFetchVolumeStatus *involstat;
+ AFSStoreVolumeStatus outvolstat;
+ char volumename[AFSNAMEMAX];
+ char offlinemsg[AFSOPAQUEMAX];
+ char motd[AFSOPAQUEMAX];
+ int error;
+ char *ptr;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = 0;
+ fid.fid.Unique = 0;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ involstat = (AFSFetchVolumeStatus *) h->msg;
+ outvolstat.Mask = 0x3; /* Store both the next fields */
+ outvolstat.MinQuota = involstat->MinQuota;
+ outvolstat.MaxQuota = involstat->MaxQuota;
+
+ ptr = h->msg + sizeof (AFSFetchVolumeStatus);
+
+ if (*ptr) {
+ strncpy (volumename, ptr, AFSNAMEMAX);
+ ptr += strlen (ptr);
+ }
+ else {
+ memset (volumename, 0, AFSNAMEMAX);
+ ptr++; /* skip 0 character */
+ }
+
+ if (*ptr) {
+ strncpy (offlinemsg, ptr, AFSOPAQUEMAX);
+ ptr += strlen (ptr);
+ }
+ else {
+ memset (offlinemsg, 0, AFSOPAQUEMAX);
+ ptr++;
+ }
+
+ strncpy (motd, ptr, AFSOPAQUEMAX);
+
+ error = setvolstat (fid, ce, &outvolstat, volumename,
+ offlinemsg, motd);
+
+ if (error == RXKADEXPIRED) {
+ cred_expire (ce);
+ cred_free (ce);
+ return viocsetvolstat (fd, h, size);
+ } else if (error != 0 && error != EACCES)
+ error = EINVAL;
+
+ cred_free (ce);
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ NULL, 0);
+ return 0;
+}
+
+/*
+ * Get info for a mount point.
+ */
+
+static int
+vioc_afs_stat_mt_pt(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ VenusFid res;
+ CredCacheEntry *ce;
+ FCacheEntry *e;
+ fbuf the_fbuf;
+ char *buf;
+ int error;
+ int symlink_fd;
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = h->handle.c;
+ fid.fid.Unique = h->handle.d;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ error = adir_lookup(fid, h->msg, &res, ce);
+ if (error) {
+ cred_free(ce);
+ return error;
+ }
+ error = fcache_get(&e, res, ce);
+ if (error) {
+ cred_free(ce);
+ return error;
+ }
+ error = fcache_get_attr (e, ce);
+ if (error) {
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return error;
+ }
+ if (e->status.FileType != TYPE_LINK) { /* Is not a mount point */
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return EINVAL;
+ }
+ error = fcache_get_data (e, ce);
+ if (error) {
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return error;
+ }
+ symlink_fd = fcache_open_file (e, O_RDONLY, 0);
+ if (symlink_fd < 0) {
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return errno;
+ }
+ error = fbuf_create (&the_fbuf, symlink_fd, e->status.Length, FBUF_READ);
+ if (error) {
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return error;
+ }
+ buf = (char *)(the_fbuf.buf);
+ if (buf[0] != '#' && buf[0] != '%') { /* Is not a mount point */
+ ReleaseWriteLock (&e->lock);
+ fbuf_end (&the_fbuf);
+ cred_free (ce);
+ return EINVAL;
+ }
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ the_fbuf.buf, the_fbuf.len - 1);
+
+ ReleaseWriteLock (&e->lock);
+ fbuf_end (&the_fbuf);
+ cred_free (ce);
+
+ return 0;
+}
+
+static int
+viocwhereis(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid;
+ CredCacheEntry *ce;
+ FCacheEntry *e;
+ int error;
+ int i;
+ int32_t addresses[8];
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = h->handle.c;
+ fid.fid.Unique = h->handle.d;
+
+ ce = cred_get (fid.Cell, h->cred.pag, CRED_ANY);
+ assert (ce != NULL);
+
+ error = fcache_get(&e, fid, ce);
+ if (error) {
+ cred_free(ce);
+ return error;
+ }
+ error = fcache_get_attr (e, ce);
+ if (error) {
+ ReleaseWriteLock (&e->lock);
+ cred_free(ce);
+ return error;
+ }
+ memset(addresses, 0, sizeof(addresses));
+ for (i = 0; (i < e->volume->entry.nServers) && (i < 8); i++)
+ addresses[i] = e->volume->entry.serverNumber[i];
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ addresses, sizeof(long) * 8);
+
+ ReleaseWriteLock (&e->lock);
+ cred_free (ce);
+
+ return 0;
+}
+
+static int
+viocgetcell(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ int i;
+ int32_t index;
+ const char *cellname;
+ int cellname_len;
+ int outsize;
+ char out[8 * sizeof(int32_t) + MAXPATHLEN]; /* XXX */
+
+ index = *((int32_t *) h->msg);
+ cellname = cell_num2name(index);
+ if (cellname == NULL)
+ return EDOM;
+
+ memset(out, 0, sizeof(out));
+ cellname_len = strlen(cellname) + 1;
+ if (cellname_len > MAXPATHLEN)
+ cellname_len = MAXPATHLEN;
+ memcpy(out + 8 * sizeof(int32_t), cellname, cellname_len);
+ outsize = 8 * sizeof(int32_t) + cellname_len;
+ for (i = 0; i < 8; i++) {
+ u_long addr = cell_listdbserver(index, i);
+ if (addr == 0)
+ break;
+ memcpy (&out[i * sizeof(int32_t)], &addr, sizeof(int32_t));
+ }
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, 0,
+ out, outsize);
+
+ return 0;
+}
+
+#ifdef KERBEROS
+
+/*
+ * Return the token for the cell in `ce'
+ */
+
+static int
+token_for_cell (int fd, struct xfs_message_pioctl *h, u_int size,
+ CredCacheEntry *ce)
+{
+ struct ClearToken ct;
+ char buf[2048];
+ size_t len;
+ char *p = buf;
+ u_int32_t tmp;
+ krbstruct *kstruct = (krbstruct *)ce->cred_data;
+ CREDENTIALS *cred = &kstruct->c;
+ const char *cell = cell_num2name (ce->cell);
+
+ ct.AuthHandle = cred->kvno;
+ memcpy (ct.HandShakeKey, cred->session, sizeof(cred->session));
+ ct.ViceId = h->cred.pag;
+ ct.BeginTimestamp = cred->issue_date + 1;
+ ct.EndTimestamp = ce->expire;
+
+ tmp = 0;
+ memcpy (p, &tmp, sizeof(tmp));
+ p += sizeof(tmp);
+ tmp = sizeof(ct);
+ memcpy (p, &tmp, sizeof(tmp));
+ p += sizeof(tmp);
+ memcpy (p, &ct, sizeof(ct));
+ p += sizeof(ct);
+ tmp = strlen(cell);
+ memcpy (p, &tmp, sizeof(tmp));
+ p += sizeof(tmp);
+ strcpy (p, cell);
+ p += strlen(cell) + 1;
+
+ len = p - buf;
+
+ memset (&ct, 0, sizeof(ct));
+
+ cred_free (ce);
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, 0,
+ buf, len);
+ return 0;
+}
+
+/*
+ * Handle the GETTOK message in `h'
+ */
+
+static int
+viocgettok (int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ if (h->insize == 0) {
+ CredCacheEntry *ce = cred_get (0, h->cred.pag, CRED_KRB4);
+
+ if (ce == NULL) {
+ xfs_send_message_wakeup (fd, h->header.sequence_num, ENOTCONN);
+ return 0;
+ }
+ return token_for_cell (fd, h, size, ce);
+ } else if (h->insize == sizeof(u_int32_t)) {
+ u_int32_t n;
+ int i, c;
+ int found;
+ CredCacheEntry *ce = NULL;
+
+ memcpy (&n, h->msg, sizeof(n));
+
+ i = 0;
+ c = 0;
+ found = 0;
+ while (!found && i <= n) {
+ if (cell_num2name(c) == NULL)
+ break;
+
+ ce = cred_get (c++, h->cred.pag, CRED_KRB4);
+ if (ce != NULL) {
+ if (i == n) {
+ found = 1;
+ } else {
+ cred_free (ce);
+ ++i;
+ }
+ }
+ }
+ if (!found) {
+ xfs_send_message_wakeup (fd, h->header.sequence_num, EDOM);
+ return 0;
+ }
+ return token_for_cell (fd, h, size, ce);
+ } else {
+ xfs_send_message_wakeup (fd, h->header.sequence_num, EINVAL);
+ }
+ return 0;
+}
+#endif /* KERBEROS */
+
+static int
+viocflush (int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ VenusFid fid ;
+ AFSCallBack broken_callback = {0, 0, CBDROPPED};
+
+ if (!h->handle.a && !h->handle.b && !h->handle.c && !h->handle.d)
+ return EINVAL;
+
+ fid.Cell = h->handle.a;
+ fid.fid.Volume = h->handle.b;
+ fid.fid.Vnode = h->handle.c;
+ fid.fid.Unique = h->handle.d;
+
+ arla_warnx(ADEBMSG,
+ "flushing (%d, %u, %u, %u)",
+ fid.Cell, fid.fid.Volume, fid.fid.Vnode, fid.fid.Unique);
+
+ fcache_stale_entry(fid, broken_callback);
+ return 0 ;
+}
+
+static int
+viocconnect(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ char *p = h->msg;
+ int32_t tmp;
+ int32_t ret;
+ int error = 0;
+
+ if (h->insize != sizeof(int32_t) ||
+ h->outsize != sizeof(int32_t)) {
+
+ ret = -EINVAL;
+ } else {
+
+ memcpy(&tmp, h->msg, sizeof(tmp));
+ p += sizeof(tmp);
+
+ ret = tmp;
+
+ switch(tmp) {
+ case CONNMODE_PROBE:
+ switch(connected_mode) {
+ case CONNECTED: ret = CONNMODE_CONN; break;
+ case FETCH_ONLY: ret = CONNMODE_FETCH; break;
+ case DISCONNECTED: ret = CONNMODE_DISCONN; break;
+ default:
+ error = EINVAL;
+ ret = 0;
+ break;
+ }
+ break;
+ case CONNMODE_CONN:
+ connected_mode = CONNECTED ;
+ break;
+ case CONNMODE_FETCH:
+ connected_mode = FETCH_ONLY ;
+ break;
+ case CONNMODE_DISCONN:
+ connected_mode = DISCONNECTED;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ }
+
+ xfs_send_message_wakeup_data (fd, h->header.sequence_num, error,
+ &ret, sizeof(ret));
+ return 0;
+}
+
+static void
+getrxkcrypt(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ if (h->outsize == sizeof(u_int32_t)) {
+ u_int32_t n;
+
+#ifdef KERBEROS
+ if (rxkad_min_level == rxkad_crypt)
+ n = 1;
+ else
+#endif
+ n = 0;
+
+ xfs_send_message_wakeup_data (fd,
+ h->header.sequence_num,
+ 0,
+ &n,
+ sizeof(n));
+ } else
+ xfs_send_message_wakeup (fd, h->header.sequence_num, EINVAL);
+}
+
+static int
+setrxkcrypt(int fd, struct xfs_message_pioctl *h, u_int size)
+{
+#ifdef KERBEROS
+ int error = 0;
+
+ if (h->insize == sizeof(u_int32_t)) {
+ u_int32_t n;
+
+ memcpy (&n, h->msg, sizeof(n));
+
+ if (n == 0)
+ rxkad_min_level = rxkad_auth;
+ else if(n == 1)
+ rxkad_min_level = rxkad_crypt;
+ else
+ error = EINVAL;
+ } else
+ error = EINVAL;
+ return error;
+#else
+ return EOPNOTSUPP;
+#endif
+}
+
+static int
+vioc_fpriostatus (int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ struct vioc_fprio *fprio;
+ int error = 0;
+ VenusFid fid;
+
+ if (h->insize != sizeof(struct vioc_fprio))
+ return EINVAL;
+
+ fprio = (struct vioc_fprio *) h->msg;
+
+ fid.Cell = fprio->Cell ;
+ fid.fid.Volume = fprio->Volume ;
+ fid.fid.Vnode = fprio->Vnode ;
+ fid.fid.Unique = fprio->Unique ;
+
+
+ switch(fprio->cmd) {
+ case FPRIO_GET: {
+ unsigned prio;
+
+ if (h->outsize != sizeof(unsigned)) {
+ error = EINVAL;
+ break;
+ }
+
+ prio = fprio_get(fid);
+ xfs_send_message_wakeup_data (fd,
+ h->header.sequence_num,
+ 0,
+ &prio,
+ sizeof(prio));
+
+ break;
+ }
+ case FPRIO_SET:
+ if (fprio->prio == 0) {
+ fprio_remove(fid);
+ error = 0;
+ } else if (fprio->prio < FPRIO_MIN ||
+ fprio->prio > FPRIO_MAX)
+ error = EINVAL;
+ else {
+ fprio_set(fid, fprio->prio);
+ error = 0;
+ }
+ break;
+ case FPRIO_GETMAX:
+ if (h->outsize != sizeof(unsigned)) {
+ error = EINVAL;
+ break;
+ }
+
+ xfs_send_message_wakeup_data (fd,
+ h->header.sequence_num,
+ 0,
+ &fprioritylevel,
+ sizeof(fprioritylevel));
+ error = 0;
+ break;
+ case FPRIO_SETMAX:
+ if (fprio->prio < FPRIO_MIN ||
+ fprio->prio > FPRIO_MAX)
+ error = EINVAL;
+ else {
+ fprioritylevel = fprio->prio;
+ error = 0;
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static int
+xfs_message_pioctl (int fd, struct xfs_message_pioctl *h, u_int size)
+{
+ int32_t sizeof_x;
+ char *t;
+ int error;
+
+ t = h->msg ;
+ switch(h->opcode) {
+#ifdef KERBEROS
+ case VIOCSETTOK: {
+ struct ClearToken ct;
+ CREDENTIALS c;
+ long cell;
+
+ /* someone probed us */
+ if (h->insize == 0) {
+ error = EINVAL ;
+ break;
+ }
+
+ /* Get ticket_st */
+ memcpy(&sizeof_x, t, sizeof(sizeof_x)) ;
+ c.ticket_st.length = sizeof_x ;
+ arla_warnx (ADEBMSG, "ticket_st has size %d", sizeof_x);
+ t += sizeof(sizeof_x) ;
+
+ memcpy(c.ticket_st.dat, t, sizeof_x) ;
+ t += sizeof_x ;
+
+ /* Get ClearToken */
+ memcpy(&sizeof_x, t, sizeof(sizeof_x)) ;
+ t += sizeof(sizeof_x) ;
+
+ memcpy(&ct, t, sizeof_x) ;
+ t += sizeof_x ;
+
+ /* Get primary cell ? */
+ memcpy(&sizeof_x, t, sizeof(sizeof_x)) ;
+ t += sizeof(sizeof_x) ;
+
+ /* Get Cellname */
+ strncpy(c.realm, t, REALM_SZ) ;
+ c.realm[REALM_SZ-1] = '\0' ;
+
+
+ /* Make this a sane world again */
+ c.kvno = ct.AuthHandle;
+ memcpy (c.session, ct.HandShakeKey, sizeof(c.session));
+ c.issue_date = ct.BeginTimestamp - 1;
+
+ cell = cell_name2num(strlwr(c.realm));
+
+ /* XXX fix ct.ViceId */
+ conn_clearcred (cell, h->cred.pag, 2);
+ fcache_purge_cred(h->cred.pag, cell);
+ cred_add (h->cred.pag, CRED_KRB4, 2, cell, ct.EndTimestamp,
+ &c, sizeof(c));
+
+
+ error = 0 ;
+ break;
+ }
+ case VIOCGETTOK :
+ return viocgettok (fd, h, size);
+ case VIOCUNPAG:
+ case VIOCUNLOG: {
+ pag_t cred = h->cred.pag ;
+
+ cred_remove(cred) ;
+ fcache_purge_cred(cred, -1);
+ error = 0;
+ break ;
+ }
+#endif /* KERBEROS */
+ case VIOCCONNECTMODE:
+ error = viocconnect(fd, h, size);
+ break;
+ case VIOCFLUSH:
+ error = viocflush(fd, h, size);
+ break;
+ case VIOC_FLUSHVOLUME:
+ error = viocflushvolume(fd, h, size);
+ break;
+ case VIOCGETFID:
+ error = xfs_send_message_wakeup_data(fd, h->header.sequence_num, 0,
+ &h->handle, sizeof(VenusFid));
+ break;
+ case VIOCGETAL:
+ error = viocgetacl(fd, h, size);
+ break;
+ case VIOCSETAL:
+ error = viocsetacl(fd, h, size);
+ break;
+ case VIOCGETVOLSTAT:
+ error = viocgetvolstat(fd, h, size);
+ break;
+ case VIOCSETVOLSTAT:
+ error = viocsetvolstat(fd, h, size);
+ break;
+ case VIOC_AFS_STAT_MT_PT:
+ error = vioc_afs_stat_mt_pt(fd, h, size);
+ break;
+ case VIOCWHEREIS:
+ error = viocwhereis(fd, h, size);
+ break;
+ case VIOCNOP:
+ error = EINVAL;
+ break;
+ case VIOCGETCELL:
+ error = viocgetcell(fd, h, size);
+ break;
+ case VIOC_VENUSLOG:
+ if (h->cred.uid != 0) {
+ error = EACCES;
+ break ;
+ }
+
+ conn_status (stderr);
+ volcache_status (stderr);
+ cred_status (stderr);
+ fcache_status (stderr);
+ rx_PrintStats(stderr);
+ error = 0 ;
+ break;
+ case VIOC_AFS_SYSNAME: {
+ char str[SYSNAMEMAXLEN+sizeof(int32_t)];
+
+ error = 0 ;
+
+ if (*((int32_t *)t)) {
+ t += sizeof(int32_t);
+ arla_warnx (ADEBMSG, "VIOC_AFS_SYSNAME: setting sysname: %s", t);
+ memcpy(arlasysname, t, h->insize);
+ arlasysname[h->insize] = '\0';
+ xfs_send_message_wakeup_data(fd, h->header.sequence_num, error,
+ str, 0);
+ } else {
+ t = str;
+ sizeof_x = strlen(arlasysname);
+ memcpy(t, &sizeof_x, sizeof(sizeof_x));
+ t += sizeof(sizeof_x);
+ h->outsize = sizeof_x;
+ strncpy(t, arlasysname, SYSNAMEMAXLEN);
+ xfs_send_message_wakeup_data(fd, h->header.sequence_num, error,
+ str, sizeof_x + sizeof(sizeof_x));
+ }
+ return 0;
+ }
+
+ case VIOC_FILE_CELL_NAME: {
+ char *cellname ;
+
+ error = 0 ;
+ cellname = (char *) cell_num2name(h->handle.a);
+
+ if (cellname)
+ xfs_send_message_wakeup_data(fd, h->header.sequence_num, error,
+ cellname, strlen(cellname)+1);
+ else
+ xfs_send_message_wakeup_data(fd, h->header.sequence_num, EINVAL,
+ NULL, 0);
+ return 0;
+ }
+ case VIOC_GET_WS_CELL: {
+ char *cellname;
+
+ cellname = (char*) cell_getthiscell();
+ xfs_send_message_wakeup_data(fd, h->header.sequence_num, 0 /*error*/,
+ cellname, strlen(cellname));
+
+ return 0;
+ }
+ case VIOCSETCACHESIZE: {
+ u_int32_t *s = (u_int32_t *)t;
+
+ if (h->cred.uid != 0) {
+ error = EPERM;
+ break ;
+ }
+
+ if (h->insize >= sizeof(int32_t) * 4)
+ error = fcache_reinit(s[0], s[1], s[2], s[3]);
+ else
+ error = fcache_reinit(*s/2, *s, *s*500, *s*1000);
+ break;
+ }
+ case VIOC_GETRXKCRYPT :
+ getrxkcrypt(fd, h, size);
+ return 0;
+ case VIOC_SETRXKCRYPT :
+ error = setrxkcrypt(fd, h, size);
+ break;
+ case VIOC_FPRIOSTATUS:
+ error = vioc_fpriostatus(fd, h, size);
+ break;
+ default:
+ arla_warnx (ADEBMSG, "unknown pioctl call %d", h->opcode);
+ error = EINVAL ;
+ }
+
+ xfs_send_message_wakeup (fd, h->header.sequence_num, error);
+
+ return 0;
+}
diff --git a/usr.sbin/afs/src/arlad/messages.h b/usr.sbin/afs/src/arlad/messages.h
new file mode 100644
index 00000000000..0d210c93d94
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/messages.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: messages.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+/* $KTH: messages.h,v 1.5 1998/03/25 03:27:20 assar Exp $ */
+
+#ifndef _MESSAGES_H_
+#define _MESSAGES_H_
+
+void xfs_message_init (void);
+int xfs_message_receive (int fd, struct xfs_message_header *h, u_int size);
+void break_callback (VenusFid fid);
+long afsfid2inode(VenusFid *fid);
+
+#endif /* _MESSAGES_H_ */
diff --git a/usr.sbin/afs/src/arlad/service.h b/usr.sbin/afs/src/arlad/service.h
new file mode 100644
index 00000000000..36bddd11fc8
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/service.h
@@ -0,0 +1,51 @@
+/* $OpenBSD: service.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: service.h,v 1.4 1998/07/14 16:00:50 lha Exp $ */
+
+/*
+ * Service IDs
+ */
+
+#define VLDB_SERVICE_ID 52
+#define PR_SERVICE_ID 73
+#define FS_SERVICE_ID 1
+#define CM_SERVICE_ID 1
+#define VOTE_SERVICE_ID 50 /* ubik */
+#define DISK_SERVICE_ID 51 /* ubik */
diff --git a/usr.sbin/afs/src/arlad/subr.h b/usr.sbin/afs/src/arlad/subr.h
new file mode 100644
index 00000000000..0073cfc2d0d
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/subr.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: subr.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 with prototypes for OS-specific functions.
+ */
+
+/* $KTH: subr.h,v 1.5 1998/03/24 02:43:00 assar Exp $ */
+
+#ifndef _SUBR_H_
+#define _SUBR_H_
+
+Result
+conv_dir (FCacheEntry *e, char *handle, size_t handle_size,
+ CredCacheEntry *ce, u_int tokens);
+
+#endif /* _SUBR_H_ */
+
diff --git a/usr.sbin/afs/src/arlad/volcache.c b/usr.sbin/afs/src/arlad/volcache.c
new file mode 100644
index 00000000000..9fa5768d639
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/volcache.c
@@ -0,0 +1,627 @@
+/* $OpenBSD: volcache.c,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Manage our cache of volume information.
+ */
+
+#include "arla_local.h"
+RCSID("$KTH: volcache.c,v 1.39 1998/07/29 21:31:06 assar Exp $") ;
+
+/*
+ * Suffixes for volume names.
+ */
+
+static char *volsuffixes[] = {
+"",
+ROSUFFIX,
+BACKSUFFIX
+};
+
+static const char *root_volume_name = "root.afs";
+
+/*
+ * Return the root volume name.
+ */
+
+const char *
+volcache_get_rootvolume (void)
+{
+ return root_volume_name;
+}
+
+/*
+ * Set the current root volume name.
+ */
+
+void
+volcache_set_rootvolume (const char *volname)
+{
+ root_volume_name = volname;
+}
+
+#define VOLCACHE_SIZE 2048
+#define VOLCACHE_INC 300
+
+/* Hashtable of entries by name */
+static Hashtab *volnamehashtab;
+
+/* Hashtable of entries by number */
+static Hashtab *volidhashtab;
+
+/* A list with all entries */
+static List *lrulist;
+
+/* # of entries */
+static unsigned nvolcacheentries = 0;
+
+/* # of active entries */
+static unsigned nactive_volcacheentries = 0;
+
+/*
+ * VolCacheEntries are indexed by (name, cell) in volnamehashtab
+ */
+
+static int
+volnamecmp (void *a, void *b)
+{
+ struct name_ptr *n1 = (struct name_ptr *)a;
+ struct name_ptr *n2 = (struct name_ptr *)b;
+
+ return strcmp (n1->name, n2->name)
+ || n1->cell != n2->cell;
+}
+
+static unsigned
+volnamehash (void *a)
+{
+ struct name_ptr *n = (struct name_ptr *)a;
+
+ return hashadd (n->name) + n->cell;
+}
+
+/*
+ * and by (volid, cell) in volidhashtab
+ */
+
+static int
+volidcmp (void *a, void *b)
+{
+ struct num_ptr *n1 = (struct num_ptr *)a;
+ struct num_ptr *n2 = (struct num_ptr *)b;
+
+ return n1->cell != n2->cell || n1->vol != n2->vol;
+}
+
+static unsigned
+volidhash (void *a)
+{
+ struct num_ptr *n = (struct num_ptr *)a;
+
+ return n->cell + n->vol;
+}
+
+/*
+ * Create `n' entries and add at the end of `lrulist'
+ */
+
+static void
+create_new_entries (unsigned n)
+{
+ VolCacheEntry *entries;
+ int i;
+
+ entries = (VolCacheEntry *)calloc (n, sizeof(VolCacheEntry));
+ if (entries == NULL)
+ arla_errx (1, ADEBERROR, "volcache: calloc failed");
+ for (i = 0; i < n; ++i) {
+ entries[i].cell = -1;
+ listaddtail (lrulist, &entries[i]);
+ }
+
+ nvolcacheentries += n;
+}
+
+/*
+ * Re-cycle an entry:
+ * remove it from the hashtab, clear it out.
+ */
+
+static void
+recycle_entry (VolCacheEntry *e)
+{
+ int i;
+
+ for (i = 0; i < MAXTYPES; ++i) {
+ if (e->name_ptr[i].ptr != NULL) {
+ FCacheEntry *fe;
+ int ret;
+ VenusFid fid;
+
+ assert (e->num_ptr[i].ptr != NULL);
+
+ fid.Cell = e->cell;
+ fid.fid.Vnode = fid.fid.Unique = 1;
+ fid.fid.Volume = e->num_ptr[i].vol;
+ ret = fcache_find (&fe, fid);
+ if (ret == 0 && fe != NULL) {
+ assert (fe->refcount > 0 && fe->flags.mountp);
+ --fe->refcount;
+ }
+
+ hashtabdel (volnamehashtab, &e->name_ptr[i]);
+ hashtabdel (volidhashtab, &e->num_ptr[i]);
+ }
+ }
+ memset (e, 0, sizeof(*e));
+}
+
+/*
+ * Get and return a free entry.
+ * Place it at the head of the lrulist.
+ */
+
+static VolCacheEntry *
+get_free_entry (void)
+{
+ Listitem *item;
+ VolCacheEntry *e;
+
+ assert (!listemptyp(lrulist));
+
+ for(item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+ e = (VolCacheEntry *)listdata(item);
+ if (e->refcount == 0) {
+ listdel (lrulist, item);
+ recycle_entry (e);
+ listaddhead (lrulist, e);
+ return e;
+ }
+ }
+
+ create_new_entries (VOLCACHE_INC);
+
+ e = (VolCacheEntry *)listdeltail (lrulist);
+ assert (e != NULL && e->refcount == 0);
+ listaddhead (lrulist, e);
+ return e;
+}
+
+/*
+ *
+ */
+
+static Bool
+volume_uptodatep (VolCacheEntry *e)
+{
+ if (connected_mode != CONNECTED)
+ return TRUE;
+
+ return e->flags.validp;
+}
+
+/*
+ *
+ */
+
+static void
+volcache_recover_state (void)
+{
+ int fd;
+ VolCacheEntry tmp;
+ unsigned n;
+
+ fd = open ("volcache", O_RDONLY | O_BINARY, 0);
+ if (fd < 0)
+ return;
+ n = 0;
+ while (read (fd, &tmp, sizeof(tmp)) == sizeof(tmp)) {
+ VolCacheEntry *e = get_free_entry ();
+ int i;
+
+ ++n;
+
+ e->entry = tmp.entry;
+ e->volsync = tmp.volsync;
+ e->cell = tmp.cell;
+ e->refcount = tmp.refcount;
+ for (i = 0; i < MAXTYPES; ++i) {
+ if (tmp.name_ptr[i].ptr != NULL) {
+ e->name_ptr[i].cell = tmp.name_ptr[i].cell;
+ strcpy (e->name_ptr[i].name, tmp.name_ptr[i].name);
+ e->name_ptr[i].ptr = e;
+ hashtabadd (volnamehashtab, (void *)&e->name_ptr[i]);
+ }
+ if (tmp.num_ptr[i].ptr != NULL) {
+ e->num_ptr[i].cell = tmp.num_ptr[i].cell;
+ e->num_ptr[i].vol = tmp.num_ptr[i].vol;
+ e->num_ptr[i].ptr = e;
+ hashtabadd (volidhashtab, (void *)&e->num_ptr[i]);
+ }
+ }
+ e->flags.validp = FALSE;
+ }
+ close (fd);
+ arla_warnx (ADEBVOLCACHE, "recovered %u entries to volcache", n);
+}
+
+/*
+ *
+ */
+
+int
+volcache_store_state (void)
+{
+ Listitem *item;
+ int fd;
+ unsigned n;
+
+ fd = open ("volcache.new", O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (fd < 0)
+ return errno;
+ n = 0;
+ for (item = listtail (lrulist);
+ item;
+ item = listprev (lrulist, item)) {
+ VolCacheEntry *entry = (VolCacheEntry *)listdata (item);
+
+ if (entry->cell == -1)
+ continue;
+ if (write (fd, entry, sizeof(*entry)) != sizeof(*entry)) {
+ close (fd);
+ return errno;
+ }
+ ++n;
+ }
+
+ if(close (fd))
+ return errno;
+ if (rename ("volcache.new", "volcache"))
+ return errno;
+
+ arla_warnx (ADEBVOLCACHE, "wrote %u entries to volcache", n);
+
+ return 0;
+}
+
+/*
+ * Initialize the volume cache with `nentries' in the free list.
+ * Try to recover state iff `recover'
+ */
+
+void
+volcache_init (unsigned nentries, Bool recover)
+{
+ volnamehashtab = hashtabnew (VOLCACHE_SIZE, volnamecmp, volnamehash);
+ if (volnamehashtab == NULL)
+ arla_errx (1, ADEBERROR, "volcache_init: hashtabnew failed");
+
+ volidhashtab = hashtabnew (VOLCACHE_SIZE, volidcmp, volidhash);
+ if (volidhashtab == NULL)
+ arla_errx (1, ADEBERROR, "volcache_init: hashtabnew failed");
+
+ lrulist = listnew ();
+ if (lrulist == NULL)
+ arla_errx (1, ADEBERROR, "volcache_init: listnew failed");
+ nvolcacheentries = 0;
+ create_new_entries (nentries);
+ if (recover)
+ volcache_recover_state ();
+}
+
+/*
+ *
+ */
+
+static int
+get_info (VolCacheEntry *e, const char *volname, CredCacheEntry *ce)
+{
+ ConnCacheEntry *conn;
+ u_long addr = cell_finddbserver (e->cell).s_addr;
+ int error, i;
+
+ conn = conn_get (e->cell, addr, afsvldbport, VLDB_SERVICE_ID, ce);
+ if (conn == NULL) {
+ struct in_addr ia;
+
+ ia.s_addr = addr;
+ arla_warnx (ADEBVOLCACHE,
+ "volcache: failed to make rx-connection to vldb %s",
+ inet_ntoa(ia));
+ return -1;
+ }
+
+ error = VL_GetEntryByName(conn->connection, volname, &e->entry);
+ conn_free (conn);
+ if (error) {
+ arla_warn (ADEBVOLCACHE, error,
+ "VL_GetEntryByName(%s)",
+ volname);
+ return -1;
+ }
+
+ i = min(strlen(volname), VLDB_MAXNAMELEN);
+ if (strncmp(volname, e->entry.name, i)) {
+ arla_warnx (ADEBERROR, "get_info: we asked for %s and got %s",
+ volname, e->entry.name);
+ }
+
+
+ if ((e->entry.volumeId[RWVOL] == e->entry.volumeId[ROVOL] &&
+ e->entry.flags & VLF_RWEXISTS && e->entry.flags & VLF_ROEXISTS) ||
+ (e->entry.volumeId[ROVOL] == e->entry.volumeId[BACKVOL] &&
+ e->entry.flags & VLF_ROEXISTS && e->entry.flags & VLF_BOEXISTS) ||
+ (e->entry.volumeId[RWVOL] == e->entry.volumeId[BACKVOL] &&
+ e->entry.flags & VLF_RWEXISTS && e->entry.flags & VLF_BOEXISTS)) {
+
+ arla_warnx (ADEBERROR, "get_info: same id on diffrent volumes: %s",
+ volname);
+ return -1;
+ }
+
+ if (e->entry.flags & VLF_RWEXISTS) {
+ e->num_ptr[RWVOL].cell = e->cell;
+ e->num_ptr[RWVOL].vol = e->entry.volumeId[RWVOL];
+ e->num_ptr[RWVOL].ptr = e;
+ hashtabadd (volidhashtab, (void *)&e->num_ptr[RWVOL]);
+
+ e->name_ptr[RWVOL].cell = e->cell;
+ snprintf (e->name_ptr[RWVOL].name, VLDB_MAXNAMELEN,
+ "%s%s", e->entry.name, volsuffixes[RWVOL]);
+ e->name_ptr[RWVOL].ptr = e;
+ hashtabadd (volnamehashtab, (void *)&e->name_ptr[RWVOL]);
+
+ }
+ if (e->entry.flags & VLF_ROEXISTS) {
+ e->num_ptr[ROVOL].cell = e->cell;
+ e->num_ptr[ROVOL].vol = e->entry.volumeId[ROVOL];
+ e->num_ptr[ROVOL].ptr = e;
+ hashtabadd (volidhashtab, (void *)&e->num_ptr[ROVOL]);
+
+ e->name_ptr[ROVOL].cell = e->cell;
+ snprintf (e->name_ptr[ROVOL].name, VLDB_MAXNAMELEN,
+ "%s%s", e->entry.name, volsuffixes[ROVOL]);
+ e->name_ptr[ROVOL].ptr = e;
+ hashtabadd (volnamehashtab, (void *)&e->name_ptr[ROVOL]);
+ }
+ if (e->entry.flags & VLF_BOEXISTS) {
+ e->num_ptr[BACKVOL].cell = e->cell;
+ e->num_ptr[BACKVOL].vol = e->entry.volumeId[BACKVOL];
+ e->num_ptr[BACKVOL].ptr = e;
+ hashtabadd (volidhashtab, (void *)&e->num_ptr[BACKVOL]);
+
+ e->name_ptr[BACKVOL].cell = e->cell;
+ snprintf (e->name_ptr[BACKVOL].name, VLDB_MAXNAMELEN,
+ "%s%s", e->entry.name, volsuffixes[BACKVOL]);
+ e->name_ptr[BACKVOL].ptr = e;
+ hashtabadd (volnamehashtab, (void *)&e->name_ptr[BACKVOL]);
+ }
+ e->flags.validp = TRUE;
+ return 0;
+}
+
+/*
+ * Add an entry for (volname, cell) to the hash table.
+ */
+
+static VolCacheEntry *
+add_entry (const char *volname, int32_t cell, CredCacheEntry *ce)
+{
+ VolCacheEntry *e;
+
+ e = get_free_entry ();
+
+ e->cell = cell;
+ e->refcount = 0;
+
+ if(get_info (e, volname, ce) == 0) {
+ ++nactive_volcacheentries;
+ return e;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Retrieve the entry for (volname, cell). If it's not in the cache,
+ * add it.
+ */
+
+VolCacheEntry *
+volcache_getbyname (const char *volname, int32_t cell, CredCacheEntry *ce)
+{
+ VolCacheEntry *e;
+ struct name_ptr *n;
+ struct name_ptr key;
+
+ key.cell = cell;
+ strncpy (key.name, volname, VLDB_MAXNAMELEN);
+ key.name[VLDB_MAXNAMELEN - 1] = '\0';
+
+ n = (struct name_ptr *)hashtabsearch (volnamehashtab, (void *)&key);
+ if (n == NULL)
+ e = add_entry (volname, cell, ce);
+ else
+ e = n->ptr;
+
+ if (e != NULL && !volume_uptodatep (e)) {
+ recycle_entry (e);
+ e->cell = cell;
+ if (get_info (e, volname, ce))
+ e = NULL;
+ }
+
+ if (e != NULL)
+ ++e->refcount;
+ return e;
+}
+
+/*
+ * Retrieve the entry for (volume-id, cell). If it's not in the cache,
+ * add it.
+ */
+
+VolCacheEntry *
+volcache_getbyid (u_int32_t id, int32_t cell, CredCacheEntry *ce)
+{
+ VolCacheEntry *e;
+ struct num_ptr *n;
+ struct num_ptr key;
+ char s[11];
+
+ snprintf (s, sizeof(s), "%u", id);
+
+ key.cell = cell;
+ key.vol = id;
+
+ n = (struct num_ptr *)hashtabsearch (volidhashtab, (void *)&key);
+ if (n == NULL) {
+ e = add_entry (s, cell, ce);
+ } else {
+ e = n->ptr;
+ }
+
+ if (e != NULL && !volume_uptodatep (e)) {
+ recycle_entry (e);
+ e->cell = cell;
+ if (get_info (e, s, ce))
+ e = NULL;
+ }
+
+ if (e != NULL)
+ ++e->refcount;
+ return e;
+}
+
+/*
+ * Invalidate the volume entry for `id'
+ */
+
+void
+volcache_invalidate (u_int32_t id, int32_t cell)
+{
+ struct num_ptr *n;
+ struct num_ptr key;
+
+ key.cell = cell;
+ key.vol = id;
+
+ n = (struct num_ptr *)hashtabsearch (volidhashtab, (void *)&key);
+ if (n != NULL) {
+ VolCacheEntry *e = n->ptr;
+
+ e->flags.validp = FALSE;
+ }
+}
+
+/*
+ * Save `volsync'
+ */
+
+void
+volcache_update_volsync (VolCacheEntry *e, AFSVolSync volsync)
+{
+ e->volsync = volsync;
+}
+
+
+/*
+ * Decrement the references and possibly remove this entry.
+ */
+
+void
+volcache_free (VolCacheEntry *e)
+{
+ --e->refcount;
+ if (e->refcount == 0)
+ --nactive_volcacheentries;
+}
+
+/*
+ * Print the entry `ptr' to the FILE `arg'
+ */
+
+static Bool
+print_entry (void *ptr, void *arg)
+{
+ struct num_ptr *n = (struct num_ptr *)ptr;
+ VolCacheEntry *e = n->ptr;
+ FILE *f = (FILE *)arg;
+ int i;
+ struct in_addr tmp;
+
+ if (n->vol != e->entry.volumeId[RWVOL])
+ return FALSE;
+
+ fprintf (f, "cell = %d (%s)\n"
+ "name = \"%s\", volumeType = %d(%s), nServers = %d\n",
+ e->cell, cell_num2name (e->cell),
+ e->entry.name,
+ e->entry.volumeType, volsuffixes[e->entry.volumeType],
+ e->entry.nServers);
+ for (i = 0; i < e->entry.nServers; ++i) {
+ tmp.s_addr = htonl(e->entry.serverNumber[i]);
+ fprintf (f, "%d: server = %s, part = %d(%c), flags = %d\n",
+ i, inet_ntoa(tmp), e->entry.serverPartition[i],
+ 'a' + e->entry.serverPartition[i],
+ e->entry.serverFlags[i]);
+ }
+ if (e->entry.flags & VLF_RWEXISTS)
+ fprintf (f, "rw clone: %d\n", e->entry.volumeId[RWVOL]);
+ if (e->entry.flags & VLF_ROEXISTS)
+ fprintf (f, "ro clone: %d\n", e->entry.volumeId[ROVOL]);
+ if (e->entry.flags & VLF_BACKEXISTS)
+ fprintf (f, "rw clone: %d\n", e->entry.volumeId[BACKVOL]);
+ fprintf (f, "refcount = %u\n\n", e->refcount);
+ return FALSE;
+}
+
+/*
+ * Print some status on the volume cache on `f'.
+ */
+
+void
+volcache_status (FILE *f)
+{
+ fprintf (f, "%u(%u) volume entries\n",
+ nactive_volcacheentries, nvolcacheentries);
+ hashtabforeach (volidhashtab, print_entry, f);
+}
diff --git a/usr.sbin/afs/src/arlad/volcache.h b/usr.sbin/afs/src/arlad/volcache.h
new file mode 100644
index 00000000000..a6900d50a0c
--- /dev/null
+++ b/usr.sbin/afs/src/arlad/volcache.h
@@ -0,0 +1,106 @@
+/* $OpenBSD: volcache.h,v 1.1.1.1 1998/09/14 21:52:57 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Our cache of volume information.
+ */
+
+/* $KTH: volcache.h,v 1.13 1998/07/29 21:29:10 assar Exp $ */
+
+#ifndef _VOLCACHE_
+#define _VOLCACHE_
+
+#include <stdio.h>
+#include <cred.h>
+
+#define BACKSUFFIX ".backup"
+#define ROSUFFIX ".readonly"
+
+struct num_ptr {
+ int32_t cell;
+ u_int32_t vol;
+ struct volcacheentry *ptr;
+};
+
+struct name_ptr {
+ int32_t cell;
+ char name[VLDB_MAXNAMELEN];
+ struct volcacheentry *ptr;
+};
+
+struct volcacheentry {
+ vldbentry entry;
+ AFSVolSync volsync;
+ int32_t cell;
+ unsigned refcount;
+ struct {
+ unsigned validp : 1;
+ } flags;
+ struct name_ptr name_ptr[MAXTYPES];
+ struct num_ptr num_ptr[MAXTYPES];
+};
+
+typedef struct volcacheentry VolCacheEntry;
+
+const char *volcache_get_rootvolume (void);
+
+void volcache_set_rootvolume (const char *volname);
+
+void volcache_init (unsigned nentries, Bool recover);
+
+VolCacheEntry *volcache_getbyname (const char *volname,
+ int32_t cell,
+ CredCacheEntry *ce);
+
+VolCacheEntry *volcache_getbyid (u_int32_t id,
+ int32_t cell,
+ CredCacheEntry *ce);
+
+void volcache_update_volsync (VolCacheEntry *e, AFSVolSync volsync);
+
+void volcache_free (VolCacheEntry *e);
+
+void volcache_invalidate (u_int32_t id, int32_t cell);
+
+void volcache_status (FILE *f);
+
+int
+volcache_store_state (void);
+
+#endif /* _VOLCACHE_ */
diff --git a/usr.sbin/afs/src/conf/CellServDB b/usr.sbin/afs/src/conf/CellServDB
new file mode 100644
index 00000000000..8728cf3b7be
--- /dev/null
+++ b/usr.sbin/afs/src/conf/CellServDB
@@ -0,0 +1,693 @@
+>wu-wien.ac.at # University of Economics, Vienna, Austria
+137.208.3.33 #afsdb1.wu-wien.ac.at
+137.208.7.4 #afsdb2.wu-wien.ac.at
+137.208.241.11 #afsdb3.wu-wien.ac.at
+>hephy.at # hephy-vienna
+193.170.243.10 #mougli.oeaw.ac.at
+193.170.243.12 #balu.oeaw.ac.at
+>jrc.flinders.edu.au # Flinders School of Info. Sci. and Tech. - Australia
+129.96.31.2 #degas.jrc.flinders.edu.au
+>glade.yorku.ca #York U, Canada
+130.63.241.16 #aqua.glade.yorku.ca
+>writer.yorku.ca #York U, Canada
+130.63.1.2 #writer.yorku.ca
+>cern.ch # European Laboratory for Particle Physics, Geneva
+137.138.129.16 #afs11.cern.ch
+137.138.128.144 #afs3.cern.ch
+137.138.129.147 #afs1.cern.ch
+>ethz.ch # Swiss Federal Inst. of Tech. - Zurich, Switzerland
+129.132.98.25 #himalia.ethz.ch
+129.132.76.2 #charon.ethz.ch
+129.132.98.68 #nereide.ethz.ch
+>zurich.ibm.ch # IBM Zurich Internet Cell
+193.5.61.131 #uetliberg.zurich.ibm.ch
+>atc.alcoa.com #Alcoa Technical Center
+132.226.16.174 #cjm-amct.atc.alcoa.com
+132.226.16.16 #afs1-amct.atc.alcoa.com
+132.226.16.17 #afs2-amct.atc.alcoa.com
+>rtp.avanticorp.com #foo
+192.160.17.221 #i
+192.160.17.222 #dont
+192.160.17.223 #know
+>cards.com # Cards - Electronic Warfare Associates
+192.133.70.11 #gofish.cards.com
+192.133.70.2 #dealer.cards.com
+192.133.70.4 #solitaire.cards.com
+>gza.com #GZA - Geer Zolot Associates cell
+192.231.148.28 #mary-chungs.gza.com
+>palo_alto.hpl.hp.com # HP Palo Alto
+15.255.176.10 #pub.hpl.hp.com
+>sleeper.nsa.hp.com #HP Cupertino
+15.255.88.33 #telford.nsa.hp.com
+>afs.hursley.ibm.com # IBM Hursley, UK (external cell)
+194.196.110.156 #sp2tr6.hursley.ibm.com
+>ctp.se.ibm.com # IBM/4C, Chalmers, Sweden
+192.36.23.71 #ritchie.ctp.se.ibm.com
+>mtxinu.com #mt Xinu Incorporated
+131.106.1.22 #kineo.mtxinu.com
+>munin.com #Munin Systems, Inc.
+192.131.124.100 #raven.munin.com
+>qualcomm.com #qualcomm
+129.46.50.67 #afs-q1.qualcomm.com
+129.46.50.68 #afs-q2.qualcomm.com
+129.46.50.69 #afs-q3.qualcomm.com
+>stars.com # STARS Technology Center - Ballston, Va.
+128.126.164.2 #falcon.stars.ballston.paramax.com
+>telos.com # Telos Systems Group - Chantilly, Va.
+198.116.7.53 #tis.telos.com
+>transarc.com # Transarc Corporation
+158.98.14.3 #oscar.transarc.com
+158.98.3.2 #ernie.transarc.com
+158.98.3.3 #bigbird.transarc.com
+>mandos.dce.transarc.com #Transarc DCE cell
+158.98.7.205 #testlab-7-205.transarc.com
+>test.transarc.com #Transarc Corporation test cell
+192.55.207.5 #barley.transarc.com
+>usenix.transarc.com #Transarc Corporation demo cell
+192.55.207.101 #afssun.transarc.com
+>stars.reston.unisys.com # Paramax (Unisys) - Reston, Va.
+128.126.162.1 #aviary.stars.reston.paramax.com
+>afs.brain.de #BeSD on Berlin Research and Information Network (BRAIN)
+130.73.72.84 #zibsw1.brain.de
+130.73.72.85 #zibsw2.brain.de
+130.73.103.29 #zibsw3.brain.de
+>desy.de # Deutsches Elektronen-Synchrotron
+131.169.30.50 #rikki.desy.de
+131.169.55.19 #shiva.desy.de
+131.169.244.60 #solar00.desy.de
+>dkrz.de #Deutsches Klimarechenzentrum Hamburg
+136.172.110.215 #donau.dkrz.de
+136.172.110.81 #rhein.dkrz.de
+136.172.100.16 #elbe.dkrz.de
+>fh-heilbronn.de #Fachhochschule Heilbronn
+141.7.1.40 #jupiter.rz.fh-heilbronn.de
+>ifh.de # DESY-IfH Zeuthen
+141.34.100.32 #moira.ifh.de
+141.34.1.29 #hekate.ifh.de
+>lrz-muenchen.de # Leibniz-Rechenzentrum Muenchen Germany
+129.187.10.36 #afs1.lrz-muenchen.de
+129.187.14.10 #afs3.lrz-muenchen.de
+129.187.14.12 #afs2.lrz-muenchen.de
+>ipp-garching.mpg.de #Institut fuer Plasmaphysik
+130.183.9.5 #afs-serv1.ipp-garching.mpg.de
+130.183.100.10 #spinf.aug.ipp-garching.mpg.de
+130.183.100.23 #s30l6s3.aug.ipp-garching.mpg.de
+>ipp-hgw.mpg.de #IPP site at Greifswald
+194.94.214.4 #greif-01.ipp-hgw.mpg.de
+>mpa-garching.mpg.de # Max-Planck-Institut fuer Astrophysik
+130.183.83.31 #ibm-1.mpa-garching.mpg.de
+130.183.83.32 #ibm-2.mpa-garching.mpg.de
+130.183.83.33 #ibm-3.mpa-garching.mpg.de
+>hrzone.th-darmstadt.de # TH-Darmstadt
+130.83.126.5 #rs25.hrz.th-darmstadt.de
+130.83.126.8 #rs102.hrz.th-darmstadt.de
+130.83.22.3 #rs100.hrz.th-darmstadt.de
+>tu-chemnitz.de # Technische Universitaet Chemnitz-Zwickau, Germany
+134.109.2.1 #zuse-f.hrz.tu-chemnitz.de
+134.109.200.7 #aetius.hrz.tu-chemnitz.de
+134.109.2.15 #phoenix.hrz.tu-chemnitz.de
+>thermo-a.mw.tu-muenchen.de # Lehrstuhl A fuer Thermodynamik,TUM
+129.187.110.38 #nusselt.thermo-a.mw.tu-muenchen.de
+>uni-bonn.de # Rheinische Friedrich Wilhelm Univesitaet Bonn
+131.220.16.10 # work1.rhrz.uni-bonn.de
+131.220.16.60 # work2.rhrz.uni-bonn.de
+>uni-freiburg.de # Albert-Ludwigs-Universitat Freiburg
+132.230.7.21 #afs1.ruf.uni-freiburg.de
+132.230.7.22 #afs2.ruf.uni-freiburg.de
+132.230.7.23 #afs3.ruf.uni-freiburg.de
+>urz.uni-heidelberg.de # Universitaet Heidelberg
+129.206.119.10 #afsdb.urz.uni-heidelberg.de
+129.206.119.16 #afsdb1.urz.uni-heidelberg.de
+129.206.119.17 #afsdb2.urz.uni-heidelberg.de
+>uni-hohenheim.de # University of Hohenheim
+144.41.2.2 #rs13.serv.uni-hohenheim.de
+144.41.2.3 #rs14.serv.uni-hohenheim.de
+144.41.2.4 #rs15.serv.uni-hohenheim.de
+>rz.uni-jena.de # Rechenzentrum University of Jena, Germany
+141.35.4.66 #fsuj01.rz.uni-jena.de
+141.35.4.21 #fsuj70.rz.uni-jena.de
+>rhrk.uni-kl.de # Rechenzentrum University of Kaiserslautern
+131.246.137.10 #aix10.rhrk.uni-kl.de
+131.246.137.11 #aix11.rhrk.uni-kl.de
+131.246.137.9 #aix9.rhrk.uni-kl.de
+>geo.uni-koeln.de # Univ. of Cologne - Inst. for Geophysics & Meteorology
+134.95.160.10 #trick.geo.uni-koeln.de
+134.95.160.11 #track.geo.uni-koeln.de
+134.95.164.120 #helferlein.geo.uni-koeln.de
+134.95.164.124 #majestix.geo.uni-koeln.de
+134.95.180.94 #nimbus.geo.uni-koeln.de
+>meteo.uni-koeln.de # Univ. of Cologne - Inst. for Geophysics & Meteorology
+134.95.144.200 #bora.meteo.uni-koeln.de
+134.95.144.208 #monsun.meteo.uni-koeln.de
+134.95.144.213 #brise.meteo.uni-koeln.de
+>rrz.uni-koeln.de # University of Cologne - Reg Comp Center
+134.95.100.212 #rs2.rrz.uni-koeln.de
+134.95.19.3 #afsdb1.rrz.uni-koeln.de
+134.95.100.220 #fileserv2.rrz.uni-koeln.de
+134.95.140.208 #dec01.rrz.uni-koeln.de
+134.95.67.97 #afs.thp.uni-koeln.de
+>urz.uni-magdeburg.de # Otto-von-Guericke-Universitaet, Magdeburg
+141.44.7.11 #arche.urz.uni-magdeburg.de
+141.44.7.12 #archiessp.urz.uni-magdeburg.de
+141.44.8.4 #dws.urz.uni-magdeburg.de
+>zdv.uni-mainz.de # Johannes-Gutenberg-Universitaet Mainz
+134.93.8.13 #kingluey.zdv.Uni-Mainz.DE
+134.93.8.169 #alice.zdv.Uni-Mainz.DE
+134.93.178.127 #donald.zdv.Uni-Mainz.DE
+>uni-mannheim.de #Uni Mannheim (Rechenzentrum)
+134.155.50.37 #afsdb1.uni-mannheim.de
+134.155.50.38 #afsdb2.uni-mannheim.de
+134.155.50.40 #afsdb3.uni-mannheim.de
+>cipool.uni-stuttgart.de #CIP Pool, Rechenzentrum University of Stuttgart
+129.69.21.12 #zeus.rus.uni-stuttgart.de
+>dce.uni-stuttgart.de #University of Stuttgart - DCE/DFS Cell
+129.69.1.170 #jupiter.rus.uni-stuttgart.de
+129.69.18.29 #uranus.rus.uni-stuttgart.de
+129.69.18.30 #saturn.rus.uni-stuttgart.de
+129.69.3.34 #fortuna.rus.uni-stuttgart.de
+>csv.ica.uni-stuttgart.de #Institut fuer Computeranwendungen, Universitaet Stuttgart
+129.69.118.12 #iris8.csv.ica.uni-stuttgart.de
+>ihf.uni-stuttgart.de # University of Stuttgart, Institut fuer Hochfrequenz-Tec
+129.69.95.103 #ihfrs3.ihf.uni-stuttgart.de
+129.69.95.105 #ihfrs5.ihf.uni-stuttgart.de
+>ike.uni-stuttgart.de #Institut fuer Kernenergetik, Universitaet Stuttgart
+129.69.25.100 #ikedc1.ike.uni-stuttgart.de
+>mathematik.uni-stuttgart.de # University of Stuttgart, Math Dept.
+129.69.116.32 #maxwell.mathematik.uni-stuttgart.de
+129.69.116.33 #hopf.mathematik.uni-stuttgart.de
+129.69.116.34 #kolmogorov.mathematik.uni-stuttgart.de
+>mathematik-cip.uni-stuttgart.de # CIP-Pool of Math. Dept, University of Stuttgart
+129.69.116.100 #cip00.mathematik.uni-stuttgart.de
+129.69.116.101 #cip01.mathematik.uni-stuttgart.de
+129.69.116.102 #cip02.mathematik.uni-stuttgart.de
+>rus.uni-stuttgart.de # Rechenzentrum University of Stuttgart
+129.69.1.155 #servus05.rus.uni-stuttgart.de
+129.69.18.216 #servus16.rus.uni-stuttgart.de
+129.69.3.4 #syssrv1.rus.uni-stuttgart.de
+>belwue.uni-tuebingen.de #ZDV Universitaet Tuebingen
+134.2.2.15 #belwue1.zdv.uni-tuebingen.de
+134.2.2.117 #belwue2.zdv.uni-tuebingen.de
+>zdvpool.uni-tuebingen.de # Eberhard-Karls-Universitaet Tuebingen, WS-Pools
+134.2.4.1 #aixserv1.zdv.uni-tuebingen.de
+>cs.arizona.edu # University of Arizona - Computer Science Dept.
+192.12.69.8 #benguiat.cs.arizona.edu
+>asu.edu # ASU
+129.219.10.69 #authen2.asu.edu
+129.219.10.70 #authen1.asu.edu
+>cs.brown.edu # Brown University Department of Computer Science
+128.148.37.20 #monk.cs.brown.edu
+>bu.edu # Boston University
+128.197.27.12 #software2.bu.edu
+128.197.27.6 #software3.bu.edu
+128.197.27.15 #ns2.bu.edu
+128.197.27.92 #ns4.bu.edu
+>gg.caltech.edu # Caltech Computer Graphics Group
+131.215.129.25 #meagger.gg.caltech.edu
+>cmu.edu # Carnegie Mellon University
+128.2.206.46 #cmu2.cs.cmu.edu
+128.2.35.186 #cmu1.acs.cmu.edu
+>andrew.cmu.edu # Carnegie Mellon University - Campus
+128.2.10.11 #vice11.fs.andrew.cmu.edu
+128.2.10.12 #vice12.fs.andrew.cmu.edu
+128.2.10.2 #vice2.fs.andrew.cmu.edu
+128.2.10.28 #vice28.fs.andrew.cmu.edu
+128.2.10.7 #vice7.fs.andrew.cmu.edu
+>club.cc.cmu.edu # Carnegie Mellon University Computer Club
+128.2.232.123 #helium.club.cc.cmu.edu
+>ce.cmu.edu # Carnegie Mellon University - Civil Eng. Dept.
+128.2.231.39 #newmark.ce.cmu.edu
+>cheme.cmu.edu # Carnegie Mellon Univ. Chemical Engineering Dept.
+128.2.55.30 #cheme.cmu.edu
+>cs.cmu.edu # Carnegie Mellon University - School of Comp. Sci.
+128.2.206.130 #cucumber.srv.cs.cmu.edu
+128.2.222.199 #papaya.srv.cs.cmu.edu
+128.2.242.86 #lemon.srv.cs.cmu.edu
+>test.cs.cmu.edu #Test Cell-CMU SCS
+128.2.209.214 #blackberry.srv.cs.cmu.edu
+128.2.222.221 #chokeberry.srv.cs.cmu.edu
+128.2.250.251 #honeydew.srv.cs.cmu.edu
+>ece.cmu.edu # Carnegie Mellon University - Elec. Comp. Eng. Dept.
+128.2.251.100 #porok.ece.cmu.edu
+128.2.251.101 #vicio.ece.cmu.edu
+128.2.251.102 #e-xing.ece.cmu.edu
+>me.cmu.edu # Carnegie Mellon University - Mechanical Engineering
+128.2.62.3 #edison.me.cmu.edu
+>haycorn.psy.cmu.edu #CMU Psy Test cell
+128.2.248.86 #haycorn.psy.cmu.edu
+>cs.cornell.edu #Cornell University Computer Science
+128.84.254.70 #kali.cs.cornell.edu
+>graphics.cornell.edu # Cornell University Program of Computer Graphics
+132.236.95.45 #potato.graphics.cornell.edu
+>msc.cornell.edu # Cornell University Materials Science Center
+128.84.231.196 #ransom.msc.cornell.edu
+128.84.241.33 #ept.msc.cornell.edu
+128.84.249.240 #locutus.msc.cornell.edu
+>theory.cornell.edu # Cornell University Theory Center
+128.84.29.37 #blynken.tc.cornell.edu
+128.84.29.56 #nod.tc.cornell.edu
+128.84.29.77 #wynken.tc.cornell.edu
+>kiewit.dartmouth.edu # Dartmouth College, Kiewit
+129.170.16.42 #northservc.dartmouth.edu
+>northstar.dartmouth.edu #Dartmouth College, Project Northstar
+129.170.16.43 #cygnusx1.dartmouth.edu
+129.170.16.205 #beehive.dartmouth.edu
+129.170.24.37 #andromeda.dartmouth.edu
+129.170.24.115 #horsehead.dartmouth.edu
+>acpub.duke.edu #Duke academic computing (clusters)
+152.3.100.1 #diana.acpub.duke.edu
+152.3.101.2 #hercules.acpub.duke.edu
+152.3.100.3 #ganymede.acpub.duke.edu
+>afs1.scri.fsu.edu # Supercomputer Computations Research Instit
+144.174.128.60 #afs1.scri.fsu.edu
+>iastate.edu # Iowa State University
+129.186.156.156 #afsdb-1.iastate.edu
+129.186.157.157 #afsdb-2.iastate.edu
+129.186.158.158 #afsdb-3.iastate.edu
+>isi.edu # University of Southern California/ISI
+128.9.208.78 #afs.isi.edu
+>cc.lehigh.edu #lehigh
+128.180.1.3 #fs1.CC.Lehigh.EDU
+128.180.1.26 #fs2.CC.Lehigh.EDU
+128.180.1.37 #fs3.CC.Lehigh.EDU
+>cva.ai.mit.edu #MIT/private Concurrent VLSI Architecture Group
+128.52.36.20 #raisin-scone.ai.mit.edu.
+>athena.mit.edu # MIT/Athena cell
+18.70.0.6 #prill.mit.edu
+18.72.0.43 #orf.mit.edu
+18.145.0.25 #agamemnon.mit.edu
+18.159.0.34 #chimera.mit.edu
+>brain.mit.edu #MIT/private Brain & Cognitive Sciences
+18.42.1.2 #ladyday.mit.edu.
+18.42.1.30 #prez.mit.edu.
+>dev.mit.edu #MIT/IS/DCNS Development cell
+18.86.0.26 #ezra.mit.edu
+>fishwrap.mit.edu #MIT/Freshman Newspaper project
+18.85.6.33 #fishwrap.mit.edu
+>lees.mit.edu #MIT/Lab for Electromagnetic and Electronic Systems
+18.90.1.184 #power.mit.edu
+>net.mit.edu # MIT/Network Group cell
+18.72.1.3 #orca.mit.edu
+18.72.0.20 #moby.mit.edu
+>sipb.mit.edu # MIT/SIPB cell
+18.181.0.19 #reynelda.mit.edu
+18.181.0.22 #rosebud.mit.edu
+18.181.0.23 #ronald-ann.mit.edu
+>zone.mit.edu #MIT/Watchmaker Zone cell
+18.177.0.20 #casio.mit.edu
+18.177.0.21 #timex.mit.edu
+18.177.0.22 #seiko.mit.edu
+>msu.edu #Michigan State University home cell
+35.9.7.10 #afsdb0.cl.msu.edu
+35.9.7.11 #afsdb1.cl.msu.edu
+35.9.7.12 #afsdb2.cl.msu.edu
+>ncat.edu # North Carolina Agricultural and Technical State Univ
+152.8.244.141 #afsserv1.ncat.edu
+152.8.244.142 #afsserv2.ncat.edu
+152.8.244.143 #afsserv3.ncat.edu
+>bp.ncsu.edu #North Carolina State University - Backbone Prototype
+152.1.1.27 #tourian.cc.ncsu.edu
+152.1.1.28 #norfair.cc.ncsu.edu
+152.1.1.29 #maridia.cc.ncsu.edu
+>catt.ncsu.edu #NCSU - Computer and Technologies Theme Program
+152.1.43.33 #nermal.catt.ncsu.edu
+>eos.ncsu.edu #NCSU - College of Engineering
+152.1.9.3 #eos05f.eos.ncsu.edu
+152.1.19.3 #eos02b.eos.ncsu.edu
+152.1.29.3 #eos03b.eos.ncsu.edu
+>tx.ncsu.edu #NCSU College of Textiles - Project Eos&Unity Mutant
+152.1.39.7 #sparc3.tx.ncsu.edu
+>unity.ncsu.edu #NCSU Campus
+152.1.1.36 #cc00db.unity.ncsu.edu
+152.1.1.37 #cc01db.unity.ncsu.edu
+152.1.1.38 #cc02db.unity.ncsu.edu
+>zorglub.ncsu.edu #NCSU Experimental Cell
+152.1.9.80 #borg.eos.ncsu.edu
+>nd.edu # University of Notre Dame
+129.74.223.17 #john.helios.nd.edu
+129.74.223.33 #lizardo.helios.nd.edu
+129.74.223.65 #buckaroo.helios.nd.edu
+>pitt.edu # University of Pittsburgh
+136.142.8.15 #afs09.srv.cis.pitt.edu
+136.142.8.20 #afs10.srv.cis.pitt.edu
+136.142.8.21 #afs11.srv.cis.pitt.edu
+>cs.pitt.edu #University of Pittsburgh - Computer Science
+136.142.79.3 #lurch.cs.pitt.edu
+>discovery.pitt.edu #University of Pittsburgh Test Cell
+130.49.254.49 #server1.discovery.pitt.edu
+>med.pitt.edu #Office of Biomedical Informatics, UPitt
+150.212.5.1 #mimas.sv.med.pitt.edu
+150.212.5.2 #titan.sv.med.pitt.edu
+>psc.edu # PSC (Pittsburgh Supercomputing Center)
+128.182.73.70 #afsrv1.psc.edu
+128.182.73.72 #afsrv3.psc.edu
+128.182.73.73 #afsrv4.psc.edu
+>big.psc.edu #PSC max strat
+128.182.62.231 #max.psc.edu
+>huge.psc.edu #PSC Max Strat server
+128.182.73.94 #utnapishtim-f.psc.edu
+>slow.psc.edu #PSC slow cell for Cray testing
+128.182.62.222 #pele.psc.edu
+>test.psc.edu #PSC Performance Evaluation
+128.182.66.71 #afsrv2.psc.edu
+>psu.edu # Penn State
+128.118.2.5 #spot.cac.psu.edu
+>cac.psu.edu #Penn State University CAC Cluster
+128.118.57.4 #camaton.cac.psu.edu
+146.186.125.1 #sundae.hbc.psu.edu
+>rose-hulman.edu # Rose-Hulman Institute of Technology
+137.112.7.11 #afs1.rose-hulman.edu
+137.112.7.12 #afs2.rose-hulman.edu
+137.112.7.13 #afs3.rose-hulman.edu
+>cs.rose-hulman.edu # Rose-Hulman Inst. of Tech., CS Department
+137.112.40.5 #afs1.cs.rose-hulman.edu
+>rpi.edu #Rensselaer Polytechnic Institute
+128.113.100.31 #asher.its.rpi.edu
+128.113.100.34 #samuel.sss.rpi.edu
+128.113.100.36 #samson.its.rpi.edu
+128.113.100.100 #nebuchadnezzar.its.rpi.edu
+>ifs.rpi.edu #RPI IFS cell
+128.113.26.81 # ifsserver.its.rpi.edu
+>dsg.stanford.edu # Stanford Univ. - Comp. Sci. - Distributed Systems
+36.18.0.243 #greyhawk.stanford.edu
+36.18.0.69 #lahaina.stanford.edu
+36.18.0.8 #pescadero.stanford.edu
+>ir.stanford.edu # Stanford University
+36.21.0.108 #bianca.stanford.edu
+36.83.0.227 #aristotle.stanford.edu
+36.83.0.228 #meno.stanford.edu
+>olympia.stanford.edu # Stanford DECathena AFS cell - local
+36.53.0.106 #olympia.stanford.edu
+>slac.stanford.edu # Stanford Linear Accelerator Center
+134.79.18.25 #afsdb1.slac.stanford.edu
+134.79.18.26 #afsdb2.slac.stanford.edu
+134.79.18.27 #afsdb3.slac.stanford.edu
+>eng.uc.edu #u cincinnati eng
+129.137.40.8 #monster.occ.uc.edu
+129.137.40.130 #sputnik.occ.uc.edu
+129.137.40.100 #nfl.occ.uc.edu
+>ece.ucdavis.edu # Univ California - Davis campus
+128.120.57.1 #clover.ece.ucdavis.edu
+128.120.57.135 #anaconda.ece.ucdavis.edu
+128.120.67.27 #vision.cipic.ucdavis.edu
+>spc.uchicago.edu # University of Chicago - Social Sciences
+128.135.252.11 #psyche.spc.uchicago.edu
+128.135.252.8 #oerestes.spc.uchicago.edu
+128.135.64.8 #goono.spc.uchicago.edu
+>ucop.edu #University of California Office of the President
+128.48.141.2 #ganges.ucop.edu
+128.48.141.9 #holmes.ucop.edu
+128.48.108.39 #volga.ucop.edu
+>cats.ucsc.edu #UC Santa Cruz, Comp and Tech Services, California U.S.A
+128.114.129.14 #elan.ucsc.edu
+128.114.129.15 #ichabod.ucsc.edu
+128.114.129.18 #maneki.ucsc.edu
+>ncsa.uiuc.edu # University of Illinois
+141.142.230.19 #jinx.ncsa.uiuc.edu
+141.142.3.5 #congo.ncsa.uiuc.edu
+141.142.3.8 #nile.ncsa.uiuc.edu
+>glue.umd.edu #University of Maryland - Project Glue
+129.2.70.82 #olmec.umd.edu
+128.8.10.21 #babylon.umd.edu
+129.2.128.53 #egypt.umd.edu
+>wam.umd.edu # University of Maryland Network WAM Project
+128.8.70.9 #csc-srv.wam.umd.edu
+128.8.73.9 #pg2-srv.wam.umd.edu
+128.8.77.2 #wor-srv.wam.umd.edu
+>umich.edu # University of Michigan - Campus
+141.211.1.32 #fear.ifs.umich.edu
+141.211.1.33 #surprise.ifs.umich.edu
+141.211.1.34 #ruthless.ifs.umich.edu
+>citi.umich.edu # University of Michigan - IFS Development
+141.211.128.99 #babble.citi.umich.edu
+>engin.umich.edu # University of Michigan - CAEN
+141.212.2.75 #artes.engin.umich.edu
+141.212.2.76 #scientia.engin.umich.edu
+141.212.2.77 #veritas.engin.umich.edu
+>aix.ifs.umich.edu #University of Michigan - AIX (test)
+141.211.168.40 #ifsaix.ifs.umich.edu
+>bigserv.ifs.umich.edu #University of Michigan - MVS (brich test)
+141.211.168.33 #barnone.ifs.umich.edu
+>mvs.ifs.umich.edu #University of Michigan - MVS (test)
+141.211.168.41 #ifsaix.ifs.umich.edu
+>lsa.umich.edu # University of Michigan - LSA College
+141.211.38.15 #schweinhund.admin.lsa.umich.edu
+141.211.61.23 #zee.admin.lsa.umich.edu
+141.211.75.246 #jake.admin.lsa.umich.edu
+>math.lsa.umich.edu # University of Michigan - Math Cell
+141.211.61.11 #patton.math.lsa.umich.edu
+141.211.61.12 #sdrr.math.lsa.umich.edu
+141.211.61.13 #bull.math.lsa.umich.edu
+>dmsv.med.umich.edu # University of Michigan - DMSV
+141.214.58.20 #pollock.dmsv.med.umich.edu
+141.214.58.21 #magritte.dmsv.med.umich.edu
+141.214.58.22 #kandinsky.dmsv.med.umich.edu
+>sph.umich.edu # University of Michigan -- School of Public
+141.211.50.41 #afssph0.sph.umich.edu
+>umr.edu # UMR - Missouri's Technological University
+131.151.1.59 #afs1.cc.umr.edu
+131.151.2.133 #mecad13.maem.umr.edu
+>cs.unc.edu # University of North Carolina at Chapel Hill
+152.2.128.3 #alpha.cs.unc.edu
+152.2.128.4 #zeta.cs.unc.edu
+152.2.128.9 #gamma.cs.unc.edu
+>isis.unc.edu #UNC campus computing
+152.2.25.120 #db0.isis.unc.edu
+152.2.25.121 #db1.isis.unc.edu
+152.2.25.122 #db2.isis.unc.edu
+>oit.unc.edu #UNC OIT development cell
+152.2.22.11 #akbash.oit.unc.edu
+>oit-miglab.unc.edu #UNC OIT test cell
+152.2.21.46 #daisy.oit.unc.edu
+>utah.edu # University of Utah Information Tech. Service
+128.110.1.1 #its.utah.edu
+128.110.1.2 #its2.utah.edu
+>cs.utah.edu # University of Utah Computer Science Dept
+128.110.2.50 #afs1.cs.utah.edu
+155.99.212.41 #afs2.cs.utah.edu
+155.99.222.104 #cadeserv.eng.utah.edu
+>css.cs.utah.edu #University of Utah - CSS center
+155.99.212.102 #jensen.cs.utah.edu
+128.110.4.156 #fast.cs.utah.edu
+>mc.vanderbilt.edu #Vanderbilt University Medical Center
+160.129.202.80 #dbmi6000.mc.vanderbilt.edu
+>cs.washington.edu # University of Washington Comp Sci Department
+128.95.2.238 #silk.cs.washington.edu
+128.95.2.239 #satin.cs.washington.edu
+128.95.2.240 #lace.cs.washington.edu
+>cs.wisc.edu # Univ. of Wisconsin-Madison, Computer Sciences Dept
+128.105.3.28 #bentley.cs.wisc.edu
+128.105.3.29 #hinkley.cs.wisc.edu
+128.105.3.35 #dool.cs.wisc.edu
+>engr.wisc.edu # Univ. of Wisconsin-Madison, College of Engineering
+144.92.240.97 #afs1.cae.wisc.edu
+144.92.240.98 #afs2.cae.wisc.edu
+144.92.240.99 #afs3.cae.wisc.edu
+>dapnia.saclay.cea.fr #Axlan-CEA
+132.166.32.7 #dphrsg.saclay.cea.fr
+>in2p3.fr # IN2P3 production cell
+134.158.232.1 #ccpnds00.in2p3.fr
+>mcc.ac.gb #University of Manchester
+130.88.203.11 #cfs1.mcc.ac.uk
+130.88.203.12 #cfs2.mcc.ac.uk
+130.88.203.14 #zeus.mcc.ac.uk
+>anl.gov # Argonne National Laboratory
+146.137.72.12 #aeneas.ctd.anl.gov
+146.137.72.2 #ajax.ctd.anl.gov
+146.137.162.88 #agamemnon.ctd.anl.gov
+>fl.mcs.anl.gov # Argonne National Laboratory MCS Division FL
+140.221.32.92 #barge.mcs.anl.gov
+>bnl.gov # Brookhaven National Laboratory
+130.199.54.21 #afs1.ccd.bnl.gov
+>phy.bnl.gov # Physics Deptpartment, Brookhaven National Lab
+130.199.80.126 #h0h08.rhic.bnl.gov
+>fnal.gov # Fermi National Acclerator Laboratory
+131.225.68.1 #fsus01.fnal.gov
+131.225.68.14 #fsus04.fnal.gov
+131.225.68.4 #fsus03.fnal.gov
+>inel.gov #Idaho National Engineering Lab
+134.20.8.7 #mica.inel.gov
+>jpl.nasa.gov # Jet Propulsion Laboratory
+137.78.50.2 #afsdb01.jpl.nasa.gov
+137.78.50.5 #afsdb02.jpl.nasa.gov
+137.78.50.6 #afsdb03.jpl.nasa.gov
+137.79.158.63 #eis-fil-afsdb06.jpl.nasa.gov
+>nersc.gov # National Energy Research Supercomputer Center
+128.55.128.250 #mars.nersc.gov
+128.55.128.252 #alfred.nersc.gov
+128.55.128.254 #lurch.nersc.gov
+>alw.nih.gov # National Institutes of Health
+137.187.114.10 #vice1.alw.nih.gov
+137.187.114.11 #vice3.alw.nih.gov
+137.187.114.15 #vice7.alw.nih.gov
+>nrel.gov #National Renewable Energy Laboratory
+192.33.19.104 #syssrv4.nrel.gov
+192.174.52.125 #sst.nrel.gov
+199.117.159.87 #syssrv7.nrel.gov
+>dce.emsl.pnl.gov # EMSL's DCE Cell
+198.128.85.133 #tomcat.emsl.pnl.gov
+198.128.85.135 #hellcat.emsl.pnl.gov
+198.128.85.136 #bearcat.emsl.pnl.gov
+>msrc.pnl.gov #EMSL's AFS Cell
+198.128.85.251 #castors.emsl.pnl.gov
+198.128.85.252 #polluxs.emsl.pnl.gov
+198.128.85.253 #rosebuds.emsl.pnl.gov
+>pppl.gov # Princeton Plasma Physics Laboratory
+198.35.4.70 #lyman.pppl.gov
+198.35.6.44 #draco.pppl.gov
+>controls.ssc.gov #Superconducting Supercollider Lab
+134.3.45.30 #psychosis.ssc.gov
+>nersc.test.gov #NERSC test cell
+128.55.128.239 #jupiter.nersc.gov
+>caspur.it # CASPUR Inter-University Computing Consortium, Rome
+193.204.5.45 #pomodoro.caspur.it
+193.204.5.46 #banana.caspur.it
+193.204.5.50 #maslo.caspur.it
+>le.caspur.it # Universita' di Lecce, Italia
+192.84.152.40 #afs1.le.infn.it
+>infn.it #Istituto Nazionale di Fisica Nucleare, Italia
+131.154.1.7 #afs1.infn.it
+141.108.3.252 #afs2.infn.it
+192.84.134.75 #afs3.infn.it
+>le.infn.it # INFN, Sezione di Lecce, Italia
+192.84.152.37 #aixserver.le.infn.it
+>lngs.infn.it # INFN, Laboratori Nazionali di Gran Sasso, Italia
+192.84.135.3 #rsgs02.lngs.infn.it
+>pi.infn.it # INFN Sezione di Pisa
+192.84.133.7 #aix.pi.infn.it
+192.84.133.50 #aix1.pi.infn.it
+>dis.uniroma1.it # DIS, Univ. "La Sapienza", Rome, area Buonarotti
+151.100.5.21 #peano.dis.uniroma1.it
+151.100.16.9 #viola.dis.uniroma1.it
+151.100.16.36 #rosa.dis.uniroma1.it
+>spv.uniroma1.it # Universita' La Sapienza, area SPV, Roma, Italia
+151.100.39.2 #aurea.ing.uniroma1.it
+>vn.uniroma3.it # University of Rome 3, Area Vasca Navale, Italy
+193.204.162.11 #euclide.inf.uniroma3.it
+>cc.keio.ac.jp # Keio University, Faculty of Science and Technology Computing Center
+131.113.1.21 #afs0.cc.keio.ac.jp
+131.113.191.21 #afs0.med.keio.ac.jp
+131.113.192.21 #afs0.mita.keio.ac.jp
+131.113.224.21 #afs0.hc.keio.ac.jp
+>sfc.keio.ac.jp # Keio University, Japan
+133.27.68.82 #afs2.sfc.keio.ac.jp
+>isl.ntt.jp # NTT Information and Communication Systems Labs.
+129.60.67.15 #mx.isl.ntt.jp
+129.60.105.29 #dufour.isl.ntt.jp
+>rwcp.or.jp # Real World Computer Partnership(rwcp)
+163.220.1.2 #fs1.trc.rwcp.or.jp
+163.220.1.4 #fs3.trc.rwcp.or.jp
+163.220.1.6 #fs2.trc.rwcp.or.jp
+>postech.ac.kr # Pohang Universtiy of Science
+141.223.112.1 # sws3.postech.ac.kr
+>ait.nrl.navy.mil #Naval Research Lab
+132.250.128.19 #intrepid.ait.nrl.navy.mil
+>cmf.nrl.navy.mil # Naval Research Lab - CCS
+134.207.10.68 #picard.cmf.nrl.navy.mil
+134.207.10.69 #riker.cmf.nrl.navy.mil
+134.207.10.70 #kirk.cmf.nrl.navy.mil
+>lcp.nrl.navy.mil # Naval Research Lab - Lab for Computational Physics
+132.250.116.39 #ernie.lcp.nrl.navy.mil
+132.250.116.48 #bert.lcp.nrl.navy.mil
+132.250.116.41 #orange.lcp.nrl.navy.mil
+>nrlfs1.nrl.navy.mil # Naval Research Lab - CCS
+132.250.118.3 #nrlfs1.nrl.navy.mil
+>vl.nrl.navy.mil #Vis Lab CCS/ITD/NRL
+132.250.110.101 #ohm.nrl.navy.mil
+132.250.110.108 #nimitz.nrl.navy.mil
+>invermexico.com.mx #fucking
+185.134.80.59 #firewalls
+>mty.itesm.mx #?
+131.178.4.4 #academ07.mty.itesm.mx
+131.178.4.17 #academ03.mty.itesm.mx
+131.178.4.18 #academ06.mty.itesm.mx
+>nce_sdsc #San Diego Supercomputer Center
+132.249.51.100 #osprey.sdsc.edu
+132.249.20.59 #anxiety-closet.sdsc.edu
+>federation.atd.net # Multi Resident AFS at Naval Research Lab - CCS
+134.207.10.40 #federation.cmf.nrl.navy.mil
+>huge.wabit.atd.net #Wabit cell
+134.207.12.37 #hades.cmf.nrl.navy.mil
+>es.net # Energy Sciences Net
+198.128.3.21 #fs1.es.net
+198.128.3.22 #fs2.es.net
+198.128.3.23 #fs3.es.net
+>hep.net # US High Energy Physics Information cell
+131.225.110.11 #hepnrc.hep.net
+>cert.org #CERT/Coordination Center
+192.88.210.121 #fs1.cert.org
+192.88.210.122 #fs2.cert.org
+192.88.210.123 #fs3.cert.org
+>ciesin.org # CIESIN
+160.39.8.90 #afsdb0.ciesin.org
+>dementia.org # dementia
+128.2.35.149 # alycia.dementia.org
+>research.ec.org # Esprit Research Network of Excellence
+128.240.150.111 #albion.ncl.ac.uk
+130.89.181.106 #cabernet.pegasus.esprit.ec.org
+140.93.13.7 #sauterne.laas.fr
+>iway.org # I-WAY - Information Wide Area Year
+128.84.152.60 #myway.tc.cornell.edu
+>dce.osf.org #OSF DCE cell
+130.105.4.17 #maalox.osf.org
+>gr.osf.org # OSF Research Institute, Grenoble
+130.105.64.17 #tallien.gr.osf.org
+130.105.64.40 #cobra.gr.osf.org
+130.105.64.9 #barere.gr.osf.org
+>ri.osf.org # OSF Research Institute
+130.105.3.23 #riafs1.osf.org
+130.105.3.24 #riafs5.osf.org
+130.105.3.25 #riafs6.osf.org
+>syseng.osf.org #OSF cell used to be ap.mit.edu
+130.105.36.2 #csserver.osf.org
+>thekeep.org #Dan Root
+128.2.35.108 #afs.thekeep.org
+>rhic #Relativistic Heavy Ion Collider
+130.199.24.7 #ribm03f.rhic.bnl.gov
+>cs.chalmers.se #Chalmers University of Technology - Comp. Sci. Dept
+129.16.2.22 #undis.cs.chalmers.se
+>others.chalmers.se # Chalmers University of Technology - General users
+129.16.19.11 #vice1.utc.chalmers.se
+129.16.19.12 #vice2.utc.chalmers.se
+129.16.20.156 #fibbla.ce.chalmers.se
+129.16.97.44 #idun.phc.chalmers.se
+>e.kth.se # Royal Institute of Technology, Elektro
+130.237.48.7 #topaz.e.kth.se
+130.237.48.8 #opal.e.kth.se
+130.237.48.244 #humle.e.kth.se
+>isk.kth.se # KTH College of Engineering
+130.237.206.13 #afsdb1.isk.kth.se
+130.237.206.29 #afsdb2.isk.kth.se
+130.237.209.141 #afsdb3.isk.kth.se
+>it.kth.se # Royal Institute of Technology, IT
+130.237.212.6 #gaia.it.kth.se
+130.237.215.3 #tristan.it.kth.se
+130.237.214.3 #isolde.it.kth.se
+>mech.kth.se # Royal Institute of Technology, MECH
+130.237.233.142 #eiger.mech.kth.se
+>nada.kth.se # Royal Institute of Technology, NADA
+130.237.222.20 #kosmos.nada.kth.se
+130.237.223.12 #sputnik.nada.kth.se
+130.237.224.78 #mir.nada.kth.se
+130.237.227.23 #gagarin.nada.kth.se
+130.237.228.28 #laika.nada.kth.se
+>pdc.kth.se # Royal Institute of Technology, PDC
+130.237.232.29 #crab.pdc.kth.se
+130.237.232.112 #anna.pdc.kth.se
+130.237.232.114 #hokkigai.pdc.kth.se
+>blubb.pdc.kth.se # blubb
+193.10.159.47 #blubb.pdc.kth.se
+>mr-afs.pdc.kth.se # PDC, MR-AFS
+193.10.159.250 #frog.pdc.kth.se
+>stacken.kth.se # Stacken Computer Club
+130.237.234.43 #hot.stacken.kth.se
+130.237.234.44 #dog.stacken.kth.se
+130.237.234.3 #milko.stacken.kth.se
+>bcc.ac.uk # Bloomsbury Computing Consortium
+128.40.101.3 #rs6-svr-3.cls-1.bcc.ac.uk
+>athena.ox.ac.uk #Oxford cell
+129.67.42.91 #neon.athena.ox.ac.uk
+129.67.42.90 #krypton.athena.ox.ac.uk
+>rl.ac.uk #Rutherford Appleton Lab, England
+130.246.12.31 #tinkerbel.cc.rl.ac.uk
+>ibm.uk # IBM UK, AIX Systems Support Centre
+160.100.240.2 #affinity.aixssc.uk.ibm.com
diff --git a/usr.sbin/afs/src/conf/ThisCell b/usr.sbin/afs/src/conf/ThisCell
new file mode 100644
index 00000000000..0f10dd24d2d
--- /dev/null
+++ b/usr.sbin/afs/src/conf/ThisCell
@@ -0,0 +1 @@
+stacken.kth.se
diff --git a/usr.sbin/afs/src/conf/arla.conf b/usr.sbin/afs/src/conf/arla.conf
new file mode 100644
index 00000000000..0eae3351e56
--- /dev/null
+++ b/usr.sbin/afs/src/conf/arla.conf
@@ -0,0 +1,49 @@
+#
+# Arla conffile
+#
+# $Id: arla.conf,v 1.1.1.1 1998/09/14 21:52:58 art Exp $
+#
+# The upper limit of (arlad) vnodes (think files and directories)
+# (high-water mark)
+#
+high_vnodes 4000
+#
+# The number of used vnodes we try to have
+# (low-water mark)
+#
+low_vnodes 3000
+#
+# The upper limit of bytes in the cache
+# (high-water mark)
+#
+high_bytes 20M
+#
+# The number of bytes we try to use
+# (low-water mark)
+#
+low_bytes 15M
+#
+# The number of credentials in arla, both unauthentic,
+# and authentic (like Kerberos V4 creds)
+#
+numcreds 100
+#
+# The maxium connections arla will have to all servers
+#
+numconns 100
+#
+# The number of volumes stored in cache.
+#
+numvols 100
+#
+# File priority, the describes how the cleaner process will
+# Clean out files, when the closer this is to 100, the higher
+# is the risk that you will lose files that you fell is important
+# to you when you are in disconnected mode. But you dont want to'
+# set this too low when you are in connected mode, since then you
+# loose valuable diskspace.
+#
+fpriority 100
+#
+#
+# The End. \ No newline at end of file
diff --git a/usr.sbin/afs/src/include/.cvsignore b/usr.sbin/afs/src/include/.cvsignore
new file mode 100644
index 00000000000..2a9005dc419
--- /dev/null
+++ b/usr.sbin/afs/src/include/.cvsignore
@@ -0,0 +1 @@
+config.h.in
diff --git a/usr.sbin/afs/src/include/bits.c b/usr.sbin/afs/src/include/bits.c
new file mode 100644
index 00000000000..6aa08cf85df
--- /dev/null
+++ b/usr.sbin/afs/src/include/bits.c
@@ -0,0 +1,207 @@
+/* $OpenBSD: bits.c,v 1.1.1.1 1998/09/14 21:52:59 art Exp $ */
+/*
+ * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: bits.c,v 1.4 1998/03/28 09:24:30 lha Exp $");
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifndef HAVE_STRUPR
+static void
+strupr(char *s)
+{
+ char *p = s;
+ while(*p){
+ if(islower((int)*p))
+ *p = toupper((int)*p);
+ p++;
+ }
+}
+#endif
+
+#define BITSIZE(TYPE) \
+{ \
+ int b = 0; TYPE x = 1, zero = 0; char *pre = "u_"; \
+ char tmp[128], tmp2[128]; \
+ while(x){ x <<= 1; b++; if(x < zero) pre=""; } \
+ if(b >= len){ \
+ int tabs; \
+ sprintf(tmp, "%sint%d_t" , pre, len); \
+ sprintf(tmp2, "typedef %s %s;", #TYPE, tmp); \
+ strupr(tmp); \
+ tabs = 5 - strlen(tmp2) / 8; \
+ fprintf(f, "%s", tmp2); \
+ while(tabs-- > 0) fprintf(f, "\t"); \
+ fprintf(f, "/* %2d bits */\n", b); \
+ return; \
+ } \
+}
+
+static void
+try_signed(FILE *f, int len)
+{
+ BITSIZE(signed char);
+ BITSIZE(short);
+ BITSIZE(int);
+ BITSIZE(long);
+#ifdef HAVE_LONG_LONG
+ BITSIZE(long long);
+#endif
+ fprintf(f, "/* There is no %d bit type */\n", len);
+}
+
+static void
+try_unsigned(FILE *f, int len)
+{
+ BITSIZE(unsigned char);
+ BITSIZE(unsigned short);
+ BITSIZE(unsigned int);
+ BITSIZE(unsigned long);
+#ifdef HAVE_LONG_LONG
+ BITSIZE(unsigned long long);
+#endif
+ fprintf(f, "/* There is no %d bit type */\n", len);
+}
+
+static int
+print_bt(FILE *f, int flag)
+{
+ if(flag == 0){
+ fprintf(f, "/* For compatibility with various type definitions */\n");
+ fprintf(f, "#ifndef __BIT_TYPES_DEFINED__\n");
+ fprintf(f, "#define __BIT_TYPES_DEFINED__\n");
+ fprintf(f, "\n");
+ }
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int flag;
+ char *fn, *hb;
+
+ if(argc < 2){
+ fn = "bits.h";
+ hb = "__BITS_H__";
+ f = stdout;
+ } else {
+ char *p;
+ fn = argv[1];
+ hb = malloc(strlen(fn) + 5);
+ sprintf(hb, "__%s__", fn);
+ for(p = hb; *p; p++){
+ if(!isalnum((int)*p))
+ *p = '_';
+ }
+ f = fopen(argv[1], "w");
+ }
+ fprintf(f, "/* %s -- this file was generated for %s by\n", fn, HOST);
+ fprintf(f, " %*s %s */\n\n", strlen(fn), "",
+ "$KTH: bits.c,v 1.4 1998/03/28 09:24:30 lha Exp $");
+ fprintf(f, "#ifndef %s\n", hb);
+ fprintf(f, "#define %s\n", hb);
+ fprintf(f, "\n");
+#ifdef HAVE_SYS_TYPES_H
+ fprintf(f, "#include <sys/types.h>\n");
+#endif
+#ifdef HAVE_INTTYPES_H
+ fprintf(f, "#include <inttypes.h>\n");
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+ fprintf(f, "#include <sys/bitypes.h>\n");
+#endif
+#ifdef HAVE_NETINET_IN6_MACHTYPES_H
+ fprintf(f, "#include <netinet/in6_machtypes.h>\n");
+#endif
+#ifdef HAVE_KTYPES_H
+ fprintf(f, "#include <ktypes.h>\n");
+#endif
+ fprintf(f, "\n");
+
+ flag = 0;
+#ifndef HAVE_INT8_T
+ flag = print_bt(f, flag);
+ try_signed (f, 8);
+#endif /* HAVE_INT8_T */
+#ifndef HAVE_INT16_T
+ flag = print_bt(f, flag);
+ try_signed (f, 16);
+#endif /* HAVE_INT16_T */
+#ifndef HAVE_INT32_T
+ flag = print_bt(f, flag);
+ try_signed (f, 32);
+#endif /* HAVE_INT32_T */
+#if 0
+#ifndef HAVE_INT64_T
+ flag = print_bt(f, flag);
+ try_signed (f, 64);
+#endif /* HAVE_INT64_T */
+#endif
+
+#ifndef HAVE_U_INT8_T
+ flag = print_bt(f, flag);
+ try_unsigned (f, 8);
+#endif /* HAVE_INT8_T */
+#ifndef HAVE_U_INT16_T
+ flag = print_bt(f, flag);
+ try_unsigned (f, 16);
+#endif /* HAVE_U_INT16_T */
+#ifndef HAVE_U_INT32_T
+ flag = print_bt(f, flag);
+ try_unsigned (f, 32);
+#endif /* HAVE_U_INT32_T */
+#if 0
+#ifndef HAVE_U_INT64_T
+ flag = print_bt(f, flag);
+ try_unsigned (f, 64);
+#endif /* HAVE_U_INT64_T */
+#endif
+
+ if(flag){
+ fprintf(f, "\n");
+ fprintf(f, "#endif /* __BIT_TYPES_DEFINED__ */\n\n");
+ }
+ fprintf(f, "#endif /* %s */\n", hb);
+ return 0;
+}
diff --git a/usr.sbin/afs/src/include/config.h b/usr.sbin/afs/src/include/config.h
new file mode 100644
index 00000000000..4ac6990c716
--- /dev/null
+++ b/usr.sbin/afs/src/include/config.h
@@ -0,0 +1,657 @@
+/* $OpenBSD: config.h,v 1.1.1.1 1998/09/14 21:52:59 art Exp $ */
+/* include/config.h. Generated automatically by configure. */
+/* include/config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define this if we can include both sys/dir.h and dirent.h */
+#define USE_SYS_DIR_H 1
+
+/* Define this if RETSIGTYPE == void */
+/* #undef VOID_RETSIGTYPE */
+
+/* Define this if struct winsize is declared in sys/termios.h */
+#define HAVE_STRUCT_WINSIZE 1
+
+/* Define this if struct winsize have ws_xpixel */
+#define HAVE_WS_XPIXEL 1
+
+/* Define this if struct winsize have ws_ypixel */
+#define HAVE_WS_YPIXEL 1
+
+/* Define this if `struct sockaddr' includes sa_len */
+#define SOCKADDR_HAS_SA_LEN 1
+
+/* define if the system is missing a prototype for strtok_r() */
+#define NEED_STRTOK_R_PROTO 1
+
+/* define if you have h_errno */
+#define HAVE_H_ERRNO 1
+
+/* define if you have h_errlist but not hstrerror */
+#define HAVE_H_ERRLIST 1
+
+/* define if you have h_nerr but not hstrerror */
+#define HAVE_H_NERR 1
+
+/* define if your system has a declaration for h_errlist */
+/* #undef HAVE_H_ERRLIST_DECLARATION */
+
+/* define if your system has a declaration for h_nerr */
+/* #undef HAVE_H_NERR_DECLARATION */
+
+/* define if your system has a declaration for h_errno */
+#define HAVE_H_ERRNO_DECLARATION 1
+
+/* define if your system has optreset */
+#define HAVE_OPTRESET 1
+
+/* define if your system has a declaration for optreset */
+#define HAVE_OPTRESET_DECLARATION 1
+
+/* define if your compiler has __FUNCTION__ */
+#define HAVE___FUNCTION__ 1
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Check if select need a prototype */
+/* #undef NEED_SELECT_PROTO */
+
+/* Define if you have the FOUR_ARGUMENT_VFS_BUSY function. */
+#define HAVE_FOUR_ARGUMENT_VFS_BUSY 1
+
+/* Define if you have the THREE_ARGUMENT_VFS_BUSY function. */
+/* #undef HAVE_THREE_ARGUMENT_VFS_BUSY */
+
+/* Define if you have the THREE_ARGUMENT_VGET function. */
+#define HAVE_THREE_ARGUMENT_VGET 1
+
+/* Define if you have the THREE_ARGUMENT_VOP_LOCK function. */
+#define HAVE_THREE_ARGUMENT_VOP_LOCK 1
+
+/* Define if you have the TWO_ARGUMENT_VFS_GETNEWFSID function. */
+/* #undef HAVE_TWO_ARGUMENT_VFS_GETNEWFSID */
+
+/* Define if you have the TWO_ARGUMENT_VGET function. */
+/* #undef HAVE_TWO_ARGUMENT_VGET */
+
+/* Define if you have the TWO_ARGUMENT_VOP_LOCK function. */
+/* #undef HAVE_TWO_ARGUMENT_VOP_LOCK */
+
+/* Define if you have the asnprintf function. */
+/* #undef HAVE_ASNPRINTF */
+
+/* Define if you have the asprintf function. */
+#define HAVE_ASPRINTF 1
+
+/* Define if you have the chown function. */
+#define HAVE_CHOWN 1
+
+/* Define if you have the daemon function. */
+#define HAVE_DAEMON 1
+
+/* Define if you have the dbm_firstkey function. */
+#define HAVE_DBM_FIRSTKEY 1
+
+/* Define if you have the dn_expand function. */
+#define HAVE_DN_EXPAND 1
+
+/* Define if you have the el_init function. */
+#define HAVE_EL_INIT 1
+
+/* Define if you have the err function. */
+#define HAVE_ERR 1
+
+/* Define if you have the errx function. */
+#define HAVE_ERRX 1
+
+/* Define if you have the fchown function. */
+#define HAVE_FCHOWN 1
+
+/* Define if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define if you have the flock function. */
+#define HAVE_FLOCK 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getdtablesize function. */
+#define HAVE_GETDTABLESIZE 1
+
+/* Define if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define if you have the getopt function. */
+#define HAVE_GETOPT 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrlimit function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if you have the getspnam function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define if you have the getspuid function. */
+/* #undef HAVE_GETSPUID */
+
+/* Define if you have the getusershell function. */
+#define HAVE_GETUSERSHELL 1
+
+/* Define if you have the getvfsbyname function. */
+/* #undef HAVE_GETVFSBYNAME */
+
+/* Define if you have the hstrerror function. */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the inet_aton function. */
+#define HAVE_INET_ATON 1
+
+/* Define if you have the initgroups function. */
+#define HAVE_INITGROUPS 1
+
+/* Define if you have the kvm_nlist function. */
+#define HAVE_KVM_NLIST 1
+
+/* Define if you have the kvm_open function. */
+#define HAVE_KVM_OPEN 1
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mkstemp function. */
+#define HAVE_MKSTEMP 1
+
+/* Define if you have the mktime function. */
+#define HAVE_MKTIME 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the rcmd function. */
+#define HAVE_RCMD 1
+
+/* Define if you have the readline function. */
+#define HAVE_READLINE 1
+
+/* Define if you have the readv function. */
+#define HAVE_READV 1
+
+/* Define if you have the recvmsg function. */
+#define HAVE_RECVMSG 1
+
+/* Define if you have the res_search function. */
+#define HAVE_RES_SEARCH 1
+
+/* Define if you have the sendmsg function. */
+#define HAVE_SENDMSG 1
+
+/* Define if you have the setegid function. */
+#define HAVE_SETEGID 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the seteuid function. */
+#define HAVE_SETEUID 1
+
+/* Define if you have the setregid function. */
+#define HAVE_SETREGID 1
+
+/* Define if you have the setresuid function. */
+/* #undef HAVE_SETRESUID */
+
+/* Define if you have the setreuid function. */
+#define HAVE_SETREUID 1
+
+/* Define if you have the setsid function. */
+#define HAVE_SETSID 1
+
+/* Define if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define if you have the snprintf function. */
+#define HAVE_SNPRINTF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strlwr function. */
+/* #undef HAVE_STRLWR */
+
+/* Define if you have the strnlen function. */
+/* #undef HAVE_STRNLEN */
+
+/* Define if you have the strsep function. */
+#define HAVE_STRSEP 1
+
+/* Define if you have the strtok_r function. */
+/* #undef HAVE_STRTOK_R */
+
+/* Define if you have the strupr function. */
+/* #undef HAVE_STRUPR */
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the sysctl function. */
+#define HAVE_SYSCTL 1
+
+/* Define if you have the syslog function. */
+#define HAVE_SYSLOG 1
+
+/* Define if you have the tgetent function. */
+#define HAVE_TGETENT 1
+
+/* Define if you have the unsetenv function. */
+#define HAVE_UNSETENV 1
+
+/* Define if you have the vasnprintf function. */
+/* #undef HAVE_VASNPRINTF */
+
+/* Define if you have the vasprintf function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the verr function. */
+#define HAVE_VERR 1
+
+/* Define if you have the verrx function. */
+#define HAVE_VERRX 1
+
+/* Define if you have the vfsisloadable function. */
+/* #undef HAVE_VFSISLOADABLE */
+
+/* Define if you have the vfsload function. */
+/* #undef HAVE_VFSLOAD */
+
+/* Define if you have the vsnprintf function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define if you have the vsyslog function. */
+#define HAVE_VSYSLOG 1
+
+/* Define if you have the vwarn function. */
+#define HAVE_VWARN 1
+
+/* Define if you have the vwarnx function. */
+#define HAVE_VWARNX 1
+
+/* Define if you have the warn function. */
+#define HAVE_WARN 1
+
+/* Define if you have the warnx function. */
+#define HAVE_WARNX 1
+
+/* Define if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <crypt.h> header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define if you have the <dbm.h> header file. */
+/* #undef HAVE_DBM_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the <ktypes.h> header file. */
+/* #undef HAVE_KTYPES_H */
+
+/* Define if you have the <kvm.h> header file. */
+#define HAVE_KVM_H 1
+
+/* Define if you have the <libelf/nlist.h> header file. */
+/* #undef HAVE_LIBELF_NLIST_H */
+
+/* Define if you have the <linux/types.h> header file. */
+/* #undef HAVE_LINUX_TYPES_H */
+
+/* Define if you have the <miscfs/genfs/genfs.h> header file. */
+/* #undef HAVE_MISCFS_GENFS_GENFS_H */
+
+/* Define if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in6.h> header file. */
+/* #undef HAVE_NETINET_IN6_H */
+
+/* Define if you have the <netinet/in6_machtypes.h> header file. */
+/* #undef HAVE_NETINET_IN6_MACHTYPES_H */
+
+/* Define if you have the <netinet6/in6.h> header file. */
+/* #undef HAVE_NETINET6_IN6_H */
+
+/* Define if you have the <nlist.h> header file. */
+#define HAVE_NLIST_H 1
+
+/* Define if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <rpcsvc/dbm.h> header file. */
+/* #undef HAVE_RPCSVC_DBM_H */
+
+/* Define if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define if you have the <sys/bitypes.h> header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define if you have the <sys/dirent.h> header file. */
+#define HAVE_SYS_DIRENT_H 1
+
+/* Define if you have the <sys/filedesc.h> header file. */
+#define HAVE_SYS_FILEDESC_H 1
+
+/* Define if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/lkm.h> header file. */
+#define HAVE_SYS_LKM_H 1
+
+/* Define if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/proc.h> header file. */
+#define HAVE_SYS_PROC_H 1
+
+/* Define if you have the <sys/queue.h> header file. */
+#define HAVE_SYS_QUEUE_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/sysconfig.h> header file. */
+/* #undef HAVE_SYS_SYSCONFIG_H */
+
+/* Define if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define if you have the <sys/sysent.h> header file. */
+/* #undef HAVE_SYS_SYSENT_H */
+
+/* Define if you have the <sys/sysproto.h> header file. */
+/* #undef HAVE_SYS_SYSPROTO_H */
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/tty.h> header file. */
+#define HAVE_SYS_TTY_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the curses library (-lcurses). */
+/* #undef HAVE_LIBCURSES */
+
+/* Define if you have the db library (-ldb). */
+/* #undef HAVE_LIBDB */
+
+/* Define if you have the edit library (-ledit). */
+#define HAVE_LIBEDIT 1
+
+/* Define if you have the gdbm library (-lgdbm). */
+/* #undef HAVE_LIBGDBM */
+
+/* Define if you have the kvm library (-lkvm). */
+#define HAVE_LIBKVM 1
+
+/* Define if you have the ndbm library (-lndbm). */
+/* #undef HAVE_LIBNDBM */
+
+/* Define if you have the nsl library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the readline library (-lreadline). */
+/* #undef HAVE_LIBREADLINE */
+
+/* Define if you have the resolv library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define if you have the socket library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define if you have the syslog library (-lsyslog). */
+/* #undef HAVE_LIBSYSLOG */
+
+/* Define if you have the termcap library (-ltermcap). */
+#define HAVE_LIBTERMCAP 1
+
+#define HAVE_INT8_T 1
+#define HAVE_INT16_T 1
+#define HAVE_INT32_T 1
+#define HAVE_INT64_T 1
+#define HAVE_U_INT8_T 1
+#define HAVE_U_INT16_T 1
+#define HAVE_U_INT32_T 1
+#define HAVE_U_INT64_T 1
+/* #undef HAVE_BOOL */
+#define HAVE_SSIZE_T 1
+#define HAVE_REGISTER_T 1
+/* #undef HAVE_INT32 */
+/* #undef HAVE_U_INT32 */
+
+#define EFF_NTOHL ntohl
+
+/* RCSID */
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+#define VERSION "0.9"
+#define PACKAGE "arla"
+
+/* Check for posix signals */
+#define HAVE_POSIX_SIGNALS 1
+
+#define HAVE_READLINE 1
+
+/* prefix for /dev/fd */
+/* #undef DEV_FD_PREFIX */
+
+/* does the system have /dev/fd? */
+/* #undef HAVE_DEV_FD */
+
+/* we always have stds.h */
+#define HAVE_STDS_H
+
+/* We have krb_principal from kth-krb ? */
+#define HAVE_KRB_PRINCIPAL 1
+
+/* If we have _res */
+/* #undef HAVE__RES */
+
+/* Define if you have kerberos */
+#define KERBEROS 1
+
+/* Define if your kernel has a vop_nolock */
+/* #undef HAVE_KERNEL_VOP_NOLOCK */
+
+/* Define if your kernel has a vop_nounlock */
+/* #undef HAVE_KERNEL_VOP_NOUNLOCK */
+
+/* Define if your kernel has a vop_noislocked */
+/* #undef HAVE_KERNEL_VOP_NOISLOCKED */
+
+/* Define if your kernel has a vop_revoke */
+/* #undef HAVE_KERNEL_VOP_REVOKE */
+
+/* Define if your kernel has a genfs_nolock */
+/* #undef HAVE_KERNEL_GENFS_NOLOCK */
+
+/* Define if your kernel has a genfs_nounlock */
+/* #undef HAVE_KERNEL_GENFS_NOUNLOCK */
+
+/* Define if your kernel has a genfs_noislocked */
+/* #undef HAVE_KERNEL_GENFS_NOISLOCKED */
+
+/* Define if your kernel has a genfs_revoke */
+/* #undef HAVE_KERNEL_GENFS_REVOKE */
+
+/* Define if your kernel has a vfs_opv_init_default */
+#define HAVE_KERNEL_VFS_OPV_INIT_DEFAULT 1
+
+/* Define if your kernel has a vfs_attach */
+/* #undef HAVE_KERNEL_VFS_ATTACH */
+
+/* Define if your kernel has a vfs_getnewfsid */
+#define HAVE_KERNEL_VFS_GETNEWFSID 1
+
+/* Define if your kernel has a vfs_opv_init_explicit */
+#define HAVE_KERNEL_VFS_OPV_INIT_EXPLICIT 1
+
+/* Define if your struct dirent has a field d_type */
+#define HAVE_STRUCT_DIRENT_D_TYPE 1
+
+/* Define if your struct vfsconf has a field vfc_refcount */
+#define HAVE_STRUCT_VFSCONF_VFC_REFCOUNT 1
+
+/* Define if your struct uio has a field uio_procp */
+/* #undef HAVE_STRUCT_UIO_UIO_PROCP */
+
+/* Define if your struct vfsops has a field vfs_opv_descs */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_OPV_DESCS */
+
+/* Define if your struct vfsops has a field vfs_name */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_NAME */
+
+/* Define if you want to use mmap:ed time */
+/* #undef USE_MMAPTIME */
+
+/* Define if your hstrerror needs const like SunOS 5.6 */
+#define NEED_HSTRERROR_CONST 1
+
+/* Define if your hstrerror need proto */
+/* #undef NEED_HSTRERROR_PROTO */
+
+/* Define if you have gnu libc */
+/* #undef HAVE_GLIBC */
+
+/* Define this if `struct sockaddr' includes sa_len */
+#define SOCKADDR_HAS_SA_LEN 1
+
+/* Define this if htnol is broken, but can be fixed with define magic */
+/* #undef HAVE_REPAIRABLE_HTONL */
+
+/* Define this if struct ViceIoctl is defined by linux/fs.h */
+/* #undef HAVE_STRUCT_VICEIOCTL_IN */
+
+/* Linux kernel types */
+/* #undef HAVE_LINUX_KERNEL_INT8_T */
+/* #undef HAVE_LINUX_KERNEL_INT16_T */
+/* #undef HAVE_LINUX_KERNEL_INT32_T */
+/* #undef HAVE_LINUX_KERNEL_INT64_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT8_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT16_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT32_T */
+/* #undef HAVE_LINUX_KERNEL_U_INT64_T */
+
+/* Define this if you have a type vop_t */
+/* #undef HAVE_VOP_T */
+
+/* Define this is you have a vfssw */
+/* #undef HAVE_VFSSW */
+
+/* Define this if struct proc have p_sigmask */
+#define HAVE_STRUCT_PROC_P_SIGMASK 1
+
diff --git a/usr.sbin/afs/src/include/stds.h b/usr.sbin/afs/src/include/stds.h
new file mode 100644
index 00000000000..cc88d3b66dc
--- /dev/null
+++ b/usr.sbin/afs/src/include/stds.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: stds.h,v 1.1.1.1 1998/09/14 21:52:59 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: stds.h,v 1.3 1998/03/19 21:28:28 assar Exp $ */
+
+#ifndef __STDS_H
+#define __STDS_H 1
+
+#ifndef HAVE_INT32
+typedef int32_t int32;
+#endif
+
+#ifndef HAVE_U_INT32
+typedef u_int32_t u_int32;
+#endif
+
+/* for compat resons with other kerberos distributions */
+#ifndef HAVE_KRB_PRINCIPAL
+typedef struct krb_principal{
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
+}krb_principal;
+#endif
+
+#endif /* __STDS_H */
diff --git a/usr.sbin/afs/src/lib/ko/gensysname.c b/usr.sbin/afs/src/lib/ko/gensysname.c
new file mode 100644
index 00000000000..05fe0d08614
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/gensysname.c
@@ -0,0 +1,242 @@
+/* $OpenBSD: gensysname.c,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "ko_locl.h"
+
+RCSID("$KTH: gensysname.c,v 1.13 1998/08/23 22:50:24 assar Exp $");
+
+typedef int (*test_sysname)(void);
+
+struct sysname {
+ const char *sysname;
+ const char *cpu;
+ const char *vendor;
+ const char *os;
+ test_sysname atest;
+};
+
+enum { O_C, O_TEXT, O_MACHINE } output = O_TEXT;
+
+/*
+ * HELP:
+ *
+ * Add your sysname to the struct below, it's searched from top
+ * to bottom, first match wins.
+ *
+ * The test is for hosts that can not be matched with config.guess
+ * (like a linux 1.2.x/elf)
+ *
+ * ? will match any character
+ * * will match any sequence of characters
+ */
+
+static int
+linux_glibc_test(void)
+{
+ int ret;
+ struct stat sb;
+
+ ret = stat("/lib/libc.so.6", &sb);
+ return ret == 0;
+}
+
+struct sysname sysnames[] = {
+ { "sparc_nbsd13", "sparc", "*", "netbsd1.3*", NULL },
+ { "sparc_obsd23", "sparc", "*", "openbsd2.3*", NULL },
+ { "sparc_linux6", "sparc", "*", "linux-gnu*", &linux_glibc_test },
+ { "sparc_linux5", "sparc", "*", "linux-gnu*", NULL },
+ { "i386_obsd23", "i*86*", "*", "openbsd2.3*", NULL },
+ { "i386_fbsd30", "i*86*", "*", "freebsd3.0*", NULL },
+ { "i386_linux6", "i*86*", "*pc*", "linux-gnu*", &linux_glibc_test },
+ { "i386_linux5", "i*86*", "*pc*", "linux-gnu*", NULL },
+ { "alpha_linux6", "alpha", "*", "linux-gnu*", &linux_glibc_test },
+ { "alpha_linux5", "alpha", "*", "linux-gnu*", NULL },
+ { "sun4x_54", "sparc", "*", "solaris2.4*", NULL },
+ { "sun4x_551", "sparc", "*", "solaris2.5.1*", NULL },
+ { "sun4x_55", "sparc", "*", "solaris2.5*", NULL },
+ { "sun4x_56", "sparc", "*", "solaris2.6*", NULL },
+ { "sun4x_57", "sparc", "*", "solaris2.7*", NULL },
+ { "sunx86_54", "i386", "*", "solaris2.4*", NULL },
+ { "sunx86_551", "i386", "*", "solaris2.5.1*", NULL },
+ { "sunx86_55", "i386", "*", "solaris2.5*", NULL },
+ { "sunx86_56", "i386", "*", "solaris2.6*", NULL },
+ { "sunx86_57", "i386", "*", "solaris2.7*", NULL },
+ {NULL}
+};
+
+static void
+printsysname(const char *sysname)
+{
+ switch (output) {
+ case O_TEXT:
+ printf("%s\n", sysname);
+ break;
+ case O_MACHINE:
+ printf("%s\n", sysname);
+ break;
+ case O_C:
+ printf("/* Generated from $KTH: gensysname.c,v 1.13 1998/08/23 22:50:24 assar Exp $ */\n");
+ printf("const char *arla_getsysname(void) { return \"%s\" ; }\n",
+ sysname);
+ break;
+ default:
+ abort();
+ }
+
+}
+
+static int machineflag = 0;
+static int ccodeflag = 0;
+static int humanflag = 0;
+static int helpflag = 0;
+static int allflag = 0;
+static int sysnameflag = 0;
+static int versionflag = 0;
+
+struct getargs args[] = {
+ {"machine", 'm', arg_flag, &machineflag, "machine output", NULL},
+ {"human", 'h', arg_flag, &humanflag, "human", NULL},
+ {"ccode", 'c', arg_flag, &ccodeflag, "", NULL},
+ {"sysname", 's', arg_flag, &sysnameflag, NULL, NULL},
+ {"version", 'v', arg_flag, &versionflag, NULL, NULL},
+ {"all", 'a', arg_flag, &allflag, NULL, NULL},
+ {"help", 0, arg_flag, &helpflag, NULL, NULL},
+ {NULL, 0, arg_end, NULL}
+};
+
+static void
+usage(void)
+{
+ arg_printusage(args, NULL, "[sysname]");
+ exit(1);
+
+}
+
+static void
+try_parsing (int *argc, char ***argv, const char **var)
+{
+ char *p;
+
+ if (*argc > 0) {
+ p = strchr (**argv, '-');
+
+ *var = **argv;
+
+ if (p != NULL) {
+ *p = '\0';
+ **argv = p + 1;
+ } else {
+ --*argc;
+ ++*argv;
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *cpu = ARLACPU;
+ const char *vendor = ARLAVENDOR;
+ const char *os = ARLAOS;
+ struct sysname *sysname = sysnames;
+ int found = 0;
+ int optind = 0;
+
+ set_progname (argv[0]);
+
+ if (getarg (args, argc, argv, &optind, ARG_GNUSTYLE))
+ usage();
+
+ argc -= optind;
+ argv += optind;
+
+ if (helpflag)
+ usage();
+
+ if (versionflag)
+ errx(0, "Version: $KTH: gensysname.c,v 1.13 1998/08/23 22:50:24 assar Exp $");
+
+ if (ccodeflag)
+ output = O_C;
+ if (humanflag)
+ output = O_TEXT;
+ if (machineflag)
+ output = O_MACHINE;
+
+ if (sysnameflag) {
+ printf ("%s-%s-%s\n", cpu, vendor, os);
+ return 0;
+ }
+
+ if (allflag) {
+ while (sysname->sysname) {
+ printf("%-20s == %s %s %s\n",
+ sysname->sysname,
+ sysname->cpu,
+ sysname->vendor,
+ sysname->os);
+ sysname++;
+ }
+ return 0;
+ }
+
+ try_parsing (&argc, &argv, &cpu);
+ try_parsing (&argc, &argv, &vendor);
+ try_parsing (&argc, &argv, &os);
+
+ while (sysname->sysname && !found) {
+ if (!strmatch(sysname->cpu, cpu) &&
+ !strmatch(sysname->vendor, vendor) &&
+ !strmatch(sysname->os, os) &&
+ (sysname->atest == NULL || ((*(sysname->atest))()))) {
+
+ found = 1;
+ printsysname(sysname->sysname);
+ }
+ sysname++;
+ }
+
+ /* XXX need some better here? */
+ if (!found) {
+ fprintf(stderr, "our host was not found using generic\n");
+ printsysname("arlahost");
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lib/ko/ko.h b/usr.sbin/afs/src/lib/ko/ko.h
new file mode 100644
index 00000000000..58d59359eed
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/ko.h
@@ -0,0 +1,85 @@
+/* $OpenBSD: ko.h,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: ko.h,v 1.10 1998/07/25 15:18:48 map Exp $ */
+
+#ifndef __KO_H
+#define __KO_H 1
+
+#include <atypes.h>
+
+typedef int32_t koerr_t;
+
+/*
+ * Error messages
+ */
+
+const char *koerr_gettext(koerr_t err);
+
+/*
+ * sysname
+ */
+
+const char *arla_getsysname(void);
+
+
+/*
+ * Cell manglening
+ */
+
+void cell_init (int cellcachesize);
+
+struct in_addr cell_finddbserver (int32_t cell);
+u_long cell_listdbserver (int32_t cell, int index);
+const char *cell_findnamedbbyname (const char *cell);
+const char *cell_getthiscell (void);
+const char *cell_getcellbyhost(const char *host);
+int32_t cell_name2num (const char *cell);
+const char *cell_num2name (int32_t cell);
+
+/* NIY
+int cell_serverdown (struct in_addr addr);
+int cell_cellup_p (int32_t cell);
+int cell_probe(int32_t cell);
+int cell_probeserver(struct in_addr addr);
+*/
+
+#endif
+
+
diff --git a/usr.sbin/afs/src/lib/ko/ko_locl.h b/usr.sbin/afs/src/lib/ko/ko_locl.h
new file mode 100644
index 00000000000..b998d9a68ce
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/ko_locl.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: ko_locl.h,v 1.1.1.1 1998/09/14 21:52:59 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 file for whole arlad
+ * $KTH: ko_locl.h,v 1.2 1998/07/16 01:14:26 lha Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <err.h>
+#include <strings.h>
+#include <roken.h>
+#include <getarg.h>
+
+#include <hash.h>
+#include <ip.h>
+
+#include "ko.h"
+#include "kodebug.h"
+
+#include "strmatch.h"
+
+
diff --git a/usr.sbin/afs/src/lib/ko/kocell.c b/usr.sbin/afs/src/lib/ko/kocell.c
new file mode 100644
index 00000000000..47c44b01c33
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/kocell.c
@@ -0,0 +1,566 @@
+/* $OpenBSD: kocell.c,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Cell information
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+
+#ifdef KERBEROS
+#include <kerberosIV/krb.h>
+#endif
+
+#include "ko_locl.h"
+#include "resolve.h"
+
+RCSID("$KTH: kocell.c,v 1.13 1998/07/28 14:54:08 assar Exp $");
+
+#define TRANSARCSYSCONFDIR "/usr/vice/etc"
+#define CELLFILENAME "CellServDB"
+#define THISCELLFILENAME "ThisCell"
+
+#define DEFCELLCACHESIZE 499
+
+typedef struct {
+ const char *name;
+ struct in_addr addr;
+} DbServerEntry;
+
+typedef struct {
+ int32_t id; /* Cell-ID */
+ const char *name; /* Domain-style name */
+ const char *expl; /* Longer name */
+ unsigned ndbservs; /* # of database servers */
+ DbServerEntry *dbservs; /* Database servers */
+} CellEntry;
+
+/*
+ * hash tables by name and by number
+ */
+
+static Hashtab *cellnamehtab, *cellnumhtab;
+
+/*
+ * name of the current cell
+ */
+
+static char *thiscell = NULL;
+
+/*
+ * Functions for handling cell entries.
+ */
+
+static int
+cellnamecmp (void *a, void *b)
+{
+ CellEntry *c1 = (CellEntry *)a;
+ CellEntry *c2 = (CellEntry *)b;
+
+ return strcmp (c1->name, c2->name);
+}
+
+static unsigned
+cellnamehash (void *a)
+{
+ CellEntry *c = (CellEntry *)a;
+
+ return hashadd (c->name);
+}
+
+static int
+cellnumcmp (void *a, void *b)
+{
+ CellEntry *c1 = (CellEntry *)a;
+ CellEntry *c2 = (CellEntry *)b;
+
+ return c1->id != c2->id;
+}
+
+static unsigned
+cellnumhash (void *a)
+{
+ CellEntry *c = (CellEntry *)a;
+
+ return c->id;
+}
+
+/*
+ * Record this cell in the hashtable
+ */
+
+static void
+recordcell (CellEntry *c, int dbnum, DbServerEntry *dbservs)
+{
+ if(dbnum == 0)
+ KODEB (KODEBMISC, ("No db-servers for cell %s\n", c->name));
+
+ c->ndbservs = dbnum;
+ c->dbservs = (DbServerEntry*)malloc (dbnum * sizeof(DbServerEntry));
+ if (c->dbservs == NULL)
+ err (1, "malloc %u", dbnum * sizeof(DbServerEntry));
+ memcpy (c->dbservs, dbservs, dbnum * sizeof (DbServerEntry));
+
+ hashtabadd (cellnamehtab, c);
+ hashtabadd (cellnumhtab, c);
+}
+
+/*
+ * New cell from cellserver-database file
+ */
+
+static CellEntry *
+newcell (const char *line, int *dbnum)
+{
+ static long cellno = 0;
+ char *hash;
+ CellEntry *c;
+ int len;
+ char *tmp;
+
+ c = (CellEntry *)malloc (sizeof (*c));
+ if (c == NULL)
+ err (1, "malloc %u", sizeof(*c));
+ len = strcspn (line, " \t#");
+ tmp = malloc (len + 1);
+ if (tmp == NULL)
+ err (1, "strdup");
+ strncpy (tmp, line, len);
+ tmp[len] = '\0';
+ c->name = tmp;
+ if (strcmp (c->name, cell_getthiscell ()) == 0)
+ c->id = 0;
+ else
+ c->id = ++cellno;
+ line += len + 1;
+ hash = strchr (line, '#');
+ if (hash != NULL) {
+ c->expl = strdup (hash+1);
+ if (c->expl == NULL)
+ err (1, "strdup");
+ } else
+ c->expl = NULL;
+ *dbnum = 0;
+ return c;
+}
+
+/*
+ * Read one line of database information.
+ */
+
+static int
+readdb (char *line, CellEntry* c, int *dbnum, int maxdbs,
+ DbServerEntry *dbservs, int lineno)
+{
+ struct in_addr numaddr;
+ char *hostname;
+
+ if (*dbnum >= maxdbs) {
+ KODEB (KODEBMISC, ("Too many database servers for "
+ "cell %s. Ignoring\n", c->name));
+ return -1;
+ }
+ if ( (hostname = strchr (line, '#')) == NULL
+ || (numaddr.s_addr = inet_addr (line)) == -1 ) {
+ KODEB (KODEBMISC, ("Syntax error at line %d in %s\n",
+ lineno, CELLFILENAME));
+ return -1;
+ } else {
+ ++hostname;
+ dbservs[*dbnum].name = strdup (hostname);
+ if (dbservs[*dbnum].name == NULL)
+ err (1, "strdup");
+ dbservs[*dbnum].addr = numaddr;
+ ++(*dbnum);
+ }
+ return 0;
+}
+
+/*
+ * Read the information from the cell-server db.
+ */
+
+static int
+readcellservdb (const char *filename)
+{
+ FILE *f;
+ char line[256];
+ CellEntry *c = NULL;
+ int lineno = 0;
+ int dbnum;
+ DbServerEntry dbservs[256];
+
+ f = fopen (filename, "r");
+ if (f == NULL) {
+ KODEB (KODEBMISC, ("Cannot read cell information from %s\n",
+ filename));
+ return 1;
+ }
+
+ while (fgets (line, sizeof (line), f)) {
+ ++lineno;
+ if (line[strlen(line) - 1 ] != '\n')
+ KODEB (KODEBMISC, ("Too long line at line %d in %s\n",
+ lineno, filename));
+ else
+ line[strlen(line) - 1] = '\0';
+ if (*line == '#' || *line == '\0')
+ continue;
+ if (*line == '>') {
+ if (c != NULL)
+ recordcell (c, dbnum, dbservs);
+ c = newcell (line + 1, &dbnum);
+ } else {
+ if (readdb(line, c, &dbnum, sizeof (dbservs) /
+ sizeof(*dbservs),
+ dbservs, lineno))
+ continue;
+ }
+ }
+ if (c != NULL)
+ recordcell (c, dbnum, dbservs);
+ fclose (f);
+ return 0;
+}
+
+/*
+ * Read name of this cell.
+ */
+
+static int
+readthiscell (const char *filename)
+{
+ FILE *f;
+ char cell[256];
+
+ f = fopen (filename, "r");
+ if (f == NULL) {
+ fprintf(stderr, "Can't open file %s.\n", filename);
+ return 1;
+ }
+
+ if (fgets (cell, sizeof cell, f) == NULL) {
+ fprintf(stderr, "Cannot read cellname from %s\n",
+ filename);
+ return 1;
+ }
+ if (cell[strlen(cell) - 1] == '\n')
+ cell[strlen(cell) - 1] = '\0';
+ thiscell = strdup (cell);
+ if (thiscell == NULL)
+ err (1, "strdup");
+ fclose (f);
+ return 0;
+}
+
+/*
+ * Initialize the cache of cell information.
+ */
+
+void
+cell_init (int cellcachesize)
+{
+ char *env;
+
+ if (thiscell != NULL) {
+ fprintf(stderr, "cell_init: Already initlized\n");
+ return;
+ }
+
+ if (cellcachesize == 0)
+ cellcachesize = DEFCELLCACHESIZE;
+
+ cellnamehtab = hashtabnew (cellcachesize, cellnamecmp, cellnamehash);
+ if (cellnamehash == NULL)
+ errx (1, "cell_init: hashtabnew failed");
+ cellnumhtab = hashtabnew (cellcachesize, cellnumcmp, cellnumhash);
+ if (cellnumhtab == NULL)
+ errx (1, "cell_init: hashtabnew failed");
+
+ env = getenv ("AFSCELL");
+ if (env != NULL) {
+ thiscell = strdup (env);
+ if (thiscell == NULL)
+ err (1, "strdup");
+ } else if (readthiscell (SYSCONFDIR "/" THISCELLFILENAME)) {
+ fprintf(stderr, "Falling back on: " TRANSARCSYSCONFDIR "\n");
+ if (readthiscell(TRANSARCSYSCONFDIR "/" THISCELLFILENAME)) {
+ fprintf(stderr, "Don't know where I am\n");
+ exit(1);
+ }
+ }
+
+ if (readcellservdb (SYSCONFDIR "/" CELLFILENAME)) {
+ fprintf(stderr, "Falling back on: " TRANSARCSYSCONFDIR "\n");
+ if (readcellservdb(TRANSARCSYSCONFDIR "/" CELLFILENAME)) {
+ fprintf(stderr, "Can't read the CellServDB file," \
+ "will use DNS AFSDB entries\n");
+ }
+ }
+}
+
+/*
+ * Find a DB server to talk to for a given cell.
+ */
+
+struct in_addr
+cell_finddbserver (int32_t cell)
+{
+ CellEntry key;
+ CellEntry *data;
+ struct in_addr addr;
+
+ key.id = cell;
+ data = hashtabsearch (cellnumhtab, &key);
+ if (data == NULL) {
+ KODEB (KODEBMISC, ("Cannot find cell %d\n", cell));
+ return addr;
+ }
+ if (data->ndbservs == 0) {
+ KODEB (KODEBMISC, ("No DB servers for cell %d\n", cell));
+ return addr;
+ }
+ if (ipgetaddr (data->dbservs[0].name, &addr))
+ return addr;
+ else
+ return data->dbservs[0].addr;
+}
+
+/*
+ * Return DB server number "index" for a given cell.
+ */
+
+u_long
+cell_listdbserver (int32_t cell, int index)
+{
+ CellEntry key;
+ CellEntry *data;
+ struct in_addr addr;
+
+ key.id = cell;
+ data = hashtabsearch (cellnumhtab, &key);
+ if (data == NULL) {
+ KODEB (KODEBMISC, ("Cannot find cell %d\n", cell));
+ return 0;
+ }
+ if (data->ndbservs <= index) {
+ return 0;
+ }
+ if (ipgetaddr (data->dbservs[index].name, &addr))
+ return addr.s_addr;
+ else
+ return data->dbservs[index].addr.s_addr;
+}
+
+
+/*
+ * Find the name of DB server to talk to for a given cell.
+ *
+ * Warning: This is not really good since name could be something
+ * like NULL.
+ */
+
+const char *
+cell_findnamedbbyname (const char *cell)
+{
+ CellEntry key;
+ CellEntry *data;
+
+ key.name = cell;
+ data = hashtabsearch (cellnamehtab, &key);
+ if (data == NULL) {
+ KODEB (KODEBMISC, ("Cannot find cell %d\n", cell));
+ return NULL;
+ }
+ if (data->ndbservs == 0) {
+ KODEB (KODEBMISC, ("No DB servers for cell %d\n", cell));
+ return NULL;
+ }
+ return data->dbservs[0].name ;
+}
+
+static void
+try_to_find_cell(const char *cell)
+{
+ struct dns_reply *r;
+ struct resource_record *rr;
+ CellEntry *c = NULL;
+ int dbnum;
+ DbServerEntry dbservs[256];
+
+ r = dns_lookup(cell, "AFSDB");
+ if (r == NULL)
+ return;
+ for(rr = r->head; rr;rr=rr->next){
+ switch(rr->type){
+ case T_AFSDB: {
+ struct mx_record *mx = (struct mx_record*)rr->u.data;
+
+ if (mx->preference != 1) {
+ KODEB (KODEBMISC,
+ ("Ignoring host with cell type %d in cell %s",
+ mx->preference, c->name));
+ break;
+ }
+ if (c == NULL)
+ c = newcell (cell, &dbnum);
+ if (dbnum >= sizeof (dbservs) / sizeof(*dbservs)) {
+ KODEB (KODEBMISC, ("Too many database servers for "
+ "cell %s. Ignoring\n", c->name));
+ break;
+ }
+ dbservs[dbnum].name = strdup (mx->domain);
+ if (dbservs[dbnum].name == NULL)
+ err (1, "strdup");
+ dbservs[dbnum].addr.s_addr = inet_addr ("0.0.0.0");
+ ++dbnum;
+ break;
+ }
+ }
+ }
+ for(rr = r->head; rr;rr=rr->next){
+ int i;
+
+ switch(rr->type){
+ case T_A: {
+ for (i = 0; i < dbnum; i++) {
+ if (strcmp(dbservs[i].name,rr->domain) == 0) {
+ dbservs[i].addr = *(rr->u.a);
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (c)
+ recordcell (c, dbnum, dbservs);
+ dns_free_data(r);
+}
+
+
+/*
+ * Get the cell of the host
+ */
+
+const char *
+cell_getcellbyhost(const char *host)
+{
+ const char *ptr = NULL;
+ assert(host);
+
+#ifdef KERBEROS
+ ptr = krb_realmofhost(host);
+#endif
+ if (ptr)
+ return ptr;
+
+ ptr = host;
+ while(*ptr && *ptr != '.') ptr++;
+
+ if (*ptr == '\0')
+ return NULL;
+
+ return strdup(ptr);
+}
+
+/*
+ * Return the ID given the name for a cell.
+ * -1 if the cell does not exist.
+ */
+
+int32_t
+cell_name2num (const char *cell)
+{
+ CellEntry key, *data;
+
+ key.name = cell;
+ data = hashtabsearch (cellnamehtab, (void *)&key);
+ if (data)
+ return data->id;
+ else {
+ try_to_find_cell(cell);
+ data = hashtabsearch (cellnamehtab, (void *)&key);
+ if (data)
+ return data->id;
+ else
+ return -1;
+ }
+}
+
+/*
+ * Return the name given the ID or NULL if the cell doesn't exist.
+ */
+
+const char *
+cell_num2name (int32_t cell)
+{
+ CellEntry key, *data;
+
+ key.id = cell;
+ data = hashtabsearch (cellnumhtab, (void *)&key);
+ if (data)
+ return data->name;
+ else
+ return NULL;
+}
+
+/*
+ * Return name of the cell of the cache manager.
+ */
+
+const char *
+cell_getthiscell (void)
+{
+ return thiscell;
+}
diff --git a/usr.sbin/afs/src/lib/ko/kodebug.c b/usr.sbin/afs/src/lib/ko/kodebug.c
new file mode 100644
index 00000000000..c18921d140a
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/kodebug.c
@@ -0,0 +1,53 @@
+/* $OpenBSD: kodebug.c,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "ko_locl.h"
+
+RCSID("$KTH: kodebug.c,v 1.1 1998/03/02 18:48:03 lha Exp $");
+
+/* X is on */
+#define X(y) y
+/* and x is off */
+#define x(y) 0
+
+int arladeb = (0
+ | X(KODEBMISC)
+ | x(KODEBTEMP)
+ | X(KODEBINIT)
+ );
diff --git a/usr.sbin/afs/src/lib/ko/kodebug.h b/usr.sbin/afs/src/lib/ko/kodebug.h
new file mode 100644
index 00000000000..54565cef455
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/kodebug.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: kodebug.h,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: kodebug.h,v 1.1 1998/03/02 18:48:03 lha Exp $ */
+
+#ifndef _kodeb_h
+#define _kodeb_h
+
+#include <stdio.h>
+
+/* masks */
+#define KODEBANY 0xffffffff
+#define KODEBMISC 0x00000001
+#define KODEBTEMP 0x00000002
+#define KODEBINIT 0x00000008 /* initialization debug */
+
+extern int kodeb;
+
+#ifdef DEBUG
+#define KODEB(mask, args) do { if (mask&arladeb) printf args; } while (0)
+#else
+#define KODEB(mask, args) do { ; } while (0)
+#endif
+
+#endif /* _kodeb_h */
diff --git a/usr.sbin/afs/src/lib/ko/koerror.c b/usr.sbin/afs/src/lib/ko/koerror.c
new file mode 100644
index 00000000000..984ad841248
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/koerror.c
@@ -0,0 +1,160 @@
+/* $OpenBSD: koerror.c,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: koerror.c,v 1.7 1998/04/03 03:36:32 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <roken.h>
+
+#include <vldb.h>
+#include <volumeserver.h>
+#ifdef KERBEROS
+#include <kerberosIV/krb.h>
+#include <des.h>
+#include <rxkad.h>
+#endif
+#include <ko.h>
+
+
+struct koerr {
+ koerr_t code;
+ const char *msg;
+};
+
+static struct koerr koerrmsg[] = {
+
+ /* VL server errors */
+
+ {VL_IDEXIST, "Volume Id entry exists in vl database."},
+ {VL_IO, "I/O related error."},
+ {VL_NAMEEXIST, "Volume name entry exists in vl database."},
+ {VL_CREATEFAIL, "Internal creation failure."},
+ {VL_NOENT, "No such entry."},
+ {VL_EMPTY, "Vl database is empty."},
+ {VL_ENTDELETED, "Entry is deleted (soft delete)."},
+ {VL_BADNAME, "Volume name is illegal."},
+ {VL_BADINDEX, "Index is out of range."},
+ {VL_BADVOLTYPE, "Bad volume type."},
+ {VL_BADPARTITION, "Illegal server number (out of range)."},
+ {VL_BADSERVER, "Bad partition number."},
+ {VL_REPSFULL, "Run out of space for Replication sites."},
+ {VL_NOREPSERVER, "No such Replication server site exists."},
+ {VL_DUPREPSERVER, "Replication site alreay exists."},
+ {VL_RWNOTFOUND, "Parent R/W entry no found."},
+ {VL_BADREFCOUNT, "Illegal reference count numner."},
+ {VL_SIZEEXCEEDED, "Vl size for attributes exceeded."},
+ {VL_BADENTRY, "Bad incming vl entry."},
+ {VL_BADVOLIDBUMP, "Illegal max volid increment."},
+ {VL_IDALREADHASED, "RO/BACK id already hashed."},
+ {VL_ENTRYLOCKED, "Vl entry is already locked."},
+ {VL_BADVOLOPER, "Bad volume operation code."},
+ {VL_BADRELLOCKTYPE, "Bad release lock type."},
+ {VL_RERELEASE, "Status report: last release was aborted."},
+ {VL_BADSERVERFLAG, "Invalid replication site server flag."},
+ {VL_PERM, "No permission access."},
+ {VL_NOMEM, "malloc(realloc) failed to alloc enough memory"},
+
+ /* VOLSER errors */
+
+ {VOLSERTRELE_ERROR, "Internal error releasing transaction."},
+ {VOLSERNO_OP, "Unknown internal error."},
+ {VOLSERREAD_DUMPERROR, "Badly formatted dump."},
+ {VOLSERDUMPERROR, "Badly formatted dump(2)."},
+ {VOLSERATTACH_ERROR, "Could not attach volume."},
+ {VOLSERILLEGAL_PARTITION, "Illegal partition."},
+ {VOLSERDETACH_ERROR, "Could not detach volume."},
+ {VOLSERBAD_ACCESS, "Insufficient privilege for volume operation."},
+ {VOLSERVLDB_ERROR, "Error from volume location database."},
+ {VOLSERBADNAME, "Bad volume name."},
+ {VOLSERVOLMOVED, "Volume moved."},
+ {VOLSERBADOP, "Illegal volume operation."},
+ {VOLSERBADRELEASE, "Volume release failed."},
+ {VOLSERVOLBUSY, "Volume still in use by volserver."},
+ {VOLSERNO_MEMORY, "Out of virtual memory."},
+ {VOLSERNOVOL, "No such volume."},
+ {VOLSERMULTIRWVOL, "More then one read/write volume."},
+ {VOLSERFAILEDOP, "Failed volume server operation."},
+
+#ifdef KERBEROS
+ /* rxkad - XXX more sane messages */
+
+ {RXKADINCONSISTENCY, "rxkad - Inconsistency."},
+ {RXKADPACKETSHORT, "rxkad - Packet too short."},
+ {RXKADLEVELFAIL, "rxkad - Security level failed."},
+ {RXKADTICKETLEN, "rxkad - Invaild ticket length."},
+ {RXKADOUTOFSEQUENCE, "rxkad - Out of sequence."},
+ {RXKADNOAUTH, "rxkad - No authentication."},
+ {RXKADBADKEY, "rxkad - Bad key."},
+ {RXKADBADTICKET, "rxkad - Bad ticket."},
+ {RXKADUNKNOWNKEY, "rxkad - Unknown key."},
+ {RXKADEXPIRED, "rxkad - Ticket expired."},
+ {RXKADSEALEDINCON, "rxkad - Seal inconsistency."},
+ {RXKADDATALEN, "rxkad - Datalength error."},
+ {RXKADILLEGALLEVEL, "rxkad - Illegal level."},
+
+#endif
+
+ /* Not a known error */
+
+ { 0L, "Unknown error"}
+};
+
+
+
+const char *
+koerr_gettext(koerr_t err)
+{
+ struct koerr *koerror = koerrmsg;
+
+ while (koerror->code != 0) {
+ if (err == koerror->code)
+ break;
+ ++koerror;
+ }
+
+ if (koerror->code)
+ return koerror->msg;
+ else
+ return strerror(err);
+}
diff --git a/usr.sbin/afs/src/lib/ko/ports.c b/usr.sbin/afs/src/lib/ko/ports.c
new file mode 100644
index 00000000000..c1398dcb8b8
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/ports.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: ports.c,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Take care of the port stuff.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <roken.h>
+#include <stdio.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+RCSID("$KTH: ports.c,v 1.5 1998/06/07 05:44:38 map Exp $") ;
+
+typedef struct {
+ const char *name; /* Name of the service */
+ const char *proto; /* Protocol */
+ int *port; /* Variable with port-value */
+ int defport; /* Default port */
+} Port;
+
+int afsport, afscallbackport, afsprport, afsvldbport,
+ afskaport, afsvolport, afserrorsport, afsbosport,
+ afsupdateport, afsrmtsys ;
+
+Port ports[] = {
+{"afs3-fileserver", "udp", &afsport, 7000},
+{"afs3-callback", "udp", &afscallbackport,7001},
+{"afs3-prserver", "udp", &afsprport, 7002},
+{"afs3-vlserver", "udp", &afsvldbport, 7003},
+{"afs3-kaserver", "udp", &afskaport, 7004},
+{"afs3-volser", "udp", &afsvolport, 7005},
+{"afs3-errors", "udp", &afserrorsport, 7006},
+{"afs3-bos", "udp", &afsbosport, 7007},
+{"afs3-update", "udp", &afsupdateport, 7008},
+{"afs3-rmtsys", "udp", &afsrmtsys, 7009}
+};
+
+/*
+ * Find all ports and set their values.
+ */
+
+void
+initports (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (ports) / sizeof (*ports); ++i) {
+ struct servent *service;
+
+ service = getservbyname (ports[i].name, ports[i].proto);
+ if (service == NULL) {
+
+ fprintf (stderr,
+ "Unable to find service %s/%s, using port %d\n",
+ ports[i].name, ports[i].proto, ports[i].defport);
+ *(ports[i].port) = ports[i].defport;
+ } else
+ *(ports[i].port) = ntohs (service->s_port);
+ }
+}
diff --git a/usr.sbin/afs/src/lib/ko/ports.h b/usr.sbin/afs/src/lib/ko/ports.h
new file mode 100644
index 00000000000..5d9767ffb35
--- /dev/null
+++ b/usr.sbin/afs/src/lib/ko/ports.h
@@ -0,0 +1,55 @@
+/* $OpenBSD: ports.h,v 1.1.1.1 1998/09/14 21:53:00 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: ports.h,v 1.1 1998/04/02 19:34:12 lha Exp $ */
+
+/*
+ * Port numbers.
+ */
+
+#ifndef _PORTS_H_
+#define _PORTS_H_
+
+extern int afsport, afscallbackport, afsprport, afsvldbport,
+ afskaport, afsvolport, afserrorsport, afsbosport,
+ afsupdateport, afsrmtsys ;
+
+void initports (void);
+
+#endif /* _PORTS_H_ */
diff --git a/usr.sbin/afs/src/lib/roken/ChangeLog b/usr.sbin/afs/src/lib/roken/ChangeLog
new file mode 100644
index 00000000000..e3d47a877dd
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/ChangeLog
@@ -0,0 +1,29 @@
+Sun Nov 9 04:48:46 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * fnmatch.c: Add fnmatch from NetBSD
+
+Sun Nov 9 02:00:08 1997 Assar Westerlund <assar@sics.se>
+
+ * parse_units.c (parse_something): ignore white-space and ','
+
+Mon Nov 3 22:38:32 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: fclose prototype
+
+ * roken.h: add prototype for vsyslog
+
+ * Makefile.in: add some more source files to make soriasis make
+ happy
+
+Sat Nov 1 00:19:21 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: include <sys/uio.h> and <errno.h>.
+ prototypes for readv and writev
+
+ * readv.c, writev.c: new files
+
+Wed Oct 29 02:21:38 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: Add ugly macros for openlog, gethostbyname,
+ gethostbyaddr, and getservbyname for the benefit of Crays. Add
+ default definition of MAXPATHLEN
diff --git a/usr.sbin/afs/src/lib/roken/base64.c b/usr.sbin/afs/src/lib/roken/base64.c
new file mode 100644
index 00000000000..14fc3b2a2a9
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/base64.c
@@ -0,0 +1,150 @@
+/* $OpenBSD: base64.c,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: base64.c,v 1.1 1998/01/13 16:25:15 lha Exp $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "base64.h"
+
+static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int pos(char c)
+{
+ char *p;
+ for(p = base64; *p; p++)
+ if(*p == c)
+ return p - base64;
+ return -1;
+}
+
+int base64_encode(const void *data, int size, char **str)
+{
+ char *s, *p;
+ int i;
+ int c;
+ unsigned char *q;
+
+ p = s = (char*)malloc(size*4/3+4);
+ q = (unsigned char*)data;
+ i=0;
+ for(i = 0; i < size;){
+ c=q[i++];
+ c*=256;
+ if(i < size)
+ c+=q[i];
+ i++;
+ c*=256;
+ if(i < size)
+ c+=q[i];
+ i++;
+ p[0]=base64[(c&0x00fc0000) >> 18];
+ p[1]=base64[(c&0x0003f000) >> 12];
+ p[2]=base64[(c&0x00000fc0) >> 6];
+ p[3]=base64[(c&0x0000003f) >> 0];
+ if(i > size)
+ p[3]='=';
+ if(i > size+1)
+ p[2]='=';
+ p+=4;
+ }
+ *p=0;
+ *str = s;
+ return strlen(s);
+}
+
+int base64_decode(const char *str, void *data)
+{
+ const char *p;
+ unsigned char *q;
+ int c;
+ int x;
+ int done = 0;
+ q=(unsigned char*)data;
+ for(p=str; *p && !done; p+=4){
+ x = pos(p[0]);
+ if(x >= 0)
+ c = x;
+ else{
+ done = 3;
+ break;
+ }
+ c*=64;
+
+ x = pos(p[1]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ c*=64;
+
+ if(p[2] == '=')
+ done++;
+ else{
+ x = pos(p[2]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ c*=64;
+
+ if(p[3] == '=')
+ done++;
+ else{
+ if(done)
+ return -1;
+ x = pos(p[3]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ if(done < 3)
+ *q++=(c&0x00ff0000)>>16;
+
+ if(done < 2)
+ *q++=(c&0x0000ff00)>>8;
+ if(done < 1)
+ *q++=(c&0x000000ff)>>0;
+ }
+ return q - (unsigned char*)data;
+}
diff --git a/usr.sbin/afs/src/lib/roken/base64.h b/usr.sbin/afs/src/lib/roken/base64.h
new file mode 100644
index 00000000000..0af453ead4e
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/base64.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: base64.h,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: base64.h,v 1.1 1998/01/13 16:25:15 lha Exp $ */
+
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+int base64_encode(const void *data, int size, char **str);
+int base64_decode(const char *str, void *data);
+
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/chown.c b/usr.sbin/afs/src/lib/roken/chown.c
new file mode 100644
index 00000000000..8a1f9f7cb94
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/chown.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: chown.c,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: chown.c,v 1.1 1998/01/13 16:25:16 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int
+chown(const char *path, uid_t owner, gid_t group)
+{
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lib/roken/daemon.c b/usr.sbin/afs/src/lib/roken/daemon.c
new file mode 100644
index 00000000000..5bf55a7fd70
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/daemon.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: daemon.c,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: daemon.c,v 1.1 1998/01/13 16:25:16 lha Exp $");
+
+#ifndef HAVE_DAEMON
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int
+daemon(int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1)
+ return (-1);
+
+ if (!nochdir)
+ chdir("/");
+
+ if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close (fd);
+ }
+ return (0);
+}
+
+#endif /* HAVE_DAEMON */
diff --git a/usr.sbin/afs/src/lib/roken/err.c b/usr.sbin/afs/src/lib/roken/err.c
new file mode 100644
index 00000000000..47b3e54e004
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/err.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: err.c,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: err.c,v 1.1 1998/01/13 16:25:17 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verr(eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/err.h b/usr.sbin/afs/src/lib/roken/err.h
new file mode 100644
index 00000000000..25b4f61eaea
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/err.h
@@ -0,0 +1,77 @@
+/* $OpenBSD: err.h,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: err.h,v 1.2 1998/05/01 20:21:15 assar Exp $ */
+
+#ifndef __ERR_H__
+#define __ERR_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern const char *__progname;
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+void warnerr(int doexit, int eval, int doerrno, const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 4, 0)));
+
+void verr(int eval, const char *fmt, va_list ap)
+ __attribute__ ((noreturn, format (printf, 2, 0)));
+void err(int eval, const char *fmt, ...)
+ __attribute__ ((noreturn, format (printf, 2, 3)));
+void verrx(int eval, const char *fmt, va_list ap)
+ __attribute__ ((noreturn, format (printf, 2, 0)));
+void errx(int eval, const char *fmt, ...)
+ __attribute__ ((noreturn, format (printf, 2, 3)));
+void vwarn(const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 1, 0)));
+void warn(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void vwarnx(const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 1, 0)));
+void warnx(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif /* __ERR_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/errx.c b/usr.sbin/afs/src/lib/roken/errx.c
new file mode 100644
index 00000000000..24bfe87c642
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/errx.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: errx.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: errx.c,v 1.1 1998/01/13 16:25:18 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/fchown.c b/usr.sbin/afs/src/lib/roken/fchown.c
new file mode 100644
index 00000000000..3160447da21
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/fchown.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: fchown.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: fchown.c,v 1.1 1998/01/13 16:25:18 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int
+fchown(int fd, uid_t owner, gid_t group)
+{
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lib/roken/flock.c b/usr.sbin/afs/src/lib/roken/flock.c
new file mode 100644
index 00000000000..7cdb2a3a638
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/flock.c
@@ -0,0 +1,93 @@
+/* $OpenBSD: flock.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: flock.c,v 1.1 1998/01/13 16:25:19 lha Exp $");
+#endif
+
+#include "roken.h"
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN)
+
+int
+flock(int fd, int operation)
+{
+#if defined(HAVE_FCNTL) && defined(F_SETLK)
+ struct flock arg;
+ int code, cmd;
+
+ arg.l_whence = SEEK_SET;
+ arg.l_start = 0;
+ arg.l_len = 0; /* means to EOF */
+
+ if (operation & LOCK_NB)
+ cmd = F_SETLK;
+ else
+ cmd = F_SETLKW; /* Blocking */
+
+ switch (operation & OP_MASK) {
+ case LOCK_UN:
+ arg.l_type = F_UNLCK;
+ code = fcntl(fd, F_SETLK, &arg);
+ break;
+ case LOCK_SH:
+ arg.l_type = F_RDLCK;
+ code = fcntl(fd, cmd, &arg);
+ break;
+ case LOCK_EX:
+ arg.l_type = F_WRLCK;
+ code = fcntl(fd, cmd, &arg);
+ break;
+ default:
+ errno = EINVAL;
+ code = -1;
+ break;
+ }
+ return code;
+#else
+ return -1;
+#endif
+}
diff --git a/usr.sbin/afs/src/lib/roken/fnmatch.c b/usr.sbin/afs/src/lib/roken/fnmatch.c
new file mode 100644
index 00000000000..88dce509a51
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/fnmatch.c
@@ -0,0 +1,174 @@
+/* $OpenBSD: fnmatch.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/* $NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $ */
+
+/*
+ * 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
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with 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(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
+#else
+static char rcsid[] = "$NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include <fnmatch.h>
+#include <string.h>
+
+#define EOS '\0'
+
+static const char *rangematch (const char *, int, int);
+
+int
+fnmatch(const char *pattern, const char *string, int flags)
+{
+ const char *stringstart;
+ char c, test;
+
+ for (stringstart = string;;)
+ switch (c = *pattern++) {
+ case EOS:
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS)
+ if (flags & FNM_PATHNAME)
+ return (strchr(string, '/') == NULL ?
+ 0 : FNM_NOMATCH);
+ else
+ return (0);
+ else if (c == '/' && flags & FNM_PATHNAME) {
+ if ((string = strchr(string, '/')) == NULL)
+ return (FNM_NOMATCH);
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
+ return (0);
+ if (test == '/' && flags & FNM_PATHNAME)
+ break;
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && flags & FNM_PATHNAME)
+ return (FNM_NOMATCH);
+ if ((pattern =
+ rangematch(pattern, *string, flags)) == NULL)
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ if (c != *string++)
+ return (FNM_NOMATCH);
+ break;
+ }
+ /* NOTREACHED */
+}
+
+static const char *
+rangematch(const char *pattern, int test, int flags)
+{
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if (negate = (*pattern == '!' || *pattern == '^'))
+ ++pattern;
+
+ for (ok = 0; (c = *pattern++) != ']';) {
+ if (c == '\\' && !(flags & FNM_NOESCAPE))
+ c = *pattern++;
+ if (c == EOS)
+ return (NULL);
+ if (*pattern == '-'
+ && (c2 = *(pattern+1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+ c2 = *pattern++;
+ if (c2 == EOS)
+ return (NULL);
+ if (c <= test && test <= c2)
+ ok = 1;
+ } else if (c == test)
+ ok = 1;
+ }
+ return (ok == negate ? NULL : pattern);
+}
diff --git a/usr.sbin/afs/src/lib/roken/fnmatch.h b/usr.sbin/afs/src/lib/roken/fnmatch.h
new file mode 100644
index 00000000000..9f84d5474a9
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/fnmatch.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: fnmatch.h,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */
+
+/*-
+ * 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.
+ *
+ * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _FNMATCH_H_
+#define _FNMATCH_H_
+
+#define FNM_NOMATCH 1 /* Match failed. */
+
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+
+int fnmatch (const char *, const char *, int);
+
+#endif /* !_FNMATCH_H_ */
diff --git a/usr.sbin/afs/src/lib/roken/get_window_size.c b/usr.sbin/afs/src/lib/roken/get_window_size.c
new file mode 100644
index 00000000000..f4efcbc18f3
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/get_window_size.c
@@ -0,0 +1,97 @@
+/* $OpenBSD: get_window_size.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: get_window_size.c,v 1.1 1998/01/13 16:25:20 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if 0 /* Where were those needed? /confused */
+#ifdef HAVE_SYS_PROC_H
+#include <sys/proc.h>
+#endif
+
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#include <roken.h>
+
+int
+get_window_size(int fd, struct winsize *wp)
+{
+#if defined(TIOCGWINSZ)
+ return ioctl(fd, TIOCGWINSZ, wp);
+#elif defined(TIOCGSIZE)
+ 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;
+#elif defined(HAVE__SCRSIZE)
+ int dst[2];
+
+ _scrsize(dst);
+ wp->ws_row = dst[1];
+ wp->ws_col = dst[0];
+ wp->ws_xpixel = 0;
+ wp->ws_ypixel = 0;
+ return 0;
+#else
+ return -1;
+#endif
+}
diff --git a/usr.sbin/afs/src/lib/roken/getarg.c b/usr.sbin/afs/src/lib/roken/getarg.c
new file mode 100644
index 00000000000..eb1bd324a47
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getarg.c
@@ -0,0 +1,474 @@
+/* $OpenBSD: getarg.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getarg.c,v 1.9 1998/08/23 22:47:54 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <roken.h>
+#include "getarg.h"
+
+#define ISFLAG(X) ((X)->type == arg_flag || (X)->type == arg_negative_flag)
+
+static size_t
+print_arg (FILE *stream, int mdoc, int longp, struct getargs *arg)
+{
+ const char *s = NULL;
+
+ if (ISFLAG(arg))
+ return 0;
+
+ if(mdoc){
+ if(longp)
+ fprintf(stream, "= Ns");
+ fprintf(stream, " Ar ");
+ }else
+ if (longp)
+ putc ('=', stream);
+ else
+ putc (' ', stream);
+
+ if (arg->arg_help)
+ s = arg->arg_help;
+ else if (arg->type == arg_integer)
+ s = "number";
+ else if (arg->type == arg_string)
+ s = "string";
+ else
+ s = "<undefined>";
+
+ fprintf (stream, "%s", s);
+ return 1 + strlen(s);
+}
+
+static void
+mandoc_template(struct getargs *args,
+ const char *extra_string)
+{
+ int i;
+ struct getargs *arg;
+ char timestr[64], cmd[64];
+ const char *p;
+ time_t t;
+
+ printf(".\\\" Things to fix:\n");
+ printf(".\\\" * correct section, and operating system\n");
+ printf(".\\\" * remove Op from mandatory flags\n");
+ printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
+ printf(".\\\"\n");
+ t = time(NULL);
+ strftime(timestr, sizeof(timestr), "%b %d, %Y", localtime(&t));
+ printf(".Dd %s\n", timestr);
+ p = strrchr(__progname, '/');
+ if(p) p++; else p = __progname;
+ strncpy(cmd, p, sizeof(cmd));
+ cmd[sizeof(cmd)-1] = '\0';
+ strupr(cmd);
+
+ printf(".Dt %s SECTION\n", cmd);
+ printf(".Os OPERATING_SYSTEM\n");
+ printf(".Sh NAME\n");
+ printf(".Nm %s\n", p);
+ printf(".Nd\n");
+ printf("in search of a description\n");
+ printf(".Sh SYNOPSIS\n");
+ printf(".Nm\n");
+ for(arg = args; arg->type; arg++) {
+ if(arg->short_name){
+ printf(".Op Fl %c", arg->short_name);
+ print_arg(stdout, 1, 0, args + i);
+ printf("\n");
+ }
+ if(arg->long_name){
+ printf(".Op Fl -%s", arg->long_name);
+ print_arg(stdout, 1, 1, args + i);
+ printf("\n");
+ }
+ /*
+ if(arg->type == arg_strings)
+ fprintf (stderr, "...");
+ */
+ }
+ if (extra_string && *extra_string)
+ printf (".Ar %s\n", extra_string);
+ printf(".Sh DESCRIPTION\n");
+ printf("Supported options:\n");
+ printf(".Bl -tag -width Ds\n");
+ for(arg = args; arg->type; arg++) {
+ if(arg->short_name){
+ printf(".It Fl %c", arg->short_name);
+ print_arg(stdout, 1, 0, args + i);
+ printf("\n");
+ }
+ if(arg->long_name){
+ printf(".It Fl -%s", arg->long_name);
+ print_arg(stdout, 1, 1, args + i);
+ printf("\n");
+ }
+ if(arg->help)
+ printf("%s\n", arg->help);
+ /*
+ if(arg->type == arg_strings)
+ fprintf (stderr, "...");
+ */
+ }
+ printf(".El\n");
+ printf(".\\\".Sh ENVIRONMENT\n");
+ printf(".\\\".Sh FILES\n");
+ printf(".\\\".Sh EXAMPLES\n");
+ printf(".\\\".Sh DIAGNOSTICS\n");
+ printf(".\\\".Sh SEE ALSO\n");
+ printf(".\\\".Sh STANDARDS\n");
+ printf(".\\\".Sh HISTORY\n");
+ printf(".\\\".Sh AUTHORS\n");
+ printf(".\\\".Sh BUGS\n");
+}
+
+void
+arg_printusage (struct getargs *args,
+ const char *progname,
+ const char *extra_string)
+{
+ struct getargs *arg;
+ size_t max_len = 0;
+
+ if(getenv("GETARGMANDOC")){
+ mandoc_template(args, extra_string);
+ return;
+ }
+ fprintf (stderr, "Usage: %s", __progname);
+ for (arg = args; arg->type; arg++) {
+ size_t len = 0;
+
+ if (arg->long_name) {
+ fprintf (stderr, " [--");
+ if (arg->type == arg_negative_flag) {
+ fprintf (stderr, "no-");
+ len += 3;
+ }
+ fprintf (stderr, "%s", arg->long_name);
+ len += 2 + strlen(arg->long_name);
+ len += print_arg (stderr, 0, 1, arg);
+ putc (']', stderr);
+ if(arg->type == arg_strings)
+ fprintf (stderr, "...");
+ }
+ if (arg->short_name) {
+ len += 2;
+ fprintf (stderr, " [-%c", arg->short_name);
+ len += print_arg (stderr, 0, 0, arg);
+ putc (']', stderr);
+ if(arg->type == arg_strings)
+ fprintf (stderr, "...");
+ }
+ if (arg->long_name && arg->short_name)
+ len += 4;
+ max_len = max(max_len, len);
+ }
+ if (extra_string)
+ fprintf (stderr, " %s\n", extra_string);
+ else
+ fprintf (stderr, "\n");
+ for (arg = args; arg->type; arg++) {
+ if (arg->help) {
+ size_t count = 0;
+
+ if (arg->short_name) {
+ fprintf (stderr, "-%c", arg->short_name);
+ count += 2;
+ count += print_arg (stderr, 0, 0, arg);
+ }
+ if (arg->short_name && arg->long_name) {
+ fprintf (stderr, " or ");
+ count += 4;
+ }
+ if (arg->long_name) {
+ fprintf (stderr, "--");
+ if (arg->type == arg_negative_flag) {
+ fprintf (stderr, "no-");
+ count += 3;
+ }
+ fprintf (stderr, "%s", arg->long_name);
+ count += 2 + strlen(arg->long_name);
+ count += print_arg (stderr, 0, 1, arg);
+ }
+ while(count++ <= max_len)
+ putc (' ', stderr);
+ fprintf (stderr, "%s\n", arg->help);
+ }
+ }
+}
+
+static void
+add_string(getarg_strings *s, char *value)
+{
+ s->strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings));
+ s->strings[s->num_strings] = value;
+ s->num_strings++;
+}
+
+static int
+parse_option(struct getargs *arg, char *optarg, int negate)
+{
+ switch(arg->type){
+ case arg_integer:
+ {
+ int tmp;
+ if(sscanf(optarg, "%d", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(int*)arg->value = tmp;
+ return 0;
+ }
+ case arg_string:
+ {
+ *(char**)arg->value = optarg;
+ return 0;
+ }
+ case arg_strings:
+ {
+ add_string((getarg_strings*)arg->value, optarg);
+ return 0;
+ }
+ case arg_flag:
+ case arg_negative_flag:
+ {
+ int *flag = arg->value;
+ if(*optarg == '\0' ||
+ strcmp(optarg, "yes") == 0 ||
+ strcmp(optarg, "true") == 0){
+ *flag = !negate;
+ return 0;
+ } else if (*optarg && strcmp(optarg, "maybe") == 0) {
+ *flag = rand() & 1;
+ } else {
+ *flag = negate;
+ return 0;
+ }
+ return ARG_ERR_BAD_ARG;
+ }
+ default:
+ abort ();
+ }
+}
+
+
+static int
+arg_match_long(struct getargs *args,
+ char **argv, int style)
+{
+ char *optarg = NULL;
+ int negate = 0;
+ int partial_match = 0;
+ struct getargs *partial = NULL;
+ struct getargs *current = NULL;
+ struct getargs *arg;
+ int argv_len;
+ char *p, *q;
+
+ if (style & ARG_LONGARG)
+ q = *argv + 2;
+ else if (style & ARG_TRANSLONG)
+ q = *argv + 1;
+ else
+ q = *argv;
+
+ argv_len = strlen(q);
+ p = strchr (q, '=');
+ if (p != NULL)
+ argv_len = p - q;
+
+ for (arg = args; arg->type ; arg++) {
+ if(arg->long_name) {
+ int len = strlen(arg->long_name);
+ char *p = q;
+ int p_len = argv_len;
+ negate = 0;
+
+ for (;;) {
+ if (strncmp (arg->long_name, p, len) == 0) {
+ current = arg;
+ if (style & ARG_TRANSLONG && *(argv +1))
+ optarg = *(argv + 1);
+ else if(p[len] == '\0')
+ optarg = p + len;
+ else
+ optarg = p + len + 1;
+ } else if (strncmp (arg->long_name,
+ p,
+ p_len) == 0) {
+ ++partial_match;
+ partial = arg;
+ optarg = p + p_len +1 ;
+ } else if (ISFLAG(arg) && strncmp (p, "no-", 3) == 0) {
+ negate = !negate;
+ p += 3;
+ p_len -= 3;
+ continue;
+ }
+ break;
+ }
+ if (current)
+ break;
+ }
+ }
+ if (current == NULL) {
+ if (partial_match == 1)
+ current = partial;
+ else
+ return ARG_ERR_NO_MATCH;
+ }
+
+ if(*optarg == '\0' && !ISFLAG(current))
+ return ARG_ERR_NO_MATCH;
+
+ return parse_option(current, optarg, negate);
+}
+
+int
+getarg(struct getargs *args,
+ int argc, char **argv, int *optind, int style)
+{
+ int i, j;
+ struct getargs *arg;
+ int ret = 0;
+ int swcount = *optind;
+
+ srand (time(NULL));
+ (*optind)++;
+ for(i = *optind; i < argc; i++) {
+ if(argv[i][0] != '-' && swcount != -1) {
+ if (!(style & ARG_SWITCHLESS))
+ break;
+ ret = parse_option(&args[swcount], argv[i], 0);
+ if (ret)
+ return ret;
+ swcount++;
+ } else if(argv[i][1] == '-' ||
+ ((style & ARG_TRANSLONG) && argv[i][1] != 0)) {
+ if(argv[i][2] == 0 && !(style & ARG_TRANSLONG)){
+ i++;
+ break;
+ }
+ swcount = -1;
+ ret = arg_match_long (args, &argv[i], style);
+ if(ret)
+ return ret;
+ if (style & ARG_TRANSLONG && argv[i+1])
+ ++i;
+ }else if (style & ARG_SHORTARG) {
+ for(j = 1; argv[i][j]; j++) {
+ for(arg = args; arg->type; arg++) {
+ char *optarg;
+ if(arg->short_name == 0)
+ continue;
+ if(argv[i][j] == arg->short_name){
+ if(arg->type == arg_flag){
+ *(int*)arg->value = 1;
+ break;
+ }
+ if(arg->type == arg_negative_flag){
+ *(int*)arg->value = 0;
+ break;
+ }
+ if(argv[i][j + 1])
+ optarg = &argv[i][j + 1];
+ else{
+ i++;
+ optarg = argv[i];
+ }
+ if(optarg == NULL)
+ return ARG_ERR_NO_ARG;
+ if(arg->type == arg_integer){
+ int tmp;
+ if(sscanf(optarg, "%d", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(int*)arg->value = tmp;
+ goto out;
+ }else if(arg->type == arg_string){
+ *(char**)arg->value = optarg;
+ goto out;
+ }else if(arg->type == arg_strings){
+ add_string((getarg_strings*)arg->value, optarg);
+ goto out;
+ }
+ return ARG_ERR_BAD_ARG;
+ }
+
+ }
+ if (!arg->type)
+ return ARG_ERR_NO_MATCH;
+ }
+ out:;
+ }
+ }
+ *optind = i;
+ return 0;
+}
+
+#if TEST
+int foo_flag = 2;
+int flag1 = 0;
+int flag2 = 0;
+int bar_int;
+char *baz_string;
+
+struct getargs args[] = {
+ { NULL, '1', arg_flag, &flag1, "one", NULL },
+ { NULL, '2', arg_flag, &flag2, "two", NULL },
+ { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
+ { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
+ { "baz", 'x', arg_string, &baz_string, "baz", "name" },
+ { NULL, 0, arg_end, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ int optind = 0;
+ while(getarg(args, 5, argc, argv, &optind))
+ printf("Bad arg: %s\n", argv[optind]);
+ printf("flag1 = %d\n", flag1);
+ printf("flag2 = %d\n", flag2);
+ printf("foo_flag = %d\n", foo_flag);
+ printf("bar_int = %d\n", bar_int);
+ printf("baz_flag = %s\n", baz_string);
+ arg_printusage (args, 5, argv[0], "nothing here");
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/getarg.h b/usr.sbin/afs/src/lib/roken/getarg.h
new file mode 100644
index 00000000000..bb35ec6cf98
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getarg.h
@@ -0,0 +1,87 @@
+/* $OpenBSD: getarg.h,v 1.1.1.1 1998/09/14 21:53:01 art Exp $ */
+/*
+ * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: getarg.h,v 1.5 1998/08/23 22:47:26 assar Exp $ */
+
+#ifndef __GETARG_H__
+#define __GETARG_H__
+
+#include <stddef.h>
+
+#define ARG_DEFAULT 0x0 /* ARG_GNUSTYLE */
+#define ARG_LONGARG 0x1 /* --foo=bar */
+#define ARG_SHORTARG 0x2 /* -abc a, b and c are all three flags */
+#define ARG_TRANSLONG 0x4 /* Incompatible with {SHORT,LONG}ARG */
+#define ARG_SWITCHLESS 0x8 /* No switches */
+#define ARG_SUBOPTION 0xF /* For manpage generation */
+
+#define ARG_GNUSTYLE (ARG_LONGARG|ARG_SHORTARG)
+#define ARG_AFSSTYLE (ARG_TRANSLONG|ARG_SWITCHLESS)
+
+struct getargs{
+ const char *long_name;
+ char short_name;
+ enum { arg_end = 0, arg_integer, arg_string,
+ arg_flag, arg_negative_flag, arg_strings,
+ arg_generic } type;
+ void *value;
+ const char *help;
+ const char *arg_help;
+ enum { arg_optional = 0, arg_mandatory } mandatoryp;
+};
+
+enum {
+ ARG_ERR_NO_MATCH = 1,
+ ARG_ERR_BAD_ARG,
+ ARG_ERR_NO_ARG
+};
+
+typedef struct getarg_strings {
+ int num_strings;
+ char **strings;
+} getarg_strings;
+
+int getarg(struct getargs *args,
+ int argc, char **argv, int *optind, int style);
+
+void arg_printusage (struct getargs *args,
+ const char *progname,
+ const char *extra_string);
+
+#endif /* __GETARG_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/getcwd.c b/usr.sbin/afs/src/lib/roken/getcwd.c
new file mode 100644
index 00000000000..8e70d0880ab
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getcwd.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: getcwd.c,v 1.1.1.1 1998/09/14 21:53:02 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getcwd.c,v 1.1 1998/01/13 16:25:22 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "roken.h"
+
+char*
+getcwd(char *path, size_t size)
+{
+ char xxx[MaxPathLen];
+ char *ret;
+ ret = getwd(xxx);
+ if(ret)
+ strncpy(path, xxx, size);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/lib/roken/getdtablesize.c b/usr.sbin/afs/src/lib/roken/getdtablesize.c
new file mode 100644
index 00000000000..1494e6bc69f
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getdtablesize.c
@@ -0,0 +1,107 @@
+/* $OpenBSD: getdtablesize.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getdtablesize.c,v 1.1 1998/01/13 16:25:22 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+int getdtablesize(void)
+{
+ int files = -1;
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ files = sysconf(_SC_OPEN_MAX);
+#else /* !defined(HAVE_SYSCONF) */
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ struct rlimit res;
+ if (getrlimit(RLIMIT_NOFILE, &res) == 0)
+ files = res.rlim_cur;
+#else /* !definded(HAVE_GETRLIMIT) */
+#if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_MAXFILES)
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_MAXFILES;
+ len = sizeof(files);
+ sysctl(&mib, 2, &files, sizeof(nfil), NULL, 0);
+#endif /* defined(HAVE_SYSCTL) */
+#endif /* !definded(HAVE_GETRLIMIT) */
+#endif /* !defined(HAVE_SYSCONF) */
+
+#ifdef OPEN_MAX
+ if (files < 0)
+ files = OPEN_MAX;
+#endif
+
+#ifdef NOFILE
+ if (files < 0)
+ files = NOFILE;
+#endif
+
+ return files;
+}
diff --git a/usr.sbin/afs/src/lib/roken/getopt.c b/usr.sbin/afs/src/lib/roken/getopt.c
new file mode 100644
index 00000000000..ea0225619e9
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getopt.c
@@ -0,0 +1,129 @@
+/* $OpenBSD: getopt.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1987, 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(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifndef __STDC__
+#define const
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * get option letter from argument vector
+ */
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+ char *p;
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return(EOF);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return(EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means EOF.
+ */
+ if (optopt == (int)'-')
+ return(EOF);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':') {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ fprintf(stderr, "%s: illegal option -- %c\n",
+ p, optopt);
+ }
+ return(BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ if (*ostr == ':')
+ return(BADARG);
+ if (opterr)
+ fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ p, optopt);
+ return(BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return(optopt); /* dump back option letter */
+}
diff --git a/usr.sbin/afs/src/lib/roken/getusershell.c b/usr.sbin/afs/src/lib/roken/getusershell.c
new file mode 100644
index 00000000000..04827cfe0b6
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/getusershell.c
@@ -0,0 +1,161 @@
+/* $OpenBSD: getusershell.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: getusershell.c,v 1.2 1998/02/12 01:01:58 assar Exp $");
+
+#ifndef HAVE_GETUSERSHELL
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef _PATH_CSHELL
+#define _PATH_CSHELL "/bin/csh"
+#endif
+
+/*
+ * Local shells should NOT be added here. They should be added in
+ * /etc/shells.
+ */
+
+static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
+static char **curshell, **shells, *strings;
+static char **initshells (void);
+
+/*
+ * Get a list of shells from _PATH_SHELLS, if it exists.
+ */
+char *
+getusershell()
+{
+ char *ret;
+
+ if (curshell == NULL)
+ curshell = initshells();
+ ret = *curshell;
+ if (ret != NULL)
+ curshell++;
+ return (ret);
+}
+
+void
+endusershell()
+{
+
+ if (shells != NULL)
+ free(shells);
+ shells = NULL;
+ if (strings != NULL)
+ free(strings);
+ strings = NULL;
+ curshell = NULL;
+}
+
+void
+setusershell()
+{
+
+ curshell = initshells();
+}
+
+static char **
+initshells()
+{
+ char **sp, *cp;
+ FILE *fp;
+ struct stat statb;
+
+ if (shells != NULL)
+ free(shells);
+ shells = NULL;
+ if (strings != NULL)
+ free(strings);
+ strings = NULL;
+ if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
+ return (okshells);
+ if (fstat(fileno(fp), &statb) == -1) {
+ fclose(fp);
+ return (okshells);
+ }
+ if ((strings = malloc((u_int)statb.st_size)) == NULL) {
+ fclose(fp);
+ return (okshells);
+ }
+ shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
+ if (shells == NULL) {
+ fclose(fp);
+ free(strings);
+ strings = NULL;
+ return (okshells);
+ }
+ sp = shells;
+ cp = strings;
+ while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
+ while (*cp != '#' && *cp != '/' && *cp != '\0')
+ cp++;
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ *sp++ = cp;
+ while (!isspace(*cp) && *cp != '#' && *cp != '\0')
+ cp++;
+ *cp++ = '\0';
+ }
+ *sp = NULL;
+ fclose(fp);
+ return (shells);
+}
+#endif /* HAVE_GETUSERSHELL */
diff --git a/usr.sbin/afs/src/lib/roken/hstrerror.c b/usr.sbin/afs/src/lib/roken/hstrerror.c
new file mode 100644
index 00000000000..a4234044d76
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/hstrerror.c
@@ -0,0 +1,93 @@
+/* $OpenBSD: hstrerror.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: hstrerror.c,v 1.2 1998/03/28 23:16:45 rb Exp $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE_HSTRERROR
+
+#include <stdio.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifndef HAVE_H_ERRNO
+int h_errno = -17; /* Some magic number */
+#endif
+
+#if !(defined(HAVE_H_ERRLIST) && defined(HAVE_H_NERR))
+static const char *const h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /* 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /* 2 TRY_AGAIN */
+ "Unknown server error", /* 3 NO_RECOVERY */
+ "No address associated with name", /* 4 NO_ADDRESS */
+};
+
+static
+const
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+#else
+
+#ifndef HAVE_H_ERRLIST_DECLARATION
+extern const char *h_errlist[];
+extern int h_nerr;
+#endif
+
+#endif
+
+#ifdef NEED_HSTRERROR_CONST
+const
+#endif
+char *
+hstrerror(int herr)
+{
+ if (0 <= herr && herr < h_nerr)
+ return (char *) h_errlist[herr];
+ else if(herr == -17)
+ return "unknown error";
+ else
+ return "Error number out of range (hstrerror)";
+}
+
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/inaddr2str.c b/usr.sbin/afs/src/lib/roken/inaddr2str.c
new file mode 100644
index 00000000000..87f40e27bab
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/inaddr2str.c
@@ -0,0 +1,96 @@
+/* $OpenBSD: inaddr2str.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: inaddr2str.c,v 1.1 1998/01/13 16:25:24 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include "roken.h"
+
+/*
+ * Get a verified name for `addr'.
+ * If unable to find it in the DNS, return x.y.z.a
+ */
+
+void
+inaddr2str(struct in_addr addr, char *s, size_t len)
+{
+ struct hostent *h;
+ char *p;
+
+ h = roken_gethostbyaddr ((const char *)&addr, sizeof(addr), AF_INET);
+ if (h) {
+ h = roken_gethostbyname (h->h_name);
+ if(h)
+ while ((p = *(h->h_addr_list)++))
+ if (memcmp (p, &addr, sizeof(addr)) == 0) {
+ strncpy (s, h->h_name, len);
+ s[len - 1] = '\0';
+ return;
+ }
+ }
+ strncpy (s, inet_ntoa (addr), len);
+ s[len - 1] = '\0';
+ return;
+}
diff --git a/usr.sbin/afs/src/lib/roken/inet_aton.c b/usr.sbin/afs/src/lib/roken/inet_aton.c
new file mode 100644
index 00000000000..f17d78cedc6
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/inet_aton.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: inet_aton.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: inet_aton.c,v 1.1 1998/01/13 16:25:25 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+/* Minimal implementation of inet_aton.
+ * Cannot distinguish between failure and a local broadcast address. */
+
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ addr->s_addr = inet_addr(cp);
+ return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/initgroups.c b/usr.sbin/afs/src/lib/roken/initgroups.c
new file mode 100644
index 00000000000..477f623f40c
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/initgroups.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: initgroups.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: initgroups.c,v 1.1 1998/01/13 16:25:25 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int
+initgroups(const char *name, gid_t basegid)
+{
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lib/roken/k_getpwnam.c b/usr.sbin/afs/src/lib/roken/k_getpwnam.c
new file mode 100644
index 00000000000..7e61f921b60
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/k_getpwnam.c
@@ -0,0 +1,70 @@
+/* $OpenBSD: k_getpwnam.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: k_getpwnam.c,v 1.1 1998/01/13 16:25:26 lha Exp $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd *
+k_getpwnam (char *user)
+{
+ struct passwd *p;
+
+ p = getpwnam (user);
+#ifdef HAVE_GETSPNAM
+ if(p)
+ {
+ struct spwd *spwd;
+
+ spwd = getspnam (user);
+ if (spwd)
+ p->pw_passwd = spwd->sp_pwdp;
+ endspent ();
+ }
+#else
+ endpwent ();
+#endif
+ return p;
+}
diff --git a/usr.sbin/afs/src/lib/roken/k_getpwuid.c b/usr.sbin/afs/src/lib/roken/k_getpwuid.c
new file mode 100644
index 00000000000..c75789a52aa
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/k_getpwuid.c
@@ -0,0 +1,70 @@
+/* $OpenBSD: k_getpwuid.c,v 1.1.1.1 1998/09/14 21:53:05 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: k_getpwuid.c,v 1.1 1998/01/13 16:25:27 lha Exp $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd *
+k_getpwuid (uid_t uid)
+{
+ struct passwd *p;
+
+ p = getpwuid (uid);
+#ifdef HAVE_GETSPUID
+ if (p)
+ {
+ struct spwd *spwd;
+
+ spwd = getspuid (uid);
+ if (spwd)
+ p->pw_passwd = spwd->sp_pwdp;
+ endspent ();
+ }
+#else
+ endpwent ();
+#endif
+ return p;
+}
diff --git a/usr.sbin/afs/src/lib/roken/lstat.c b/usr.sbin/afs/src/lib/roken/lstat.c
new file mode 100644
index 00000000000..3289c5dbb57
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/lstat.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: lstat.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: lstat.c,v 1.1 1998/01/13 16:25:27 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int
+lstat(const char *path, struct stat *buf)
+{
+ return stat(path, buf);
+}
diff --git a/usr.sbin/afs/src/lib/roken/memmove.c b/usr.sbin/afs/src/lib/roken/memmove.c
new file mode 100644
index 00000000000..c815e599408
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/memmove.c
@@ -0,0 +1,70 @@
+/* $OpenBSD: memmove.c,v 1.1.1.1 1998/09/14 21:53:03 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: memmove.c,v 1.1 1998/01/13 16:25:28 lha Exp $");
+#endif
+
+/*
+ * memmove for systems that doesn't have it
+ */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+void* memmove(void *s1, const void *s2, size_t n)
+{
+ char *s=(char*)s2, *d=(char*)s1;
+
+ if(d > s){
+ s+=n-1;
+ d+=n-1;
+ while(n){
+ *d--=*s--;
+ n--;
+ }
+ }else if(d < s)
+ while(n){
+ *d++=*s++;
+ n--;
+ }
+ return s1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/mini_inetd.c b/usr.sbin/afs/src/lib/roken/mini_inetd.c
new file mode 100644
index 00000000000..6e5f6f17baf
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/mini_inetd.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: mini_inetd.c,v 1.1.1.1 1998/09/14 21:53:05 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: mini_inetd.c,v 1.3 1998/02/11 01:33:46 assar Exp $");
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+
+#include <roken.h>
+
+void
+mini_inetd (int port)
+{
+ struct sockaddr_in sa;
+ int s;
+ int s2;
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if(s < 0) {
+ perror("socket");
+ exit(1);
+ }
+#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
+ {
+ int one = 1;
+
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
+ sizeof(one)) < 0){
+ perror("setsockopt");
+ exit(1);
+ }
+ }
+#endif
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = port;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ if(bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0){
+ perror("bind");
+ exit(1);
+ }
+ if(listen(s, SOMAXCONN) < 0){
+ perror("listen");
+ exit(1);
+ }
+ s2 = accept(s, NULL, 0);
+ if(s2 < 0){
+ perror("accept");
+ exit(1);
+ }
+ close(s);
+ dup2(s2, STDIN_FILENO);
+ dup2(s2, STDOUT_FILENO);
+ /* dup2(s2, STDERR_FILENO); */
+ close(s2);
+}
diff --git a/usr.sbin/afs/src/lib/roken/mkstemp.c b/usr.sbin/afs/src/lib/roken/mkstemp.c
new file mode 100644
index 00000000000..99c7b83cf4a
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/mkstemp.c
@@ -0,0 +1,90 @@
+/* $OpenBSD: mkstemp.c,v 1.1.1.1 1998/09/14 21:53:05 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+
+RCSID("$KTH: mkstemp.c,v 1.1 1998/01/13 16:25:29 lha Exp $");
+
+#ifndef HAVE_MKSTEMP
+
+int
+mkstemp(char *template)
+{
+ int start, i;
+ pid_t val;
+ val = getpid();
+ start = strlen(template) - 1;
+ while(template[start] == 'X') {
+ template[start] = '0' + val % 10;
+ val /= 10;
+ start--;
+ }
+
+ do{
+ int fd;
+ fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if(fd >= 0 || errno != EEXIST)
+ return fd;
+ i = start + 1;
+ do{
+ if(template[i] == 0)
+ return -1;
+ template[i]++;
+ if(template[i] == '9' + 1)
+ template[i] = 'a';
+ if(template[i] <= 'z')
+ break;
+ template[i] = 'a';
+ i++;
+ }while(1);
+ }while(1);
+}
+
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/parse_time.c b/usr.sbin/afs/src/lib/roken/parse_time.c
new file mode 100644
index 00000000000..8e0c8140664
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/parse_time.c
@@ -0,0 +1,72 @@
+/* $OpenBSD: parse_time.c,v 1.1.1.1 1998/09/14 21:53:05 art Exp $ */
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_time.c,v 1.1 1998/01/13 16:25:29 lha Exp $");
+#endif
+
+#include <parse_units.h>
+#include "parse_time.h"
+
+static units time_units[] = {
+ {"year", 365 * 24 * 60 * 60},
+ {"month", 30 * 24 * 60 * 60},
+ {"week", 7 * 24 * 60 * 60},
+ {"day", 24 * 60 * 60},
+ {"hour", 60 * 60},
+ {"h", 60 * 60},
+ {"minute", 60},
+ {"m", 60},
+ {"second", 1},
+ {"s", 1},
+ {NULL, 0},
+};
+
+int
+parse_time (const char *s, const char *def_unit)
+{
+ return parse_units (s, time_units, def_unit);
+}
+
+size_t
+unparse_time (int t, char *s, size_t len)
+{
+ return unparse_units (t, time_units, s, len);
+}
diff --git a/usr.sbin/afs/src/lib/roken/parse_time.h b/usr.sbin/afs/src/lib/roken/parse_time.h
new file mode 100644
index 00000000000..f81f510eeb3
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/parse_time.h
@@ -0,0 +1,51 @@
+/* $OpenBSD: parse_time.h,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: parse_time.h,v 1.1 1998/01/13 16:25:30 lha Exp $ */
+
+#ifndef __PARSE_TIME_H__
+#define __PARSE_TIME_H__
+
+int
+parse_time (const char *s, const char *def_unit);
+
+size_t
+unparse_time (int t, char *s, size_t len);
+
+#endif /* __PARSE_TIME_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/parse_units.c b/usr.sbin/afs/src/lib/roken/parse_units.c
new file mode 100644
index 00000000000..3e9a36dfe7a
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/parse_units.c
@@ -0,0 +1,325 @@
+/* $OpenBSD: parse_units.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_units.c,v 1.3 1998/03/21 14:51:05 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <roken.h>
+#include "parse_units.h"
+
+/*
+ * Parse string in `s' according to `units' and return value.
+ * def_unit defines the default unit.
+ */
+
+static int
+parse_something (const char *s, const struct units *units,
+ const char *def_unit,
+ int (*func)(int res, int val, unsigned mult),
+ int init,
+ int accept_no_val_p)
+{
+ const char *p;
+ int res = init;
+ unsigned def_mult = 1;
+
+ if (def_unit != NULL) {
+ const struct units *u;
+
+ for (u = units; u->name; ++u) {
+ if (strcasecmp (u->name, def_unit) == 0) {
+ def_mult = u->mult;
+ break;
+ }
+ }
+ if (u->name == NULL)
+ return -1;
+ }
+
+ p = s;
+ while (*p) {
+ double val;
+ char *next;
+ const struct units *u, *partial_unit;
+ size_t u_len;
+ unsigned partial;
+
+ while(isspace(*p) || *p == ',')
+ ++p;
+
+ val = strtod (p, &next); /* strtol(p, &next, 0); */
+ if (val == 0 && p == next) {
+ if(accept_no_val_p)
+ val = 1;
+ else
+ return -1;
+ }
+ p = next;
+ while (isspace(*p))
+ ++p;
+ if (*p == '\0') {
+ res = (*func)(res, val, def_mult);
+ if (res < 0)
+ return res;
+ break;
+ } else if (*p == '+') {
+ ++p;
+ } else if (*p == '-') {
+ ++p;
+ val = -1;
+ }
+ u_len = strcspn (p, ", \t");
+ partial = 0;
+ partial_unit = NULL;
+ if (u_len > 1 && p[u_len - 1] == 's')
+ --u_len;
+ for (u = units; u->name; ++u) {
+ if (strncasecmp (p, u->name, u_len) == 0) {
+ if (u_len == strlen (u->name)) {
+ p += u_len;
+ res = (*func)(res, val, u->mult);
+ if (res < 0)
+ return res;
+ break;
+ } else {
+ ++partial;
+ partial_unit = u;
+ }
+ }
+ }
+ if (u->name == NULL) {
+ if (partial == 1) {
+ p += u_len;
+ res = (*func)(res, val, partial_unit->mult);
+ if (res < 0)
+ return res;
+ } else {
+ return -1;
+ }
+ }
+ if (*p == 's')
+ ++p;
+ }
+ return res;
+}
+
+/*
+ * The string consists of a sequence of `n unit'
+ */
+
+static int
+acc_units(int res, int val, unsigned mult)
+{
+ return res + val * mult;
+}
+
+int
+parse_units (const char *s, const struct units *units,
+ const char *def_unit)
+{
+ return parse_something (s, units, def_unit, acc_units, 0, 0);
+}
+
+/*
+ * The string consists of a sequence of `[+-]flag'. `orig' consists
+ * the original set of flags, those are then modified and returned as
+ * the function value.
+ */
+
+static int
+acc_flags(int res, int val, unsigned mult)
+{
+ if(val == 1)
+ return res | mult;
+ else if(val == -1)
+ return res & ~mult;
+ else
+ return -1;
+}
+
+int
+parse_flags (const char *s, const struct units *units,
+ int orig)
+{
+ return parse_something (s, units, NULL, acc_flags, orig, 1);
+}
+
+/*
+ * Return a string representation according to `units' of `num' in `s'
+ * with maximum length `len'. The actual length is the function value.
+ */
+
+static size_t
+unparse_something (int num, const struct units *units, char *s, size_t len,
+ int (*print) (char *s, size_t len, int div,
+ const char *name, int rem),
+ int (*update) (int in, unsigned mult),
+ const char *zero_string)
+{
+ const struct units *u;
+ size_t ret = 0, tmp;
+
+ if (num == 0)
+ return snprintf (s, len, "%s", zero_string);
+
+ for (u = units; num > 0 && u->name; ++u) {
+ int div;
+
+ div = num / u->mult;
+ if (div) {
+ num = (*update) (num, u->mult);
+ tmp = (*print) (s, len, div, u->name, num);
+
+ len -= tmp;
+ s += tmp;
+ ret += tmp;
+ }
+ }
+ return ret;
+}
+
+static int
+print_unit (char *s, size_t len, int div, const char *name, int rem)
+{
+ return snprintf (s, len, "%u %s%s%s",
+ div, name,
+ div == 1 ? "" : "s",
+ rem > 0 ? " " : "");
+}
+
+static int
+update_unit (int in, unsigned mult)
+{
+ return in % mult;
+}
+
+static int
+update_unit_approx (int in, unsigned mult)
+{
+ if (in / mult > 0)
+ return 0;
+ else
+ return update_unit (in, mult);
+}
+
+size_t
+unparse_units (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_unit,
+ update_unit,
+ "0");
+}
+
+size_t
+unparse_units_approx (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_unit,
+ update_unit_approx,
+ "0");
+}
+
+void
+print_units_table (const struct units *units, FILE *f)
+{
+ const struct units *u, *u2;
+ unsigned max_sz = 0;
+
+ for (u = units; u->name; ++u) {
+ max_sz = max(max_sz, strlen(u->name));
+ }
+
+ for (u = units; u->name;) {
+ char buf[1024];
+ const struct units *next;
+
+ for (next = u + 1; next->name && next->mult == u->mult; ++next)
+ ;
+
+ if (next->name) {
+ for (u2 = next;
+ u2->name && u->mult % u2->mult != 0;
+ ++u2)
+ ;
+ if (u2->name == NULL)
+ --u2;
+ unparse_units (u->mult, u2, buf, sizeof(buf));
+ fprintf (f, "1 %*s = %s\n", max_sz, u->name, buf);
+ } else {
+ fprintf (f, "1 %s\n", u->name);
+ }
+ u = next;
+ }
+}
+
+static int
+print_flag (char *s, size_t len, int div, const char *name, int rem)
+{
+ return snprintf (s, len, "%s%s", name, rem > 0 ? ", " : "");
+}
+
+static int
+update_flag (int in, unsigned mult)
+{
+ return in - mult;
+}
+
+size_t
+unparse_flags (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_flag,
+ update_flag,
+ "");
+}
+
+void
+print_flags_table (const struct units *units, FILE *f)
+{
+ const struct units *u;
+
+ for(u = units; u->name; ++u)
+ fprintf(f, "%s%s", u->name, (u+1)->name ? ", " : "\n");
+}
diff --git a/usr.sbin/afs/src/lib/roken/parse_units.h b/usr.sbin/afs/src/lib/roken/parse_units.h
new file mode 100644
index 00000000000..5b727492680
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/parse_units.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: parse_units.h,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: parse_units.h,v 1.2 1998/03/21 14:51:22 assar Exp $ */
+
+#ifndef __PARSE_UNITS_H__
+#define __PARSE_UNITS_H__
+
+#include <stdio.h>
+#include <stddef.h>
+
+struct units {
+ const char *name;
+ unsigned mult;
+};
+
+typedef struct units units;
+
+int
+parse_units (const char *s, const struct units *units,
+ const char *def_unit);
+
+void
+print_units_table (const struct units *units, FILE *f);
+
+int
+parse_flags (const char *s, const struct units *units,
+ int orig);
+
+size_t
+unparse_units (int num, const struct units *units, char *s, size_t len);
+
+size_t
+unparse_units_approx (int num, const struct units *units, char *s,
+ size_t len);
+
+size_t
+unparse_flags (int num, const struct units *units, char *s, size_t len);
+
+void
+print_flags_table (const struct units *units, FILE *f);
+
+#endif /* __PARSE_UNITS_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/putenv.c b/usr.sbin/afs/src/lib/roken/putenv.c
new file mode 100644
index 00000000000..4011144ba50
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/putenv.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: putenv.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: putenv.c,v 1.1 1998/01/13 16:25:31 lha Exp $");
+#endif
+
+#include <stdlib.h>
+
+extern char **environ;
+
+/*
+ * putenv --
+ * String points to a string of the form name=value.
+ *
+ * Makes the value of the environment variable name equal to
+ * value by altering an existing variable or creating a new one.
+ */
+int putenv(const char *string)
+{
+ int i;
+ int len;
+
+ len = string - strchr(string, '=') + 1;
+
+ if(environ == NULL){
+ environ = malloc(sizeof(char*));
+ if(environ == NULL)
+ return 1;
+ environ[0] = NULL;
+ }
+
+ for(i = 0; environ[i]; i++)
+ if(strncmp(string, environ[i], len)){
+ environ[len] = string;
+ return 0;
+ }
+ environ = realloc(environ, sizeof(char*) * (i + 1));
+ if(environ == NULL)
+ return 1;
+ environ[i] = string;
+ environ[i+1] = NULL;
+ return 0;
+}
+
diff --git a/usr.sbin/afs/src/lib/roken/rcmd.c b/usr.sbin/afs/src/lib/roken/rcmd.c
new file mode 100644
index 00000000000..d2b739d0c2c
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/rcmd.c
@@ -0,0 +1,58 @@
+/* $OpenBSD: rcmd.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: rcmd.c,v 1.1 1998/01/13 16:25:32 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <stdio.h>
+
+int
+rcmd(char **ahost,
+ unsigned short inport,
+ const char *locuser,
+ const char *remuser,
+ const char *cmd,
+ int *fd2p)
+{
+ fprintf(stderr, "Only kerberized services are implemented\n");
+ return -1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/readv.c b/usr.sbin/afs/src/lib/roken/readv.c
new file mode 100644
index 00000000000..3e300b7bbbe
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/readv.c
@@ -0,0 +1,73 @@
+/* $OpenBSD: readv.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: readv.c,v 1.1 1998/01/13 16:25:32 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t
+readv(int d, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret, nb;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+
+ for(i = 0; i < iovcnt; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ nb = ret = read (d, buf, tot);
+ p = buf;
+ while (nb > 0) {
+ ssize_t cnt = min(nb, iov->iov_len);
+
+ memcpy (iov->iov_base, p, cnt);
+ p += cnt;
+ nb -= cnt;
+ }
+ free(buf);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/lib/roken/recvmsg.c b/usr.sbin/afs/src/lib/roken/recvmsg.c
new file mode 100644
index 00000000000..6e08c3c7dac
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/recvmsg.c
@@ -0,0 +1,74 @@
+/* $OpenBSD: recvmsg.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: recvmsg.c,v 1.1 1998/03/29 01:24:44 assar Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t
+recvmsg(int s, struct msghdr *msg, int flags)
+{
+ ssize_t ret, nb;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+ struct iovec *iov = msg->msg_iov;
+
+ for(i = 0; i < msg->msg_iovlen; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ nb = ret = recvfrom (s, buf, tot, flags, msg->msg_name, &msg->msg_namelen);
+ p = buf;
+ while (nb > 0) {
+ ssize_t cnt = min(nb, iov->iov_len);
+
+ memcpy (iov->iov_base, p, cnt);
+ p += cnt;
+ nb -= cnt;
+ }
+ free(buf);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/lib/roken/resolve.c b/usr.sbin/afs/src/lib/roken/resolve.c
new file mode 100644
index 00000000000..70bbfbe33e2
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/resolve.c
@@ -0,0 +1,346 @@
+/* $OpenBSD: resolve.c,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include "resolve.h"
+
+RCSID("$KTH: resolve.c,v 1.6 1998/04/27 20:13:43 assar Exp $");
+
+#if defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND)
+
+#define DECL(X) {#X, T_##X}
+
+static struct stot{
+ char *name;
+ int type;
+}stot[] = {
+ DECL(A),
+ DECL(NS),
+ DECL(CNAME),
+ DECL(PTR),
+ DECL(MX),
+ DECL(TXT),
+ DECL(AFSDB),
+ DECL(SRV),
+ {NULL, 0}
+};
+
+int _resolve_debug;
+
+static int
+string_to_type(const char *name)
+{
+ struct stot *p = stot;
+ for(p = stot; p->name; p++)
+ if(strcasecmp(name, p->name) == 0)
+ return p->type;
+ return -1;
+}
+
+
+void
+dns_free_data(struct dns_reply *r)
+{
+ struct resource_record *rr;
+ if(r->q.domain)
+ free(r->q.domain);
+ for(rr = r->head; rr;){
+ struct resource_record *tmp = rr;
+ if(rr->domain)
+ free(rr->domain);
+ if(rr->u.data)
+ free(rr->u.data);
+ rr = rr->next;
+ free(tmp);
+ }
+ free (r);
+}
+
+static struct dns_reply*
+parse_reply(unsigned char *data, int len)
+{
+ unsigned char *p;
+ char host[128];
+ int status;
+
+ struct dns_reply *r;
+ struct resource_record **rr;
+
+ r = (struct dns_reply*)malloc(sizeof(struct dns_reply));
+ if (r == NULL)
+ return NULL;
+ memset(r, 0, sizeof(struct dns_reply));
+
+ p = data;
+ memcpy(&r->h, p, sizeof(HEADER));
+ p += sizeof(HEADER);
+ status = dn_expand(data, data + len, p, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ r->q.domain = strdup(host);
+ if(r->q.domain == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ p += status;
+ r->q.type = (p[0] << 8 | p[1]);
+ p += 2;
+ r->q.class = (p[0] << 8 | p[1]);
+ p += 2;
+ rr = &r->head;
+ while(p < data + len){
+ int type, class, ttl, size;
+ status = dn_expand(data, data + len, p, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ p += status;
+ type = (p[0] << 8) | p[1];
+ p += 2;
+ class = (p[0] << 8) | p[1];
+ p += 2;
+ ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ p += 4;
+ size = (p[0] << 8) | p[1];
+ p += 2;
+ *rr = (struct resource_record*)calloc(1,
+ sizeof(struct resource_record));
+ if(*rr == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->domain = strdup(host);
+ if((*rr)->domain == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->type = type;
+ (*rr)->class = class;
+ (*rr)->ttl = ttl;
+ (*rr)->size = size;
+ switch(type){
+ case T_NS:
+ case T_CNAME:
+ case T_PTR:
+ status = dn_expand(data, data + len, p, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->u.txt = strdup(host);
+ if((*rr)->u.txt == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:{
+ status = dn_expand(data, data + len, p + 2, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
+ strlen(host));
+ if((*rr)->u.mx == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->u.mx->preference = (p[0] << 8) | p[1];
+ strcpy((*rr)->u.mx->domain, host);
+ break;
+ }
+ case T_SRV:{
+ status = dn_expand(data, data + len, p + 6, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->u.srv =
+ (struct srv_record*)malloc(sizeof(struct srv_record) +
+ strlen(host));
+ if((*rr)->u.srv == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->u.srv->priority = (p[0] << 8) | p[1];
+ (*rr)->u.srv->weight = (p[2] << 8) | p[3];
+ (*rr)->u.srv->port = (p[4] << 8) | p[5];
+ strcpy((*rr)->u.srv->target, host);
+ break;
+ }
+ case T_TXT:{
+ (*rr)->u.txt = (char*)malloc(size + 1);
+ if((*rr)->u.txt == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ strncpy((*rr)->u.txt, (char*)p + 1, *p);
+ (*rr)->u.txt[*p] = 0;
+ break;
+ }
+
+ default:
+ (*rr)->u.data = (unsigned char*)malloc(size);
+ if((*rr)->u.data == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ memcpy((*rr)->u.data, p, size);
+ }
+ p += size;
+ rr = &(*rr)->next;
+ }
+ *rr = NULL;
+ return r;
+}
+
+struct dns_reply *
+dns_lookup(const char *domain, const char *type_name)
+{
+ unsigned char reply[1024];
+ int len;
+ int type;
+ struct dns_reply *r = NULL;
+#ifdef HAVE__RES
+ u_long old_options = 0;
+#endif
+
+ type = string_to_type(type_name);
+ if (_resolve_debug) {
+#ifdef HAVE__RES
+ old_options = _res.options;
+ _res.options |= RES_DEBUG;
+#endif
+ fprintf(stderr, "dns_lookup(%s, %s)\n", domain, type_name);
+ }
+ len = res_search(domain, C_IN, type, reply, sizeof(reply));
+ if (_resolve_debug) {
+#ifdef HAVE__RES
+ _res.options = old_options;
+#endif
+ fprintf(stderr, "dns_lookup(%s, %s) --> %d\n", domain, type_name, len);
+ }
+ if (len >= 0)
+ r = parse_reply(reply, len);
+ return r;
+}
+
+#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
+
+struct dns_reply *
+dns_lookup(const char *domain, const char *type_name)
+{
+ return NULL;
+}
+
+void
+dns_free_data(struct dns_reply *r)
+{
+}
+
+#endif
+
+#ifdef TEST
+static char *
+type_to_string(int type)
+{
+ struct stot *p = stot;
+ for(p = stot; p->name; p++)
+ if(type == p->type)
+ return p->name;
+ return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct dns_reply *r;
+ struct resource_record *rr;
+ r = dns_lookup(argv[1], argv[2]);
+ if(r == NULL){
+ printf("No reply.\n");
+ return 1;
+ }
+ for(rr = r->head; rr;rr=rr->next){
+ printf("%s %s %d ", rr->domain, type_to_string(rr->type), rr->ttl);
+ switch(rr->type){
+ case T_NS:
+ printf("%s\n", (char*)rr->u.data);
+ break;
+ case T_A:
+ printf("%d.%d.%d.%d\n",
+ ((unsigned char*)rr->u.data)[0],
+ ((unsigned char*)rr->u.data)[1],
+ ((unsigned char*)rr->u.data)[2],
+ ((unsigned char*)rr->u.data)[3]);
+ break;
+ case T_MX:
+ case T_AFSDB:{
+ struct mx_record *mx = (struct mx_record*)rr->u.data;
+ printf("%d %s\n", mx->preference, mx->domain);
+ break;
+ }
+ case T_SRV:{
+ struct srv_record *srv = (struct srv_record*)rr->u.data;
+ printf("%d %d %d %s\n", srv->priority, srv->weight,
+ srv->port, srv->target);
+ break;
+ }
+ default:
+ printf("\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/resolve.h b/usr.sbin/afs/src/lib/roken/resolve.h
new file mode 100644
index 00000000000..a6ffdaddb38
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/resolve.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: resolve.h,v 1.1.1.1 1998/09/14 21:53:06 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: resolve.h,v 1.2 1998/05/23 05:59:01 assar Exp $ */
+
+#ifndef __RESOLVE_H__
+#define __RESOLVE_H__
+
+/* We use these, but they are not always present in <arpa/nameser.h> */
+
+#ifndef T_A
+#define T_A 1
+#endif
+
+#ifndef T_TXT
+#define T_TXT 16
+#endif
+#ifndef T_AFSDB
+#define T_AFSDB 18
+#endif
+#ifndef T_SRV
+#define T_SRV 33
+#endif
+
+struct dns_query{
+ char *domain;
+ unsigned type;
+ unsigned class;
+};
+
+struct mx_record{
+ unsigned preference;
+ char domain[1];
+};
+
+struct srv_record{
+ unsigned priority;
+ unsigned weight;
+ unsigned port;
+ char target[1];
+};
+
+struct resource_record{
+ char *domain;
+ unsigned type;
+ unsigned class;
+ unsigned ttl;
+ unsigned size;
+ union {
+ void *data;
+ struct mx_record *mx;
+ struct mx_record *afsdb; /* mx and afsdb are identical */
+ struct srv_record *srv;
+ struct in_addr *a;
+ char *txt;
+ }u;
+ struct resource_record *next;
+};
+
+#ifndef T_A /* XXX if <arpa/nameser.h> isn't included */
+typedef int HEADER; /* will never be used */
+#endif
+
+struct dns_reply{
+ HEADER h;
+ struct dns_query q;
+ struct resource_record *head;
+};
+
+
+struct dns_reply* dns_lookup(const char *, const char *);
+
+void dns_free_data(struct dns_reply *r);
+
+#endif /* __RESOLVE_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/roken.def b/usr.sbin/afs/src/lib/roken/roken.def
new file mode 100644
index 00000000000..da32b31f7e0
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/roken.def
@@ -0,0 +1,10 @@
+LIBRARY roken
+EXPORTS
+ gettimeofday
+ strcasecmp
+ strtok_r
+ snprintf
+ asprintf
+ vsnprintf
+ base64_decode
+ base64_encode
diff --git a/usr.sbin/afs/src/lib/roken/roken.h b/usr.sbin/afs/src/lib/roken/roken.h
new file mode 100644
index 00000000000..2851b1e06de
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/roken.h
@@ -0,0 +1,458 @@
+/* $OpenBSD: roken.h,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: roken.h,v 1.9 1998/06/07 05:19:20 map Exp $ */
+
+#ifndef __ROKEN_H__
+#define __ROKEN_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
+#include <sys/ioctl.h>
+#endif
+
+#if !defined(HAVE_SETSID) && defined(HAVE__SETSID)
+#define setsid _setsid
+#endif
+
+#ifndef HAVE_PUTENV
+int putenv(const char *string);
+#endif
+
+#ifndef HAVE_SETENV
+int setenv(const char *var, const char *val, int rewrite);
+#endif
+
+#ifndef HAVE_UNSETENV
+void unsetenv(const char *name);
+#endif
+
+#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO)
+char *getusershell(void);
+#endif
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+#ifndef HAVE_SNPRINTF
+int snprintf (char *str, size_t sz, const char *format, ...)
+ __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#ifndef HAVE_VSNPRINTF
+int vsnprintf (char *str, size_t sz, const char *format, va_list ap)
+ __attribute__((format (printf, 3, 0)));
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf (char **ret, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf (char **ret, const char *format, va_list ap)
+ __attribute__((format (printf, 2, 0)));
+#endif
+
+#ifndef HAVE_ASNPRINTF
+int asnprintf (char **ret, size_t max_sz, const char *format, ...)
+ __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#ifndef HAVE_VASNPRINTF
+int vasnprintf (char **ret, size_t max_sz, const char *format, va_list ap)
+ __attribute__((format (printf, 3, 0)));
+#endif
+
+#ifndef HAVE_STRDUP
+char * strdup(const char *old);
+#endif
+
+#ifndef HAVE_STRLWR
+char * strlwr(char *);
+#endif
+
+#ifndef HAVE_STRNLEN
+int strnlen(char*, int);
+#endif
+
+#ifndef HAVE_STRSEP
+char *strsep(char**, const char*);
+#endif
+
+#ifdef NEED_FCLOSE_PROTO
+int fclose(FILE *);
+#endif
+
+#ifdef NEED_STRTOK_R_PROTO
+char *strtok_r(char *s1, const char *s2, char **lasts);
+#endif
+
+#ifndef HAVE_STRUPR
+char * strupr(char *);
+#endif
+
+#ifndef HAVE_GETDTABLESIZE
+int getdtablesize(void);
+#endif
+
+#if IRIX != 4 /* fix for compiler bug */
+#ifdef RETSIGTYPE
+typedef RETSIGTYPE (*SigAction)(/* int??? */);
+SigAction signal(int iSig, SigAction pAction); /* BSD compatible */
+#endif
+#endif
+
+#ifndef SIG_ERR
+#define SIG_ERR ((RETSIGTYPE (*)())-1)
+#endif
+
+#if !defined(HAVE_STRERROR) && !defined(strerror)
+char *strerror(int eno);
+#endif
+
+#ifdef NEED_HSTRERROR_PROTO
+#ifdef NEED_HSTRERROR_CONST
+const
+#endif
+char *hstrerror(int herr);
+#endif
+
+#ifndef HAVE_H_ERRNO_DECLARATION
+extern int h_errno;
+#endif
+
+#ifndef HAVE_INET_ATON
+/* Minimal implementation of inet_aton. Doesn't handle hex numbers. */
+int inet_aton(const char *cp, struct in_addr *adr);
+#endif
+
+#if !defined(HAVE_GETCWD)
+char* getcwd(char *path, size_t size);
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+struct passwd *k_getpwnam (char *user);
+struct passwd *k_getpwuid (uid_t uid);
+#endif
+
+#ifndef HAVE_SETEUID
+int seteuid(uid_t euid);
+#endif
+
+#ifndef HAVE_SETEGID
+int setegid(gid_t egid);
+#endif
+
+#ifndef HAVE_LSTAT
+int lstat(const char *path, struct stat *buf);
+#endif
+
+#ifndef HAVE_MKSTEMP
+int mkstemp(char *);
+#endif
+
+#ifndef HAVE_INITGROUPS
+int initgroups(const char *name, gid_t basegid);
+#endif
+
+#ifndef HAVE_FCHOWN
+int fchown(int fd, uid_t owner, gid_t group);
+#endif
+
+#ifndef HAVE_CHOWN
+int chown(const char *path, uid_t owner, gid_t group);
+#endif
+
+#ifndef HAVE_RCMD
+int rcmd(char **ahost, unsigned short inport, const char *locuser,
+ const char *remuser, const char *cmd, int *fd2p);
+#endif
+
+#ifndef HAVE_WRITEV
+ssize_t
+writev(int d, const struct iovec *iov, int iovcnt);
+#endif
+
+#ifndef HAVE_READV
+ssize_t
+readv(int d, const struct iovec *iov, int iovcnt);
+#endif
+
+#ifndef HAVE_FLOCK
+#ifndef LOCK_SH
+#define LOCK_SH 1 /* Shared lock */
+#endif
+#ifndef LOCK_EX
+#define LOCK_EX 2 /* Exclusive lock */
+#endif
+#ifndef LOCK_NB
+#define LOCK_NB 4 /* Don't block when locking */
+#endif
+#ifndef LOCK_UN
+#define LOCK_UN 8 /* Unlock */
+#endif
+
+int flock(int fd, int operation);
+#endif /* HAVE_FLOCK */
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+time_t tm2time (struct tm tm, int local);
+
+int unix_verify_user(char *user, char *password);
+
+void inaddr2str(struct in_addr addr, char *s, size_t len);
+
+void mini_inetd (int port);
+
+#ifndef HAVE_STRUCT_WINSIZE
+struct winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+#endif
+
+int get_window_size(int fd, struct winsize *);
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#ifndef SOMAXCONN
+#define SOMAXCONN 5
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+/* Misc definitions for old syslogs */
+
+#ifndef LOG_DAEMON
+#define openlog(id,option,facility) openlog((id),(option))
+#define LOG_DAEMON 0
+#endif
+#ifndef LOG_ODELAY
+#define LOG_ODELAY 0
+#endif
+#ifndef LOG_NDELAY
+#define LOG_NDELAY 0x08
+#endif
+#ifndef LOG_CONS
+#define LOG_CONS 0
+#endif
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+#endif
+
+#ifndef HAVE_VSYSLOG
+void vsyslog(int pri, const char *fmt, va_list ap);
+#endif
+
+#ifndef HAVE_OPTARG_DECLARATION
+extern char *optarg;
+#endif
+#ifndef HAVE_OPTIND_DECLARATION
+extern int optind;
+#endif
+#ifndef HAVE_OPTERR_DECLARATION
+extern int opterr;
+#endif
+
+#ifndef HAVE___PROGNAME_DECLARATION
+extern const char *__progname;
+#endif
+
+/*
+ * kludges and such
+ */
+
+#ifdef GETHOSTBYNAME_PROTO_COMPATIBLE
+#define roken_gethostbyname(x) gethostbyname(x)
+#else
+#define roken_gethostbyname(x) gethostbyname((char *)x)
+#endif
+
+#ifdef GETHOSTBYADDR_PROTO_COMPATIBLE
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr(a, l, t)
+#else
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr((char *)a, l, t)
+#endif
+
+#ifdef GETSERVBYNAME_PROTO_COMPATIBLE
+#define roken_getservbyname(x,y) getservbyname(x,y)
+#else
+#define roken_getservbyname(x,y) getservbyname((char *)x, (char *)y)
+#endif
+
+#ifdef OPENLOG_PROTO_COMPATIBLE
+#define roken_openlog(a,b,c) openlog(a,b,c)
+#else
+#define roken_openlog(a,b,c) openlog((char *)a,b,c)
+#endif
+
+void set_progname(char *argv0);
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE 003
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024+4)
+#endif
+
+
+#ifdef NEED_SELECT_PROTO
+int
+select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout);
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t; /* XXX real hot stuff */
+#endif
+
+#ifdef HAVE_REPAIRABLE_HTONL
+#define htonl(x) __cpu_to_be32(x)
+#define ntohl(x) __be32_to_cpu(x)
+#define htons(x) __cpu_to_be16(x)
+#define ntohs(x) __be16_to_cpu(x)
+#endif
+
+#endif /* __ROKEN_H__ */
diff --git a/usr.sbin/afs/src/lib/roken/roken.mak b/usr.sbin/afs/src/lib/roken/roken.mak
new file mode 100644
index 00000000000..d1c23330d4c
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/roken.mak
@@ -0,0 +1,316 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=roken - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to roken - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "roken - Win32 Release" && "$(CFG)" != "roken - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "roken.mak" CFG="roken - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "roken - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "roken - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "roken - Win32 Debug"
+MTL=mktyplib.exe
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "roken - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\roken.dll"
+
+CLEAN :
+ -@erase "$(INTDIR)\gettimeofday.obj"
+ -@erase "$(INTDIR)\snprintf.obj"
+ -@erase "$(INTDIR)\strcasecmp.obj"
+ -@erase "$(INTDIR)\strtok_r.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(OUTDIR)\roken.dll"
+ -@erase "$(OUTDIR)\roken.exp"
+ -@erase "$(OUTDIR)\roken.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MT /GX /O2 /I "..\krb" /I "..\des" /I "..\..\include" /I "..\..\include\win32" /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "HAVE_CONFIG_H" /YX /c
+CPP_PROJ=/nologo /MT /GX /O2 /I "..\krb" /I "..\des" /I "..\..\include" /I\
+ "..\..\include\win32" /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "HAVE_CONFIG_H" /Fp"$(INTDIR)/roken.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/roken.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:0x68e7780 /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /base:0x68e7780 /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/roken.pdb" /machine:I386 /def:".\roken.def"\
+ /out:"$(OUTDIR)/roken.dll" /implib:"$(OUTDIR)/roken.lib"
+DEF_FILE= \
+ ".\roken.def"
+LINK32_OBJS= \
+ "$(INTDIR)\gettimeofday.obj" \
+ "$(INTDIR)\snprintf.obj" \
+ "$(INTDIR)\strcasecmp.obj" \
+ "$(INTDIR)\strtok_r.obj" \
+ "$(INTDIR)\base64.obj"
+
+"$(OUTDIR)\roken.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "roken - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\roken.dll"
+
+CLEAN :
+ -@erase "$(INTDIR)\gettimeofday.obj"
+ -@erase "$(INTDIR)\snprintf.obj"
+ -@erase "$(INTDIR)\strcasecmp.obj"
+ -@erase "$(INTDIR)\strtok_r.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
+ -@erase "$(OUTDIR)\roken.dll"
+ -@erase "$(OUTDIR)\roken.exp"
+ -@erase "$(OUTDIR)\roken.ilk"
+ -@erase "$(OUTDIR)\roken.lib"
+ -@erase "$(OUTDIR)\roken.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MTd /Gm /GX /Zi /Od /I "..\krb" /I "..\des" /I "..\..\include" /I "..\..\include\win32" /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "HAVE_CONFIG_H" /YX /c
+CPP_PROJ=/nologo /MTd /Gm /GX /Zi /Od /I "..\krb" /I "..\des" /I\
+ "..\..\include" /I "..\..\include\win32" /I "." /D "_DEBUG" /D "WIN32" /D\
+ "_WINDOWS" /D "HAVE_CONFIG_H" /Fp"$(INTDIR)/roken.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/roken.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:0x68e7780 /subsystem:windows /dll /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /base:0x68e7780 /subsystem:windows /dll /incremental:yes\
+ /pdb:"$(OUTDIR)/roken.pdb" /debug /machine:I386 /def:".\roken.def"\
+ /out:"$(OUTDIR)/roken.dll" /implib:"$(OUTDIR)/roken.lib"
+DEF_FILE= \
+ ".\roken.def"
+LINK32_OBJS= \
+ "$(INTDIR)\gettimeofday.obj" \
+ "$(INTDIR)\snprintf.obj" \
+ "$(INTDIR)\strcasecmp.obj" \
+ "$(INTDIR)\strtok_r.obj" \
+ "$(INTDIR)\base64.obj"
+
+"$(OUTDIR)\roken.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "roken - Win32 Release"
+# Name "roken - Win32 Debug"
+
+!IF "$(CFG)" == "roken - Win32 Release"
+
+!ELSEIF "$(CFG)" == "roken - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\roken.def
+
+!IF "$(CFG)" == "roken - Win32 Release"
+
+!ELSEIF "$(CFG)" == "roken - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\strcasecmp.c
+DEP_CPP_STRCA=\
+ "..\..\include\sys/cdefs.h"\
+ "..\..\include\win32\config.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+
+"$(INTDIR)\strcasecmp.obj" : $(SOURCE) $(DEP_CPP_STRCA) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE="..\krb\gettimeofday.c"
+DEP_CPP_GETTI=\
+ "..\..\include\protos.h"\
+ "..\..\include\sys/cdefs.h"\
+ "..\..\include\win32\config.h"\
+ "..\..\include\win32\ktypes.h"\
+ "..\des\des.h"\
+ "..\krb\krb.h"\
+ "..\krb\krb_locl.h"\
+ "..\krb\krb_log.h"\
+ "..\krb\prot.h"\
+ "..\krb\resolve.h"\
+ ".\roken.h"\
+ {$(INCLUDE)}"\sys\stat.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+
+"$(INTDIR)\gettimeofday.obj" : $(SOURCE) $(DEP_CPP_GETTI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snprintf.c
+DEP_CPP_SNPRI=\
+ "..\..\include\protos.h"\
+ "..\..\include\win32\config.h"\
+ ".\roken.h"\
+ {$(INCLUDE)}"\sys\stat.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+
+"$(INTDIR)\snprintf.obj" : $(SOURCE) $(DEP_CPP_SNPRI) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\strtok_r.c
+DEP_CPP_STRTO=\
+ "..\..\include\protos.h"\
+ "..\..\include\win32\config.h"\
+ ".\roken.h"\
+ {$(INCLUDE)}"\sys\stat.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+
+"$(INTDIR)\strtok_r.obj" : $(SOURCE) $(DEP_CPP_STRTO) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\base64.c
+DEP_CPP_STRTO=\
+ "..\..\include\protos.h"\
+ "..\..\include\win32\config.h"\
+ ".\roken.h"\
+ {$(INCLUDE)}"\sys\stat.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+
+"$(INTDIR)\base64.obj" : $(SOURCE) $(DEP_CPP_STRTO) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/usr.sbin/afs/src/lib/roken/sendmsg.c b/usr.sbin/afs/src/lib/roken/sendmsg.c
new file mode 100644
index 00000000000..efba32002ec
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/sendmsg.c
@@ -0,0 +1,71 @@
+/* $OpenBSD: sendmsg.c,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: sendmsg.c,v 1.1 1998/03/29 01:24:44 assar Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t
+sendmsg(int s, const struct msghdr *msg, int flags)
+{
+ ssize_t ret;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+ struct iovec *iov = msg->msg_iov;
+
+ for(i = 0; i < msg->msg_iovlen; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ p = buf;
+ for (i = 0; i < msg->msg_iovlen; ++i) {
+ memcpy (p, iov[i].iov_base, iov[i].iov_len);
+ p += iov[i].iov_len;
+ }
+ ret = sendto (s, buf, tot, flags, msg->msg_name, msg->msg_namelen);
+ free (buf);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/lib/roken/setegid.c b/usr.sbin/afs/src/lib/roken/setegid.c
new file mode 100644
index 00000000000..8f10f3c991a
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/setegid.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: setegid.c,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: setegid.c,v 1.1 1998/01/13 16:25:34 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int
+setegid(gid_t egid)
+{
+#ifdef HAVE_SETREGID
+ return setregid(-1, egid);
+#endif
+
+#ifdef HAVE_SETRESGID
+ return setresgid(-1, egid, -1);
+#endif
+
+ return -1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/setenv.c b/usr.sbin/afs/src/lib/roken/setenv.c
new file mode 100644
index 00000000000..41e1de5bacf
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/setenv.c
@@ -0,0 +1,72 @@
+/* $OpenBSD: setenv.c,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: setenv.c,v 1.1 1998/01/13 16:25:35 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This is the easy way out, use putenv to implement setenv. We might
+ * leak some memory but that is ok since we are usally about to exec
+ * anyway.
+ */
+
+int
+setenv(const char *var, const char *val, int rewrite)
+{
+ char *t;
+
+ if (!rewrite && getenv(var) != 0)
+ return 0;
+
+ asprintf (&t, "%s=%s", var, val);
+ if (t == NULL)
+ return -1;
+
+ if (putenv(t) == 0)
+ return 0;
+ else
+ return -1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/seteuid.c b/usr.sbin/afs/src/lib/roken/seteuid.c
new file mode 100644
index 00000000000..b3458d8bba6
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/seteuid.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: seteuid.c,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: seteuid.c,v 1.1 1998/01/13 16:25:35 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int
+seteuid(uid_t euid)
+{
+#ifdef HAVE_SETREUID
+ return setreuid(-1, euid);
+#endif
+
+#ifdef HAVE_SETRESUID
+ return setresuid(-1, euid, -1);
+#endif
+
+ return -1;
+}
diff --git a/usr.sbin/afs/src/lib/roken/signal.c b/usr.sbin/afs/src/lib/roken/signal.c
new file mode 100644
index 00000000000..2e5c09bff3e
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/signal.c
@@ -0,0 +1,87 @@
+/* $OpenBSD: signal.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: signal.c,v 1.1 1998/01/13 16:25:36 lha Exp $");
+#endif
+
+#include <signal.h>
+
+/*
+ * We would like to always use this signal but there is a link error
+ * on NEXTSTEP
+ */
+#ifndef NeXT
+/*
+ * Bugs:
+ *
+ * Do we need any extra hacks for SIGCLD and/or SIGCHLD?
+ */
+
+typedef RETSIGTYPE (*SigAction)(/* int??? */);
+
+SigAction
+signal(int iSig, SigAction pAction)
+{
+ struct sigaction saNew, saOld;
+
+ saNew.sa_handler = pAction;
+ sigemptyset(&saNew.sa_mask);
+ saNew.sa_flags = 0;
+
+ if (iSig == SIGALRM)
+ {
+#ifdef SA_INTERRUPT
+ saNew.sa_flags |= SA_INTERRUPT;
+#endif
+ }
+ else
+ {
+#ifdef SA_RESTART
+ saNew.sa_flags |= SA_RESTART;
+#endif
+ }
+
+ if (sigaction(iSig, &saNew, &saOld) < 0)
+ return(SIG_ERR);
+
+ return(saOld.sa_handler);
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/snprintf.c b/usr.sbin/afs/src/lib/roken/snprintf.c
new file mode 100644
index 00000000000..94c68504103
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/snprintf.c
@@ -0,0 +1,621 @@
+/* $OpenBSD: snprintf.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: snprintf.c,v 1.7 1998/03/18 19:31:44 art Exp $");
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <roken.h>
+
+enum format_flags {
+ minus_flag = 1,
+ plus_flag = 2,
+ space_flag = 4,
+ alternate_flag = 8,
+ zero_flag = 16
+};
+
+/*
+ * Common state
+ */
+
+struct state {
+ char *str;
+ char *s;
+ char *theend;
+ size_t sz;
+ size_t max_sz;
+ int (*append_char)(struct state *, char);
+ int (*reserve)(struct state *, size_t);
+ /* XXX - methods */
+};
+
+#ifndef HAVE_VSNPRINTF
+static int
+sn_reserve (struct state *state, size_t n)
+{
+ return state->s + n > state->theend;
+}
+
+
+static int
+sn_append_char (struct state *state, char c)
+{
+ if (sn_reserve (state, 1)) {
+ return 1;
+ } else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+#endif
+
+static int
+as_reserve (struct state *state, size_t n)
+{
+ if (state->s + n > state->theend) {
+ int off = state->s - state->str;
+ char *tmp;
+
+ if (state->max_sz && state->sz >= state->max_sz)
+ return 1;
+
+ state->sz = max(state->sz * 2, state->sz + n);
+ if (state->max_sz)
+ state->sz = min(state->sz, state->max_sz);
+ tmp = realloc (state->str, state->sz);
+ if (tmp == NULL)
+ return 1;
+ state->str = tmp;
+ state->s = state->str + off;
+ state->theend = state->str + state->sz - 1;
+ }
+ return 0;
+}
+
+static int
+as_append_char (struct state *state, char c)
+{
+ if(as_reserve (state, 1))
+ return 1;
+ else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+
+static int
+append_number(struct state *state,
+ unsigned long num, unsigned base, char *rep,
+ int width, int prec, int flags, int minusp)
+{
+ int len = 0;
+ int i;
+
+ /* given precision, ignore zero flag */
+ if(prec != -1)
+ flags &= ~zero_flag;
+ else
+ prec = 1;
+ /* zero value with zero precision -> "" */
+ if(prec == 0 && num == 0)
+ return 0;
+ do{
+ if((*state->append_char)(state, rep[num % base]))
+ return 1;
+ len++;
+ num /= base;
+ }while(num);
+ prec -= len;
+ /* pad with prec zeros */
+ while(prec-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ /* add length of alternate prefix (added later) to len */
+ if(flags & alternate_flag && (base == 16 || base == 8))
+ len += base / 8;
+ /* pad with zeros */
+ if(flags & zero_flag){
+ width -= len;
+ if(minusp || (flags & space_flag) || (flags & plus_flag))
+ width--;
+ while(width-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ }
+ /* add alternate prefix */
+ if(flags & alternate_flag && (base == 16 || base == 8)){
+ if(base == 16)
+ if((*state->append_char)(state, rep[10] + 23)) /* XXX */
+ return 1;
+ if((*state->append_char)(state, '0'))
+ return 1;
+ }
+ /* add sign */
+ if(minusp){
+ if((*state->append_char)(state, '-'))
+ return 1;
+ len++;
+ } else if(flags & plus_flag) {
+ if((*state->append_char)(state, '+'))
+ return 1;
+ len++;
+ } else if(flags & space_flag) {
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(flags & minus_flag)
+ /* swap before padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+ width -= len;
+ while(width-- > 0){
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(!(flags & minus_flag))
+ /* swap after padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+
+ return 0;
+}
+
+static int
+append_string (struct state *state,
+ char *arg,
+ int width,
+ int prec,
+ int flags)
+{
+ if(prec != -1)
+ width -= prec;
+ else
+ width -= strlen(arg);
+ if(!(flags & minus_flag))
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ if (prec != -1) {
+ while (*arg && prec--)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ } else {
+ while (*arg)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ }
+ if(flags & minus_flag)
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ return 0;
+}
+
+static int
+append_char(struct state *state,
+ char arg,
+ int width,
+ int flags)
+{
+ while(!(flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ if((*state->append_char) (state, arg))
+ return 1;
+ while((flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * This can't be made into a function...
+ */
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_flag) \
+ res = va_arg(arg, unsig long); \
+else if (short_flag) \
+ res = va_arg(arg, unsig short); \
+else \
+ res = va_arg(arg, unsig int)
+
+/*
+ * zyxprintf - return 0 or -1
+ */
+
+static int
+xyzprintf (struct state *state, const char *format, va_list ap)
+{
+ char c;
+
+ while((c = *format++)) {
+ if (c == '%') {
+ int flags = 0;
+ int width = 0;
+ int prec = -1;
+ int long_flag = 0;
+ int short_flag = 0;
+
+ /* flags */
+ while((c = *format++)){
+ if(c == '-')
+ flags |= minus_flag;
+ else if(c == '+')
+ flags |= plus_flag;
+ else if(c == ' ')
+ flags |= space_flag;
+ else if(c == '#')
+ flags |= alternate_flag;
+ else if(c == '0')
+ flags |= zero_flag;
+ else
+ break;
+ }
+
+ if((flags & space_flag) && (flags & plus_flag))
+ flags ^= space_flag;
+
+ if((flags & minus_flag) && (flags & zero_flag))
+ flags ^= zero_flag;
+
+ /* width */
+ if (isdigit(c))
+ do {
+ width = width * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if(c == '*') {
+ width = va_arg(ap, int);
+ c = *format++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ prec = 0;
+ c = *format++;
+ if (isdigit(c))
+ do {
+ prec = prec * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if (c == '*') {
+ prec = va_arg(ap, int);
+ c = *format++;
+ }
+ }
+
+ /* size */
+
+ if (c == 'h') {
+ short_flag = 1;
+ c = *format++;
+ } else if (c == 'l') {
+ long_flag = 1;
+ c = *format++;
+ }
+
+ switch (c) {
+ case 'c' :
+ if(append_char(state, va_arg(ap, int), width, flags))
+ return -1;
+ break;
+ case 's' :
+ if (append_string(state,
+ va_arg(ap, char*),
+ width,
+ prec,
+ flags))
+ return -1;
+ break;
+ case 'd' :
+ case 'i' : {
+ long arg;
+ unsigned long num;
+ int minusp = 0;
+
+ PARSE_INT_FORMAT(arg, ap, signed);
+
+ if (arg < 0) {
+ minusp = 1;
+ num = -arg;
+ } else
+ num = arg;
+
+ if (append_number (state, num, 10, "0123456789",
+ width, prec, flags, minusp))
+ return -1;
+ break;
+ }
+ case 'u' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 10, "0123456789",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'o' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 010, "01234567",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'x' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789abcdef",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'X' :{
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'p' : {
+ unsigned long arg = (unsigned long)va_arg(ap, void*);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'n' : {
+ int *arg = va_arg(ap, int*);
+ *arg = state->s - state->str;
+ break;
+ }
+ case '%' :
+ if ((*state->append_char)(state, c))
+ return -1;
+ break;
+ default :
+ if ( (*state->append_char)(state, '%')
+ || (*state->append_char)(state, c))
+ return -1;
+ break;
+ }
+ } else
+ if ((*state->append_char) (state, c))
+ return -1;
+ }
+ return 0;
+}
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf (char *str, size_t sz, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = vsnprintf (str, sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+
+ tmp = malloc (sz);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (ret != ret2 || strcmp(str, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return ret;
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int
+asprintf (char **ret, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasprintf (ret, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#ifndef HAVE_ASNPRINTF
+int
+asnprintf (char **ret, size_t max_sz, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasnprintf (ret, max_sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int
+vasprintf (char **ret, const char *format, va_list args)
+{
+ return vasnprintf (ret, 0, format, args);
+}
+#endif
+
+
+#ifndef HAVE_VASNPRINTF
+int
+vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+{
+ int st;
+ size_t len;
+ struct state state;
+
+ state.max_sz = max_sz;
+ state.sz = 1;
+ state.str = malloc(state.sz);
+ if (state.str == NULL) {
+ *ret = NULL;
+ return -1;
+ }
+ state.s = state.str;
+ state.theend = state.s + state.sz - 1;
+ state.append_char = as_append_char;
+ state.reserve = as_reserve;
+
+ st = xyzprintf (&state, format, args);
+ if (st) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ } else {
+ char *tmp;
+
+ *state.s = '\0';
+ len = state.s - state.str;
+ tmp = realloc (state.str, len+1);
+ if (state.str == NULL) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ }
+ *ret = tmp;
+ return len;
+ }
+}
+#endif
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf (char *str, size_t sz, const char *format, va_list args)
+{
+ struct state state;
+ int ret;
+
+ state.max_sz = 0;
+ state.sz = sz;
+ state.str = str;
+ state.s = str;
+ state.theend = str + sz - 1;
+ state.append_char = sn_append_char;
+ state.reserve = sn_reserve;
+
+ ret = xyzprintf (&state, format, args);
+ *state.s = '\0';
+ if (ret)
+ return sz;
+ else
+ return state.s - state.str;
+}
+#endif
+
diff --git a/usr.sbin/afs/src/lib/roken/strcasecmp.c b/usr.sbin/afs/src/lib/roken/strcasecmp.c
new file mode 100644
index 00000000000..0e81c0a34da
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strcasecmp.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: strcasecmp.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1987, 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strcasecmp.c,v 1.1 1998/01/13 16:25:38 lha Exp $");
+#endif
+
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/cdefs.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * 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 const unsigned 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', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\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',
+};
+
+int
+strcasecmp(const char *s1, const char *s2)
+{
+ const unsigned char *cm = charmap,
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ while (cm[*us1] == cm[*us2++])
+ if (*us1++ == '\0')
+ return (0);
+ return (cm[*us1] - cm[*--us2]);
+}
+
+int
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *cm = charmap,
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ do {
+ if (cm[*us1] != cm[*us2++])
+ return (cm[*us1] - cm[*--us2]);
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/usr.sbin/afs/src/lib/roken/strdup.c b/usr.sbin/afs/src/lib/roken/strdup.c
new file mode 100644
index 00000000000..5f1281056f1
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strdup.c
@@ -0,0 +1,56 @@
+/* $OpenBSD: strdup.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strdup.c,v 1.1 1998/01/13 16:25:39 lha Exp $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef HAVE_STRDUP
+char *
+strdup(const char *old)
+{
+ char *t = malloc(strlen(old)+1);
+ if (t != 0)
+ strcpy(t, old);
+ return t;
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/strerror.c b/usr.sbin/afs/src/lib/roken/strerror.c
new file mode 100644
index 00000000000..71b419ba5f7
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strerror.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: strerror.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strerror.c,v 1.1 1998/01/13 16:25:40 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char*
+strerror(int eno)
+{
+ static char emsg[1024];
+
+ if(eno < 0 || eno >= sys_nerr)
+ snprintf(emsg, sizeof(emsg), "Error %d occurred.", eno);
+ else
+ strcpy(emsg, sys_errlist[eno]);
+
+ return emsg;
+}
diff --git a/usr.sbin/afs/src/lib/roken/strftime.c b/usr.sbin/afs/src/lib/roken/strftime.c
new file mode 100644
index 00000000000..dbe1d8ad87b
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strftime.c
@@ -0,0 +1,302 @@
+/* $OpenBSD: strftime.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#define TM_YEAR_BASE 1900 /* from <tzfile.h> */
+#include <string.h>
+
+static char *afmt[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+};
+static char *Afmt[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+ "Saturday",
+};
+static char *bfmt[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec",
+};
+static char *Bfmt[] = {
+ "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December",
+};
+
+static size_t gsize;
+static char *pt;
+
+static int _add (char *);
+static int _conv (int, int, int);
+#ifdef HAVE_MKTIME
+static int _secs (const struct tm *);
+#endif /* HAVE_MKTIME */
+static size_t _fmt (const char *, const struct tm *);
+
+size_t
+strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
+{
+
+ pt = s;
+ if ((gsize = maxsize) < 1)
+ return(0);
+ if (_fmt(format, t)) {
+ *pt = '\0';
+ return(maxsize - gsize);
+ }
+ return(0);
+}
+
+static size_t
+_fmt(const char *format, const struct tm *t)
+{
+ for (; *format; ++format) {
+ if (*format == '%')
+ switch(*++format) {
+ case '\0':
+ --format;
+ break;
+ case 'A':
+ if (t->tm_wday < 0 || t->tm_wday > 6)
+ return(0);
+ if (!_add(Afmt[t->tm_wday]))
+ return(0);
+ continue;
+ case 'a':
+ if (t->tm_wday < 0 || t->tm_wday > 6)
+ return(0);
+ if (!_add(afmt[t->tm_wday]))
+ return(0);
+ continue;
+ case 'B':
+ if (t->tm_mon < 0 || t->tm_mon > 11)
+ return(0);
+ if (!_add(Bfmt[t->tm_mon]))
+ return(0);
+ continue;
+ case 'b':
+ case 'h':
+ if (t->tm_mon < 0 || t->tm_mon > 11)
+ return(0);
+ if (!_add(bfmt[t->tm_mon]))
+ return(0);
+ continue;
+ case 'C':
+ if (!_fmt("%a %b %e %H:%M:%S %Y", t))
+ return(0);
+ continue;
+ case 'c':
+ if (!_fmt("%m/%d/%y %H:%M:%S", t))
+ return(0);
+ continue;
+ case 'D':
+ if (!_fmt("%m/%d/%y", t))
+ return(0);
+ continue;
+ case 'd':
+ if (!_conv(t->tm_mday, 2, '0'))
+ return(0);
+ continue;
+ case 'e':
+ if (!_conv(t->tm_mday, 2, ' '))
+ return(0);
+ continue;
+ case 'H':
+ if (!_conv(t->tm_hour, 2, '0'))
+ return(0);
+ continue;
+ case 'I':
+ if (!_conv(t->tm_hour % 12 ?
+ t->tm_hour % 12 : 12, 2, '0'))
+ return(0);
+ continue;
+ case 'j':
+ if (!_conv(t->tm_yday + 1, 3, '0'))
+ return(0);
+ continue;
+ case 'k':
+ if (!_conv(t->tm_hour, 2, ' '))
+ return(0);
+ continue;
+ case 'l':
+ if (!_conv(t->tm_hour % 12 ?
+ t->tm_hour % 12 : 12, 2, ' '))
+ return(0);
+ continue;
+ case 'M':
+ if (!_conv(t->tm_min, 2, '0'))
+ return(0);
+ continue;
+ case 'm':
+ if (!_conv(t->tm_mon + 1, 2, '0'))
+ return(0);
+ continue;
+ case 'n':
+ if (!_add("\n"))
+ return(0);
+ continue;
+ case 'p':
+ if (!_add(t->tm_hour >= 12 ? "PM" : "AM"))
+ return(0);
+ continue;
+ case 'R':
+ if (!_fmt("%H:%M", t))
+ return(0);
+ continue;
+ case 'r':
+ if (!_fmt("%I:%M:%S %p", t))
+ return(0);
+ continue;
+ case 'S':
+ if (!_conv(t->tm_sec, 2, '0'))
+ return(0);
+ continue;
+#ifdef HAVE_MKTIME
+ case 's':
+ if (!_secs(t))
+ return(0);
+ continue;
+#endif /* HAVE_MKTIME */
+ case 'T':
+ case 'X':
+ if (!_fmt("%H:%M:%S", t))
+ return(0);
+ continue;
+ case 't':
+ if (!_add("\t"))
+ return(0);
+ continue;
+ case 'U':
+ if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7,
+ 2, '0'))
+ return(0);
+ continue;
+ case 'W':
+ if (!_conv((t->tm_yday + 7 -
+ (t->tm_wday ? (t->tm_wday - 1) : 6))
+ / 7, 2, '0'))
+ return(0);
+ continue;
+ case 'w':
+ if (!_conv(t->tm_wday, 1, '0'))
+ return(0);
+ continue;
+ case 'x':
+ if (!_fmt("%m/%d/%y", t))
+ return(0);
+ continue;
+ case 'y':
+ if (!_conv((t->tm_year + TM_YEAR_BASE)
+ % 100, 2, '0'))
+ return(0);
+ continue;
+ case 'Y':
+ if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0'))
+ return(0);
+ continue;
+#ifdef notdef
+ case 'Z':
+ if (!t->tm_zone || !_add(t->tm_zone))
+ return(0);
+ continue;
+#endif
+ case '%':
+ /*
+ * X311J/88-090 (4.12.3.5): if conversion char is
+ * undefined, behavior is undefined. Print out the
+ * character itself as printf(3) does.
+ */
+ default:
+ break;
+ }
+ if (!gsize--)
+ return(0);
+ *pt++ = *format;
+ }
+ return(gsize);
+}
+
+#ifdef HAVE_MKTIME
+static int
+_secs(const struct tm *t)
+{
+ static char buf[15];
+ time_t s;
+ char *p;
+ struct tm tmp;
+
+ /* Make a copy, mktime(3) modifies the tm struct. */
+ tmp = *t;
+ s = mktime(&tmp);
+ for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
+ *p-- = s % 10 + '0';
+ return(_add(++p));
+}
+#endif /* HAVE_MKTIME */
+
+static int
+_conv(int n, int digits, int pad)
+{
+ static char buf[10];
+ char *p;
+
+ for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
+ *p-- = n % 10 + '0';
+ while (p > buf && digits-- > 0)
+ *p-- = pad;
+ return(_add(++p));
+}
+
+static int
+_add(str)
+ char *str;
+{
+ for (;; ++pt, --gsize) {
+ if (!gsize)
+ return(0);
+ if (!(*pt = *str++))
+ return(1);
+ }
+}
diff --git a/usr.sbin/afs/src/lib/roken/strlwr.c b/usr.sbin/afs/src/lib/roken/strlwr.c
new file mode 100644
index 00000000000..f8bf4318819
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strlwr.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: strlwr.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strlwr.c,v 1.2 1998/03/13 00:31:27 art Exp $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include <roken.h>
+
+#ifndef HAVE_STRLWR
+char *
+strlwr(char *str)
+{
+ char *s;
+
+ for(s = str; *s; s++)
+ *s = tolower((int)*s);
+ return str;
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/strnlen.c b/usr.sbin/afs/src/lib/roken/strnlen.c
new file mode 100644
index 00000000000..e8e3aaec714
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strnlen.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: strnlen.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strnlen.c,v 1.1 1998/01/13 16:25:42 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int
+strnlen(char *s, int len)
+{
+ int i;
+ for(i = 0; i < len && s[i]; i++)
+ ;
+ return i;
+}
diff --git a/usr.sbin/afs/src/lib/roken/strsep.c b/usr.sbin/afs/src/lib/roken/strsep.c
new file mode 100644
index 00000000000..72329799387
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strsep.c
@@ -0,0 +1,67 @@
+/* $OpenBSD: strsep.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strsep.c,v 1.1 1998/01/13 16:25:42 lha Exp $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRSEP
+
+char *
+strsep(char **str, const char *delim)
+{
+ char *save = *str;
+ if(*str == NULL)
+ return NULL;
+ *str = *str + strcspn(*str, delim);
+ if(**str == 0)
+ *str = NULL;
+ else{
+ **str = 0;
+ (*str)++;
+ }
+ return save;
+}
+
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/strtok_r.c b/usr.sbin/afs/src/lib/roken/strtok_r.c
new file mode 100644
index 00000000000..f202bd307a2
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strtok_r.c
@@ -0,0 +1,71 @@
+/* $OpenBSD: strtok_r.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strtok_r.c,v 1.1 1998/01/13 16:25:43 lha Exp $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRTOK_R
+
+char *
+strtok_r(char *s1, const char *s2, char **lasts)
+{
+ char *ret;
+
+ if (s1 == NULL)
+ s1 = *lasts;
+ while(*s1 && strchr(s2, *s1))
+ ++s1;
+ if(*s1 == '\0')
+ return NULL;
+ ret = s1;
+ while(*s1 && !strchr(s2, *s1))
+ ++s1;
+ if(*s1)
+ *s1++ = '\0';
+ *lasts = s1;
+ return ret;
+}
+
+#endif /* HAVE_STRTOK_R */
diff --git a/usr.sbin/afs/src/lib/roken/strupr.c b/usr.sbin/afs/src/lib/roken/strupr.c
new file mode 100644
index 00000000000..f5c9ea74a57
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/strupr.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: strupr.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strupr.c,v 1.2 1998/03/13 00:32:33 art Exp $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include <roken.h>
+
+#ifndef HAVE_STRUPR
+char *
+strupr(char *str)
+{
+ char *s;
+
+ for(s = str; *s; s++)
+ *s = toupper((int)*s);
+ return str;
+}
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/tm2time.c b/usr.sbin/afs/src/lib/roken/tm2time.c
new file mode 100644
index 00000000000..ab8336882d8
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/tm2time.c
@@ -0,0 +1,67 @@
+/* $OpenBSD: tm2time.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: tm2time.c,v 1.1 1998/01/13 16:25:44 lha Exp $");
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include "roken.h"
+
+time_t
+tm2time (struct tm tm, int local)
+{
+ time_t t;
+
+ tm.tm_isdst = -1;
+
+ t = mktime (&tm);
+
+ if (!local)
+ t += t - mktime (gmtime (&t));
+ return t;
+}
diff --git a/usr.sbin/afs/src/lib/roken/unsetenv.c b/usr.sbin/afs/src/lib/roken/unsetenv.c
new file mode 100644
index 00000000000..891d6f00def
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/unsetenv.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: unsetenv.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: unsetenv.c,v 1.1 1998/01/13 16:25:45 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "roken.h"
+
+extern char **environ;
+
+/*
+ * unsetenv --
+ */
+void
+unsetenv(const char *name)
+{
+ int len;
+ const char *np;
+ char **p;
+
+ if (name == 0 || environ == 0)
+ return;
+
+ for (np = name; *np && *np != '='; np++)
+ /* nop */;
+ len = np - name;
+
+ for (p = environ; *p != 0; p++)
+ if (strncmp(*p, name, len) == 0 && (*p)[len] == '=')
+ break;
+
+ for (; *p != 0; p++)
+ *p = *(p + 1);
+}
+
diff --git a/usr.sbin/afs/src/lib/roken/verify.c b/usr.sbin/afs/src/lib/roken/verify.c
new file mode 100644
index 00000000000..f7440232d43
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/verify.c
@@ -0,0 +1,68 @@
+/* $OpenBSD: verify.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verify.c,v 1.1 1998/01/13 16:25:45 lha Exp $");
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#include "roken.h"
+
+int
+unix_verify_user(char *user, char *password)
+{
+ struct passwd *pw;
+
+ pw = k_getpwnam(user);
+ if(pw == NULL)
+ return -1;
+ if(strlen(pw->pw_passwd) == 0 && strlen(password) == 0)
+ return 0;
+ if(strcmp(crypt(password, pw->pw_passwd), pw->pw_passwd) == 0)
+ return 0;
+ return -1;
+}
+
diff --git a/usr.sbin/afs/src/lib/roken/verr.c b/usr.sbin/afs/src/lib/roken/verr.c
new file mode 100644
index 00000000000..127422c0aaa
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/verr.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: verr.c,v 1.1.1.1 1998/09/14 21:53:07 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verr.c,v 1.1 1998/01/13 16:25:46 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+verr(int eval, const char *fmt, va_list ap)
+{
+ warnerr(1, eval, 1, fmt, ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/verrx.c b/usr.sbin/afs/src/lib/roken/verrx.c
new file mode 100644
index 00000000000..eb88bc1b1c3
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/verrx.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: verrx.c,v 1.1.1.1 1998/09/14 21:53:08 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verrx.c,v 1.1 1998/01/13 16:25:46 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+verrx(int eval, const char *fmt, va_list ap)
+{
+ warnerr(1, eval, 0, fmt, ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/vsyslog.c b/usr.sbin/afs/src/lib/roken/vsyslog.c
new file mode 100644
index 00000000000..d01a1f363be
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/vsyslog.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: vsyslog.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vsyslog.c,v 1.1 1998/01/13 16:25:47 lha Exp $");
+#endif
+
+#ifndef HAVE_VSYSLOG
+
+#include <stdio.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "roken.h"
+
+void
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+ char *p;
+
+ asprintf (&p, fmt, ap);
+ syslog (pri, "%s", p);
+ free (p);
+}
+
+#endif
diff --git a/usr.sbin/afs/src/lib/roken/vwarn.c b/usr.sbin/afs/src/lib/roken/vwarn.c
new file mode 100644
index 00000000000..5b66020bece
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/vwarn.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: vwarn.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vwarn.c,v 1.1 1998/01/13 16:25:47 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+vwarn(const char *fmt, va_list ap)
+{
+ warnerr(0, 0, 1, fmt, ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/vwarnx.c b/usr.sbin/afs/src/lib/roken/vwarnx.c
new file mode 100644
index 00000000000..6b58e3b5b84
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/vwarnx.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: vwarnx.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vwarnx.c,v 1.1 1998/01/13 16:25:48 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+vwarnx(const char *fmt, va_list ap)
+{
+ warnerr(0, 0, 0, fmt, ap);
+}
+
diff --git a/usr.sbin/afs/src/lib/roken/warn.c b/usr.sbin/afs/src/lib/roken/warn.c
new file mode 100644
index 00000000000..aca96c6dd0d
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/warn.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: warn.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warn.c,v 1.1 1998/01/13 16:25:48 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/warnerr.c b/usr.sbin/afs/src/lib/roken/warnerr.c
new file mode 100644
index 00000000000..e838f4b557c
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/warnerr.c
@@ -0,0 +1,87 @@
+/* $OpenBSD: warnerr.c,v 1.1.1.1 1998/09/14 21:53:09 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warnerr.c,v 1.1 1998/01/13 16:25:49 lha Exp $");
+#endif
+
+#include "roken.h"
+#include "err.h"
+
+#ifndef HAVE___PROGNAME
+const char *__progname;
+#endif
+
+void
+set_progname(char *argv0)
+{
+#ifndef HAVE___PROGNAME
+ char *p;
+ if(argv0 == NULL)
+ return;
+ p = strrchr(argv0, '/');
+ if(p == NULL)
+ p = argv0;
+ else
+ p++;
+ __progname = p;
+#endif
+}
+
+void
+warnerr(int doexit, int eval, int doerrno, const char *fmt, va_list ap)
+{
+ int sverrno = errno;
+ if(__progname != NULL){
+ fprintf(stderr, "%s", __progname);
+ if(fmt != NULL || doerrno)
+ fprintf(stderr, ": ");
+ }
+ if (fmt != NULL){
+ vfprintf(stderr, fmt, ap);
+ if(doerrno)
+ fprintf(stderr, ": ");
+ }
+ if(doerrno)
+ fprintf(stderr, "%s", strerror(sverrno));
+ fprintf(stderr, "\n");
+ if(doexit)
+ exit(eval);
+}
diff --git a/usr.sbin/afs/src/lib/roken/warnx.c b/usr.sbin/afs/src/lib/roken/warnx.c
new file mode 100644
index 00000000000..450d9586768
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/warnx.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: warnx.c,v 1.1.1.1 1998/09/14 21:53:10 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warnx.c,v 1.1 1998/01/13 16:25:49 lha Exp $");
+#endif
+
+#include "err.h"
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
diff --git a/usr.sbin/afs/src/lib/roken/writev.c b/usr.sbin/afs/src/lib/roken/writev.c
new file mode 100644
index 00000000000..170cd337dce
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/writev.c
@@ -0,0 +1,70 @@
+/* $OpenBSD: writev.c,v 1.1.1.1 1998/09/14 21:53:10 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: writev.c,v 1.1 1998/01/13 16:25:50 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t
+writev(int d, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+
+ for(i = 0; i < iovcnt; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ p = buf;
+ for (i = 0; i < iovcnt; ++i) {
+ memcpy (p, iov[i].iov_base, iov[i].iov_len);
+ p += iov[i].iov_len;
+ }
+ ret = write (d, buf, tot);
+ free (buf);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/lib/roken/xdbm.h b/usr.sbin/afs/src/lib/roken/xdbm.h
new file mode 100644
index 00000000000..d40bd530e06
--- /dev/null
+++ b/usr.sbin/afs/src/lib/roken/xdbm.h
@@ -0,0 +1,76 @@
+/* $OpenBSD: xdbm.h,v 1.1.1.1 1998/09/14 21:53:10 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: xdbm.h,v 1.1 1998/01/13 16:25:50 lha Exp $ */
+
+/* Generic *dbm include file */
+
+#ifndef __XDBM_H__
+#define __XDBM_H__
+
+#ifdef HAVE_NDBM_H
+#include <ndbm.h>
+#elif defined(HAVE_DBM_H)
+#include <dbm.h>
+#elif defined(HAVE_RPCSVC_DBM_H)
+#include <rpcsvc/dbm.h>
+#endif
+
+/* Macros to convert ndbm names to dbm names.
+ * Note that dbm_nextkey() cannot be simply converted using a macro, since
+ * it is invoked giving the database, and nextkey() needs the previous key.
+ *
+ * Instead, all routines call "dbm_next" instead.
+ */
+
+#ifndef NDBM
+typedef char DBM;
+
+#define dbm_open(file, flags, mode) ((dbminit(file) == 0)?"":((char *)0))
+#define dbm_fetch(db, key) fetch(key)
+#define dbm_store(db, key, content, flag) store(key, content)
+#define dbm_delete(db, key) delete(key)
+#define dbm_firstkey(db) firstkey()
+#define dbm_next(db,key) nextkey(key)
+#define dbm_close(db) dbmclose()
+#else
+#define dbm_next(db,key) dbm_nextkey(db)
+#endif
+
+#endif /* __XDBM_H__ */
diff --git a/usr.sbin/afs/src/lib/sl/ChangeLog b/usr.sbin/afs/src/lib/sl/ChangeLog
new file mode 100644
index 00000000000..03b31d9b56f
--- /dev/null
+++ b/usr.sbin/afs/src/lib/sl/ChangeLog
@@ -0,0 +1,8 @@
+Tue Mar 3 00:03:17 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (install): removed '-m 444'
+
+Mon Oct 20 01:13:21 1997 Assar Westerlund <assar@sics.se>
+
+ * sl.c (sl_help): actually use the `help' field of `SL_cmd'
+
diff --git a/usr.sbin/afs/src/lib/sl/sl.c b/usr.sbin/afs/src/lib/sl/sl.c
new file mode 100644
index 00000000000..1fe6c6356f2
--- /dev/null
+++ b/usr.sbin/afs/src/lib/sl/sl.c
@@ -0,0 +1,285 @@
+/* $OpenBSD: sl.c,v 1.1.1.1 1998/09/14 21:53:10 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: sl.c,v 1.3 1998/06/21 21:35:58 lha Exp $");
+#endif
+
+#include "sl_locl.h"
+
+static void
+mandoc_template(SL_cmd *cmds,
+ const char *extra_string)
+{
+ SL_cmd *c, *prev;
+ char timestr[64], cmd[64];
+ const char *p;
+ time_t t;
+
+ printf(".\\\" Things to fix:\n");
+ printf(".\\\" * correct section, and operating system\n");
+ printf(".\\\" * remove Op from mandatory flags\n");
+ printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
+ printf(".\\\"\n");
+ t = time(NULL);
+ strftime(timestr, sizeof(timestr), "%b %d, %Y", localtime(&t));
+ printf(".Dd %s\n", timestr);
+ p = strrchr(__progname, '/');
+ if(p) p++; else p = __progname;
+ strncpy(cmd, p, sizeof(cmd));
+ cmd[sizeof(cmd)-1] = '\0';
+ strupr(cmd);
+
+ printf(".Dt %s SECTION\n", cmd);
+ printf(".Os OPERATING_SYSTEM\n");
+ printf(".Sh NAME\n");
+ printf(".Nm %s\n", p);
+ printf(".Nd\n");
+ printf("in search of a description\n");
+ printf(".Sh SYNOPSIS\n");
+ printf(".Nm\n");
+ for(c = cmds; c->name; ++c) {
+/* if (c->func == NULL)
+ continue; */
+ printf(".Op Fl %s", c->name);
+/* print_sl(stdout, 1, 0, c);*/
+ printf("\n");
+
+ }
+ if (extra_string && *extra_string)
+ printf (".Ar %s\n", extra_string);
+ printf(".Sh DESCRIPTION\n");
+ printf("Supported options:\n");
+ printf(".Bl -tag -width Ds\n");
+ prev = NULL;
+ for(c = cmds; c->name; ++c) {
+ if (c->func) {
+ if (prev)
+ printf ("\n%s\n", prev->usage);
+
+ printf (".It Fl %s", c->name);
+ prev = c;
+ } else
+ printf (", %s\n", c->name);
+ }
+ if (prev)
+ printf ("\n%s\n", prev->usage);
+
+ printf(".El\n");
+ printf(".\\\".Sh ENVIRONMENT\n");
+ printf(".\\\".Sh FILES\n");
+ printf(".\\\".Sh EXAMPLES\n");
+ printf(".\\\".Sh DIAGNOSTICS\n");
+ printf(".\\\".Sh SEE ALSO\n");
+ printf(".\\\".Sh STANDARDS\n");
+ printf(".\\\".Sh HISTORY\n");
+ printf(".\\\".Sh AUTHORS\n");
+ printf(".\\\".Sh BUGS\n");
+}
+
+static SL_cmd *
+sl_match (SL_cmd *cmds, char *cmd, int exactp)
+{
+ SL_cmd *c, *current = NULL, *partial_cmd = NULL;
+ int partial_match = 0;
+
+ for (c = cmds; c->name; ++c) {
+ if (c->func)
+ current = c;
+ if (strcmp (cmd, c->name) == 0)
+ return current;
+ else if (strncmp (cmd, c->name, strlen(cmd)) == 0 &&
+ partial_cmd != current) {
+ ++partial_match;
+ partial_cmd = current;
+ }
+ }
+ if (partial_match == 1 && !exactp)
+ return partial_cmd;
+ else
+ return NULL;
+}
+
+void
+sl_help (SL_cmd *cmds, int argc, char **argv)
+{
+ SL_cmd *c, *prev_c;
+
+ if (getenv("SLMANDOC")) {
+ mandoc_template(cmds, NULL);
+ return;
+ }
+
+ if (argc == 1) {
+ prev_c = NULL;
+ for (c = cmds; c->name; ++c) {
+ if (c->func) {
+ if(prev_c)
+ printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
+ prev_c->usage ? "\n" : "");
+ prev_c = c;
+ printf ("%s", c->name);
+ } else
+ printf (", %s", c->name);
+ }
+ if(prev_c)
+ printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
+ prev_c->usage ? "\n" : "");
+ } else {
+ c = sl_match (cmds, argv[1], 0);
+ if (c == NULL)
+ printf ("No such command: %s. "
+ "Try \"help\" for a list of all commands\n",
+ argv[1]);
+ else {
+ printf ("%s\t%s", c->name, c->usage);
+ if(c->help && *c->help)
+ printf ("%s\n", c->help);
+ if((++c)->name && c->func == NULL) {
+ printf ("\nSynonyms:");
+ while (c->name && c->func == NULL)
+ printf ("\t%s", (c++)->name);
+ }
+ printf ("\n");
+ }
+ }
+}
+
+#ifdef HAVE_READLINE
+
+char *readline(char *prompt);
+void add_history(char *p);
+
+#else
+
+static char *
+readline(char *prompt)
+{
+ char buf[BUFSIZ];
+ printf ("%s", prompt);
+ fflush (stdout);
+ if(fgets(buf, sizeof(buf), stdin) == NULL)
+ return NULL;
+ if (buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ return strdup(buf);
+}
+
+static void
+add_history(char *p)
+{
+}
+
+#endif
+
+int
+sl_command(SL_cmd *cmds, int argc, char **argv)
+{
+ SL_cmd *c;
+ c = sl_match (cmds, argv[0], 0);
+ if (c == NULL)
+ return SL_BADCOMMAND;
+ return (*c->func)(argc, argv);
+}
+
+int
+sl_loop (SL_cmd *cmds, char *prompt)
+{
+ unsigned max_count;
+ char **ptr;
+ int ret;
+
+ max_count = 17;
+ ptr = malloc(max_count * sizeof(*ptr));
+ if (ptr == NULL) {
+ printf ("sl_loop: failed to allocate %u bytes of memory\n",
+ (int) max_count * sizeof(*ptr));
+ return -1;
+ }
+
+ for (;;) {
+ char *buf;
+ unsigned count;
+ SL_cmd *c;
+
+ ret = 0;
+ buf = readline(prompt);
+ if(buf == NULL)
+ break;
+
+ if(*buf)
+ add_history(buf);
+ count = 0;
+ {
+ char *foo = NULL;
+ char *p;
+
+ for(p = strtok_r (buf, " \t", &foo);
+ p;
+ p = strtok_r (NULL, " \t", &foo)) {
+ if(count == max_count) {
+ max_count *= 2;
+ ptr = realloc (ptr, max_count * sizeof(*ptr));
+ if (ptr == NULL) {
+ printf ("sl_loop: failed to allocate %u "
+ "bytes of memory\n",
+ (unsigned) max_count * sizeof(*ptr));
+ return -1;
+ }
+ }
+ ptr[count++] = p;
+ }
+ }
+ if (count > 0) {
+ c = sl_match (cmds, ptr[0], 0);
+ if (c) {
+ ret = (*c->func)(count, ptr);
+ if (ret != 0) {
+ free (buf);
+ break;
+ }
+ } else
+ printf ("Unrecognized command: %s\n", ptr[0]);
+ }
+ free(buf);
+ }
+ free (ptr);
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lib/sl/sl.h b/usr.sbin/afs/src/lib/sl/sl.h
new file mode 100644
index 00000000000..222ef8575a8
--- /dev/null
+++ b/usr.sbin/afs/src/lib/sl/sl.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: sl.h,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: sl.h,v 1.2 1998/06/21 21:35:59 lha Exp $ */
+
+#ifndef _SL_H
+#define _SL_H
+
+#define SL_BADCOMMAND -1
+
+typedef int (*cmd_func)(int, char **);
+
+struct sl_cmd {
+ char *name;
+ cmd_func func;
+ char *usage;
+ char *help;
+};
+
+typedef struct sl_cmd SL_cmd;
+
+void sl_help (SL_cmd *, int argc, char **argv);
+int sl_loop (SL_cmd *, char *prompt);
+int sl_command (SL_cmd *cmds, int argc, char **argv);
+
+
+#endif /* _SL_H */
diff --git a/usr.sbin/afs/src/lib/sl/sl_locl.h b/usr.sbin/afs/src/lib/sl/sl_locl.h
new file mode 100644
index 00000000000..28ace952a2a
--- /dev/null
+++ b/usr.sbin/afs/src/lib/sl/sl_locl.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: sl_locl.h,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: sl_locl.h,v 1.1 1998/01/13 19:33:51 lha Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <roken.h>
+
+#include <sl.h>
diff --git a/usr.sbin/afs/src/lwp/fasttime.c b/usr.sbin/afs/src/lwp/fasttime.c
new file mode 100644
index 00000000000..08128ac0508
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/fasttime.c
@@ -0,0 +1,184 @@
+/* $OpenBSD: fasttime.c,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+/*
+ * fasttime.c -- Get the time of day quickly by mapping the kernel's
+ * time of day variable.
+ *
+ * David Nichols
+ * 6 January 1986
+ *
+ * Modification History
+ * 3/21/86: Added FT_ApproxTime which returns the last time
+ * in seconds returned by RT_FastTime. The intent is to give
+ * routines which aren't too concerned about the exact time
+ * fast access to the time, even on kernels without mmap.
+ * - Bob Sidebotham.
+ * 4/2/86: Fixed my previous mod and fixed FT_Init so it doesn't initialize
+ * a second time if explicitly called after being implicitly called.
+ * This saves a (precious) file descriptor.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: fasttime.c,v 1.6 1998/03/28 16:35:44 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#ifndef AFS_AIX_ENV
+#include <sys/mman.h>
+#endif
+
+#ifdef HAVE_NLIST_H
+#include <nlist.h>
+#else
+#ifdef HAVE_LIBELF_NLIST_H
+#include <libelf/nlist.h>
+#endif
+#endif
+#ifdef USE_MMAPTIME
+#include <mmaptime.h>
+#endif
+
+
+extern char *valloc();
+int ft_debug;
+
+#define TRUE 1
+#define FALSE 0
+
+static enum InitState {
+ notTried, tried, done
+} initState = notTried;
+
+/* last time returned by RT_FastTime. Used to implement FT_ApproxTime */
+struct timeval FT_LastTime;
+
+
+/*
+ * Call this to get the memory mapped. It will return -1 if anything went
+ * wrong. In that case, calls to FT_GetTimeOfDay will call gettimeofday
+ * instead. If printErrors is true, errors in initialization will cause
+ * error messages to be printed on stderr. If notReally is true, then
+ * things are set up so that all calls to FT_GetTimeOfDay call gettimeofday.
+ * You might want this if your program won't run too long and the nlist
+ * call is too expensive. Yeah, it's pretty horrible.
+ */
+int
+FT_Init(int printErrors, int notReally)
+{
+
+ /*
+ * This is in case explicit initialization occurs after automatic
+ * initialization
+ */
+ if (initState != notTried && !notReally)
+ return (initState == done ? 0 : -1);
+
+ initState = tried;
+ if (notReally)
+ return 0; /* fake success, but leave initState
+ * wrong. */
+#ifdef USE_MMAPTIME
+ printErrors = mmaptime_probe();
+#endif
+
+ if (printErrors)
+ fprintf(stderr, "FT_Init: mmap not implemented on this kernel\n");
+ return (-1);
+}
+
+/*
+ * Call this to get the time of day. It will automatically initialize the
+ * first time you call it. If you want error messages when you initialize,
+ * call FT_Init yourself. If the initialization failed, this will just
+ * call gettimeofday. If you ask for the timezone info, this routine will
+ * punt to gettimeofday.
+ */
+int
+FT_GetTimeOfDay(register struct timeval * tv, register struct timezone * tz)
+{
+ register int ret;
+
+#ifdef USE_MMAPTIME
+ ret = mmaptime_gettimeofday(tv, tz);
+#else
+ ret = gettimeofday(tv, tz);
+#endif
+ if (!ret) {
+
+ /*
+ * need to bounds check 'cause Unix can fail these checks, (esp on
+ * Suns) and time package can generate invalid (to select syscall)
+ * values for the time until the next interesting event if it
+ * encounters out of range microsecond fields
+ */
+ if (tv->tv_usec < 0)
+ tv->tv_usec = 0;
+ if (tv->tv_usec > 999999)
+ tv->tv_usec = 999999;
+ FT_LastTime.tv_sec = tv->tv_sec;
+ FT_LastTime.tv_usec = tv->tv_usec;
+ }
+ return ret;
+}
+
+
+/* For compatibility. Should go away. */
+int
+TM_GetTimeOfDay(struct timeval * tv, struct timezone * tz)
+{
+ return FT_GetTimeOfDay(tv, tz);
+}
+
+int
+FT_AGetTimeOfDay(struct timeval * tv, struct timezone * tz)
+{
+#ifdef USE_MMAPTIME
+ return mmaptime_gettimeofday(tv, tz);
+#else
+ if (FT_LastTime.tv_sec) {
+ tv->tv_sec = FT_LastTime.tv_sec;
+ tv->tv_usec = FT_LastTime.tv_usec;
+ return 0;
+ }
+ return FT_GetTimeOfDay(tv, tz);
+#endif
+}
+
+unsigned int
+FT_ApproxTime(void)
+{
+#ifdef USE_MMAPTIME
+ mmaptime_gettimeofday(&FT_LastTime, NULL);
+#else
+ if (!FT_LastTime.tv_sec) {
+ FT_GetTimeOfDay(&FT_LastTime, 0);
+ }
+#endif
+ return FT_LastTime.tv_sec;
+}
+
+
+
diff --git a/usr.sbin/afs/src/lwp/iomgr.c b/usr.sbin/afs/src/lwp/iomgr.c
new file mode 100644
index 00000000000..9c3d943938f
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/iomgr.c
@@ -0,0 +1,868 @@
+/* $OpenBSD: iomgr.c,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+* *
+\*******************************************************************/
+
+
+/*
+ * IO Manager routines & server process for VICE server.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: iomgr.c,v 1.18 1998/07/09 19:56:27 art Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "lwp.h"
+#include <sys/time.h>
+#include "timer.h"
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include "q.h"
+#include <unistd.h>
+#include <string.h>
+#include <roken.h>
+
+/* Prototypes */
+static void SignalIO(int, fd_set *, fd_set *, fd_set *) ;
+static void SignalTimeout(int fds, struct timeval *timeout) ;
+static int SignalSignals (void);
+
+int FT_GetTimeOfDay(register struct timeval *, register struct timezone *);
+
+/********************************\
+* *
+* Stuff for managing IoRequests *
+* *
+\********************************/
+
+struct IoRequest {
+
+ /* Pid of process making request (for use in IOMGR_Cancel) */
+ PROCESS pid;
+
+ /* Descriptor masks for requests */
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+
+ fd_set *rfds;
+ fd_set *wfds;
+ fd_set *efds;
+
+ int nfds;
+
+ struct TM_Elem timeout;
+
+ /* Result of select call */
+ int result;
+ struct IoRequest *next;
+};
+
+/********************************\
+* *
+* Stuff for managing signals *
+* *
+\********************************/
+
+#define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
+#define mysigmask(signo) (1 << ((signo)-1))
+
+extern int errno;
+
+static long openMask; /* mask of open files on an IOMGR abort */
+static long sigsHandled; /* sigmask(signo) is on if we handle signo */
+static int anySigsDelivered; /* true if any have been delivered. */
+#ifdef AFS_POSIX_SIGNALS
+static struct sigaction oldVecs[NSIG]; /* the old signal vectors */
+#else
+static struct sigvec oldVecs[NSIG]; /* the old signal vectors */
+#endif
+static char *sigEvents[NSIG]; /* the event to do an LWP signal on */
+static int sigDelivered[NSIG]; /*
+ * True for signals delivered so far.
+ * This is an int array to make sure
+ * there are no conflicts when trying
+ * to write it
+ */
+/* software 'signals' */
+#define NSOFTSIG 4
+static void (*sigProc[NSOFTSIG])();
+static char *sigRock[NSOFTSIG];
+
+
+static struct IoRequest *iorFreeList = 0;
+
+static struct TM_Elem *Requests; /* List of requests */
+static struct timeval iomgr_timeout; /* global so signal handler can zap it */
+
+/* stuff for debugging */
+static int iomgr_errno;
+static struct timeval iomgr_badtv;
+static PROCESS iomgr_badpid;
+
+void
+FreeRequest(struct IoRequest *req)
+{
+ req->next = iorFreeList;
+ iorFreeList = req;
+}
+
+/* stuff for handling select fd_sets */
+
+#ifndef FD_COPY
+#define FD_COPY(f, t) memcpy((t), (f), sizeof(*(f)))
+#endif
+
+/*
+ * FD_OR - bitwise or of two fd_sets
+ * The result goes into set1
+ */
+static void
+FD_OR(fd_set *set1, fd_set *set2)
+{
+ int i;
+
+#ifdef FD_SPEED_HACK
+ unsigned long *s1 = (unsigned long *)set1;
+ unsigned long *s2 = (unsigned long *)set2;
+
+ for (i = 0; i < sizeof(fd_set)/sizeof(unsigned long); i++)
+ s1[i] |= s2[i];
+#else
+ for (i = 0; i < FD_SETSIZE; i++)
+ if (FD_ISSET(i, set1) || FD_ISSET(i, set2))
+ FD_SET(i, set1);
+#endif
+}
+
+/*
+ * FD_AND - bitwise and of two fd_sets
+ * The result goes into set1
+ */
+static void
+FD_AND(fd_set *set1, fd_set *set2)
+{
+ int i;
+
+#ifdef FD_SPEED_HACK
+ unsigned long *s1 = (unsigned long *)set1;
+ unsigned long *s2 = (unsigned long *)set2;
+
+ for(i = 0; i < sizeof(fd_set)/sizeof(unsigned long); i++)
+ s1[i] &= s2[i];
+#else
+ for(i = 0; i < FD_SETSIZE; i++)
+ if (FD_ISSET(i, set1) && FD_ISSET(i, set2))
+ FD_SET(i, set1);
+#endif
+}
+
+/*
+ * FD_LOGAND - "logical" and of two fd_sets
+ * returns 0 if there are no fds that are the same in both fd_sets
+ * otherwise it returns 1
+ */
+static int
+FD_LOGAND(fd_set *set1, fd_set *set2)
+{
+#ifdef FD_SPEED_HACK
+ int i;
+
+ unsigned long *s1 = (unsigned long *)set1;
+ unsigned long *s2 = (unsigned long *)set2;
+
+ for(i = 0; i < sizeof(fd_set)/sizeof(unsigned long); i++)
+ if ((s1[i] & s2[i]) != 0)
+ return 1;
+ return 0;
+#else
+ fd_set tmp;
+
+ FD_COPY(set1, &tmp);
+ FD_AND(&tmp, set2);
+
+ return !FD_ISZERO(&tmp);
+#endif
+}
+
+static struct IoRequest *
+NewRequest(void)
+{
+ register struct IoRequest *request;
+
+ if ((request = iorFreeList) != NULL)
+ iorFreeList = request->next;
+ else
+ request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
+
+ return request;
+}
+
+#define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
+#define MAX_FDS 32
+
+/* The IOMGR process */
+
+/*
+ * Important invariant: process->iomgrRequest is null iff request not in
+ * timer queue also, request->pid is valid while request is in queue, also,
+ * don't signal selector while request in queue, since selector free's request.
+ */
+
+static void
+IOMGR(char *dummy)
+{
+ for (;;) {
+ /*
+ * commented out to match use - kazar
+ * static struct timeval Poll = { 0, 0 };
+ */
+ int fds;
+ int nfds;
+ fd_set readfds, writefds, exceptfds;
+ fd_set *rfds, *wfds, *efds;
+ struct TM_Elem *earliest;
+ struct timeval timeout, junk;
+ bool woke_someone;
+
+ /*
+ * Wake up anyone who has expired or who has received a
+ * Unix signal between executions. Keep going until we
+ * run out.
+ */
+ do {
+ woke_someone = FALSE;
+ /* Wake up anyone waiting on signals. */
+ /* Note: SignalSignals() may yield! */
+ if (anySigsDelivered && SignalSignals ())
+ woke_someone = TRUE;
+ TM_Rescan(Requests);
+ for (;;) {
+ register struct IoRequest *req;
+ struct TM_Elem *expired;
+ expired = TM_GetExpired(Requests);
+ if (expired == NULL) break;
+ woke_someone = TRUE;
+ req = (struct IoRequest *) expired -> BackPointer;
+#ifdef DEBUG
+ if (lwp_debug != 0) puts("[Polling SELECT]");
+#endif /* DEBUG */
+ FD_ZERO(&req->readfds);
+ FD_ZERO(&req->writefds);
+ FD_ZERO(&req->exceptfds);
+ /* no data ready */
+ req->nfds = 0;
+ req->rfds = req->wfds = req->efds = NULL;
+
+ req->result = 0;
+ /* no fds ready */
+
+ TM_Remove(Requests, &req->timeout);
+#ifdef DEBUG
+ req -> timeout.Next = (struct TM_Elem *) 2;
+ req -> timeout.Prev = (struct TM_Elem *) 2;
+#endif /* DEBUG */
+ LWP_QSignal(req->pid);
+ req->pid->iomgrRequest = 0;
+ }
+ if (woke_someone) LWP_DispatchProcess();
+ } while (woke_someone);
+
+
+ /* Collect requests & update times */
+ FD_ZERO(&readfds); /* XXX - should not be needed */
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ nfds = 0;
+ rfds = wfds = efds = NULL;
+ FOR_ALL_ELTS(r, Requests, {
+ register struct IoRequest *req;
+ req = (struct IoRequest *) r -> BackPointer;
+ if (req->rfds) {
+ if (rfds)
+ FD_OR(rfds, req->rfds);
+ else {
+ rfds = &readfds;
+ FD_COPY(req->rfds, rfds);
+ }
+ }
+
+ if (req->wfds) {
+ if (wfds)
+ FD_OR(wfds, req->wfds);
+ else {
+ wfds = &readfds;
+ FD_COPY(req->wfds, wfds);
+ }
+ }
+
+ if (req->efds) {
+ if (efds)
+ FD_OR(efds, req->efds);
+ else {
+ efds = &readfds;
+ FD_COPY(req->efds, efds);
+ }
+ }
+ nfds = max(nfds, req->nfds);
+ })
+ earliest = TM_GetEarliest(Requests);
+ if (earliest != NULL) {
+ timeout = earliest -> TimeLeft;
+
+ /* Do select */
+#ifdef DEBUG
+ if (lwp_debug != 0) {
+ printf("[select(%d, %p, %p, %p, ", nfds,
+ rfds, wfds, efds);
+ if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
+ puts("INFINITE)]");
+ else
+ printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec);
+ }
+#endif /* DEBUG */
+ iomgr_timeout = timeout;
+ if (timeout.tv_sec == -1 && timeout.tv_usec == -1) {
+ /* infinite, sort of */
+ iomgr_timeout.tv_sec = 100000000;
+ iomgr_timeout.tv_usec = 0;
+ }
+ /*
+ * Check one last time for a signal delivery. If one comes after
+ * this, the signal handler will set iomgr_timeout to zero,
+ * causing the select to return immediately. The timer package
+ * won't return a zero timeval because all of those guys were
+ * handled above.
+ *
+ * I'm assuming that the kernel masks signals while it's picking up
+ * the parameters to select. This may a bad assumption. -DN
+ */
+ if (anySigsDelivered)
+ continue; /* go to the top and handle them. */
+
+ /*
+ * select runs much faster if NULL's are passed instead of &0s
+ */
+
+ fds = select(nfds, rfds, wfds, efds, &iomgr_timeout);
+
+ /*
+ * For SGI and SVR4 - poll & select can return EAGAIN ...
+ */
+ if (fds < 0 && errno != EINTR && errno != EAGAIN) {
+ iomgr_errno = errno;
+ for(fds = 0; fds < FD_SETSIZE; fds++) {
+ if (fcntl(fds, F_GETFD, 0) < 0 && errno == EBADF)
+ openMask |= (1<<fds);
+ }
+ abort();
+ }
+
+ /* force a new gettimeofday call so FT_AGetTimeOfDay calls work */
+ FT_GetTimeOfDay(&junk, 0);
+
+ /* See what happened */
+ if (fds > 0)
+ /* Action -- wake up everyone involved */
+ SignalIO(fds, rfds, wfds, efds);
+ else if (fds == 0
+ && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0))
+ /* Real timeout only if signal handler hasn't set
+ iomgr_timeout to zero. */
+ SignalTimeout(fds, &timeout);
+
+ }
+ LWP_DispatchProcess();
+ }
+}
+
+/************************\
+* *
+* Signalling routines *
+* *
+\************************/
+
+static void
+SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efds)
+{
+ /* Look at everyone who's bit mask was affected */
+ FOR_ALL_ELTS(r, Requests, {
+ register struct IoRequest *req;
+ register PROCESS pid;
+ int doit = 0;
+ req = (struct IoRequest *) r -> BackPointer;
+
+ if (rfds && req->rfds && FD_LOGAND(req->rfds, rfds)) {
+ FD_AND(req->rfds, rfds);
+ doit = 1;
+ }
+ if (wfds && req->wfds && FD_LOGAND(req->wfds, wfds)) {
+ FD_AND(req->wfds, wfds);
+ doit = 1;
+ }
+ if (efds && req->efds && FD_LOGAND(req->efds, efds)) {
+ FD_AND(req->efds, efds);
+ doit = 1;
+ }
+
+ if (doit) {
+ req -> result = fds;
+ TM_Remove(Requests, &req->timeout);
+ LWP_QSignal(pid=req->pid);
+ pid->iomgrRequest = 0;
+
+ }
+ })
+}
+
+static void
+SignalTimeout(int fds, register struct timeval *timeout)
+{
+ /* Find everyone who has specified timeout */
+ FOR_ALL_ELTS(r, Requests, {
+ register struct IoRequest *req;
+ register PROCESS pid;
+ req = (struct IoRequest *) r -> BackPointer;
+ if (TM_eql(&r->TimeLeft, timeout)) {
+ req -> result = fds;
+ TM_Remove(Requests, &req->timeout);
+ LWP_QSignal(pid=req->pid);
+ pid->iomgrRequest = 0;
+ } else
+ return;
+ })
+}
+
+/*****************************************************\
+* *
+* Signal handling routine (not to be confused with *
+* signalling routines, above). *
+* *
+\*****************************************************/
+static RETSIGTYPE
+SigHandler (int signo)
+{
+ if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
+ return; /* can't happen. */
+ sigDelivered[signo] = TRUE;
+ anySigsDelivered = TRUE;
+ /* Make sure that the IOMGR process doesn't pause on the select. */
+ iomgr_timeout.tv_sec = 0;
+ iomgr_timeout.tv_usec = 0;
+}
+
+/* Alright, this is the signal signalling routine. It delivers LWP signals
+ to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
+static int
+SignalSignals (void)
+{
+ bool gotone = FALSE;
+ register int i;
+ register void (*p)();
+ long stackSize;
+
+ anySigsDelivered = FALSE;
+
+ /* handle software signals */
+ stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen?
+ lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
+ for (i=0; i < NSOFTSIG; i++) {
+ PROCESS pid;
+ if ((p = sigProc[i]) != NULL) /* This yields!!! */
+ LWP_CreateProcess(p, stackSize, LWP_NORMAL_PRIORITY, sigRock[i],
+ "SignalHandler", &pid);
+ sigProc[i] = 0;
+ }
+
+ for (i = 1; i <= NSIG; ++i) /* forall !badsig(i) */
+ if ((sigsHandled & mysigmask(i)) && sigDelivered[i] == TRUE) {
+ sigDelivered[i] = FALSE;
+ LWP_NoYieldSignal (sigEvents[i]);
+ gotone = TRUE;
+ }
+ return gotone;
+}
+
+
+/***************************\
+* *
+* User-callable routines *
+* *
+\***************************/
+
+
+/* Keep IOMGR process id */
+static PROCESS IOMGR_Id = NULL;
+
+int
+IOMGR_SoftSig(void (*aproc)(), char *arock)
+{
+ register int i;
+ for (i=0;i<NSOFTSIG;i++) {
+ if (sigProc[i] == 0) {
+ /* a free entry */
+ sigProc[i] = aproc;
+ sigRock[i] = arock;
+ anySigsDelivered = TRUE;
+ iomgr_timeout.tv_sec = 0;
+ iomgr_timeout.tv_usec = 0;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int
+IOMGR_Initialize(void)
+{
+ extern int TM_Init();
+ PROCESS pid;
+
+ /* If lready initialized, just return */
+ if (IOMGR_Id != NULL) return LWP_SUCCESS;
+
+ /* Init LWP if someone hasn't yet. */
+ if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid)
+ != LWP_SUCCESS)
+ return -1;
+
+ /* Initialize request lists */
+ if (TM_Init(&Requests) < 0) return -1;
+
+ /* Initialize signal handling stuff. */
+ sigsHandled = 0;
+ anySigsDelivered = TRUE; /*
+ * A soft signal may have happened before
+ * IOMGR_Initialize: so force a check for
+ * signals regardless
+ */
+
+ return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0,
+ "IO MANAGER", &IOMGR_Id);
+}
+
+int
+IOMGR_Finalize(void)
+{
+ int status;
+
+ Purge(Requests)
+ TM_Final(&Requests);
+ status = LWP_DestroyProcess(IOMGR_Id);
+ IOMGR_Id = NULL;
+ return status;
+}
+
+/*
+ * signal I/O for anyone who is waiting for a FD or a timeout;
+ * not too cheap, since forces select and timeofday check
+ */
+long
+IOMGR_Poll(void)
+{
+ fd_set readfds, writefds, exceptfds;
+ fd_set *rfds, *wfds, *efds;
+ long code;
+ struct timeval tv;
+ int nfds;
+
+ FT_GetTimeOfDay(&tv, 0); /* force accurate time check */
+ TM_Rescan(Requests);
+ for (;;) {
+ register struct IoRequest *req;
+ struct TM_Elem *expired;
+ expired = TM_GetExpired(Requests);
+ if (expired == NULL) break;
+ req = (struct IoRequest *) expired -> BackPointer;
+#ifdef DEBUG
+ if (lwp_debug != 0) puts("[Polling SELECT]");
+#endif /* DEBUG */
+ /* no data ready */
+
+ FD_ZERO(&req->readfds);
+ FD_ZERO(&req->writefds);
+ FD_ZERO(&req->exceptfds);
+
+ req->nfds = 0;
+ req->rfds = req->wfds = req->efds = NULL;
+
+ req->result = 0; /* no fds ready */
+ TM_Remove(Requests, &req->timeout);
+#ifdef DEBUG
+ req -> timeout.Next = (struct TM_Elem *) 2;
+ req -> timeout.Prev = (struct TM_Elem *) 2;
+#endif /* DEBUG */
+ LWP_QSignal(req->pid);
+ req->pid->iomgrRequest = 0;
+ }
+
+ /* Collect requests & update times */
+ FD_ZERO(&readfds); /* XXX - should not be needed */
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ rfds = wfds = efds = NULL;
+ nfds = 0;
+ FOR_ALL_ELTS(r, Requests, {
+ struct IoRequest *req;
+ req = (struct IoRequest *) r -> BackPointer;
+
+ if (req->rfds) {
+ if (rfds)
+ FD_OR(rfds, req->rfds);
+ else {
+ rfds = &readfds;
+ FD_COPY(req->rfds, rfds);
+ }
+ }
+
+ if (req->wfds) {
+ if (wfds)
+ FD_OR(wfds, req->wfds);
+ else {
+ wfds = &readfds;
+ FD_COPY(req->wfds, wfds);
+ }
+ }
+
+ if (req->efds) {
+ if (efds)
+ FD_OR(efds, req->efds);
+ else {
+ efds = &readfds;
+ FD_COPY(req->efds, efds);
+ }
+ }
+ nfds = max(nfds, req->nfds);
+ })
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ code = select(nfds, &readfds, &writefds, &exceptfds, &tv);
+
+ if (code > 0) {
+ SignalIO(code, rfds, wfds, efds);
+ }
+
+ LWP_DispatchProcess(); /* make sure others run */
+ LWP_DispatchProcess();
+ return 0;
+}
+
+int
+IOMGR_Select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout)
+{
+ register struct IoRequest *request;
+ int result;
+
+ /* See if polling request. If so, handle right here */
+ if (timeout != NULL) {
+ if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ int fds;
+#ifdef DEBUG
+ if (lwp_debug != 0) puts("[Polling SELECT]");
+#endif /* DEBUG */
+
+ do {
+ timeout->tv_sec = 0;
+ timeout->tv_usec = 0;
+ fds = select(nfds, readfds, writefds, exceptfds,
+ timeout);
+ } while (fds < 0 && errno == EAGAIN);
+
+ return (fds > 1 ? 1 : fds);
+ }
+ }
+
+ /* Construct request block & insert */
+ request = NewRequest();
+ if (readfds == NULL)
+ request->rfds = NULL;
+ else {
+ request->rfds = &request->readfds;
+ FD_COPY(readfds, request->rfds);
+ }
+
+ if (writefds == NULL)
+ request->wfds = NULL;
+ else {
+ request->wfds = &request->writefds;
+ FD_COPY(writefds, request->wfds);
+ }
+
+ if (exceptfds == NULL)
+ request->efds = NULL;
+ else {
+ request->efds = &request->exceptfds;
+ FD_COPY(exceptfds, request->efds);
+ }
+
+ request->nfds = nfds;
+
+ if (timeout == NULL) {
+ request -> timeout.TotalTime.tv_sec = -1;
+ request -> timeout.TotalTime.tv_usec = -1;
+ } else {
+ request -> timeout.TotalTime = *timeout;
+ /* check for bad request */
+ if (timeout->tv_sec < 0 ||
+ timeout->tv_usec < 0 ||
+ timeout->tv_usec > 999999) {
+ /* invalid arg */
+ iomgr_badtv = *timeout;
+ iomgr_badpid = LWP_ActiveProcess;
+ /* now fixup request */
+ if(request->timeout.TotalTime.tv_sec < 0)
+ request->timeout.TotalTime.tv_sec = 1;
+ request->timeout.TotalTime.tv_usec = 100000;
+ }
+ }
+
+ request -> timeout.BackPointer = (char *) request;
+
+ /* Insert my PID in case of IOMGR_Cancel */
+ request -> pid = LWP_ActiveProcess;
+ LWP_ActiveProcess -> iomgrRequest = request;
+
+#ifdef DEBUG
+ request -> timeout.Next = (struct TM_Elem *) 1;
+ request -> timeout.Prev = (struct TM_Elem *) 1;
+#endif /* DEBUG */
+ TM_Insert(Requests, &request->timeout);
+
+ /* Wait for action */
+ LWP_QWait();
+
+ /* Update parameters & return */
+ if (readfds != NULL) FD_COPY(&request->readfds, readfds);
+ if (writefds != NULL) FD_COPY(&request->writefds, writefds);
+ if (exceptfds != NULL) FD_COPY(&request->exceptfds, exceptfds);
+ result = request -> result;
+ FreeRequest(request);
+ return (result > 1 ? 1 : result);
+}
+
+int
+IOMGR_Cancel(register PROCESS pid)
+{
+ register struct IoRequest *request;
+
+ if ((request = pid->iomgrRequest) == 0) return -1; /* Pid not found */
+
+ FD_ZERO(&request->readfds);
+ FD_ZERO(&request->writefds);
+ FD_ZERO(&request->exceptfds);
+ request->rfds = request->wfds = request->efds = NULL;
+ request->nfds = 0;
+
+ request -> result = -2;
+ TM_Remove(Requests, &request->timeout);
+#ifdef DEBUG
+ request -> timeout.Next = (struct TM_Elem *) 5;
+ request -> timeout.Prev = (struct TM_Elem *) 5;
+#endif /* DEBUG */
+ LWP_QSignal(request->pid);
+ pid->iomgrRequest = 0;
+
+ return 0;
+}
+
+/*
+ * Cause delivery of signal signo to result in a LWP_SignalProcess of
+ * event.
+ */
+int
+IOMGR_Signal (int signo, char *event)
+{
+#ifdef AFS_POSIX_SIGNALS
+ struct sigaction sa;
+#else
+ struct sigvec sv;
+#endif
+
+ if (badsig(signo))
+ return LWP_EBADSIG;
+ if (event == NULL)
+ return LWP_EBADEVENT;
+#ifdef AFS_POSIX_SIGNALS
+ sa.sa_handler = SigHandler;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags=0;
+#else
+ sv.sv_handler = SigHandler;
+ sv.sv_mask = ~0; /* mask all signals */
+ sv.sv_onstack = 0;
+#endif
+ sigsHandled |= mysigmask(signo);
+ sigEvents[signo] = event;
+ sigDelivered[signo] = FALSE;
+#ifdef AFS_POSIX_SIGNALS
+ if (sigaction (signo, &sa, &oldVecs[signo]) == -1)
+ return LWP_ESYSTEM;
+#else
+ if (sigvec (signo, &sv, &oldVecs[signo]) == -1)
+ return LWP_ESYSTEM;
+#endif
+ return LWP_SUCCESS;
+}
+
+/* Stop handling occurances of signo. */
+int
+IOMGR_CancelSignal (int signo)
+{
+ if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
+ return LWP_EBADSIG;
+#ifdef AFS_POSIX_SIGNALS
+ sigaction (signo, &oldVecs[signo], (struct sigaction *)0);
+#else
+ sigvec (signo, &oldVecs[signo], (struct sigvec *)0);
+#endif
+ sigsHandled &= ~mysigmask(signo);
+ return LWP_SUCCESS;
+}
+
+/*
+ * This routine calls select is a fashion that simulates the standard
+ * sleep routine
+ */
+void
+IOMGR_Sleep (unsigned int seconds)
+{
+ struct timeval timeout;
+
+ timeout.tv_sec = seconds;
+ timeout.tv_usec = 0;
+ IOMGR_Select(0, NULL, NULL, NULL, &timeout);
+}
diff --git a/usr.sbin/afs/src/lwp/lock.c b/usr.sbin/afs/src/lwp/lock.c
new file mode 100644
index 00000000000..6e7f5c0d6fa
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/lock.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: lock.c,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+* *
+\*******************************************************************/
+
+/*
+ * Locking routines for Vice.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+RCSID("$KTH: lock.c,v 1.7 1998/01/27 19:58:27 art Exp $");
+#endif
+#include "lwp.h"
+#include "lock.h"
+#include <stdio.h>
+#include <sys/time.h>
+
+
+#define FALSE 0
+#define TRUE 1
+
+void
+Lock_Init(register struct Lock *lock)
+{
+ lock -> readers_reading = 0;
+ lock -> excl_locked = 0;
+ lock -> wait_states = 0;
+ lock -> num_waiting = 0;
+}
+
+void
+Lock_Obtain(register struct Lock *lock, int how)
+{
+ switch (how) {
+
+ case READ_LOCK: lock->num_waiting++;
+ do {
+ lock -> wait_states |= READ_LOCK;
+ LWP_WaitProcess(&lock->readers_reading);
+ } while (lock->excl_locked & WRITE_LOCK);
+ lock->num_waiting--;
+ lock->readers_reading++;
+ break;
+
+ case WRITE_LOCK: lock->num_waiting++;
+ do {
+ lock -> wait_states |= WRITE_LOCK;
+ LWP_WaitProcess(&lock->excl_locked);
+ } while (lock->excl_locked || lock->readers_reading);
+ lock->num_waiting--;
+ lock->excl_locked = WRITE_LOCK;
+ break;
+
+ case SHARED_LOCK: lock->num_waiting++;
+ do {
+ lock->wait_states |= SHARED_LOCK;
+ LWP_WaitProcess(&lock->excl_locked);
+ } while (lock->excl_locked);
+ lock->num_waiting--;
+ lock->excl_locked = SHARED_LOCK;
+ break;
+
+ case BOOSTED_LOCK: lock->num_waiting++;
+ do {
+ lock->wait_states |= WRITE_LOCK;
+ LWP_WaitProcess(&lock->excl_locked);
+ } while (lock->readers_reading);
+ lock->num_waiting--;
+ lock->excl_locked = WRITE_LOCK;
+ break;
+
+ default: printf("Can't happen, bad LOCK type: %d\n", how);
+ abort();
+ }
+}
+
+/* release a lock, giving preference to new readers */
+void
+Lock_ReleaseR(register struct Lock *lock)
+{
+ if (lock->wait_states & READ_LOCK) {
+ lock->wait_states &= ~READ_LOCK;
+ LWP_NoYieldSignal(&lock->readers_reading);
+ }
+ else {
+ lock->wait_states &= ~EXCL_LOCKS;
+ LWP_NoYieldSignal(&lock->excl_locked);
+ }
+}
+
+/* release a lock, giving preference to new writers */
+void
+Lock_ReleaseW(register struct Lock *lock)
+{
+ if (lock->wait_states & EXCL_LOCKS) {
+ lock->wait_states &= ~EXCL_LOCKS;
+ LWP_NoYieldSignal(&lock->excl_locked);
+ }
+ else {
+ lock->wait_states &= ~READ_LOCK;
+ LWP_NoYieldSignal(&lock->readers_reading);
+ }
+}
+
+/*
+ * These next guys exist to provide an interface to drop a lock atomically with
+ * blocking. They're trivial to do in a non-preemptive LWP environment.
+ */
+
+/* release a write lock and sleep on an address, atomically */
+void
+LWP_WaitProcessR(register char *addr, register struct Lock *alock)
+{
+ ReleaseReadLock(alock);
+ LWP_WaitProcess(addr);
+}
+
+/* release a write lock and sleep on an address, atomically */
+void
+LWP_WaitProcessW(register char *addr, register struct Lock *alock)
+{
+ ReleaseWriteLock(alock);
+ LWP_WaitProcess(addr);
+}
+
+/* release a write lock and sleep on an address, atomically */
+void
+LWP_WaitProcessS(register char *addr, register struct Lock *alock)
+{
+ ReleaseSharedLock(alock);
+ LWP_WaitProcess(addr);
+}
+
+#ifndef HAVE___FUNCTION__
+#define __FUNCTION__ "unknown"
+#endif
+
+#define PANICPRINT(msg) fprintf(stderr,"Panic in %s at %s:%d: %s\n", __FUNCTION__, __FILE__, __LINE__, msg)
+
+static int
+WillBlock (register struct Lock *lock, int how)
+{
+ switch (how) {
+ case READ_LOCK:
+ return ((lock)->excl_locked & WRITE_LOCK) || (lock)->wait_states;
+ case WRITE_LOCK:
+ return (lock)->excl_locked || (lock)->readers_reading;
+ case SHARED_LOCK:
+ return (lock)->excl_locked || (lock)->wait_states;
+ default:
+ PANICPRINT("unknown locking type");
+ return 1; /* Block if unknown */
+ }
+}
+
+static void
+ObtainOneLock(register struct Lock *lock, int how)
+{
+ switch (how) {
+ case READ_LOCK:
+ if (!WillBlock(lock, how))
+ (lock) -> readers_reading++;
+ else
+ Lock_Obtain(lock, how);
+ break;
+ case WRITE_LOCK:
+ case SHARED_LOCK:
+ if (!WillBlock(lock, how))
+ (lock) -> excl_locked = how;
+ else
+ Lock_Obtain(lock, how);
+ break;
+ default:
+ PANICPRINT("unknown locking type");
+ fprintf(stderr,"%d\n",how);
+ }
+}
+
+static void
+ReleaseOneLock(register struct Lock *lock, int how)
+{
+ switch(how) {
+ case READ_LOCK:
+ if (!--(lock)->readers_reading && (lock)->wait_states)
+ Lock_ReleaseW(lock);
+ break;
+ case WRITE_LOCK:
+ (lock)->excl_locked &= ~WRITE_LOCK;
+ if ((lock)->wait_states) Lock_ReleaseR(lock);
+ break;
+ case SHARED_LOCK:
+ (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);
+ if ((lock)->wait_states) Lock_ReleaseR(lock);
+ break;
+ default:
+ PANICPRINT("unknown locking type");
+ }
+}
+
+/*
+ * Obtains two locks in a secure fashion (that's the idea)
+ *
+ * Takes two locks and two locking modes as parameters.
+ */
+
+void
+_ObtainTwoLocks(register struct Lock *lock1, int how1,
+ register struct Lock *lock2, int how2)
+{
+ struct timeval timeout;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1000;
+
+start:
+ ObtainOneLock(lock1, how1);
+ if (WillBlock(lock2, how2)) {
+ ReleaseOneLock(lock1, how1);
+ IOMGR_Select(0, 0, 0, 0, &timeout);
+ goto start;
+ } else {
+ ObtainOneLock(lock2, how2);
+ }
+}
diff --git a/usr.sbin/afs/src/lwp/lock.h b/usr.sbin/afs/src/lwp/lock.h
new file mode 100644
index 00000000000..07f383b9dc4
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/lock.h
@@ -0,0 +1,225 @@
+/* $OpenBSD: lock.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/lock.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/lock.h,v $ */
+
+#ifndef LOCK_H
+#define LOCK_H
+
+#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
+static char *rcsidlock = "$Header: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/lock.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $";
+#endif
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+* *
+\*******************************************************************/
+
+/*
+ Include file for using Vice locking routines.
+*/
+
+/* The following macros allow multi statement macros to be defined safely, i.e.
+ - the multi statement macro can be the object of an if statement;
+ - the call to the multi statement macro may be legally followed by a semi-colon.
+ BEGINMAC and ENDMAC have been tested with both the portable C compiler and
+ Hi-C. Both compilers were from the Palo Alto 4.2BSD software releases, and
+ both optimized out the constant loop code. For an example of the use
+ of BEGINMAC and ENDMAC, see the definition for ReleaseWriteLock, below.
+ An alternative to this, using "if(1)" for BEGINMAC is not used because it
+ may generate worse code with pcc, and may generate warning messages with hi-C.
+*/
+
+#define BEGINMAC do {
+#define ENDMAC } while (0)
+
+/* all locks wait on excl_locked except for READ_LOCK, which waits on readers_reading */
+struct Lock {
+ unsigned char wait_states; /* type of lockers waiting */
+ unsigned char excl_locked; /* anyone have boosted, shared or write lock? */
+ unsigned char readers_reading; /* # readers actually with read locks */
+ unsigned char num_waiting; /* probably need this soon */
+};
+
+/* Prototypes */
+
+void Lock_ReleaseR(register struct Lock *);
+void Lock_ReleaseW(register struct Lock *);
+void Lock_Obtain(register struct Lock *, int);
+void Lock_Init(register struct Lock *);
+
+#define READ_LOCK 1
+#define WRITE_LOCK 2
+#define SHARED_LOCK 4
+/* this next is not a flag, but rather a parameter to Lock_Obtain */
+#define BOOSTED_LOCK 6
+
+/* next defines wait_states for which we wait on excl_locked */
+#define EXCL_LOCKS (WRITE_LOCK|SHARED_LOCK)
+
+#ifdef LOCK_DEBUG
+#define DEBUGWRITE(message,lock) do { \
+ fprintf(stderr,message,lock,__FILE__,__LINE__); } while (0)
+#define DEBUGWRITE_4(message,lock1,how1,lock2,how2) do { \
+ fprintf(stderr,message,lock1,how1,lock2,how2,__FILE__,__LINE__); } while (0)
+#else
+#define DEBUGWRITE(message,lock) do { ; } while (0)
+#define DEBUGWRITE_4(message,lock1,how1,lock2,how2) do { ; } while (0)
+#endif
+#define ObtainReadLock(lock) \
+ BEGINMAC\
+ DEBUGWRITE("ObtainReadLock: %p at %s:%d starting\n",lock);\
+ if (!((lock)->excl_locked & WRITE_LOCK) && !(lock)->wait_states)\
+ (lock) -> readers_reading++;\
+ else\
+ Lock_Obtain(lock, READ_LOCK);\
+ DEBUGWRITE("ObtainReadLock: %p at %s:%d got it\n",lock);\
+ ENDMAC
+
+#define ObtainWriteLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("ObtainWriteLock: %p at %s:%d starting\n",lock);\
+ if (!(lock)->excl_locked && !(lock)->readers_reading)\
+ (lock) -> excl_locked = WRITE_LOCK;\
+ else\
+ Lock_Obtain(lock, WRITE_LOCK);\
+ DEBUGWRITE("ObtainReadLock: %p at %s:%d got it\n",lock);\
+ ENDMAC
+
+#define ObtainSharedLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("ObtainSharedLock: %p at %s:%d starting\n",lock);\
+ if (!(lock)->excl_locked && !(lock)->wait_states)\
+ (lock) -> excl_locked = SHARED_LOCK;\
+ else\
+ Lock_Obtain(lock, SHARED_LOCK);\
+ DEBUGWRITE("ObtainSharedLock: %p at %s:%d got it\n",lock);\
+ ENDMAC
+
+#define BoostSharedLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("BoostSharedLock: %p at %s:%d starting\n",lock);\
+ if (!(lock)->readers_reading)\
+ (lock)->excl_locked = WRITE_LOCK;\
+ else\
+ Lock_Obtain(lock, BOOSTED_LOCK);\
+ DEBUGWRITE("BoostSharedLock: %p at %s:%d got it\n",lock);\
+ ENDMAC
+
+/* this must only be called with a WRITE or boosted SHARED lock! */
+#define UnboostSharedLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("UnboostSharedLock: %p at %s:%d\n",lock);\
+ (lock)->excl_locked = SHARED_LOCK; \
+ if((lock)->wait_states) \
+ Lock_ReleaseR(lock); \
+ ENDMAC
+
+#ifdef notdef
+/* this is what UnboostSharedLock looked like before the hi-C compiler */
+/* this must only be called with a WRITE or boosted SHARED lock! */
+#define UnboostSharedLock(lock)\
+ ((lock)->excl_locked = SHARED_LOCK,\
+ ((lock)->wait_states ?\
+ Lock_ReleaseR(lock) : 0))
+#endif /* notdef */
+
+#define ReleaseReadLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("ReleaseReadLock: %p at %s:%d\n",lock);\
+ if (!--(lock)->readers_reading && (lock)->wait_states)\
+ Lock_ReleaseW(lock) ; \
+ ENDMAC
+
+
+#ifdef notdef
+/* This is what the previous definition should be, but the hi-C compiler generates
+ a warning for each invocation */
+#define ReleaseReadLock(lock)\
+ (!--(lock)->readers_reading && (lock)->wait_states ?\
+ Lock_ReleaseW(lock) :\
+ 0)
+#endif /* notdef */
+
+#define ReleaseWriteLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("ReleaseWriteLock: %p at %s:%d\n",lock);\
+ (lock)->excl_locked &= ~WRITE_LOCK;\
+ if ((lock)->wait_states) Lock_ReleaseR(lock);\
+ ENDMAC
+
+#ifdef notdef
+/* This is what the previous definition should be, but the hi-C compiler generates
+ a warning for each invocation */
+#define ReleaseWriteLock(lock)\
+ ((lock)->excl_locked &= ~WRITE_LOCK,\
+ ((lock)->wait_states ?\
+ Lock_ReleaseR(lock) : 0))
+#endif /* notdef */
+
+/* can be used on shared or boosted (write) locks */
+#define ReleaseSharedLock(lock)\
+ BEGINMAC\
+ DEBUGWRITE("ReleaseLock: %p at %s:%d\n",lock);\
+ (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
+ if ((lock)->wait_states) Lock_ReleaseR(lock);\
+ ENDMAC
+
+#ifdef notdef
+/* This is what the previous definition should be, but the hi-C compiler generates
+ a warning for each invocation */
+/* can be used on shared or boosted (write) locks */
+#define ReleaseSharedLock(lock)\
+ ((lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK),\
+ ((lock)->wait_states ?\
+ Lock_ReleaseR(lock) : 0))
+#endif /* notdef */
+
+
+/* I added this next macro to make sure it is safe to nuke a lock -- Mike K. */
+#define LockWaiters(lock)\
+ ((int) ((lock)->num_waiting))
+
+#define CheckLock(lock)\
+ ((lock)->excl_locked? (int) -1 : (int) (lock)->readers_reading)
+
+#define WriteLocked(lock)\
+ ((lock)->excl_locked & WRITE_LOCK)
+
+/* This attempts to obtain two locks in a secure fashion */
+
+#define ObtainTwoLocks(lock1, how1, lock2, how2) \
+ BEGINMAC\
+ DEBUGWRITE_4("ObtainTwoLocks: %p(%d) %p(%d) at %s:%d\n",lock1,how1,lock2,how2);\
+ _ObtainTwoLocks(lock1, how1, lock2, how2);\
+ ENDMAC
+
+void
+_ObtainTwoLocks(register struct Lock *lock1, int how1,
+ register struct Lock *lock2, int how2);
+
+#endif /* LOCK_H */
diff --git a/usr.sbin/afs/src/lwp/lwp.c b/usr.sbin/afs/src/lwp/lwp.c
new file mode 100644
index 00000000000..f9163252362
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/lwp.c
@@ -0,0 +1,1055 @@
+/* $OpenBSD: lwp.c,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+\*******************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* allocate externs here */
+#define LWP_KERNEL
+
+#include "lwp.h"
+
+RCSID("$KTH: lwp.c,v 1.10 1998/02/22 20:02:25 joda Exp $");
+
+#ifdef AFS_AIX32_ENV
+#include <ulimit.h>
+#include <sys/errno.h>
+#include <sys/user.h>
+#include <sys/pseg.h>
+#include <sys/core.h>
+#pragma alloca
+#endif
+
+extern char PRE_Block; /* from preempt.c */
+
+#define ON 1
+#define OFF 0
+#define TRUE 1
+#define FALSE 0
+#define READY 2
+#define WAITING 3
+#define DESTROYED 4
+#define QWAITING 5
+#define MAXINT (~(1<<((sizeof(int)*8)-1)))
+#define MINSTACK 44
+
+
+/*
+ * I don't really know if this is the right thing to do, but
+ * now I don't get any unalinged memory access on my alpha /lha
+ */
+
+#ifdef __alpha
+#define REGSIZE 8
+#else
+#define REGSIZE 4
+#endif
+
+
+#ifdef __hp9000s800
+#define MINFRAME 64
+#endif
+
+/* Debugging macro */
+#ifdef DEBUG
+#define Debug(level, msg)\
+ if (lwp_debug && lwp_debug >= level) {\
+ printf("***LWP (%p): ", lwp_cpptr);\
+ printf msg;\
+ putchar('\n');\
+ }
+
+#else
+#define Debug(level, msg)
+
+#endif
+
+/* Prototypes */
+static void Abort_LWP(char *msg) ;
+static void Dispatcher(void);
+static void Create_Process_Part2(void);
+static void purge_dead_pcbs(void) ;
+static void Overflow_Complain (void) ;
+static void Dispose_of_Dead_PCB (PROCESS cur) ;
+static void Free_PCB(PROCESS pid) ;
+static void Exit_LWP();
+static void Initialize_PCB(PROCESS temp, int priority, char *stack,
+ int stacksize, void (*ep)() , char *parm,
+ char *name) ;
+static long Initialize_Stack(char *stackptr,int stacksize) ;
+static int Stack_Used(char *stackptr, int stacksize) ;
+static int Internal_Signal(register char *event) ;
+char (*RC_to_ASCII());
+
+#define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
+
+struct QUEUE {
+ PROCESS head;
+ int count;
+} runnable[MAX_PRIORITIES], blocked;
+/*
+ * Invariant for runnable queues: The head of each queue points to the
+ * currently running process if it is in that queue, or it points to the
+ * next process in that queue that should run.
+ */
+
+/* Offset of stack field within pcb -- used by stack checking stuff */
+int stack_offset;
+
+/* special user-tweakable option for AIX */
+int lwp_MaxStackSize = 32768;
+
+/* biggest LWP stack created so far */
+int lwp_MaxStackSeen = 0;
+
+/* Stack checking action */
+int lwp_overflowAction = LWP_SOABORT;
+
+/* Controls stack size counting. */
+int lwp_stackUseEnabled = TRUE; /* pay the price */
+
+int lwp_nextindex;
+
+static void
+lwp_remove(register PROCESS p, register struct QUEUE *q)
+{
+ /* Special test for only element on queue */
+ if (q->count == 1)
+ q -> head = NULL;
+ else {
+ /* Not only element, do normal remove */
+ p -> next -> prev = p -> prev;
+ p -> prev -> next = p -> next;
+ }
+ /* See if head pointing to this element */
+ if (q->head == p) q -> head = p -> next;
+ q->count--;
+ p -> next = p -> prev = NULL;
+}
+
+static void
+insert(register PROCESS p, register struct QUEUE *q)
+{
+ if (q->head == NULL) { /* Queue is empty */
+ q -> head = p;
+ p -> next = p -> prev = p;
+ } else { /* Regular insert */
+ p -> prev = q -> head -> prev;
+ q -> head -> prev -> next = p;
+ q -> head -> prev = p;
+ p -> next = q -> head;
+ }
+ q->count++;
+}
+
+static void
+move(PROCESS p, struct QUEUE *from, struct QUEUE *to)
+{
+ lwp_remove(p, from);
+
+ insert(p, to);
+}
+
+/* Iterator macro */
+#define for_all_elts(var, q, body)\
+ {\
+ register PROCESS var, _NEXT_;\
+ register int _I_;\
+ for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
+ _NEXT_ = var -> next;\
+ body\
+ }\
+ }
+
+/* */
+/*****************************************************************************\
+* *
+* Following section documents the Assembler interfaces used by LWP code *
+* *
+\*****************************************************************************/
+
+/*
+ * savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
+ * XXX - the above prototype is a lie.
+ * Stub for Assembler routine that will
+ * save the current SP value in the passed
+ * context savearea and call the function
+ * whose entry point is in ep. If the sp
+ * parameter is NULL, the current stack is
+ * used, otherwise sp becomes the new stack
+ * pointer.
+ *
+ * returnto(struct lwp_context *savearea);
+ *
+ * Stub for Assembler routine that will
+ * restore context from a passed savearea
+ * and return to the restored C frame.
+ *
+ */
+
+void savecontext(void (*)(), struct lwp_context *, char *);
+void returnto(struct lwp_context *);
+
+/* Macro to force a re-schedule. Strange name is historical */
+#define Set_LWP_RC() savecontext(Dispatcher, &lwp_cpptr->context, NULL)
+
+static struct lwp_ctl *lwp_init = 0;
+
+int
+LWP_QWait(void)
+{
+ register PROCESS tp;
+ (tp=lwp_cpptr) -> status = QWAITING;
+ lwp_remove(tp, &runnable[tp->priority]);
+ Set_LWP_RC();
+ return LWP_SUCCESS;
+}
+
+int
+LWP_QSignal(register PROCESS pid)
+{
+ if (pid->status == QWAITING) {
+ pid->status = READY;
+ insert(pid, &runnable[pid->priority]);
+ return LWP_SUCCESS;
+ }
+ else return LWP_ENOWAIT;
+}
+
+#ifdef AFS_AIX32_ENV
+char *
+reserveFromStack(size)
+ register long size;
+{
+ char *x;
+ x = alloca(size);
+ return x;
+}
+#endif
+
+int
+LWP_CreateProcess(void (*ep)(), int stacksize, int priority,
+ char *parm, char *name, PROCESS *pid)
+{
+ PROCESS temp, temp2;
+#ifdef AFS_AIX32_ENV
+ static char *stackptr = 0;
+#else
+ char *stackptr;
+#endif
+
+#if defined(AFS_LWP_MINSTACKSIZE)
+ /*
+ * on some systems (e.g. hpux), a minimum usable stack size has
+ * been discovered
+ */
+ if (stacksize < AFS_LWP_MINSTACKSIZE) {
+ stacksize = AFS_LWP_MINSTACKSIZE;
+ }
+#endif /* defined(AFS_LWP_MINSTACKSIZE) */
+ /* more stack size computations; keep track of for IOMGR */
+ if (lwp_MaxStackSeen < stacksize)
+ lwp_MaxStackSeen = stacksize;
+
+ Debug(0, ("Entered LWP_CreateProcess"))
+ /* Throw away all dead process control blocks */
+ purge_dead_pcbs();
+ if (lwp_init) {
+ temp = (PROCESS) malloc (sizeof (struct lwp_pcb));
+ if (temp == NULL) {
+ Set_LWP_RC();
+ return LWP_ENOMEM;
+ }
+ if (stacksize < MINSTACK)
+ stacksize = 1000;
+ else
+#ifdef __hp9000s800
+ stacksize = 8 * ((stacksize+7) / 8);
+#else
+ stacksize = REGSIZE * ((stacksize+REGSIZE-1) / REGSIZE);
+#endif
+#ifdef AFS_AIX32_ENV
+ if (!stackptr) {
+ /*
+ * The following signal action for AIX is necessary so that in case of a
+ * crash (i.e. core is generated) we can include the user's data section
+ * in the core dump. Unfortunately, by default, only a partial core is
+ * generated which, in many cases, isn't too useful.
+ *
+ * We also do it here in case the main program forgets to do it.
+ */
+ struct sigaction nsa;
+ extern int geteuid();
+
+ sigemptyset(&nsa.sa_mask);
+ nsa.sa_handler = SIG_DFL;
+ nsa.sa_flags = SA_FULLDUMP;
+ sigaction(SIGSEGV, &nsa, NULL);
+
+ /*
+ * First we need to increase the default resource limits,
+ * if necessary, so that we can guarantee that we have the
+ * resources to create the core file, but we can't always
+ * do it as an ordinary user.
+ */
+ if (!geteuid()) {
+ setlim(RLIMIT_FSIZE, 0, 1048575); /* 1 Gig */
+ setlim(RLIMIT_STACK, 0, 65536); /* 65 Meg */
+ setlim(RLIMIT_CORE, 0, 131072); /* 131 Meg */
+ }
+ /*
+ * Now reserve in one scoop all the stack space that will be used
+ * by the particular application's main (i.e. non-lwp) body. This
+ * is plenty space for any of our applications.
+ */
+ stackptr = reserveFromStack(lwp_MaxStackSize);
+ }
+ stackptr -= stacksize;
+#else
+ if ((stackptr = (char *) malloc(stacksize)) == NULL) {
+ Set_LWP_RC();
+ return LWP_ENOMEM;
+ }
+#endif
+ if (priority < 0 || priority >= MAX_PRIORITIES) {
+ Set_LWP_RC();
+ return LWP_EBADPRI;
+ }
+ Initialize_Stack(stackptr, stacksize);
+ Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
+ insert(temp, &runnable[priority]);
+ temp2 = lwp_cpptr;
+ if (PRE_Block != 0) Abort_LWP("PRE_Block not 0");
+
+ /* Gross hack: beware! */
+ PRE_Block = 1;
+ lwp_cpptr = temp;
+#ifdef __hp9000s800
+ savecontext(Create_Process_Part2, &temp2->context, stackptr+MINFRAME);
+#else
+ savecontext(Create_Process_Part2, &temp2->context,
+ stackptr+stacksize-REGSIZE);
+#endif
+ /* End of gross hack */
+
+ Set_LWP_RC();
+ *pid = temp;
+ return 0;
+ } else
+ return LWP_EINIT;
+}
+
+/* returns pid of current process */
+int
+LWP_CurrentProcess(PROCESS *pid)
+{
+ Debug(0, ("Entered Current_Process"))
+ if (lwp_init) {
+ *pid = lwp_cpptr;
+ return LWP_SUCCESS;
+ } else
+ return LWP_EINIT;
+}
+
+#define LWPANCHOR (*lwp_init)
+
+/* destroy a lightweight process */
+int
+LWP_DestroyProcess(PROCESS pid)
+{
+ PROCESS temp;
+
+ Debug(0, ("Entered Destroy_Process"))
+ if (lwp_init) {
+ if (lwp_cpptr != pid) {
+ Dispose_of_Dead_PCB(pid);
+ Set_LWP_RC();
+ } else {
+ pid -> status = DESTROYED;
+ move(pid, &runnable[pid->priority], &blocked);
+ temp = lwp_cpptr;
+#ifdef __hp9000s800
+ savecontext(Dispatcher, &(temp -> context),
+ &(LWPANCHOR.dsptchstack[MINFRAME]));
+#else
+ savecontext(Dispatcher, &(temp -> context),
+ &(LWPANCHOR.dsptchstack[(sizeof LWPANCHOR.dsptchstack)-REGSIZE]));
+#endif
+ }
+ return LWP_SUCCESS;
+ } else
+ return LWP_EINIT;
+}
+
+/* explicit voluntary preemption */
+int
+LWP_DispatchProcess(void)
+{
+ Debug(2, ("Entered Dispatch_Process"))
+ if (lwp_init) {
+ Set_LWP_RC();
+ return LWP_SUCCESS;
+ } else
+ return LWP_EINIT;
+}
+
+#ifdef DEBUG
+static void Dump_One_Process(PROCESS pid);
+
+void
+Dump_Processes(void)
+{
+ if (lwp_init) {
+ register int i;
+ for (i=0; i<MAX_PRIORITIES; i++)
+ for_all_elts(x, runnable[i], {
+ printf("[Priority %d]\n", i);
+ Dump_One_Process(x);
+ })
+ for_all_elts(x, blocked, { Dump_One_Process(x); })
+ } else
+ printf("***LWP: LWP support not initialized\n");
+}
+#endif
+
+/* returns process priority */
+int
+LWP_GetProcessPriority(PROCESS pid, int *priority)
+{
+ Debug(0, ("Entered Get_Process_Priority"))
+ if (lwp_init) {
+ *priority = pid -> priority;
+ return 0;
+ } else
+ return LWP_EINIT;
+}
+
+int
+LWP_InitializeProcessSupport(int priority, PROCESS *pid)
+{
+ PROCESS temp;
+ struct lwp_pcb dummy;
+ register int i;
+
+ Debug(0, ("Entered LWP_InitializeProcessSupport"))
+ if (lwp_init != NULL) return LWP_SUCCESS;
+
+ /* Set up offset for stack checking -- do this as soon as possible */
+ stack_offset = (char *) &dummy.stack - (char *) &dummy;
+
+ if (priority >= MAX_PRIORITIES) return LWP_EBADPRI;
+ for (i=0; i<MAX_PRIORITIES; i++) {
+ runnable[i].head = NULL;
+ runnable[i].count = 0;
+ }
+ blocked.head = NULL;
+ blocked.count = 0;
+ lwp_init = (struct lwp_ctl *) malloc(sizeof(struct lwp_ctl));
+ temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
+ if (lwp_init == NULL || temp == NULL)
+ Abort_LWP("Insufficient Storage to Initialize LWP Support");
+ LWPANCHOR.processcnt = 1;
+ LWPANCHOR.outerpid = temp;
+ LWPANCHOR.outersp = NULL;
+ Initialize_PCB(temp, priority, NULL, 0, NULL, NULL,
+ "Main Process [created by LWP]");
+ insert(temp, &runnable[priority]);
+ savecontext(Dispatcher, &temp->context, NULL);
+ LWPANCHOR.outersp = temp -> context.topstack;
+ Set_LWP_RC();
+ *pid = temp;
+ return LWP_SUCCESS;
+}
+
+/* signal the occurence of an event */
+int
+LWP_INTERNALSIGNAL(void *event, int yield)
+{
+ Debug(2, ("Entered LWP_SignalProcess"))
+ if (lwp_init) {
+ int rc;
+ rc = Internal_Signal(event);
+ if (yield) Set_LWP_RC();
+ return rc;
+ } else
+ return LWP_EINIT;
+}
+
+/* terminate all LWP support */
+int
+LWP_TerminateProcessSupport(void)
+{
+ register int i;
+
+ Debug(0, ("Entered Terminate_Process_Support"))
+ if (lwp_init == NULL) return LWP_EINIT;
+ if (lwp_cpptr != LWPANCHOR.outerpid)
+ Abort_LWP("Terminate_Process_Support invoked from wrong process!");
+ for (i=0; i<MAX_PRIORITIES; i++)
+ for_all_elts(cur, runnable[i], { Free_PCB(cur); })
+ for_all_elts(cur, blocked, { Free_PCB(cur); })
+ free(lwp_init);
+ lwp_init = NULL;
+ return LWP_SUCCESS;
+}
+
+/* wait on m of n events */
+int
+LWP_MwaitProcess(int wcount, char *evlist[])
+{
+ register int ecount, i;
+
+
+ Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount))
+
+ if (evlist == NULL) {
+ Set_LWP_RC();
+ return LWP_EBADCOUNT;
+ }
+
+ for (ecount = 0; evlist[ecount] != NULL; ecount++) ;
+
+ if (ecount == 0) {
+ Set_LWP_RC();
+ return LWP_EBADCOUNT;
+ }
+
+ if (lwp_init) {
+
+ if (wcount>ecount || wcount<0) {
+ Set_LWP_RC();
+ return LWP_EBADCOUNT;
+ }
+ if (ecount > lwp_cpptr->eventlistsize) {
+
+ lwp_cpptr->eventlist = (char **)realloc(lwp_cpptr->eventlist,
+ ecount*sizeof(char *));
+ lwp_cpptr->eventlistsize = ecount;
+ }
+ for (i=0; i<ecount; i++) lwp_cpptr -> eventlist[i] = evlist[i];
+ if (wcount > 0) {
+ lwp_cpptr -> status = WAITING;
+
+ move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
+ }
+ lwp_cpptr -> wakevent = 0;
+ lwp_cpptr -> waitcnt = wcount;
+ lwp_cpptr -> eventcnt = ecount;
+
+ Set_LWP_RC();
+
+ return LWP_SUCCESS;
+ }
+
+ return LWP_EINIT;
+}
+
+/* wait on a single event */
+int
+LWP_WaitProcess(void *event)
+{
+ char *tempev[2];
+
+ Debug(2, ("Entered Wait_Process"))
+ if (event == NULL) return LWP_EBADEVENT;
+ tempev[0] = event;
+ tempev[1] = NULL;
+ return LWP_MwaitProcess(1, tempev);
+}
+
+int
+LWP_StackUsed(PROCESS pid, int *max, int *used)
+{
+ *max = pid -> stacksize;
+ *used = Stack_Used(pid->stack, *max);
+ if (*used == 0)
+ return LWP_NO_STACK;
+ return LWP_SUCCESS;
+}
+
+/*
+ * The following functions are strictly
+ * INTERNAL to the LWP support package.
+ */
+
+static void
+Abort_LWP(char *msg)
+{
+ struct lwp_context tempcontext;
+
+ Debug(0, ("Entered Abort_LWP"))
+ printf("***LWP: %s\n",msg);
+ printf("***LWP: Abort --- dumping PCBs ...\n");
+#ifdef DEBUG
+ Dump_Processes();
+#endif
+ if (LWPANCHOR.outersp == NULL)
+ Exit_LWP();
+ else
+ savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
+}
+
+/* creates a context for the new process */
+static void
+Create_Process_Part2(void)
+{
+ PROCESS temp;
+
+ Debug(2, ("Entered Create_Process_Part2"))
+ temp = lwp_cpptr; /* Get current process id */
+ savecontext(Dispatcher, &temp->context, NULL);
+ (*temp->ep)(temp->parm);
+ LWP_DestroyProcess(temp);
+}
+
+/* remove a PCB from the process list */
+static void
+Delete_PCB(register PROCESS pid)
+{
+ Debug(4, ("Entered Delete_PCB"))
+ lwp_remove(pid, (pid->blockflag ||
+ pid->status==WAITING ||
+ pid->status==DESTROYED
+ ? &blocked
+ : &runnable[pid->priority]));
+ LWPANCHOR.processcnt--;
+}
+
+#ifdef DEBUG
+static void
+Dump_One_Process(PROCESS pid)
+{
+ int i;
+
+ printf("***LWP: Process Control Block at %p\n", pid);
+ printf("***LWP: Name: %s\n", pid->name);
+ if (pid->ep != NULL)
+ printf("***LWP: Initial entry point: %p\n", pid->ep);
+ if (pid->blockflag) printf("BLOCKED and ");
+ switch (pid->status) {
+ case READY: printf("READY"); break;
+ case WAITING: printf("WAITING"); break;
+ case DESTROYED: printf("DESTROYED"); break;
+ default: printf("unknown");
+ }
+ putchar('\n');
+ printf("***LWP: Priority: %d \tInitial parameter: %p\n",
+ pid->priority, pid->parm);
+ if (pid->stacksize != 0) {
+ printf("***LWP: Stacksize: %d \tStack base address: %p\n",
+ pid->stacksize, pid->stack);
+ printf("***LWP: HWM stack usage: ");
+ printf("%d\n", Stack_Used(pid->stack,pid->stacksize));
+ free (pid->stack);
+ }
+ printf("***LWP: Current Stack Pointer: %p\n", pid->context.topstack);
+ if (pid->eventcnt > 0) {
+ printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
+ printf("***LWP: Event id list:");
+ for (i=0;i<pid->eventcnt;i++)
+ printf(" %p", pid->eventlist[i]);
+ putchar('\n');
+ }
+ if (pid->wakevent>0)
+ printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
+}
+#endif
+
+static void
+purge_dead_pcbs(void)
+{
+ for_all_elts(cur, blocked, {
+ if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);
+ })
+}
+
+int LWP_TraceProcesses = 0;
+
+/* Lightweight process dispatcher */
+static void
+Dispatcher(void)
+{
+ register int i;
+#ifdef DEBUG
+ static int dispatch_count = 0;
+
+ if (LWP_TraceProcesses > 0) {
+ for (i=0; i<MAX_PRIORITIES; i++) {
+ printf("[Priority %d, runnable (%d):", i, runnable[i].count);
+ for_all_elts(p, runnable[i], {
+ printf(" \"%s\"", p->name);
+ })
+ puts("]");
+ }
+ printf("[Blocked (%d):", blocked.count);
+ for_all_elts(p, blocked, {
+ printf(" \"%s\"", p->name);
+ })
+ puts("]");
+ }
+#endif
+
+ /*
+ * Check for stack overflow if this lwp has a stack. Check for
+ * the guard word at the front of the stack being damaged and
+ * for the stack pointer being below the front of the stack.
+ * WARNING! This code assumes that stacks grow downward.
+ */
+#ifdef __hp9000s800
+ /* Fix this (stackcheck at other end of stack???) */
+ if (lwp_cpptr != NULL && lwp_cpptr->stack != NULL
+ && (lwp_cpptr->stackcheck !=
+ *(long *)((lwp_cpptr->stack) + lwp_cpptr->stacksize - 4)
+ || lwp_cpptr->context.topstack >
+ lwp_cpptr->stack + lwp_cpptr->stacksize - 4)) {
+#else
+ if (lwp_cpptr != NULL && lwp_cpptr->stack != NULL
+ && (lwp_cpptr->stackcheck != *(long *)(lwp_cpptr->stack)
+ || lwp_cpptr->context.topstack < lwp_cpptr->stack)) {
+#endif
+
+ printf("stackcheck = %lul: stack = %lul\n",
+ lwp_cpptr->stackcheck,
+ *(long *)lwp_cpptr->stack);
+ printf("topstack = %lul\n", *(long *)lwp_cpptr->context.topstack);
+
+ switch (lwp_overflowAction) {
+ case LWP_SOQUIET:
+ break;
+ case LWP_SOABORT:
+ Overflow_Complain();
+ abort ();
+ case LWP_SOMESSAGE:
+ default:
+ Overflow_Complain();
+ lwp_overflowAction = LWP_SOQUIET;
+ break;
+ }
+ }
+
+
+ /*
+ * Move head of current runnable queue forward if current LWP
+ * is still in it.
+ */
+ if (lwp_cpptr != NULL && lwp_cpptr == runnable[lwp_cpptr->priority].head)
+ runnable[lwp_cpptr->priority].head = runnable[lwp_cpptr->priority].head->next;
+ /* Find highest priority with runnable processes. */
+ for (i=MAX_PRIORITIES-1; i>=0; i--)
+ if (runnable[i].head != NULL) break;
+
+ if (i < 0) Abort_LWP("No READY processes");
+
+#ifdef DEBUG
+ if (LWP_TraceProcesses > 0)
+ printf("Dispatch %d [PCB at %p] \"%s\"\n",
+ ++dispatch_count,
+ runnable[i].head,
+ runnable[i].head->name);
+#endif
+ if (PRE_Block != 1) Abort_LWP("PRE_Block not 1");
+ lwp_cpptr = runnable[i].head;
+
+ returnto(&lwp_cpptr->context);
+}
+
+/* Complain of a stack overflow to stderr without using stdio. */
+static void
+Overflow_Complain (void)
+{
+ static char msg1[] = "LWP: stack overflow in process ";
+ static char msg2[] = "!\n";
+
+ write (2, msg1, sizeof(msg1) - 1);
+ write (2, lwp_cpptr->name, strlen(lwp_cpptr->name));
+ write (2, msg2, sizeof(msg2) - 1);
+}
+
+static void
+Dispose_of_Dead_PCB (PROCESS cur)
+{
+ Debug(4, ("Entered Dispose_of_Dead_PCB"))
+ Delete_PCB(cur);
+ Free_PCB(cur);
+/*
+ Internal_Signal(cur);
+*/
+}
+
+static void
+Exit_LWP(void)
+{
+ abort();
+}
+
+static void
+Free_PCB(PROCESS pid)
+{
+ Debug(4, ("Entered Free_PCB"))
+ if (pid -> stack != NULL) {
+ Debug(0, ("HWM stack usage: %d, [PCB at %p]",
+ Stack_Used(pid->stack,pid->stacksize), pid))
+ free(pid -> stack);
+ }
+ if (pid->eventlist != NULL) free(pid->eventlist);
+ free(pid);
+}
+
+static void
+Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
+ void (*ep)(), char *parm, char *name)
+{
+ register int i = 0;
+
+ Debug(4, ("Entered Initialize_PCB"))
+ if (name != NULL)
+ while (((temp -> name[i] = name[i]) != '\0') && (i < 31)) i++;
+ temp -> name[31] = '\0';
+ temp -> status = READY;
+ temp -> eventlist = (char **)malloc(EVINITSIZE*sizeof(char *));
+ temp -> eventlistsize = EVINITSIZE;
+ temp -> eventcnt = 0;
+ temp -> wakevent = 0;
+ temp -> waitcnt = 0;
+ temp -> blockflag = 0;
+ temp -> iomgrRequest = 0;
+ temp -> priority = priority;
+ temp -> index = lwp_nextindex++;
+ temp -> stack = stack;
+ temp -> stacksize = stacksize;
+#ifdef __hp9000s800
+ if (temp -> stack != NULL)
+ temp -> stackcheck = *(long *) ((temp -> stack) + stacksize - 4);
+#else
+ if (temp -> stack != NULL)
+ temp -> stackcheck = *(long *) (temp -> stack);
+#endif
+ temp -> ep = ep;
+ temp -> parm = parm;
+ temp -> misc = NULL; /* currently unused */
+ temp -> next = NULL;
+ temp -> prev = NULL;
+ temp -> rused = 0;
+ temp -> level = 1; /* non-preemptable */
+}
+
+static int
+Internal_Signal(register char *event)
+{
+ int rc = LWP_ENOWAIT;
+ register int i;
+
+ Debug(0, ("Entered Internal_Signal [event id %p]", event))
+ if (!lwp_init) return LWP_EINIT;
+ if (event == NULL) return LWP_EBADEVENT;
+ for_all_elts(temp, blocked, {
+ if (temp->status == WAITING)
+ for (i=0; i < temp->eventcnt; i++) {
+ if (temp -> eventlist[i] == event) {
+ temp -> eventlist[i] = NULL;
+ rc = LWP_SUCCESS;
+ Debug(0, ("Signal satisfied for PCB %p", temp))
+ if (--temp->waitcnt == 0) {
+ temp -> status = READY;
+ temp -> wakevent = i+1;
+ move(temp, &blocked, &runnable[temp->priority]);
+ break;
+ }
+ }
+ }
+ })
+ return rc;
+}
+
+/* This can be any unlikely pattern except 0x00010203 or the reverse. */
+#define STACKMAGIC 0xBADBADBA
+static long
+Initialize_Stack(char *stackptr, int stacksize)
+{
+ register int i;
+
+ Debug(4, ("Entered Initialize_Stack"))
+ if (lwp_stackUseEnabled)
+ for (i=0; i<stacksize; i++)
+ stackptr[i] = i &0xff;
+ else
+#ifdef __hp9000s800
+ *(long *)(stackptr + stacksize - 4) = STACKMAGIC;
+#else
+ *(long *)stackptr = STACKMAGIC;
+#endif
+ return 0; /* XXX - added. No clue what it should be */
+}
+
+static int
+Stack_Used(register char *stackptr, int stacksize)
+{
+ register int i;
+
+#ifdef __hp9000s800
+ if (*(long *) (stackptr + stacksize - 4) == STACKMAGIC)
+ return 0;
+ else {
+ for (i = stacksize - 1; i >= 0 ; i--)
+ if ((unsigned char) stackptr[i] != (i & 0xff))
+ return (i);
+ return 0;
+ }
+#else
+ if (*(long *) stackptr == STACKMAGIC)
+ return 0;
+ else {
+ for (i = 0; i < stacksize; i++)
+ if ((unsigned char) stackptr[i] != (i & 0xff))
+ return (stacksize - i);
+ return 0;
+ }
+#endif
+}
+
+
+/*
+ * Finds a free rock and sets its value to Value.
+ * Return codes:
+ * LWP_SUCCESS Rock did not exist and a new one was used
+ * LWP_EBADROCK Rock already exists.
+ * LWP_ENOROCKS All rocks are in use.
+
+ * From the above semantics, you can only set a rock value once.
+ * This is specificallY to prevent multiple users of the LWP package from
+ * accidentally using the same Tag value and clobbering others. You can always
+ * use one level of indirection to obtain a rock whose contents can change.
+ */
+
+int
+LWP_NewRock(int Tag, char *Value)
+{
+ register int i;
+ register struct rock *ra; /* rock array */
+
+ ra = lwp_cpptr->rlist;
+
+ for (i = 0; i < lwp_cpptr->rused; i++)
+ if (ra[i].tag == Tag) return(LWP_EBADROCK);
+
+ if (lwp_cpptr->rused < MAXROCKS)
+ {
+ ra[lwp_cpptr->rused].tag = Tag;
+ ra[lwp_cpptr->rused].value = Value;
+ lwp_cpptr->rused++;
+ return(LWP_SUCCESS);
+ }
+ else return(LWP_ENOROCKS);
+}
+
+/*
+ * Obtains the pointer Value associated with the rock Tag of this LWP.
+ * Returns:
+ * LWP_SUCCESS if specified rock exists and Value has been filled
+ * LWP_EBADROCK rock specified does not exist
+ */
+int
+LWP_GetRock(int Tag, char **Value)
+{
+ register int i;
+ register struct rock *ra;
+
+ ra = lwp_cpptr->rlist;
+
+ for (i = 0; i < lwp_cpptr->rused; i++)
+ if (ra[i].tag == Tag)
+ {
+ *Value = ra[i].value;
+ return(LWP_SUCCESS);
+ }
+ return(LWP_EBADROCK);
+}
+
+
+#ifdef AFS_AIX32_ENV
+setlim(limcon, hard, limit)
+ int limcon;
+ uchar_t hard;
+{
+ struct rlimit rlim;
+
+ (void) getrlimit(limcon, &rlim);
+
+ limit = limit * 1024;
+ if (hard)
+ rlim.rlim_max = limit;
+ else if (limit == RLIM_INFINITY && geteuid() != 0)
+ rlim.rlim_cur = rlim.rlim_max;
+ else
+ rlim.rlim_cur = limit;
+
+ /* Must use ulimit() due to Posix constraints */
+ if (limcon == RLIMIT_FSIZE) {
+ if (ulimit(UL_SETFSIZE, ((hard ? rlim.rlim_max : rlim.rlim_cur) / 512)) < 0) {
+ printf("Can't %s%s limit\n",
+ limit == RLIM_INFINITY ? "remove" : "set", hard ? " hard" : "");
+ return (-1);
+ }
+ } else {
+ if (setrlimit(limcon, &rlim) < 0) {
+ perror("");
+ printf("Can't %s%s limit\n",
+ limit == RLIM_INFINITY ? "remove" : "set", hard ? " hard" : "");
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+
+#ifdef notdef
+/*
+ * Print the specific limit out
+ */
+plim(name, lc, hard)
+ char *name;
+ long lc;
+ uchar_t hard;
+{
+ struct rlimit rlim;
+ int lim;
+
+ printf("%s \t", name);
+ (void) getrlimit(lc, &rlim);
+ lim = hard ? rlim.rlim_max : rlim.rlim_cur;
+ if (lim == RLIM_INFINITY)
+ printf("unlimited");
+ printf("%d %s", lim / 1024, "kbytes");
+ printf("\n");
+}
+#endif
+#endif
diff --git a/usr.sbin/afs/src/lwp/lwp.h b/usr.sbin/afs/src/lwp/lwp.h
new file mode 100644
index 00000000000..8c0492021a0
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/lwp.h
@@ -0,0 +1,209 @@
+/* $OpenBSD: lwp.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+\*******************************************************************/
+
+/* $KTH: lwp.h,v 1.8 1998/07/20 02:52:24 assar Exp $ */
+
+#ifndef __LWP_INCLUDE_
+#define __LWP_INCLUDE_ 1
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_POSIX_SIGNALS
+#define AFS_POSIX_SIGNALS 1
+#endif
+
+#define LWP_SUCCESS 0
+#define LWP_EBADPID -1
+#define LWP_EBLOCKED -2
+#define LWP_EINIT -3
+#define LWP_EMAXPROC -4
+#define LWP_ENOBLOCK -5
+#define LWP_ENOMEM -6
+#define LWP_ENOPROCESS -7
+#define LWP_ENOWAIT -8
+#define LWP_EBADCOUNT -9
+#define LWP_EBADEVENT -10
+#define LWP_EBADPRI -11
+#define LWP_NO_STACK -12
+/* These two are for the signal mechanism. */
+#define LWP_EBADSIG -13 /* bad signal number */
+#define LWP_ESYSTEM -14 /* system call failed */
+/* These are for the rock mechanism */
+#define LWP_ENOROCKS -15 /* all rocks are in use */
+#define LWP_EBADROCK -16 /* the specified rock does not exist */
+
+
+/* Maximum priority permissible (minimum is always 0) */
+#define LWP_MAX_PRIORITY 4 /* changed from 1 by Satya, 22 Nov. 85 */
+
+/* Usual priority used by user LWPs */
+#define LWP_NORMAL_PRIORITY (LWP_MAX_PRIORITY-2)
+
+/* Initial size of eventlist in a PCB; grows dynamically */
+#define EVINITSIZE 5
+
+typedef struct lwp_pcb *PROCESS;
+
+struct lwp_context { /* saved context for dispatcher */
+ char *topstack; /* ptr to top of process stack */
+#ifdef sparc
+#ifdef save_allregs
+ long globals[7+1+32+2+32+2]; /* g1-g7, y reg, f0-f31, fsr, fq, c0-c31, csr, cq. */
+#else
+ long globals[8]; /* g1-g7 and y registers. */
+#endif
+#endif
+#if defined(powerpc) || defined(ppc) || defined(powerc)
+ char *linkRegister; /* the contents of the link register */
+ long conditionRegister; /* the contents of the condition register */
+#endif /* defined(powerpc) || defined(ppc) || defined(powerc) */
+};
+
+struct rock
+ {/* to hide things associated with this LWP under */
+ int tag; /* unique identifier for this rock */
+ char *value; /* pointer to some arbitrary data structure */
+ };
+
+#define MAXROCKS 4 /* max no. of rocks per LWP */
+
+struct lwp_pcb { /* process control block */
+ char name[32]; /* ASCII name */
+ int rc; /* most recent return code */
+ char status; /* status flags */
+ char blockflag; /* if (blockflag), process blocked */
+ char eventlistsize; /* size of eventlist array */
+ char padding; /* force 32-bit alignment */
+ char **eventlist; /* ptr to array of eventids */
+ int eventcnt; /* no. of events currently in eventlist array*/
+ int wakevent; /* index of eventid causing wakeup */
+ int waitcnt; /* min number of events awaited */
+ int priority; /* dispatching priority */
+ struct lwp_pcb *misc; /* for LWP internal use only */
+ char *stack; /* ptr to process stack */
+ int stacksize; /* size of stack */
+ long stackcheck; /* first word of stack for overflow checking */
+ void (*ep)(); /* initial entry point */
+ char *parm; /* initial parm for process */
+ struct lwp_context
+ context; /* saved context for next dispatch */
+ int rused; /* no of rocks presently in use */
+ struct rock rlist[MAXROCKS]; /* set of rocks to hide things under */
+ struct lwp_pcb *next, *prev; /* ptrs to next and previous pcb */
+ int level; /* nesting level of critical sections */
+ struct IoRequest *iomgrRequest; /* request we're waiting for */
+ int index; /* LWP index: should be small index; actually is
+ incremented on each lwp_create_process */
+ };
+
+extern int lwp_nextindex; /* Next lwp index to assign */
+
+
+#ifndef LWP_KERNEL
+#define LWP_ActiveProcess (lwp_cpptr+0)
+#define LWP_Index() (LWP_ActiveProcess->index)
+#define LWP_HighestIndex() (lwp_nextindex - 1)
+#define LWP_SignalProcess(event) LWP_INTERNALSIGNAL(event, 1)
+#define LWP_NoYieldSignal(event) LWP_INTERNALSIGNAL(event, 0)
+
+extern
+#endif
+ PROCESS lwp_cpptr; /* pointer to current process pcb */
+
+struct lwp_ctl { /* LWP control structure */
+ int processcnt; /* number of lightweight processes */
+ char *outersp; /* outermost stack pointer */
+ struct lwp_pcb *outerpid; /* process carved by Initialize */
+ struct lwp_pcb *first, last; /* ptrs to first and last pcbs */
+#ifdef __hp9000s800
+ double dsptchstack[100]; /* stack for dispatcher use only */
+ /* force 8 byte alignment */
+#else
+ char dsptchstack[800]; /* stack for dispatcher use only */
+#endif
+};
+
+#ifndef LWP_KERNEL
+extern
+#endif
+ char lwp_debug; /* ON = show LWP debugging trace */
+
+#if defined(AFS_SUN5_ENV) || defined(AFS_LINUX_ENV)
+#define AFS_POSIX_SIGNALS
+#endif
+
+/*
+ * Under hpux, any stack size smaller than 16K seems prone to
+ * overflow problems.
+ */
+#if defined(AFS_HPUX_ENV) || defined(AFS_NEXT_ENV) /*|| defined(AFS_SUN5_ENV)*/
+#define AFS_LWP_MINSTACKSIZE (24 * 1024)
+#else
+#define AFS_LWP_MINSTACKSIZE (16 * 1024)
+#endif /* defined(AFS_HPUX_ENV) */
+
+/* Action to take on stack overflow. */
+#define LWP_SOQUIET 1 /* do nothing */
+#define LWP_SOABORT 2 /* abort the program */
+#define LWP_SOMESSAGE 3 /* print a message and be quiet */
+extern int lwp_overflowAction;
+
+/* Tells if stack size counting is enabled. */
+extern int lwp_stackUseEnabled;
+extern int lwp_MaxStackSeen;
+
+struct timeval;
+
+int LWP_QSignal(PROCESS);
+int LWP_DispatchProcess();
+int LWP_InitializeProcessSupport(int, PROCESS *);
+int LWP_DestroyProcess(PROCESS);
+int LWP_QWait();
+
+/* exported interface */
+int LWP_CreateProcess(void (*)(), int, int, char *, char *, PROCESS *);
+int LWP_WaitProcess(void *);
+int LWP_INTERNALSIGNAL(void *, int);
+
+void IOMGR_Sleep(unsigned int);
+int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int IOMGR_Cancel(register PROCESS);
+int IOMGR_Initialize(void);
+
+#endif /* __LWP_INCLUDE_ */
diff --git a/usr.sbin/afs/src/lwp/make-process.o.sh.in b/usr.sbin/afs/src/lwp/make-process.o.sh.in
new file mode 100644
index 00000000000..a7dc4780fc6
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/make-process.o.sh.in
@@ -0,0 +1,161 @@
+#!/bin/sh
+#
+# make-process.o.sh
+# Try to make process.o various ways.
+#
+# $Id: make-process.o.sh.in,v 1.1.1.1 1998/09/14 21:53:12 art Exp $
+#
+
+srcdir=@srcdir@
+
+CC="@CC@"
+GCC="@GCC@"
+CPP="@CPP@"
+AS=as
+RM=rm
+HOST_CPU="@host_cpu@"
+HOST_OS="@host_os@"
+LN_S="@LN_S@"
+
+#
+# Here is a test to check if we manage to build process.o
+# (use this because some sh doesn't have functions)
+#
+# $CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+# $RM -f process.o
+
+#
+# Options that you may need to override for your CPU/OS
+#
+
+PROCESS_S="process.S"
+USE_AS="no"
+MYDEF=""
+
+
+#
+# Clean out the process.o
+#
+
+$RM -f process.o
+
+#
+# Add CPUDEFs that you CPU needs
+#
+
+case "$HOST_CPU" in
+ sparc) CPUDEF="-Dsparc" ;;
+ i*86*) CPUDEF="-DAFS_386i_ENV" ;;
+ m68k) CPUDEF="-Dmc68000" ;;
+ mips) CPUDEF="-Dmips" ;;
+ alpha) CPUDEF="-Dalpha" ;;
+ hppa*) CPUDEF="" ;;
+ powerpc) CPUDEF="-D__powerpc__" ;;
+ rs6000) CPUDEF="-DRIOS" ;;
+ *) echo "Unknown host_cpu, good luck" ;;
+esac
+
+#
+# Add OSDEF your OS need
+#
+
+case "$HOST_OS" in
+ *bsd*) OSDEF="-DAFS_NETBSD_ENV" ;;
+ *linux*) OSDEF="-DAFS_LINUX_ENV" ;;
+ *irix*) OSDEF="-Dsgi" ;;
+ *dux* | *osf*) OSDEF="-DAFS_OSF_ENV" ;;
+ *solaris*) OSDEF="-DAFS_SUN5_ENV -D_ASM" USE_AS="yes" ;;
+ *irix*) OSDEF="-Dsgi" ;;
+ *hpux*) OSDEF="-DAFS_HPUX_ENV" PROCESS_S="process.s.hpux" ;;
+ rhapsody*) OSDEF="-DAFS_NETBSD_ENV" ;;
+ aix*) CPUDEF="-DRIOS"; OSDEF="" ;;
+ *) ;;
+esac
+
+#
+# Now try to do the magic stuff.
+#
+
+
+#
+# Can we use $CC to do the asm for us ? (GCC)
+#
+
+if test "$GCC" = "yes" -a "$USE_AS" = "no"; then
+ ${CC} $MYDEF $CPUDEF $OSDEF -c ${srcdir}/${PROCESS_S} ;
+
+# process.o there ?
+ $CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+ $RM -f process.o
+fi
+
+#
+# Try to use $AS -P for assably
+#
+
+$AS -P $MYDEF $CPUDEF $OSDEF ${srcdir}/${PROCESS_S} -o process.o
+
+# process.o there ?
+$CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+$RM -f process.o
+
+
+#
+# Some $AS does "intresting" things, like ignorings the -o flag
+# and creats a .i file that is preprocessed. (Digital Unix)
+#
+
+if test -s process.i ; then
+ $AS process.i -o process.o
+ $RM -f process.i
+
+ # process.o there ?
+ $CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+ $RM -f process.o
+fi
+
+#
+# Try to use $AS (without -P) for assably
+#
+
+$AS $MYDEF $CPUDEF $OSDEF ${srcdir}/${PROCESS_S} -o process.o
+
+# process.o there ?
+$CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+$RM -f process.o
+
+
+#
+# Some $AS does "intresting" things, like ignorings the -o flag
+# and creats a .i file that is preprocessed. (Digital Unix)
+#
+
+if test -s process.i ; then
+ $AS process.i -o process.o
+ $RM -f process.i
+
+ # process.o there ?
+ $CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+ $RM -f process.o
+fi
+
+#
+# Try to fool $CC by adding a .c extension.
+#
+
+$RM -f foo.c && $LN_S ${srcdir}/${PROCESS_S} foo.c
+$CPP $MYDEF $CPUDEF $OSDEF foo.c > process.ss
+$AS process.ss -o process.o
+$RM -f process.ss
+
+# process.o there ?
+$CC -o testprocess testprocess.o process.o preempt.o lwp.o && exit 0
+$RM -f process.o
+
+echo "WE HAVE NO process.o !"
+exit 1
+
+
+
+
+
diff --git a/usr.sbin/afs/src/lwp/preempt.c b/usr.sbin/afs/src/lwp/preempt.c
new file mode 100644
index 00000000000..ba1d8cefb58
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/preempt.c
@@ -0,0 +1,146 @@
+/* $OpenBSD: preempt.c,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* Bradley White and M. Satyanarayanan *
+\*******************************************************************/
+
+#include <sys/time.h>
+#include <signal.h>
+#include "lwp.h"
+#include "preempt.h"
+
+RCSID("$KTH: preempt.c,v 1.5 1998/02/06 03:18:30 art Exp $");
+
+char PRE_Block = 0; /* used in lwp.c and process.s */
+
+
+static RETSIGTYPE
+#if defined(AFS_POSIX_SIGNALS)
+AlarmHandler(int sig)
+#else
+AlarmHandler(int sig, int code, struct sigcontext *scp)
+#endif
+{
+#ifdef AFS_POSIX_SIGNALS
+ sigset_t mask ;
+#endif
+
+ if (PRE_Block == 0 && lwp_cpptr->level == 0) {
+ PRE_BeginCritical();
+#if defined(AFS_POSIX_SIGNALS)
+ sigemptyset(&mask);
+ sigaddset(&mask, sig);
+ sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)0);
+#else
+ sigsetmask(scp->sc_mask);
+#endif
+ LWP_DispatchProcess();
+ PRE_EndCritical();
+ }
+
+}
+
+
+
+int
+PRE_InitPreempt(struct timeval *slice)
+{
+ struct itimerval itv;
+#ifdef AFS_POSIX_SIGNALS
+ struct sigaction sa;
+#else
+ struct sigvec vec;
+#endif
+
+ if (lwp_cpptr == 0) return (LWP_EINIT);
+
+ if (slice == 0) {
+ itv.it_interval.tv_sec = itv.it_value.tv_sec = DEFAULTSLICE;
+ itv.it_interval.tv_usec = itv.it_value.tv_usec = 0;
+ } else {
+ itv.it_interval = itv.it_value = *slice;
+ }
+
+#ifdef AFS_POSIX_SIGNALS
+ sa.sa_handler = AlarmHandler;
+#ifndef SA_NODEFER
+#define SA_NODEFER 0
+#endif
+#ifdef SA_SIGINFO
+ sa.sa_flags = SA_SIGINFO|SA_NODEFER;
+#else
+ sa.sa_flags = SA_NODEFER;
+#endif
+
+ if ((sigaction(SIGALRM, &sa, (struct sigaction *)0) == -1) ||
+ (setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1))
+ return(LWP_ESYSTEM);
+#else
+ vec.sv_handler = AlarmHandler;
+ vec.sv_mask = vec.sv_onstack = 0;
+
+ if ((sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1) ||
+ (setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1))
+ return(LWP_ESYSTEM);
+#endif
+
+ return(LWP_SUCCESS);
+}
+
+int
+PRE_EndPreempt(void)
+{
+ struct itimerval itv;
+#ifdef AFS_POSIX_SIGNALS
+ struct sigaction sa;
+#else
+ struct sigvec vec;
+#endif
+
+ if (lwp_cpptr == 0)
+ return (LWP_EINIT);
+
+ itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
+
+#ifdef AFS_POSIX_SIGNALS
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags=0;
+
+ if ((setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1) ||
+ (sigaction(SIGALRM, &sa, (struct sigaction *)0) == -1))
+ return(LWP_ESYSTEM);
+#else
+ vec.sv_handler = SIG_DFL;;
+ vec.sv_mask = vec.sv_onstack = 0;
+
+ if ((setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1) ||
+ (sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1))
+ return(LWP_ESYSTEM);
+#endif
+
+ return(LWP_SUCCESS);
+}
diff --git a/usr.sbin/afs/src/lwp/preempt.h b/usr.sbin/afs/src/lwp/preempt.h
new file mode 100644
index 00000000000..6640747586c
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/preempt.h
@@ -0,0 +1,43 @@
+/* $OpenBSD: preempt.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/preempt.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/preempt.h,v $ */
+
+#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
+static char *rcsidpreempt = "$Header: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/preempt.h,v 1.1.1.1 1998/09/14 21:53:12 art Exp $";
+#endif
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* Bradley White and M. Satyanarayanan *
+\*******************************************************************/
+
+
+#define PRE_PreemptMe() lwp_cpptr->level = 0
+#define PRE_BeginCritical() lwp_cpptr->level++
+#define PRE_EndCritical() lwp_cpptr->level--
+
+#define DEFAULTSLICE 10
diff --git a/usr.sbin/afs/src/lwp/process.S b/usr.sbin/afs/src/lwp/process.S
new file mode 100644
index 00000000000..ecbf0e1b137
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/process.S
@@ -0,0 +1,1427 @@
+/* $Header: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/process.S,v 1.1.1.1 1998/09/14 21:53:12 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/lwp/Attic/process.S,v $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#if defined(RIOS)
+
+/* lws 92.11.18 I don't know if we have to save the TOC (R2) or not...
+ * Note that stack-frame is supposed to be aligned on
+ * a double-word boundary.
+ * For details about RIOS calling conventions
+ * see the Assembler manual and /usr/include/sys/asdef.s
+ */
+
+
+/*
+ * savecontext(f, area1, newsp)
+ * int (*f)(); struct savearea *area1; char *newsp;
+ */
+ .set topstack, 0
+ .set cr0, 0
+ .set toc, 2
+ .set r0, 0
+ .set r1, 1
+ .set r2, 2
+ .set r3, 3
+ .set r4, 4
+ .set r5, 5
+ .set r6, 6
+ .set r7, 7
+ .set r12, 12
+ .set a_f, r3
+ .set a_area1, r4
+ .set a_newsp, r5
+
+ .set argarea, 32
+ .set linkarea, 24
+ .set nfprs, 18
+ .set ngprs, 20
+ .set szdsa, 8*nfprs+4*ngprs+linkarea+argarea
+
+ .csect .savecontext[PR]
+ .globl .savecontext[PR]
+
+ mflr r0 # save link register
+
+/*
+ * save floating point registers. Interleave some other stuff for
+ * timing reasons. Set up conditions and registers for branches
+ * early, so that processor can prefetch instructions.
+ */
+ stfd 14, -144(1)
+ stfd 15, -136(1)
+
+ mfcr r12 # save CR
+
+ stfd 16, -128(1)
+ stfd 17, -120(1)
+
+ l 11, 0(a_f) # r11 <- *(a_f)
+
+ stfd 18, -112(1)
+ stfd 19, -104(1)
+
+ cmpi cr0, a_newsp, 0 # cr0 <- (a_newsp :: 0)
+
+ stfd 20, -96(1)
+ stfd 21, -88(1)
+ stfd 22, -80(1)
+
+ mtlr 11 # set up lr early so prefetch works
+
+ stfd 23, -72(1)
+ stfd 24, -64(1)
+ stfd 25, -56(1)
+
+ st r0, 8(r1) # save return addr
+
+ stfd 26, -48(1)
+ stfd 27, -40(1)
+ stfd 28, -32(1)
+
+ st 12, 4(r1) # save CR
+
+ stfd 29, -24(1)
+ stfd 30, -16(1)
+ stfd 31, -8(1)
+
+/*
+ * save general-purpose registers
+ */
+ stm 12, -8*nfprs-4*ngprs(r1)# save the general-purpose regs
+ stu r1, -szdsa(r1) # dec SP and save back chain
+
+ l r7, PRE_Block.S(toc) # r7 <- &PRE_Block
+ cal r6, 1(r0) # r6 <- #1
+ stb r6, 0(r7) # r6 -> PRE_Block
+
+ st r1, topstack(a_area1) # save old SP
+
+ beq L1 # if (a_newsp == 0) goto L1
+
+ mr r1, r5 # r1 <- a_newsp -- load new SP
+
+L1: brl # pc <- lr -- (*a_f)()
+
+/*
+ * returnto(area2) This is a little jumbled, I tried to interleave
+ * memory accesses with simple instructions for speed, and I tried to
+ * set up the link register and condition register reasonably early
+ * so that processor instruction prefetching might help us out a little.
+ */
+ .set a_area2, r3
+
+ .csect .returnto[PR]
+ .globl .returnto[PR]
+
+ l r1, topstack(a_area2) # r1 <- a_area2->topstack
+ cal r1, szdsa(r1) # pop off frame
+ l r7, PRE_Block.S(toc) # r7 <- &PRE_Block
+
+ l 8, 8(1) # restore lr
+ mtlr 8 # do it early so prefetch works
+
+ lm 12, -8*nfprs-4*ngprs(r1)
+ cal r6, 0(r0) # r6 <- #0
+ mtcrf 0x38, 12 # put back cr
+ stb r6, 0(r7) # r6 -> PRE_Block
+
+/*
+ * restore FPRs here!
+ */
+ lfd 14, -144(1)
+ lfd 15, -136(1)
+ lfd 16, -128(1)
+ lfd 17, -120(1)
+ lfd 18, -112(1)
+ lfd 19, -104(1)
+ lfd 20, -96(1)
+ lfd 21, -88(1)
+ lfd 22, -80(1)
+ lfd 23, -72(1)
+ lfd 24, -64(1)
+ lfd 25, -56(1)
+ lfd 26, -48(1)
+ lfd 27, -40(1)
+ lfd 28, -32(1)
+ lfd 29, -24(1)
+ lfd 30, -16(1)
+ lfd 31, -8(1)
+
+ brl # pc <- lr -- return
+
+ .toc
+
+PRE_Block.S:
+ .tc PRE_Block[tc], PRE_Block[ua]
+ .extern PRE_Block[ua]
+
+#endif /* RIOS */
+
+#ifdef mc68000
+/*
+#
+# Information Technology Center
+# Carnegie-Mellon University
+#
+#
+*/
+ .data
+
+/*
+#
+# Process assembly language assist for Suns.
+#
+*/
+
+ .text
+ .even
+
+/*
+#
+# struct savearea {
+# char *topstack;
+# }
+#
+*/
+
+ .globl _PRE_Block
+
+topstack = 0
+
+/* Stuff to allow saving/restoring registers */
+nregs = 13
+regs = 0x3ffe | d1-d7 & a0-a5
+
+/*
+# savecontext(f, area1, newsp)
+# int (*f)(); struct savearea *area1; char *newsp;
+*/
+
+/* Stack offsets of arguments */
+f = 8
+area1 = 12
+newsp = 16
+
+ .globl _savecontext
+_savecontext:
+ movb #1,_PRE_Block | Dont allow any interrupt finagling
+ link a6,#-(nregs*4) | Save frame pointer & ...
+ | ... allocate space for nregs registers
+/* Save registers */
+ moveml #regs,sp@
+
+ movl a6@(area1),a0 | a0 = base of savearea
+ movl sp,a0@(topstack) | area->topstack = sp
+ movl a6@(newsp),d0 | Get new sp
+ jeq forw1 | If newsp == 0, no stack switch
+ movl d0,sp | Switch to new stack
+forw1:
+ movl a6@(f),a0 | a0 = f
+ jbsr a0@ | f()
+
+/* It is impossible to be here, so abort() */
+
+ jbsr _abort
+
+/*
+# returnto(area2)
+# struct savearea *area2;
+*/
+
+/* Stack offset of argument */
+area2 = 8
+
+ .globl _returnto
+_returnto:
+ link a6,#0
+ movl a6@(area2),a0 | Base of savearea
+ movl a0@(topstack),sp | Restore sp
+/* Restore registers */
+ moveml sp@,#regs
+
+ addl #(nregs*4),sp
+ movl sp,a6 | Argghh...be careful here
+ unlk a6
+ clrb _PRE_Block
+ rts | Return to previous process
+#endif /* mc68000 */
+#ifdef sparc
+#ifdef AFS_SUN5_ENV
+#include <sys/asm_linkage.h>
+#include <sys/trap.h>
+#else
+#ifdef AFS_NETBSD_ENV
+#include <machine/trap.h>
+#define ST_FLUSH_WINDOWS ST_FLUSHWIN
+#define MINFRAME 92
+#define SA(x) (((x)+7)&~7)
+#define STACK_ALIGN 8
+#else
+#ifdef AFS_LINUX_ENV
+#define AFS_SUN5_ENV 1 /* Make believe this is Solaris */
+#define ST_FLUSH_WINDOWS 0x03 /* XXX: from asm/traps.h */
+#define MINFRAME 92
+#define SA(x) (((x)+7)&~7)
+#define STACK_ALIGN 8
+#else /* SunOS 4: */
+#include <sun4/asm_linkage.h>
+#include <sun4/trap.h>
+#endif
+#endif
+#endif
+ .data
+#ifdef AFS_SUN5_ENV
+ .globl PRE_Block
+#else
+ .globl _PRE_Block
+#endif
+topstack = 0
+globals = 4
+/*
+# savecontext(f, area1, newsp)
+# int (*f)(); struct savearea *area1; char *newsp;
+*/
+ .text
+#ifdef AFS_SUN5_ENV
+ .globl savecontext
+savecontext:
+#else
+ .globl _savecontext
+_savecontext:
+#endif
+ save %sp, -SA(MINFRAME), %sp ! Get new window
+ ta ST_FLUSH_WINDOWS ! FLush all other active windows
+
+ /* The following 3 lines do the equivalent of: _PRE_Block = 1 */
+#ifdef AFS_SUN5_ENV
+ set PRE_Block, %l0
+#else
+ set _PRE_Block, %l0
+#endif
+ mov 1,%l1
+ stb %l1, [%l0]
+
+ st %fp,[%i1+topstack] ! area1->topstack = sp
+
+ st %g1, [%i1 + globals + 0] /* Save all globals just in case */
+ st %g2, [%i1 + globals + 4]
+ st %g3, [%i1 + globals + 8]
+ st %g4, [%i1 + globals + 12]
+ st %g5, [%i1 + globals + 16]
+ st %g6, [%i1 + globals + 20]
+ st %g7, [%i1 + globals + 24]
+ mov %y, %g1
+ st %g1, [%i1 + globals + 28]
+
+#ifdef save_allregs
+ st %f0, [%i1 + globals + 32 + 0] ! Save all floating point registers
+ st %f1, [%i1 + globals + 32 + 4]
+ st %f2, [%i1 + globals + 32 + 8]
+ st %f3, [%i1 + globals + 32 + 12]
+ st %f4, [%i1 + globals + 32 + 16]
+ st %f5, [%i1 + globals + 32 + 20]
+ st %f6, [%i1 + globals + 32 + 24]
+ st %f7, [%i1 + globals + 32 + 28]
+ st %f8, [%i1 + globals + 64 + 0]
+ st %f9, [%i1 + globals + 64 + 4]
+ st %f10, [%i1 + globals + 64 + 8]
+ st %f11, [%i1 + globals + 64 + 12]
+ st %f12, [%i1 + globals + 64 + 16]
+ st %f13, [%i1 + globals + 64 + 20]
+ st %f14, [%i1 + globals + 64 + 24]
+ st %f15, [%i1 + globals + 64 + 28]
+ st %f16, [%i1 + globals + 64 + 32]
+ st %f17, [%i1 + globals + 64 + 36]
+ st %f18, [%i1 + globals + 64 + 40]
+ st %f19, [%i1 + globals + 64 + 44]
+ st %f20, [%i1 + globals + 64 + 48]
+ st %f21, [%i1 + globals + 64 + 52]
+ st %f22, [%i1 + globals + 64 + 56]
+ st %f23, [%i1 + globals + 64 + 60]
+ st %f24, [%i1 + globals + 64 + 64]
+ st %f25, [%i1 + globals + 64 + 68]
+ st %f26, [%i1 + globals + 64 + 72]
+ st %f27, [%i1 + globals + 64 + 76]
+ st %f28, [%i1 + globals + 64 + 80]
+ st %f29, [%i1 + globals + 64 + 84]
+ st %f30, [%i1 + globals + 64 + 88]
+ st %f31, [%i1 + globals + 64 + 92]
+#ifdef notdef
+ mov %fsr,%g1
+ st %g1, [%i1 + globals + 64 + 96]
+ mov %fq,%g1
+ st %g1, [%i1 + globals + 64 + 100]
+#endif
+
+ st %c0, [%i1 + globals + 168 + 0] ! Save all coprocessor registers
+ st %c1, [%i1 + globals + 168 + 4]
+ st %c2, [%i1 + globals + 168 + 8]
+ st %c3, [%i1 + globals + 168 + 12]
+ st %c4, [%i1 + globals + 168 + 16]
+ st %c5, [%i1 + globals + 168 + 20]
+ st %c6, [%i1 + globals + 168 + 24]
+ st %c7, [%i1 + globals + 168 + 28]
+ st %c8, [%i1 + globals + 200 + 0]
+ st %c9, [%i1 + globals + 200 + 4]
+ st %c10, [%i1 + globals + 200 + 8]
+ st %c11, [%i1 + globals + 200 + 12]
+ st %c12, [%i1 + globals + 200 + 16]
+ st %c13, [%i1 + globals + 200 + 20]
+ st %c14, [%i1 + globals + 200 + 24]
+ st %c15, [%i1 + globals + 200 + 28]
+ st %c16, [%i1 + globals + 200 + 32]
+ st %c17, [%i1 + globals + 200 + 36]
+ st %c18, [%i1 + globals + 200 + 40]
+ st %c19, [%i1 + globals + 200 + 44]
+ st %c20, [%i1 + globals + 200 + 48]
+ st %c21, [%i1 + globals + 200 + 52]
+ st %c22, [%i1 + globals + 200 + 56]
+ st %c23, [%i1 + globals + 200 + 60]
+ st %c24, [%i1 + globals + 200 + 64]
+ st %c25, [%i1 + globals + 200 + 68]
+ st %c26, [%i1 + globals + 200 + 72]
+ st %c27, [%i1 + globals + 200 + 76]
+ st %c28, [%i1 + globals + 200 + 80]
+ st %c29, [%i1 + globals + 200 + 84]
+ st %c30, [%i1 + globals + 200 + 88]
+ st %c31, [%i1 + globals + 200 + 92]
+#ifdef notdef
+ mov %csr,%g1
+ st %g1, [%i1 + globals + 200 + 96]
+ mov %cq,%g1
+ st %g1, [%i1 + globals + 200 + 100]
+#endif
+#endif
+ cmp %i2, 0
+ be,a L1 ! if (newsp == 0) no stack switch
+ nop
+#ifdef notdef
+ add %i2, STACK_ALIGN - 1, %i2
+ and %i2, ~(STACK_ALIGN - 1), %i2
+ sub %i2, SA(MINFRAME), %fp
+ call %i0
+ restore
+#else
+ ! This used to compute a new stack frame base, write it into
+ ! FP, and restore to enter the new frame. But that left a window
+ ! in which FP could be written into the backing store for this
+ ! frame, to be tripped over later by returnto. So instead we do
+ ! the restore first, then modify SP to enter the new frame. We
+ ! can still refer to our argument as %02.
+ restore
+ add %o2, STACK_ALIGN - 1, %o2
+ and %o2, ~(STACK_ALIGN - 1), %o2
+ call %o0
+ sub %o2, SA(MINFRAME), %sp
+#endif
+
+L1: call %i0 ! call f()
+ nop
+
+
+! returnto(area1)
+! struct savearea *area1;
+#ifdef AFS_SUN5_ENV
+ .globl returnto
+returnto:
+#else
+ .globl _returnto
+_returnto:
+#endif
+ ta ST_FLUSH_WINDOWS ! FLush all other active windows
+ ld [%o0+topstack],%g1 ! sp = area1->topstack
+ sub %g1, SA(MINFRAME), %fp ! Adjust sp to the right place
+ sub %fp, SA(MINFRAME), %sp
+
+#ifdef save_allregs
+ ld [%o0 + globals + 32 + 0],%f0 ! Restore floating-point registers
+ ld [%o0 + globals + 32 + 4],%f1
+ ld [%o0 + globals + 32 + 8],%f2
+ ld [%o0 + globals + 32 + 12],%f3
+ ld [%o0 + globals + 32 + 16],%f4
+ ld [%o0 + globals + 32 + 20],%f5
+ ld [%o0 + globals + 32 + 24],%f6
+ ld [%o0 + globals + 32 + 28],%f7
+ ld [%o0 + globals + 64 + 0],%f8
+ ld [%o0 + globals + 64 + 4],%f9
+ ld [%o0 + globals + 64 + 8],%f10
+ ld [%o0 + globals + 64 + 12],%f11
+ ld [%o0 + globals + 64 + 16],%f12
+ ld [%o0 + globals + 64 + 20],%f13
+ ld [%o0 + globals + 64 + 24],%f14
+ ld [%o0 + globals + 64 + 28],%f15
+ ld [%o0 + globals + 64 + 32],%f16
+ ld [%o0 + globals + 64 + 36],%f17
+ ld [%o0 + globals + 64 + 40],%f18
+ ld [%o0 + globals + 64 + 44],%f19
+ ld [%o0 + globals + 64 + 48],%f20
+ ld [%o0 + globals + 64 + 52],%f21
+ ld [%o0 + globals + 64 + 56],%f22
+ ld [%o0 + globals + 64 + 60],%f23
+ ld [%o0 + globals + 64 + 64],%f24
+ ld [%o0 + globals + 64 + 68],%f25
+ ld [%o0 + globals + 64 + 72],%f26
+ ld [%o0 + globals + 64 + 76],%f27
+ ld [%o0 + globals + 64 + 80],%f28
+ ld [%o0 + globals + 64 + 84],%f29
+ ld [%o0 + globals + 64 + 88],%f30
+ ld [%o0 + globals + 64 + 92],%f31
+#ifdef notdef
+ ld [%o0 + globals + 64 + 96],%g1
+ mov %g1, %fsr
+ ld [%o0 + globals + 64 + 100],%g1
+ mov %g1, %fq
+#endif
+
+ ld [%o0 + globals + 168 + 0],%c0 ! Restore floating-point registers
+ ld [%o0 + globals + 168 + 4],%c1
+ ld [%o0 + globals + 168 + 8],%c2
+ ld [%o0 + globals + 168 + 12],%c3
+ ld [%o0 + globals + 168 + 16],%c4
+ ld [%o0 + globals + 168 + 20],%c5
+ ld [%o0 + globals + 168 + 24],%c6
+ ld [%o0 + globals + 168 + 28],%c7
+ ld [%o0 + globals + 200 + 0],%c8
+ ld [%o0 + globals + 200 + 4],%c9
+ ld [%o0 + globals + 200 + 8],%c10
+ ld [%o0 + globals + 200 + 12],%c11
+ ld [%o0 + globals + 200 + 16],%c12
+ ld [%o0 + globals + 200 + 20],%c13
+ ld [%o0 + globals + 200 + 24],%c14
+ ld [%o0 + globals + 200 + 28],%c15
+ ld [%o0 + globals + 200 + 32],%c16
+ ld [%o0 + globals + 200 + 36],%c17
+ ld [%o0 + globals + 200 + 40],%c18
+ ld [%o0 + globals + 200 + 44],%c19
+ ld [%o0 + globals + 200 + 48],%c20
+ ld [%o0 + globals + 200 + 52],%c21
+ ld [%o0 + globals + 200 + 56],%c22
+ ld [%o0 + globals + 200 + 60],%c23
+ ld [%o0 + globals + 200 + 64],%c24
+ ld [%o0 + globals + 200 + 68],%c25
+ ld [%o0 + globals + 200 + 72],%c26
+ ld [%o0 + globals + 200 + 76],%c27
+ ld [%o0 + globals + 200 + 80],%c28
+ ld [%o0 + globals + 200 + 84],%c29
+ ld [%o0 + globals + 200 + 88],%c30
+ ld [%o0 + globals + 200 + 92],%c31
+#ifdef notdef
+ ld [%o0 + globals + 200 + 96],%g1
+ mov %g1, %csr
+ ld [%o0 + globals + 200 + 100],%g1
+ mov %g1, %cq
+#endif
+#endif
+ ld [%o0 + globals + 28], %g1 ! Restore global regs back
+ mov %g1, %y
+ ld [%o0 + globals + 0], %g1
+ ld [%o0 + globals + 4], %g2
+ ld [%o0 + globals + 8], %g3
+ ld [%o0 + globals + 12],%g4
+ ld [%o0 + globals + 16],%g5
+ ld [%o0 + globals + 20],%g6
+ ld [%o0 + globals + 24],%g7
+
+ /* The following 3 lines are equivalent to: _PRE_Block = 0 */
+#ifdef AFS_SUN5_ENV
+ set PRE_Block, %l0
+#else
+ set _PRE_Block, %l0
+#endif
+ mov 0,%l1
+ stb %l1, [%l0]
+
+ restore
+ restore
+
+ retl
+ nop
+
+#endif /* sparc */
+#ifdef ibm032
+|
+| Information Technology Center
+| Carnegie-Mellon University
+|
+|
+ .data
+ .globl .oVncs
+ .set .oVncs,0
+
+ .globl _savecontext
+_savecontext:
+ .long _.savecontext
+
+ .globl _returnto
+_returnto:
+ .long _.returnto
+
+|
+| Process assembly language assist for Sailboats.
+|
+
+ .text
+ .align 2
+
+|
+| struct savearea {
+| char *topstack;
+| }
+|
+
+| Offsets of fields
+.set topstack,0
+
+| Stuff to allow saving/restoring registers
+.set regspace,64
+.set freg,0
+
+|
+| savecontext(f, area1, newsp)
+| int (*f)(); struct savearea *area1; char *newsp;
+|
+
+ .globl _.savecontext
+_.savecontext:
+ ai sp,sp,-regspace | Save frame pointer & ...
+ | ... allocate space for 16 registers
+| Save registers
+ stm r0,0(sp) | Change this if save fewer regs.
+| Set preemption semaphore
+ get r6,$1
+ get r7,$_PRE_Block
+ putc r6,0(r7) | PRE_Block = 1
+| r3 = base of savearea
+ put sp,topstack(r3) | area1->topstack = sp
+| New sp is in r4.
+ cis r4,0
+ be L1 | If newsp == 0, no stack switch
+ cas sp,r4,r0 | Switch to new stack
+L1:
+ get r6,0(r2) | r2 = _f
+ balrx r15,r6 | f()
+ cas r0,r2,r0
+
+|
+| returnto(area2)
+| struct savearea *area2;
+|
+
+ .globl _.returnto
+_.returnto:
+ get sp,topstack(r2)
+| Now in the context of the savecontext stack to be restored.
+| Start with the registers...
+| Clear preemption semaphore
+ get r6,$0
+ get r7,$_PRE_Block
+ putc r6,0(r7) | PRE_Block = 0
+ lm r0,0(sp) | Change if saving fewer regs.
+ brx r15 | Return to previous process
+ ai sp,sp,regspace
+ .data
+ .ltorg
+#endif
+
+#ifdef AFS_AIX22_ENV
+/*
+#
+# Information Technology Center
+# Carnegie-Mellon University
+#
+*/
+/*
+#
+# Process assembly language assist for Sailboats.
+#
+*/
+
+ .text
+ .globl .savecontext
+ .align 1
+
+/*
+#
+# struct savearea {
+# char *topstack;
+# }
+#
+*/
+
+
+/*# Offsets of fields*/
+.set topstack,0
+
+/*# Stuff to allow saving/restoring registers*/
+.set regspace,64
+.set freg,0
+
+/*
+#
+# savecontext(f, area1, newsp)
+# int (*f)(); struct savearea *area1; char *newsp;
+#
+*/
+
+.savecontext:
+ ai 1,1,-regspace # Save frame pointer & ...
+
+/*# Save registers*/
+ stm 0,0(1) # Change this if save fewer regs.
+ lr 14,0
+/*# Set preemption semaphore*/
+ lis 6,1
+ l 7,4(14)
+ stc 6,0(7)
+/*# r3 = base of savearea*/
+ st 1,topstack(3) # area1->topstack = sp
+/*# New sp is in r4.*/
+ ci 4,0
+ beq L1 # If newsp == 0, no stack switch
+ cas 1,4,0 # Switch to new stack
+L1:
+ l 6,0(2) # r2 = _f
+ balrx 15,6 # f()
+ cas 0,2,0
+ .data 3
+ .globl _savecontext
+_savecontext:
+ .long .savecontext
+ .long _PRE_Block
+/*
+#
+# returnto(area2)
+# struct savearea *area2;
+#
+*/
+
+ .text
+ .globl .returnto
+ .align 1
+.returnto:
+ l 1,topstack(2)
+/*
+# Now in the context of the savecontext stack to be restored.
+# Start with the registers...
+# Clear preemption semaphore
+*/
+ lr 14,0
+ lis 6,0
+ l 7,4(14)
+ stc 6,0(7)
+ lm 0,0(1) # Change if saving fewer regs.
+ brx 15 # Return to previous process
+ ai 1,1,regspace
+ .data 3
+ .globl _returnto
+_returnto:
+ .long .returnto
+ .long _PRE_Block
+#endif /* AFS_AIX_ENV */
+
+#ifdef vax
+/*
+#
+# Information Technology Center
+# Carnegie-Mellon University
+#
+#
+*/
+ .data
+
+/*
+#
+# Transcribed for Vaxen by M. Satyanarayanan, September 1985
+# Algorithm: "Monkey see, monkey do"
+#
+*/
+
+ .text
+
+/*
+#
+# struct savearea {
+# char *topstack;
+# }
+#
+*/
+
+ .set topstack,0
+
+/* Stuff to allow saving/restoring registers */
+
+/*
+# savecontext(f, area1, newsp)
+# int (*f)(); struct savearea *area1; char *newsp;
+*/
+
+/* Stack offsets of arguments */
+ .set f,4
+ .set area1,8
+ .set newsp,12
+
+.globl _PRE_Block
+.globl _savecontext
+
+_savecontext:
+ .word 0x0ffc # Save regs R2-R11
+ movb $1,_PRE_Block # Critical section for preemption code
+ pushl ap # save old ap
+ pushl fp # save old fp
+ movl area1(ap),r0 # r0 = base of savearea
+ movl sp,topstack(r0) # area->topstack = sp
+ movl newsp(ap),r0 # Get new sp
+ beql L1 # if new sp is 0, dont change stacks
+ movl r0,sp # else switch to new stack
+L1:
+ movl f(ap),r1 # r1 = f
+ calls $0,0(r1) # f()
+
+/* It is impossible to be here, so abort() */
+
+ calls $0,_abort
+
+/*
+# returnto(area2)
+# struct savearea *area2;
+*/
+
+/* Stack offset of argument */
+ .set area2,4
+
+ .globl _returnto
+_returnto:
+ .word 0x0 # Who cares about these regs?
+ movl area2(ap),r0 # r0 = address of area2
+ movl topstack(r0),sp # Restore sp
+ movl (sp)+,fp # Restore fp
+ movl (sp)+,ap # ,,,,
+ clrb _PRE_Block # End of preemption critical section
+ ret
+
+ pushl $1234 # I will gloat, Kazar
+ calls $0,_abort
+#endif
+
+#ifdef mips
+#ifdef sgi
+ .option pic2
+
+#include <regdef.h> /* Allow use of symbolic names for registers. */
+/* 9 sregs, ra, 6 fp regs, gp, pad to 8 byte boundary */
+#define regspace 9 * 4 + 4 + 6 * 8 + 4 + 4
+#define floats 0
+#define registers floats + 6 * 8
+#define returnaddr regspace - 4
+#define topstack 0
+#define GPOFF regspace - 8
+ .globl savecontext /* MIPS' C compiler doesnt prepend underscores. */
+ .ent savecontext /* Insert debugger information. */
+savecontext:
+ .set noreorder
+ .cpload t9 # set up gp for KPIC
+ .set reorder
+ subu sp, regspace
+ .cprestore GPOFF # trigger t9/jalr
+ .set noreorder
+ li t0, 1
+ .extern PRE_Block
+ sb t0, PRE_Block
+ .set reorder
+ .frame sp, regspace, ra
+/* Save registers. */
+ sw s0, registers + 0(sp)
+ sw s1, registers + 4(sp)
+ sw s2, registers + 8(sp)
+ sw s3, registers + 12(sp)
+ sw s4, registers + 16(sp)
+ sw s5, registers + 20(sp)
+ sw s6, registers + 24(sp)
+ sw s7, registers + 28(sp)
+ sw s8, registers + 32(sp)
+/* Save return address */
+ sw ra, returnaddr(sp)
+ .mask 0xc0ff0000, -4
+/* Need to save floating point registers? */
+ s.d $f20, floats + 0(sp)
+ s.d $f22, floats + 8(sp)
+ s.d $f24, floats + 16(sp)
+ s.d $f26, floats + 24(sp)
+ s.d $f28, floats + 32(sp)
+ s.d $f30, floats + 40(sp)
+ .fmask 0x55400000, regspace
+ sw sp, topstack(a1)
+ beq a2, $0, samestack
+ move sp, a2
+samestack:
+ move t9, a0
+ j t9
+ .end savecontext
+
+ .globl returnto
+ .ent returnto
+returnto:
+ .set noreorder
+ .cpload t9 # set up gp for KPIC
+ .set reorder
+
+ lw sp, topstack(a0)
+ lw s0, registers + 0(sp)
+ lw s1, registers + 4(sp)
+ lw s2, registers + 8(sp)
+ lw s3, registers + 12(sp)
+ lw s4, registers + 16(sp)
+ lw s5, registers + 20(sp)
+ lw s6, registers + 24(sp)
+ lw s7, registers + 28(sp)
+ lw s8, registers + 32(sp)
+/* Save return address */
+ lw ra, returnaddr(sp)
+/* Need to save floating point registers? */
+ l.d $f20, floats + 0(sp)
+ l.d $f22, floats + 8(sp)
+ l.d $f24, floats + 16(sp)
+ l.d $f26, floats + 24(sp)
+ l.d $f28, floats + 32(sp)
+ l.d $f30, floats + 40(sp)
+ .set noreorder
+ addu sp, regspace
+ la t0, PRE_Block
+ j ra
+ sb zero, 0(t0)
+ .set reorder
+ .end returnto
+
+#else
+/* Code for MIPS R2000/R3000 architecture
+ * Written by Zalman Stern April 30th, 1989.
+ */
+#include <regdef.h> /* Allow use of symbolic names for registers. */
+#define regspace 9 * 4 + 4 + 6 * 8
+#define floats 0
+#define registers floats + 6 * 8
+#define returnaddr regspace - 4
+#define topstack 0
+ .globl savecontext /* MIPS' C compiler doesnt prepend underscores. */
+ .ent savecontext /* Insert debugger information. */
+savecontext:
+ li t0, 1
+ .extern PRE_Block
+ sb t0, PRE_Block
+ subu sp, regspace
+ .frame sp, regspace, ra
+/* Save registers. */
+ sw s0, registers + 0(sp)
+ sw s1, registers + 4(sp)
+ sw s2, registers + 8(sp)
+ sw s3, registers + 12(sp)
+ sw s4, registers + 16(sp)
+ sw s5, registers + 20(sp)
+ sw s6, registers + 24(sp)
+ sw s7, registers + 28(sp)
+ sw s8, registers + 32(sp)
+/* Save return address */
+ sw ra, returnaddr(sp)
+ .mask 0xc0ff0000, -4
+/* Need to save floating point registers? */
+ s.d $f20, floats + 0(sp)
+ s.d $f22, floats + 8(sp)
+ s.d $f24, floats + 16(sp)
+ s.d $f26, floats + 24(sp)
+ s.d $f28, floats + 32(sp)
+ s.d $f30, floats + 40(sp)
+ .fmask 0x55400000, regspace
+ sw sp, topstack(a1)
+ beq a2, $0, samestack
+ addu sp, $0, a2
+samestack:
+ jal a0
+ .end savecontext
+
+ .globl returnto
+ .ent returnto
+returnto:
+ lw sp, topstack(a0)
+ lw s0, registers + 0(sp)
+ lw s1, registers + 4(sp)
+ lw s2, registers + 8(sp)
+ lw s3, registers + 12(sp)
+ lw s4, registers + 16(sp)
+ lw s5, registers + 20(sp)
+ lw s6, registers + 24(sp)
+ lw s7, registers + 28(sp)
+ lw s8, registers + 32(sp)
+/* Save return address */
+ lw ra, returnaddr(sp)
+/* Need to save floating point registers? */
+ l.d $f20, floats + 0(sp)
+ l.d $f22, floats + 8(sp)
+ l.d $f24, floats + 16(sp)
+ l.d $f26, floats + 24(sp)
+ l.d $f28, floats + 32(sp)
+ l.d $f30, floats + 40(sp)
+ addu sp, regspace
+ sb $0, PRE_Block
+ j ra
+ .end returnto
+#endif /* sgi */
+#endif
+
+#ifdef AFS_HPUX_ENV
+#include "process.s.hpux"
+#endif /* AFS_HPUX_ENV */
+
+#if defined(AFS_386i_ENV)
+/* i386 Assembly
+ *
+ * Written by Derek Atkins <warlord@MIT.EDU>
+ * (debugging help by Chris Provenzano <proven@mit.edu>)
+ * 11/1991
+ * + * "ojala que sea correcto!"
+ */
+
+#if !defined(SYSV) && !defined(__ELF__) && !defined(AFS_SUN5_ENV)
+#ifdef __STDC__
+#define SYMBOL(name) _##name
+#define ENTRY(name) _##name##:
+#else
+#define SYMBOL(name) _/**/name
+#define ENTRY(name) _/**/name/**/:
+#endif
+#else /* SYSV || __ELF__ || AFS_SUN5_ENV */
+#define SYMBOL(name) name
+#define ENTRY(name) name:
+#endif
+
+ .file "process.s"
+
+ .data
+
+ .text
+
+/*
+ * struct savearea {
+ * char *topstack;
+ * }
+ */
+
+ .set topstack,0
+
+/*
+ * savecontext(f, area1, newsp)
+ * int (*f)(); struct savearea *area1; char *newsp;
+ */
+
+/* offsets, to make my life easier! */
+ .set f,8
+ .set area1,12
+ .set newsp,16
+
+.globl SYMBOL(PRE_Block)
+.globl SYMBOL(savecontext)
+
+ENTRY(savecontext)
+ pushl %ebp /* New Frame! */
+ movl %esp,%ebp
+ pushal /* Push all registers */
+ movl $1,SYMBOL(PRE_Block) /* Do not allow any interrupt finagling */
+ movl area1(%ebp),%eax /* eax = base of savearea */
+ movl %esp,topstack(%eax) /* area->topstack = esp */
+ movl newsp(%ebp),%eax /* get new sp into eax */
+ cmpl $0,%eax
+ je L1 /* if new sp is 0 then dont change esp */
+ movl %eax,%esp /* go ahead. make my day! */
+L1:
+ jmp *f(%ebp) /* ebx = &f */
+
+/* Shouldnt be here....*/
+
+ call SYMBOL(abort)
+
+/*
+ * returnto(area2)
+ * struct savearea *area2;
+ */
+
+/* stack offset */
+ .set area2,8
+
+.globl SYMBOL(returnto)
+
+ENTRY(returnto)
+ pushl %ebp
+ movl %esp, %ebp /* New frame, to get correct pointer */
+ movl area2(%ebp),%eax /* eax = area2 */
+ movl topstack(%eax),%esp /* restore esp */
+ popal
+ movl $0,SYMBOL(PRE_Block) /* clear it up... */
+ popl %ebp
+ ret
+
+/* I see, said the blind man, as he picked up his hammer and saw! */
+ pushl $1234
+ call SYMBOL(abort)
+
+#endif /* AFS_386i_ENV */
+
+#ifdef __alpha
+/* Code for DEC Alpha architecture */
+#ifdef AFS_OSF_ENV
+#include <machine/asm.h>
+#include <machine/regdef.h>
+#define fs0 $f2
+#define fs1 $f3
+#define fs2 $f4
+#define fs3 $f5
+#define fs4 $f6
+#define fs5 $f7
+#define fs6 $f8
+#define fs7 $f9
+#elif AFS_LINUX_ENV
+#define v0 $0
+#define t0 $1
+#define t1 $2
+#define t2 $3
+#define t3 $4
+#define t4 $5
+#define t5 $6
+#define t6 $7
+#define t7 $8
+
+#define s0 $9
+#define s1 $10
+#define s2 $11
+#define s3 $12
+#define s4 $13
+#define s5 $14
+#define s6 $15
+
+#define fp $15
+#define a0 $16
+#define a1 $17
+#define a2 $18
+#define a3 $19
+#define a4 $20
+#define a5 $21
+#define t8 $22
+#define t9 $23
+#define t10 $24
+#define t11 $25
+#define ra $26
+#define pv $27
+#define t12 $27
+#define at $28
+#define gp $29
+#define sp $30
+#define zero $31
+
+#define fs0 $f2
+#define fs1 $f3
+#define fs2 $f4
+#define fs3 $f5
+#define fs4 $f6
+#define fs5 $f7
+#define fs6 $f8
+#define fs7 $f9
+
+#define M_S0 0x00000200
+#define M_S1 0x00000400
+#define M_S2 0x00000800
+#define M_S3 0x00001000
+#define M_S4 0x00002000
+#define M_S5 0x00004000
+#define M_S6 0x00008000
+
+#define M_RA 0x04000000
+
+#define END(proc) \
+ .end proc
+
+#define NESTED(x, fsize, rpc) \
+ .globl x ; \
+ .ent x,0 ; \
+x: ; \
+ .frame sp,fsize, rpc
+
+
+#define LEAF(x) \
+ .globl x ; \
+ .ent x,0 ; \
+x: ; \
+ .frame sp,0,ra
+
+#define IMPORT(sym, size) \
+ .extern sym,size
+#elif AFS_NETBSD_ENV
+#include <machine/asm.h>
+#else /* OSF */
+#include <mach/alpha/asm.h>
+#endif /* OSF */
+
+#define FRAMESIZE ((8*8)+8+(7*8))
+#define floats 0
+#define registers (floats+(8*8))
+#define returnaddr (FRAMESIZE-8)
+#define topstack 0
+
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX_ENV)
+ IMPORT(PRE_Block,4)
+#endif
+.align 4
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX_ENV)
+NESTED(savecontext,FRAMESIZE,ra)
+#else /* OSF || LINUX */
+NESTED(savecontext,3,FRAMESIZE,ra,0x0400f700,0x000003fc)
+#endif /* OSF */
+ ldgp gp,0(pv)
+ lda t0, 1(zero)
+ stl t0, PRE_Block
+ lda sp,-FRAMESIZE(sp)
+/* Save callee-saved registers. */
+ stq s0, (registers+0) (sp)
+ stq s1, (registers+8) (sp)
+ stq s2, (registers+16) (sp)
+ stq s3, (registers+24) (sp)
+ stq s4, (registers+32) (sp)
+ stq s5, (registers+40) (sp)
+ stq s6, (registers+48) (sp)
+/* Save return address */
+ stq ra, returnaddr(sp)
+
+#if !defined(AFS_NETBSD_ENV)
+ .mask (M_S0|M_S1|M_S2|M_S3|M_S4|M_S5|M_S6|M_RA), -FRAMESIZE
+#endif
+
+/* Save floating point registers */
+ stt fs0, (floats+0) (sp)
+ stt fs1, (floats+8) (sp)
+ stt fs2, (floats+16) (sp)
+ stt fs3, (floats+24) (sp)
+ stt fs4, (floats+32) (sp)
+ stt fs5, (floats+40) (sp)
+ stt fs6, (floats+48) (sp)
+ stt fs7, (floats+56) (sp)
+
+ .prologue 1
+ stq sp, topstack(a1)
+ or a0,zero,pv /* call point in pv */
+ beq a2, samestack
+ or a2,zero,sp /* switch stack */
+samestack:
+ jsr ra,(pv),0 /* off we go */
+ END(savecontext)
+
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX_ENV)
+LEAF(returnto)
+#else
+LEAF(returnto,1)
+#endif
+ ldgp gp,0(pv)
+
+ .prologue 1
+ ldq sp, topstack(a0)
+/* Restore callee-saved regs */
+ ldq s0, (registers+0) (sp)
+ ldq s1, (registers+8) (sp)
+ ldq s2, (registers+16) (sp)
+ ldq s3, (registers+24) (sp)
+ ldq s4, (registers+32) (sp)
+ ldq s5, (registers+40) (sp)
+ ldq s6, (registers+48) (sp)
+/* Return address */
+ ldq ra, returnaddr(sp)
+/* Floating point registers */
+ ldt fs0, (floats+0) (sp)
+ ldt fs1, (floats+8) (sp)
+ ldt fs2, (floats+16) (sp)
+ ldt fs3, (floats+24) (sp)
+ ldt fs4, (floats+32) (sp)
+ ldt fs5, (floats+40) (sp)
+ ldt fs6, (floats+48) (sp)
+ ldt fs7, (floats+56) (sp)
+ lda sp, FRAMESIZE(sp)
+ stl zero, PRE_Block
+ RET
+ END(returnto)
+#endif
+
+
+#if defined(__powerpc__)
+
+/* Comments:
+ * 1. Registers R10..R31 and CR0..CR7 are saved
+ * 2. "struct savearea" must hold at least 3 pointers (long)
+ * 3. This code will only work on 32 bit machines (601..604), not 620
+ * 4. No floating point registers are saved
+ * 5. The save stack "frame" is bigger than absolutely necessary. The
+ * PowerPC [AIX] ABI needs this extra space.
+ */
+
+
+/* Mach-O assemblers */
+#if !defined(NeXT) && !defined(__APPLE__)
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+#endif /* !NeXT && !__APPLE__ */
+
+
+/*
+ * savecontext(int (*f)(), struct savearea *save, char *newsp)
+ */
+
+#define FRAME_SIZE (32*4)+(8*4)
+#define FRAME_OFFSET (8*4)
+
+#define TOP_OF_STACK (0*4)
+#define RETURN (1*4)
+#define CCR (2*4)
+
+#if defined(NeXT) || defined(__APPLE__)
+ .globl _savecontext
+_savecontext:
+ lis r9,ha16(_PRE_Block) /* Disable interrupt fiddling */
+ li r8,1
+ stb r8,lo16(_PRE_Block)(r9)
+#else
+ .globl savecontext
+savecontext:
+ lis r9,PRE_Block@ha /* Disable interrupt fiddling */
+ li r8,1
+ stb r8,PRE_Block@l(r9)
+#endif /* NeXT || __APPLE__ */
+ subi r1,r1,FRAME_SIZE
+ mfcr r9
+ stw r9,CCR(r4)
+ stw r10,10*4+FRAME_OFFSET(r1) /* Save registers */
+ stw r11,11*4+FRAME_OFFSET(r1)
+ stw r12,12*4+FRAME_OFFSET(r1)
+ stw r13,13*4+FRAME_OFFSET(r1)
+ stw r14,14*4+FRAME_OFFSET(r1)
+ stw r15,15*4+FRAME_OFFSET(r1)
+ stw r16,16*4+FRAME_OFFSET(r1)
+ stw r17,17*4+FRAME_OFFSET(r1)
+ stw r18,18*4+FRAME_OFFSET(r1)
+ stw r19,19*4+FRAME_OFFSET(r1)
+ stw r20,20*4+FRAME_OFFSET(r1)
+ stw r21,21*4+FRAME_OFFSET(r1)
+ stw r22,22*4+FRAME_OFFSET(r1)
+ stw r23,23*4+FRAME_OFFSET(r1)
+ stw r24,24*4+FRAME_OFFSET(r1)
+ stw r25,25*4+FRAME_OFFSET(r1)
+ stw r26,26*4+FRAME_OFFSET(r1)
+ stw r27,27*4+FRAME_OFFSET(r1)
+ stw r28,28*4+FRAME_OFFSET(r1)
+ stw r29,29*4+FRAME_OFFSET(r1)
+ stw r30,30*4+FRAME_OFFSET(r1)
+ stw r31,31*4+FRAME_OFFSET(r1)
+ stw r1,TOP_OF_STACK(r4)
+ cmpi 0,r5,0 /* New stack specified? */
+ mflr r0
+ stw r0,RETURN(r4)
+ mtlr r3
+ beq L1 /* No - don't muck with pointer */
+
+ mr r1,r5
+L1: blr /* Return */
+
+/*
+ * returnto(struct savearea *area)
+ */
+#if defined(NeXT) || defined(__APPLE__)
+ .globl _returnto
+_returnto:
+#else
+ .globl returnto
+returnto:
+#endif /* NeXT || __APPLE__ */
+ lwz r1,TOP_OF_STACK(r3) /* Update stack pointer */
+ lwz r0,RETURN(r3) /* Get return address */
+ mtlr r0
+ lwz r4,CCR(r3)
+ mtcrf 0xFF,r4
+ lwz r10,10*4+FRAME_OFFSET(r1) /* Restore registers */
+ lwz r11,11*4+FRAME_OFFSET(r1)
+ lwz r12,12*4+FRAME_OFFSET(r1)
+ lwz r13,13*4+FRAME_OFFSET(r1)
+ lwz r14,14*4+FRAME_OFFSET(r1)
+ lwz r15,15*4+FRAME_OFFSET(r1)
+ lwz r16,16*4+FRAME_OFFSET(r1)
+ lwz r17,17*4+FRAME_OFFSET(r1)
+ lwz r18,18*4+FRAME_OFFSET(r1)
+ lwz r19,19*4+FRAME_OFFSET(r1)
+ lwz r20,20*4+FRAME_OFFSET(r1)
+ lwz r21,21*4+FRAME_OFFSET(r1)
+ lwz r22,22*4+FRAME_OFFSET(r1)
+ lwz r23,23*4+FRAME_OFFSET(r1)
+ lwz r24,24*4+FRAME_OFFSET(r1)
+ lwz r25,25*4+FRAME_OFFSET(r1)
+ lwz r26,26*4+FRAME_OFFSET(r1)
+ lwz r27,27*4+FRAME_OFFSET(r1)
+ lwz r28,28*4+FRAME_OFFSET(r1)
+ lwz r29,29*4+FRAME_OFFSET(r1)
+ lwz r30,30*4+FRAME_OFFSET(r1)
+ lwz r31,31*4+FRAME_OFFSET(r1)
+#if defined(NeXT) || defined(__APPLE__)
+ lis r9,ha16(_PRE_Block) /* Re-enable interrupt fiddling */
+ li r8,0
+ stb r8,lo16(_PRE_Block)(r9)
+#else
+ lis r9,PRE_Block@ha /* Re-enable interrupt fiddling */
+ li r8,0
+ stb r8,PRE_Block@l(r9)
+#endif /* NeXT || __APPLE__ */
+ addi r1,r1,FRAME_SIZE
+ blr
+#endif /* __powerpc__ */
+
diff --git a/usr.sbin/afs/src/lwp/process.s.hpux b/usr.sbin/afs/src/lwp/process.s.hpux
new file mode 100644
index 00000000000..873f9c45c44
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/process.s.hpux
@@ -0,0 +1,219 @@
+#ifdef AFS_HPUX_ENV
+#ifdef hp9000s300
+/*
+#
+# Process assembly language assist for HP 9000 series 300s.
+#
+*/
+
+ text
+
+/*
+#
+# struct savearea {
+# char *topstack;
+# }
+#
+*/
+
+ global _PRE_Block
+
+ set topstack,0
+
+/* Stuff to allow saving/restoring registers */
+ set NREGS,13
+ set REGS,0x3ffe # d1-d7 & a0-a5
+
+/*
+# savecontext(f, area1, newsp)
+# int (*f)(); struct savearea *area1; char *newsp;
+*/
+
+/* Stack offsets of arguments */
+ set f,8
+ set area1,12
+ set newsp,16
+
+ global _savecontext
+_savecontext:
+ mov.b &1,_PRE_Block # Dont allow any interrupt finagling
+ link %a6,&-(NREGS*4) # Save frame pointer & ...
+ # ... allocate space for nregs registers
+/* Save registers */
+ movem.l &REGS,(%sp)
+
+ mov.l area1(%a6),%a0 # a0 = base of savearea
+ mov.l %sp,topstack(%a0) # area->topstack = sp
+ mov.l newsp(%a6),%d0 # Get new sp
+ beq.b l1 # If newsp == 0, no stack switch
+ mov.l %d0,%sp # Switch to new stack
+l1:
+ mov.l f(%a6),%a0 # a0 = f
+ jsr (%a0) # f()
+
+/* It is impossible to be here, so abort() */
+
+ jsr _abort
+
+/*
+# returnto(area2)
+# struct savearea *area2;
+*/
+
+/* Stack offset of argument */
+set area2,8
+
+ global _returnto
+_returnto:
+ link %a6,&0
+ mov.l area2(%a6),%a0 # Base of savearea
+ mov.l topstack(%a0),%sp # Restore sp
+/* Restore registers */
+ movem.l (%sp),&REGS
+
+ add.l &(NREGS*4),%sp
+ mov.l %sp,%a6 # Argghh...be careful here
+ unlk %a6
+ clr.b _PRE_Block
+ rts # Return to previous process
+#else
+
+/* start of S700 code */
+#ifdef AFS_HPUX_PIC_ENV
+/* this code is PIC */
+ .CODE
+
+ ;
+ ; savecontext(f, area1, newsp)
+ ; int (*f)();
+ ; struct savearea *area1;
+ ; char *newsp;
+ ;
+savecontext
+ .PROC
+ ;
+ ; Callinfo sets up register saves using the ENTRY_GR
+ ; and ENTRY_FR parameters. ENTRY_FR=21 is only valid
+ ; for PA 1.1. (How to deal with this for 800?)
+ ;
+ .CALLINFO CALLER,FRAME=0,SAVE_RP,ENTRY_GR=18,ENTRY_FR=21
+ ; The ENTER statement generates register saves and
+ ; procedure setup.
+ .ENTER
+
+ LDI 1,%r1 ; Store a (char) 1 in
+ LDW T'PRE_Block(0,%r19),%r31 ; global variable
+ STB %r1,0(0,%r31) ; PRE_Block.
+
+
+ COPY %arg0,%r22 ; Copy arg0 (f) to dyncall's input register.
+
+ COMIB,= 0,%arg2,L$0001 ; Compare arg2 (newsp) to 0. Execute the
+ ; next instruction regardless of value.
+ STW %r30,0(0,%arg1) ; Store the stack pointer in the first
+ ; element (0th offset) of arg1 (area1).
+ COPY %arg2,%r30 ; Move arg2 (newsp) into the stack ptr.
+
+L$0001
+ .CALL
+ BL $$dyncall,%r31 ; Dynamic call using pointer in r22.
+ COPY %r31,%r2
+ COPY %r20, %r19 ; restore link table.
+
+ .CALL
+ BL exit,%r2 ; Can't get here, so abort.
+ NOP
+ .LEAVE
+ .PROCEND
+
+ ; returnto(area2)
+ ; struct savearea *area2;
+ ;
+returnto
+ .PROC
+ .CALLINFO CALLER,FRAME=0,SAVE_RP,ENTRY_GR=18,ENTRY_FR=21
+ ; No ENTRY is used since this is a magic routine.
+ LDWS 0(0,%arg0),%r30 ; Load the stack pointer from area2
+
+ LDW T'PRE_Block(0,%r19),%r31 ; set PRE_Block = 0;
+ STB %r0,0(0,%r31)
+ .LEAVE
+ .PROCEND
+
+ .EXPORT savecontext,ENTRY
+ .EXPORT returnto,ENTRY
+ .IMPORT PRE_Block,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .IMPORT exit,CODE
+
+ .END
+#else /* AFS_HPUX_PIC_ENV */
+/* non-pic'ified code */
+ .CODE
+
+ ;
+ ; savecontext(f, area1, newsp)
+ ; int (*f)();
+ ; struct savearea *area1;
+ ; char *newsp;
+ ;
+savecontext
+ .PROC
+ ;
+ ; Callinfo sets up register saves using the ENTRY_GR
+ ; and ENTRY_FR parameters. ENTRY_FR=21 is only valid
+ ; for PA 1.1. (How to deal with this for 800?)
+ ;
+ .CALLINFO CALLER,FRAME=0,SAVE_RP,ENTRY_GR=18,ENTRY_FR=21
+ ; The ENTER statement generates register saves and
+ ; procedure setup.
+ .ENTER
+
+ LDI 1,%r31 ; Store a (char) 1 in
+ ADDIL LR'PRE_Block-$global$,%r27 ; global variable
+ STB %r31,RR'PRE_Block-$global$(0,%r1) ; PRE_Block.
+
+ COPY %r26,%r22 ; Copy arg0 (f) to dyncall's input register.
+
+ COMIB,= 0,%r24,L$0001 ; Compare arg2 (newsp) to 0. Execute the
+ ; next instruction regardless of value.
+ STWS %r30,0(0,%r25) ; Store the stack pointer in the first
+ ; element (0th offset) of arg1 (area1).
+ COPY %r24,%r30 ; Move arg2 (newsp) into the stack ptr.
+
+L$0001
+ .CALL
+ BL $$dyncall,%r31 ; Dynamic call using pointer in r22.
+ COPY %r31,%r2
+
+ .CALL
+ BL abort,%r2 ; Can't get here, so abort.
+ NOP
+ .LEAVE
+ .PROCEND
+
+ ; returnto(area2)
+ ; struct savearea *area2;
+ ;
+returnto
+ .PROC
+ .CALLINFO CALLER,FRAME=0,SAVE_RP,ENTRY_GR=18,ENTRY_FR=21
+ ; No ENTRY is used since this is a magic routine.
+ ADDIL LR'PRE_Block-$global$,%r27 ; PRE_Block = 0
+ STB %r0,RR'PRE_Block-$global$(0,%r1)
+
+ LDWS 0(0,%r26),%r30 ; Load the stack pointer from area2
+ .LEAVE
+ .PROCEND
+
+ .EXPORT savecontext,ENTRY
+ .EXPORT returnto,ENTRY
+ .IMPORT $global$,DATA
+ .IMPORT PRE_Block,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .IMPORT abort,CODE
+
+ .END
+#endif /* AFS_HPUX_PIC_ENV */
+#endif /* hp9000s300 */
+#endif /* AFS_HPUX_ENV */
diff --git a/usr.sbin/afs/src/lwp/q.c b/usr.sbin/afs/src/lwp/q.c
new file mode 100644
index 00000000000..5acf8286227
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/q.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: q.c,v 1.1.1.1 1998/09/14 21:53:13 art Exp $ */
+/*
+ * Emulate the vax instructions for queue insertion and deletion, somewhat.
+ * A std_queue structure is defined here and used by these routines. These
+ * routines use caddr_ts so they can operate on any structure. The std_queue
+ * structure is used rather than proc structures so that when the proc struct
+ * changes only process management code breaks. The ideal solution would be
+ * to define a std_queue as a global type which is part of all the structures
+ * which are manipulated by these routines. This would involve considerable
+ * effort...
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: q.c,v 1.7 1998/02/12 01:03:14 assar Exp $") ;
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#include <utime.h>
+
+/* Ansified, made more readable, and mayby fixed /lha */
+
+struct std_queue {
+ struct std_queue *q_link;
+ struct std_queue *q_rlink;
+} ;
+
+void lwp_insque(void *elementp, void *quep)
+{
+ struct std_queue *que = (struct std_queue *) quep ;
+ struct std_queue *element = (struct std_queue *) elementp ;
+
+ element->q_link = que->q_link;
+ element->q_rlink = que;
+
+ que->q_link->q_rlink = element;
+ que->q_link = element;
+}
+
+void lwp_remque(void *elementp)
+{
+ struct std_queue *element = (struct std_queue *) elementp ;
+
+ element->q_link->q_rlink = element->q_rlink;
+ element->q_rlink->q_link = element->q_link;
+
+ element->q_rlink = element->q_link = (struct std_queue *) 0;
+}
+
diff --git a/usr.sbin/afs/src/lwp/q.h b/usr.sbin/afs/src/lwp/q.h
new file mode 100644
index 00000000000..590db96c7bb
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/q.h
@@ -0,0 +1,5 @@
+/* $OpenBSD: q.h,v 1.1.1.1 1998/09/14 21:53:13 art Exp $ */
+/* $KTH: q.h,v 1.2 1998/02/12 01:03:32 assar Exp $ */
+
+void lwp_insque(void *, void *);
+void lwp_remque(void *);
diff --git a/usr.sbin/afs/src/lwp/testlwp.c b/usr.sbin/afs/src/lwp/testlwp.c
new file mode 100644
index 00000000000..f967691ea09
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/testlwp.c
@@ -0,0 +1,314 @@
+/* $OpenBSD: testlwp.c,v 1.1.1.1 1998/09/14 21:53:13 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * testlwp
+ *
+ * Checks if lwp seams to work, and demostrates how to use lwp.
+ * Give multiple commands om the argumentline to run several
+ * tests on the same time.
+ *
+ * $KTH: testlwp.c,v 1.2 1998/07/15 12:50:58 map Exp $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <lwp.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+static void Producer(void *foo) ;
+static void Consumer(void *foo) ;
+
+#define LWPTEST_STACKSIZE (16*1024)
+
+/*
+ * Classic Producer Consumer thread testing
+ *
+ * Observe the use of SignalNoYield, you can't signal anything
+ * that isn't sleeping.
+ */
+
+static char pcfoo = 'a' - 1;
+
+static void
+Producer(void *foo)
+{
+ while (1) {
+ LWP_WaitProcess((char *)Producer);
+ pcfoo++;
+ if (pcfoo > 'z')
+ pcfoo = 'a';
+ printf("[producer] creating %c\n", pcfoo);
+ LWP_NoYieldSignal ((char *)Consumer);
+ }
+}
+
+static void
+Consumer(void *foo)
+{
+ LWP_NoYieldSignal ((char *)Producer);
+ while (1) {
+ LWP_WaitProcess((char *)Consumer);
+ printf("[consumer] eating %c\n", pcfoo);
+ LWP_NoYieldSignal ((char *)Producer);
+ }
+}
+
+static int
+startPCtest(void)
+{
+ PROCESS consumer, producer;
+
+ if (LWP_CreateProcess (Producer, LWPTEST_STACKSIZE, 1,
+ NULL, "producer", &consumer))
+ errx (1, "Cannot create producer process");
+
+ if (LWP_CreateProcess (Consumer, LWPTEST_STACKSIZE, 1,
+ NULL, "consumer", &producer))
+ errx (1, "Cannot create consumer process");
+ return 0;
+}
+
+/*
+ * Test the LWP_Sleep() function
+ */
+
+static void
+MrSleepy(void *foo)
+{
+ printf("[mrsleepy] I'm going to bed\n");
+ while (1) {
+ IOMGR_Sleep(1);
+ printf("[mrsleepy] yawn\n");
+ }
+}
+
+static int
+putMrSleeptoBed(void)
+{
+ PROCESS mrsleepy;
+
+ if (LWP_CreateProcess (MrSleepy, LWPTEST_STACKSIZE, 1,
+ NULL, "mrsleepy", &mrsleepy))
+ errx (1, "Cannot create consumer process");
+ return 0;
+}
+
+/*
+ * The Producer Consumer thingy done over a pipe
+ */
+
+int pipa[2] = { -1, -1 };
+
+static void
+SelectProducer(void *foo)
+{
+ char *str = (char *) foo;
+ int len ;
+
+ if (str == NULL)
+ str = "foo";
+ len = strlen (str) ;
+
+ while(1) {
+ IOMGR_Sleep(1) ;
+ printf("[selprodu] %s\n", str);
+ }
+}
+
+static void
+SelectConsumer(void *foo)
+{
+ char str[200];
+ int len ;
+ fd_set readset;
+
+ while(1) {
+ FD_ZERO(&readset);
+ FD_SET(pipa[0], &readset);
+ IOMGR_Select(pipa[0] + 1, &readset, NULL, NULL, NULL);
+ len = read(pipa[0], str, 199);
+ if (len < 0)
+ err(1, "read");
+ str[len] = '\0';
+ printf("[selcomsu] %s\n", str);
+ }
+}
+
+void
+startSelectPC (char *progname)
+{
+ int pid;
+ PROCESS consumer;
+
+ if (pipa[0] == -1) {
+ if (pipe(pipa))
+ err(1, "pipe");
+
+ if (LWP_CreateProcess (SelectConsumer, LWPTEST_STACKSIZE, 1,
+ NULL, "selconsu", &consumer))
+ errx (1, "Cannot create select consumer process");
+ }
+
+ pid = fork();
+ switch (pid) {
+ case -1: /* error */
+ err(1, "fork");
+ case 0: /* child */
+ close(0);
+ if (dup2(pipa[1], 0) == -1)
+ err(1, "dup2");
+ close(pipa[1]);
+ execl(progname, "testlwp", "selectproducer", NULL);
+ err(1, "execl");
+ default:
+ break;
+ }
+}
+
+/*
+ * Test cancel
+ */
+
+static void
+onStrike(void *foo)
+{
+ while (1) {
+ printf("[onstrike] I'll never quit, block, block, block\n");
+ IOMGR_Select(0, NULL, NULL, NULL, NULL);
+ printf("[onstrike] Bah, you will never pay enough\n");
+ }
+}
+
+static void
+freeEnterprise(void *foo)
+{
+ PROCESS *pid = (PROCESS *) foo;
+
+ while(1) {
+ IOMGR_Sleep(1);
+ printf("[enterpri] Raise salery\n");
+ IOMGR_Cancel(*pid);
+ }
+}
+
+static void
+yaEndlessLoop(void)
+{
+ static PROCESS worker, enterprise;
+
+ if (LWP_CreateProcess (onStrike, LWPTEST_STACKSIZE, 1,
+ NULL, "worker", &worker))
+ errx (1, "Cannot create worker process");
+
+ if (LWP_CreateProcess (freeEnterprise, LWPTEST_STACKSIZE, 1,
+ (void *)&worker, "enterprise", &enterprise))
+ errx (1, "Cannot create enterprise process");
+}
+
+
+/*
+ * Usage
+ */
+
+static void
+usage(char *progname)
+{
+ fprintf(stderr, "usage: %s cmd ...\nWhere cmd is one of:\n", progname);
+ fprintf(stderr,
+ "pc\t\tProducer Consumer test\n"
+ "sleep\t\tSleeptest\n"
+ "selectconsumer\tSelect consumer\n"
+ "selectproducer\t(special case, just print a string on stdout repeatally)\n"
+ "cancel\t\tTest iomgr cancel\n"
+ "version\t\tPrint version\n");
+
+ printf("Use several of these tests together to test their interopability\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ PROCESS pid;
+ char *progname = strdup(argv[0]);
+
+ if (progname == NULL)
+ progname = "foo";
+
+ if (argc <= 1 )
+ usage(progname);
+
+ printf("starting LWP support\n");
+ if (LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid))
+ errx(1, "LWP_InitializeProcessSupport()\n");
+
+ printf("starting IOMGR support\n");
+ if (IOMGR_Initialize())
+ errx(1, "IOMGR_Initialize()\n");
+
+ while (argv[1]) {
+ if (strcasecmp("pc", argv[1]) == 0) {
+ startPCtest();
+ } else if (strcasecmp("sleep", argv[1]) == 0) {
+ putMrSleeptoBed();
+ } else if (strcasecmp("selectproducer", argv[1]) == 0) {
+ SelectProducer(NULL);
+ exit(1); /* Special case */
+ } else if (strcasecmp("selectconsumer", argv[1]) == 0) {
+ startSelectPC (progname);
+ } else if (strcasecmp("cancel", argv[1]) == 0) {
+ yaEndlessLoop();
+ } else if (strcasecmp("version", argv[1]) == 0) {
+ printf("Version: $KTH: testlwp.c,v 1.2 1998/07/15 12:50:58 map Exp $\n");
+ } else {
+ printf("unknown command %s\n", argv[1]);
+ }
+
+ argc--;
+ argv++;
+ }
+ LWP_WaitProcess((char *) main);
+ return 0;
+}
+
+
diff --git a/usr.sbin/afs/src/lwp/testprocess.c b/usr.sbin/afs/src/lwp/testprocess.c
new file mode 100644
index 00000000000..9b72f791130
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/testprocess.c
@@ -0,0 +1,23 @@
+/* $OpenBSD: testprocess.c,v 1.1.1.1 1998/09/14 21:53:11 art Exp $ */
+#include <lwp.h>
+
+/*
+ * This is no test-program for lwp, this is just to make
+ * sure we got a process.o that we can link with.
+ * Run it if you want a coredump...
+ *
+ *
+ * Todo: really a test-program
+ *
+ * $KTH: testprocess.c,v 1.1 1998/06/09 11:52:53 lha Exp $
+ */
+
+int savecontext();
+int returnto();
+
+int main(void)
+{
+ savecontext();
+ returnto();
+ return 0;
+}
diff --git a/usr.sbin/afs/src/lwp/timer.c b/usr.sbin/afs/src/lwp/timer.c
new file mode 100644
index 00000000000..a24fa261a8d
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/timer.c
@@ -0,0 +1,266 @@
+/* $OpenBSD: timer.c,v 1.1.1.1 1998/09/14 21:53:13 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+* *
+\*******************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: timer.c,v 1.5 1998/05/18 05:44:41 art Exp $");
+#endif
+
+#include <sys/time.h>
+#define _TIMER_IMPL_
+#include "timer.h"
+#include "q.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define NIL 0
+
+#define expiration TotalTime
+
+#define new_elem() ((struct TM_Elem *) malloc(sizeof(struct TM_Elem)))
+
+#define MILLION 1000000
+
+static int globalInitDone = 0;
+
+/* t1 = t2 - t3 */
+
+static void
+subtract(register struct timeval *t1,
+ register struct timeval *t2,
+ register struct timeval *t3)
+{
+ register int sec2, usec2, sec3, usec3;
+
+ sec2 = t2 -> tv_sec;
+ usec2 = t2 -> tv_usec;
+ sec3 = t3 -> tv_sec;
+ usec3 = t3 -> tv_usec;
+
+ /* Take care of the probably non-existent case where the
+ * usec field has more than 1 second in it. */
+
+ while (usec3 > usec2) {
+ usec2 += MILLION;
+ sec2--;
+ }
+
+ /* Check for a negative time and use zero for the answer,
+ * since the tv_sec field is unsigned */
+
+ if (sec3 > sec2) {
+ t1 -> tv_usec = 0;
+ t1 -> tv_sec = (unsigned long) 0;
+ } else {
+ t1 -> tv_usec = usec2 - usec3;
+ t1 -> tv_sec = sec2 - sec3;
+ }
+}
+
+/* t1 += t2; */
+
+static void
+add(register struct timeval *t1, register struct timeval *t2)
+{
+ t1 -> tv_usec += t2 -> tv_usec;
+ t1 -> tv_sec += t2 -> tv_sec;
+ if (t1->tv_usec >= MILLION) {
+ t1 -> tv_sec ++;
+ t1 -> tv_usec -= MILLION;
+ }
+}
+
+/* t1 == t2 */
+
+bool
+TM_eql(register struct timeval *t1, register struct timeval *t2)
+{
+ return (t1->tv_usec == t2->tv_usec) && (t1->tv_sec == t2->tv_sec);
+}
+
+/* t1 >= t2 */
+
+/*
+obsolete, commentless procedure, all done by hand expansion now.
+static bool
+geq(register struct timeval *t1, register struct timeval *t2)
+{
+ return (t1->tv_sec > t2->tv_sec) ||
+ (t1->tv_sec == t2->tv_sec && t1->tv_usec >= t2->tv_usec);
+}
+*/
+
+static bool
+blocking(register struct TM_Elem *t)
+{
+ return (t->TotalTime.tv_sec < 0 || t->TotalTime.tv_usec < 0);
+}
+
+
+
+/*
+ * Initializes a list -- returns -1 if failure, else 0.
+ */
+
+int
+TM_Init(register struct TM_Elem **list)
+{
+ if (!globalInitDone) {
+ FT_Init (0, 0);
+ globalInitDone = 1;
+ }
+ *list = new_elem();
+ if (*list == NIL)
+ return -1;
+ else {
+ (*list) -> Next = *list;
+ (*list) -> Prev = *list;
+ (*list) -> TotalTime.tv_sec = 0;
+ (*list) -> TotalTime.tv_usec = 0;
+ (*list) -> TimeLeft.tv_sec = 0;
+ (*list) -> TimeLeft.tv_usec = 0;
+ (*list) -> BackPointer = NIL;
+
+ return 0;
+ }
+}
+
+int
+TM_Final(register struct TM_Elem **list)
+{
+ if (list == NIL || *list == NIL)
+ return -1;
+ else {
+ free(*list);
+ *list = NIL;
+ return 0;
+ }
+}
+
+/*
+ * Inserts elem into the timer list pointed to by *tlistPtr.
+ */
+
+void
+TM_Insert(struct TM_Elem *tlistPtr, struct TM_Elem *elem)
+/* pointer to head pointer of timer list */
+/* element to be inserted */
+{
+ register struct TM_Elem *next;
+
+ /* TimeLeft must be set for function IOMGR with infinite timeouts */
+ elem -> TimeLeft = elem -> TotalTime;
+
+ /* Special case -- infinite timeout */
+ if (blocking(elem)) {
+ lwp_insque(elem, tlistPtr->Prev);
+ return;
+ }
+
+ /* Finite timeout, set expiration time */
+ FT_AGetTimeOfDay(&elem->expiration, 0);
+ add(&elem->expiration, &elem->TimeLeft);
+ next = NIL;
+ FOR_ALL_ELTS(p, tlistPtr, {
+ if (blocking(p) || !(elem->TimeLeft.tv_sec > p->TimeLeft.tv_sec ||
+ (elem->TimeLeft.tv_sec == p->TimeLeft.tv_sec && elem->TimeLeft.tv_usec >= p->TimeLeft.tv_usec))
+ ) {
+ next = p; /* Save ptr to element that will be after this one */
+ break;
+ }
+ })
+
+ if (next == NIL) next = tlistPtr;
+ lwp_insque(elem, next->Prev);
+}
+
+/*
+ * Walks through the specified list and updates the TimeLeft fields in it.
+ * Returns number of expired elements in the list.
+ */
+
+int
+TM_Rescan(struct TM_Elem *tlist)
+/* head pointer of timer list */
+{
+ struct timeval time;
+ register int expired;
+
+ FT_AGetTimeOfDay(&time, 0);
+ expired = 0;
+ FOR_ALL_ELTS(e, tlist, {
+ if (!blocking(e)) {
+ subtract(&e->TimeLeft, &e->expiration, &time);
+ if (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec && 0 >=
+ e->TimeLeft.tv_usec))
+ expired++;
+ }
+ })
+ return expired;
+}
+
+/*
+ * RETURNS POINTER TO earliest expired entry from tlist.
+ * Returns 0 if no expired entries are present.
+ */
+
+struct TM_Elem *
+TM_GetExpired(struct TM_Elem *tlist)
+/* head pointer of timer list */
+{
+ FOR_ALL_ELTS(e, tlist, {
+ if (!blocking(e) &&
+ (0 > e->TimeLeft.tv_sec || (0 == e->TimeLeft.tv_sec
+ && 0 >= e->TimeLeft.tv_usec)))
+ return e;
+ })
+ return NIL;
+}
+
+/*
+ * Returns a pointer to the earliest unexpired element in tlist.
+ * Its TimeLeft field will specify how much time is left.
+ * Returns 0 if tlist is empty or if there are no unexpired elements.
+ */
+
+struct TM_Elem *
+TM_GetEarliest(struct TM_Elem *tlist)
+{
+ register struct TM_Elem *e;
+
+ e = tlist -> Next;
+ return (e == tlist ? NIL : e);
+}
diff --git a/usr.sbin/afs/src/lwp/timer.h b/usr.sbin/afs/src/lwp/timer.h
new file mode 100644
index 00000000000..3a069eff37f
--- /dev/null
+++ b/usr.sbin/afs/src/lwp/timer.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: timer.h,v 1.1.1.1 1998/09/14 21:53:13 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*******************************************************************\
+* *
+* Information Technology Center *
+* Carnegie-Mellon University *
+* *
+* *
+\*******************************************************************/
+
+struct TM_Elem {
+ struct TM_Elem *Next; /* filled by package */
+ struct TM_Elem *Prev; /* filled by package */
+ struct timeval TotalTime; /* filled in by caller -- modified by package */
+ struct timeval TimeLeft; /* filled by package */
+ char *BackPointer; /* filled by caller, not interpreted by package */
+};
+
+#ifndef _TIMER_IMPL_
+extern void Tm_Insert();
+#define TM_Remove(list, elem) lwp_remque(elem)
+extern int TM_Rescan();
+extern struct TM_Elem *TM_GetExpired();
+extern struct TM_Elem *TM_GetEarliest();
+#endif
+
+typedef unsigned char bool; /* XXX - this is not the correct place */
+
+bool TM_eql(register struct timeval *, register struct timeval *);
+int TM_Final(register struct TM_Elem **);
+void TM_Insert(struct TM_Elem *, struct TM_Elem *);
+
+#define FOR_ALL_ELTS(var, list, body)\
+ {\
+ register struct TM_Elem *_LIST_, *var, *_NEXT_;\
+ _LIST_ = (list);\
+ for (var = _LIST_ -> Next; var != _LIST_; var = _NEXT_) {\
+ _NEXT_ = var -> Next;\
+ body\
+ }\
+ }
+
+/* ---------------------- */
+
+/*
+ * FT - prototypes.
+ * This is completly wrong place to place this.
+ * But fasttime doesn't have any own prototypes.
+ * (fasttime should be shot anyway)
+ */
+
+int FT_Init(int, int);
+int FT_AGetTimeOfDay(struct timeval *, struct timezone *);
+
diff --git a/usr.sbin/afs/src/rx/LICENSE b/usr.sbin/afs/src/rx/LICENSE
new file mode 100644
index 00000000000..59db278cb0f
--- /dev/null
+++ b/usr.sbin/afs/src/rx/LICENSE
@@ -0,0 +1,27 @@
+This software is provided on a 'no charge' basis.
+
+No limitations or constraints are imposed on the use of the software; No
+'license or use' provisions are applicable. The software is truly 'publicly'
+available.
+
+IBM claims the following copyright:
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
diff --git a/usr.sbin/afs/src/rx/doyle b/usr.sbin/afs/src/rx/doyle
new file mode 100644
index 00000000000..9f0a5589d54
--- /dev/null
+++ b/usr.sbin/afs/src/rx/doyle
@@ -0,0 +1,17 @@
+From: Jim Doyle <jrd@bu.edu>
+To: "Derrick J. Brashear" <shadow@DEMENTIA.ORG>
+Subject: Re: more Krb4 issues
+Date: Tue, 5 Mar 1996 16:47:51 -0500 (EST)
+
+In here are the two TAR files (rxbase.tar.gz, rxkad.tar.gz) that
+Transarc gave me with permission to freely redistribute.. This code
+was given to me by Mike Kazar and it was OK'd for release by Al Spector.
+
+From what I understand, Rx was developed at CMU as part of a DARPA
+funded research project jointly funded by IBM. Rx was picked up by
+the AFS group and then used.. So, by all rights, the Rx stack is in
+the public domain because the DARPA funding requirement placed it
+there... You can read the copyright in the header for the full
+legalese.
+
+[snip]
diff --git a/usr.sbin/afs/src/rx/rx.c b/usr.sbin/afs/src/rx/rx.c
new file mode 100644
index 00000000000..ffc5b62778a
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx.c
@@ -0,0 +1,4067 @@
+/* $OpenBSD: rx.c,v 1.1.1.1 1998/09/14 21:53:14 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* RX: Extended Remote Procedure Call */
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx.c,v 1.5 1998/02/24 01:36:30 art Exp $");
+
+/*
+ * quota system: each attached server process must be able to make
+ * progress to avoid system deadlock, so we ensure that we can always
+ * handle the arrival of the next unacknowledged data packet for an
+ * attached call. rxi_dataQuota gives the max # of packets that must be
+ * reserved for active calls for them to be able to make progress, which is
+ * essentially enough to queue up a window-full of packets (the first packet
+ * may be missing, so these may not get read) + the # of packets the thread
+ * may use before reading all of its input (# free must be one more than send
+ * packet quota). Thus, each thread allocates rx_Window+1 (max queued input
+ * packets) + an extra for sending data. The system also reserves
+ * RX_MAX_QUOTA (must be more than RX_PACKET_QUOTA[i], which is 10), so that
+ * the extra packet can be sent (must be under the system-wide send packet
+ * quota to send any packets)
+ */
+/* # to reserve so that thread with input can still make calls (send packets)
+ without blocking */
+long rx_tq_dropped = 0; /* Solaris only temp variable */
+long rxi_dataQuota = RX_MAX_QUOTA; /* packets to reserve for active
+ * threads */
+
+/*
+ * Variables for handling the minProcs implementation. availProcs gives the
+ * number of threads available in the pool at this moment (not counting dudes
+ * executing right now). totalMin gives the total number of procs required
+ * for handling all minProcs requests. minDeficit is a dynamic variable
+ * tracking the # of procs required to satisfy all of the remaining minProcs
+ * demands.
+ */
+
+long rxi_availProcs = 0; /* number of threads in the pool */
+long rxi_totalMin; /* Sum(minProcs) forall services */
+long rxi_minDeficit = 0; /* number of procs needed to handle
+ * all minProcs */
+long Rx0 = 0, Rx1 = 0;
+
+struct rx_serverQueueEntry *rx_waitForPacket = 0;
+struct rx_packet *rx_allocedP = 0;
+#if 0
+static char rxrcsid[] = "@(#)$KTH: rx.c,v 1.5 1998/02/24 01:36:30 art Exp $";
+#endif
+
+/* ------------Exported Interfaces------------- */
+
+
+/*
+ * This function allows rxkad to set the epoch to a suitably random number
+ * which rx_NewConnection will use in the future. The principle purpose is to
+ * get rxnull connections to use the same epoch as the rxkad connections do, at
+ * least once the first rxkad connection is established. This is important now
+ * that the host/port addresses aren't used in FindConnection: the uniqueness
+ * of epoch/cid matters and the start time won't do.
+ */
+
+void
+rx_SetEpoch(u_long epoch)
+{
+ rx_epoch = epoch;
+}
+
+/*
+ * Initialize rx. A port number may be mentioned, in which case this
+ * becomes the default port number for any service installed later.
+ * If 0 is provided for the port number, a random port will be chosen
+ * by the kernel. Whether this will ever overlap anything in
+ * /etc/services is anybody's guess... Returns 0 on success, -1 on
+ * error.
+ */
+static int rxinit_status = 1;
+
+int
+rx_Init(u_short port)
+{
+ struct timeval tv;
+ char *htable, *ptable;
+
+ SPLVAR;
+
+ if (rxinit_status != 1)
+ return rxinit_status; /* Already done; return previous error
+ * code. */
+
+ /*
+ * Allocate and initialize a socket for client and perhaps server
+ * connections
+ */
+ rx_socket = rxi_GetUDPSocket(port);
+
+ if (rx_socket == OSI_NULLSOCKET) {
+ return RX_ADDRINUSE;
+ }
+#if defined(AFS_GLOBAL_SUNLOCK) && defined(KERNEL)
+ LOCK_INIT(&afs_rxglobal_lock, "afs_rxglobal_lock");
+#endif
+#ifdef RX_ENABLE_LOCKS
+ LOCK_INIT(&rx_freePktQ_lock, "rx_freePktQ_lock");
+ LOCK_INIT(&freeSQEList_lock, "freeSQEList lock");
+ LOCK_INIT(&rx_waitingForPackets_lock, "rx_waitingForPackets lock");
+ LOCK_INIT(&rx_freeCallQueue_lock, "rx_waitingForPackets lock");
+#endif
+
+ rxi_nCalls = 0;
+ rx_connDeadTime = 12;
+ memset((char *) &rx_stats, 0, sizeof(struct rx_stats));
+
+ htable = (char *) osi_Alloc(rx_hashTableSize *
+ sizeof(struct rx_connection *));
+ PIN(htable, rx_hashTableSize *
+ sizeof(struct rx_connection *)); /* XXXXX */
+ memset(htable, 0, rx_hashTableSize *
+ sizeof(struct rx_connection *));
+ ptable = (char *) osi_Alloc(rx_hashTableSize * sizeof(struct rx_peer *));
+ PIN(ptable, rx_hashTableSize * sizeof(struct rx_peer *)); /* XXXXX */
+ memset(ptable, 0, rx_hashTableSize * sizeof(struct rx_peer *));
+ NETPRI;
+
+ osi_GetTime(&tv);
+ /*
+ * *Slightly* random start time for the cid. This is just to help
+ * out with the hashing function at the peer
+ */
+ rx_port = port;
+ rx_stats.minRtt.sec = 9999999;
+ rx_SetEpoch(tv.tv_sec); /*
+ * Start time of this package, rxkad
+ * will provide a randomer value.
+ */
+ rxi_dataQuota += rx_extraQuota; /*
+ * + extra packets caller asked to
+ * reserve
+ */
+ rx_nPackets = rx_extraPackets + RX_MAX_QUOTA + 2; /* fudge */
+ rx_nextCid = ((tv.tv_sec ^ tv.tv_usec) << RX_CIDSHIFT);
+ rx_connHashTable = (struct rx_connection **) htable;
+ rx_peerHashTable = (struct rx_peer **) ptable;
+
+ rx_lastAckDelay.sec = 0;
+ rx_lastAckDelay.usec = 500000;
+
+ clock_Init();
+ rxevent_Init(20, rxi_ReScheduleEvents);
+
+ /* Malloc up a bunch of packet buffers */
+ rx_nFreePackets = 0;
+ queue_Init(&rx_freePacketQueue);
+ rx_nFreeCbufs = 0;
+ rxi_NeedMoreCbufs = FALSE;
+ queue_Init(&rx_freeCbufQueue);
+ USERPRI;
+ rxi_MorePackets(rx_nPackets);
+ rx_CheckCbufs(0);
+ NETPRI;
+
+ /* Initialize various global queues */
+ queue_Init(&rx_idleServerQueue);
+ queue_Init(&rx_incomingCallQueue);
+ queue_Init(&rx_freeCallQueue);
+
+ /*
+ * Start listener process (exact function is dependent on the
+ * implementation environment--kernel or user space)
+ */
+ rxi_StartListener();
+
+ USERPRI;
+ rxinit_status = 0;
+ return rxinit_status;
+}
+
+/*
+ * called with unincremented nRequestsRunning to see if it is OK to start
+ * a new thread in this service. Could be "no" for two reasons: over the
+ * max quota, or would prevent others from reaching their min quota.
+ */
+static int
+QuotaOK(struct rx_service * aservice)
+{
+ /* check if over max quota */
+ if (aservice->nRequestsRunning >= aservice->maxProcs)
+ return 0;
+
+ /* under min quota, we're OK */
+ if (aservice->nRequestsRunning < aservice->minProcs)
+ return 1;
+
+ /*
+ * otherwise, can use only if there are enough to allow everyone to go to
+ * their min quota after this guy starts.
+ */
+ if (rxi_availProcs > rxi_minDeficit)
+ return 1;
+ else
+ return 0;
+}
+
+
+/*
+ * This routine must be called if any services are exported. If the
+ * donateMe flag is set, the calling process is donated to the server
+ * process pool
+ */
+void
+rx_StartServer(int donateMe)
+{
+ struct rx_service *service;
+ int i;
+
+ SPLVAR;
+ clock_NewTime();
+
+ NETPRI;
+ /*
+ * Start server processes, if necessary (exact function is dependent
+ * on the implementation environment--kernel or user space). DonateMe
+ * will be 1 if there is 1 pre-existing proc, i.e. this one. In this
+ * case, one less new proc will be created rx_StartServerProcs.
+ */
+ rxi_StartServerProcs(donateMe);
+
+ /*
+ * count up the # of threads in minProcs, and add set the min deficit to
+ * be that value, too.
+ */
+ for (i = 0; i < RX_MAX_SERVICES; i++) {
+ service = rx_services[i];
+ if (service == (struct rx_service *) 0)
+ break;
+ rxi_totalMin += service->minProcs;
+ /*
+ * below works even if a thread is running, since minDeficit would
+ * still have been decremented and later re-incremented.
+ */
+ rxi_minDeficit += service->minProcs;
+ }
+
+ /* Turn on reaping of idle server connections */
+ rxi_ReapConnections();
+
+ if (donateMe)
+ rx_ServerProc(); /* Never returns */
+ USERPRI;
+ return;
+}
+
+/*
+ * Create a new client connection to the specified service, using the
+ * specified security object to implement the security model for this
+ * connection.
+ */
+struct rx_connection *
+rx_NewConnection(u_long shost, u_short sport, u_short sservice,
+ struct rx_securityClass * securityObject,
+ int serviceSecurityIndex)
+{
+ int hashindex;
+ long cid;
+ struct rx_connection *conn;
+
+ SPLVAR;
+#if defined(AFS_SGIMP_ENV)
+ GLOCKSTATE ms;
+
+#endif
+
+ clock_NewTime();
+ dpf(("rx_NewConnection(host %x, port %u, service %u, "
+ "securityObject %x, serviceSecurityIndex %d)\n",
+ shost, sport, sservice, securityObject, serviceSecurityIndex));
+ GLOBAL_LOCK();
+#if defined(AFS_SGIMP_ENV)
+ AFS_GRELEASE(&ms);
+ /* NETPRI protects Cid and Alloc */
+ NETPRI;
+#endif
+ cid = (rx_nextCid += RX_MAXCALLS);
+ conn = rxi_AllocConnection();
+#if !defined(AFS_SGIMP_ENV)
+ NETPRI;
+#endif
+ conn->type = RX_CLIENT_CONNECTION;
+ conn->cid = cid;
+ conn->epoch = rx_epoch;
+ conn->peer = rxi_FindPeer(shost, sport);
+ conn->serviceId = sservice;
+ conn->securityObject = securityObject;
+ conn->securityData = (void *) 0;
+ conn->securityIndex = serviceSecurityIndex;
+ conn->maxPacketSize = MIN(conn->peer->packetSize, OLD_MAX_PACKET_SIZE);
+ rx_SetConnDeadTime(conn, rx_connDeadTime);
+
+ RXS_NewConnection(securityObject, conn);
+ hashindex = CONN_HASH(shost, sport, conn->cid, conn->epoch,
+ RX_CLIENT_CONNECTION);
+ conn->next = rx_connHashTable[hashindex];
+ rx_connHashTable[hashindex] = conn;
+ rx_stats.nClientConns++;
+
+ conn->refCount++;
+ USERPRI;
+#if defined(AFS_SGIMP_ENV)
+ AFS_GACQUIRE(&ms);
+#endif
+ GLOBAL_UNLOCK();
+ return conn;
+}
+
+void
+rxi_SetConnDeadTime(struct rx_connection * conn, int seconds)
+{
+ /*
+ * This is completely silly; perhaps exponential back off
+ * would be more reasonable? XXXX
+ */
+ conn->secondsUntilDead = seconds;
+ conn->secondsUntilPing = seconds / 6;
+ if (conn->secondsUntilPing == 0)
+ conn->secondsUntilPing = 1; /* XXXX */
+}
+
+/* Destroy the specified connection */
+void
+rx_DestroyConnection(struct rx_connection * conn)
+{
+ struct rx_connection **conn_ptr;
+ int i;
+ int havecalls = 0;
+
+ SPLVAR;
+
+ clock_NewTime();
+
+ NETPRI;
+ if (--conn->refCount > 0) {
+ /* Busy; wait till the last guy before proceeding */
+ USERPRI;
+ return;
+ }
+ /*
+ * If the client previously called rx_NewCall, but it is still
+ * waiting, treat this as a running call, and wait to destroy the
+ * connection later when the call completes.
+ */
+ if ((conn->type == RX_CLIENT_CONNECTION) &&
+ (conn->flags & RX_CONN_MAKECALL_WAITING)) {
+ conn->flags |= RX_CONN_DESTROY_ME;
+ USERPRI;
+ return;
+ }
+ /* Check for extant references to this connection */
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ struct rx_call *call = conn->call[i];
+
+ if (call) {
+ havecalls = 1;
+ if (conn->type == RX_CLIENT_CONNECTION) {
+ if (call->delayedAckEvent) {
+ /*
+ * Push the final acknowledgment out now--there
+ * won't be a subsequent call to acknowledge the
+ * last reply packets
+ */
+ rxevent_Cancel(call->delayedAckEvent);
+ rxi_AckAll((struct rxevent *) 0, call, 0);
+ }
+ }
+ }
+ }
+
+ if (havecalls) {
+ /*
+ * Don't destroy the connection if there are any call
+ * structures still in use
+ */
+ conn->flags |= RX_CONN_DESTROY_ME;
+ USERPRI;
+ return;
+ }
+ /* Remove from connection hash table before proceeding */
+ conn_ptr = &rx_connHashTable[CONN_HASH(peer->host, peer->port, conn->cid,
+ conn->epoch, conn->type)];
+ for (; *conn_ptr; conn_ptr = &(*conn_ptr)->next) {
+ if (*conn_ptr == conn) {
+ *conn_ptr = conn->next;
+ break;
+ }
+ }
+
+ /*
+ * Notify the service exporter, if requested, that this connection
+ * is being destroyed
+ */
+ if (conn->type == RX_SERVER_CONNECTION && conn->service->destroyConnProc)
+ (*conn->service->destroyConnProc) (conn);
+
+ /* Notify the security module that this connection is being destroyed */
+ RXS_DestroyConnection(conn->securityObject, conn);
+
+ /* Make sure that the connection is completely reset before deleting it. */
+ rxi_ResetConnection(conn);
+
+ if (--conn->peer->refCount == 0)
+ conn->peer->idleWhen = clock_Sec();
+
+ if (conn->type == RX_SERVER_CONNECTION)
+ rx_stats.nServerConns--;
+ else
+ rx_stats.nClientConns--;
+
+
+ MUTEX_DESTROY(&conn->lock);
+ rxi_FreeConnection(conn);
+ USERPRI;
+}
+
+/*
+ * Start a new rx remote procedure call, on the specified connection.
+ * If wait is set to 1, wait for a free call channel; otherwise return
+ * 0. Maxtime gives the maximum number of seconds this call may take,
+ * after rx_MakeCall returns. After this time interval, a call to any
+ * of rx_SendData, rx_ReadData, etc. will fail with RX_CALL_TIMEOUT.
+ */
+struct rx_call *
+rx_NewCall(struct rx_connection * conn)
+{
+ int i;
+ struct rx_call *call;
+
+ SPLVAR;
+#if defined(AFS_SGIMP_ENV)
+ GLOCKSTATE ms;
+
+#endif
+ clock_NewTime();
+ dpf(("rx_MakeCall(conn %x)\n", conn));
+
+ GLOBAL_LOCK();
+#if defined(AFS_SGIMP_ENV)
+ AFS_GRELEASE(&ms);
+#endif
+ NETPRI;
+ for (;;) {
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ call = conn->call[i];
+ if (call) {
+ if (call->state == RX_STATE_DALLY) {
+ MUTEX_ENTER(&call->lock);
+ rxi_ResetCall(call);
+ (*call->callNumber)++;
+ break;
+ }
+ } else {
+ call = rxi_NewCall(conn, i);
+ MUTEX_ENTER(&call->lock);
+ break;
+ }
+ }
+ if (i < RX_MAXCALLS) {
+ break;
+ }
+ conn->flags |= RX_CONN_MAKECALL_WAITING;
+#ifdef RX_ENABLE_LOCKS
+ cv_wait(&conn->cv, &conn->lock);
+#else
+ osi_rxSleep(conn);
+#endif
+ }
+
+ /* Client is initially in send mode */
+ call->state = RX_STATE_ACTIVE;
+ call->mode = RX_MODE_SENDING;
+
+ /* remember start time for call in case we have hard dead time limit */
+ call->startTime = clock_Sec();
+
+ /* Turn on busy protocol. */
+ rxi_KeepAliveOn(call);
+
+ MUTEX_EXIT(&call->lock);
+ USERPRI;
+#if defined(AFS_SGIMP_ENV)
+ AFS_GACQUIRE(&ms);
+#endif
+ GLOBAL_UNLOCK();
+ return call;
+}
+
+int
+rxi_HasActiveCalls(struct rx_connection * aconn)
+{
+ int i;
+ struct rx_call *tcall;
+
+ SPLVAR;
+
+ NETPRI;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ if ((tcall = aconn->call[i]) != NULL) {
+ if ((tcall->state == RX_STATE_ACTIVE)
+ || (tcall->state == RX_STATE_PRECALL)) {
+ USERPRI;
+ return 1;
+ }
+ }
+ }
+ USERPRI;
+ return 0;
+}
+
+int
+rxi_GetCallNumberVector(const struct rx_connection * aconn,
+ int32_t *alongs)
+{
+ int i;
+ struct rx_call *tcall;
+
+ SPLVAR;
+
+ NETPRI;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
+ alongs[i] = aconn->callNumber[i] + 1;
+ else
+ alongs[i] = aconn->callNumber[i];
+ }
+ USERPRI;
+ return 0;
+}
+
+int
+rxi_SetCallNumberVector(struct rx_connection * aconn,
+ int32_t *alongs)
+{
+ int i;
+ struct rx_call *tcall;
+
+ SPLVAR;
+
+ NETPRI;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
+ aconn->callNumber[i] = alongs[i] - 1;
+ else
+ aconn->callNumber[i] = alongs[i];
+ }
+ USERPRI;
+ return 0;
+}
+
+/*
+ * Advertise a new service. A service is named locally by a UDP port
+ * number plus a 16-bit service id. Returns (struct rx_service *) 0
+ * on a failure.
+ */
+struct rx_service *
+rx_NewService(u_short port, u_short serviceId, char *serviceName,
+ struct rx_securityClass ** securityObjects,
+ int nSecurityObjects, long (*serviceProc) ())
+{
+ osi_socket socket = OSI_NULLSOCKET;
+ struct rx_service *tservice;
+ int i;
+
+ SPLVAR;
+
+ clock_NewTime();
+
+ if (serviceId == 0) {
+ (osi_Msg "rx_NewService: service id for service %s is not"
+ " non-zero.\n",
+ serviceName);
+ return 0;
+ }
+ if (port == 0) {
+ if (rx_port == 0) {
+ (osi_Msg "rx_NewService: A non-zero port must be specified on "
+ "this call if a non-zero port was not provided at Rx "
+ "initialization (service %s).\n", serviceName);
+ return 0;
+ }
+ port = rx_port;
+ socket = rx_socket;
+ }
+ tservice = rxi_AllocService();
+ NETPRI;
+ for (i = 0; i < RX_MAX_SERVICES; i++) {
+ struct rx_service *service = rx_services[i];
+
+ if (service) {
+ if (port == service->servicePort) {
+ if (service->serviceId == serviceId) {
+ /*
+ * The identical service has already been
+ * installed; if the caller was intending to
+ * change the security classes used by this
+ * service, he/she loses.
+ */
+ (osi_Msg "rx_NewService: tried to install service %s "
+ "with service id %d, which is already in use "
+ "for service %s\n", serviceName, serviceId,
+ service->serviceName);
+ USERPRI;
+ rxi_FreeService(tservice);
+ return service;
+ }
+
+ /*
+ * Different service, same port: re-use the socket which is
+ * bound to the same port
+ */
+ socket = service->socket;
+ }
+ } else {
+ if (socket == OSI_NULLSOCKET) {
+
+ /*
+ * If we don't already have a socket (from another service on
+ * same port) get a new one
+ */
+ socket = rxi_GetUDPSocket(port);
+ if (socket == OSI_NULLSOCKET) {
+ USERPRI;
+ rxi_FreeService(tservice);
+ return 0;
+ }
+ }
+ service = tservice;
+ service->socket = socket;
+ service->servicePort = port;
+ service->serviceId = serviceId;
+ service->serviceName = serviceName;
+ service->nSecurityObjects = nSecurityObjects;
+ service->securityObjects = securityObjects;
+ service->minProcs = 0;
+ service->maxProcs = 1;
+ service->idleDeadTime = 60;
+ service->connDeadTime = rx_connDeadTime;
+ service->executeRequestProc = serviceProc;
+ rx_services[i] = service; /* not visible until now */
+ USERPRI;
+ return service;
+ }
+ }
+ USERPRI;
+ rxi_FreeService(tservice);
+ (osi_Msg "rx_NewService: cannot support > %d services\n", RX_MAX_SERVICES);
+ return 0;
+}
+
+/*
+ * This is the server process's request loop. This routine should
+ * either be each server proc's entry point, or it should be called by
+ * the server process (depending upon the rx implementation
+ * environment).
+ */
+void
+rx_ServerProc(void)
+{
+ struct rx_call *call;
+ long code;
+ struct rx_service *tservice;
+
+#if defined(AFS_SGIMP_ENV)
+ SPLVAR;
+ GLOCKSTATE ms;
+
+ AFS_GRELEASE(&ms);
+ NETPRI;
+#endif
+
+ rxi_dataQuota += rx_Window + 2; /*
+ * reserve a window of packets for
+ * hard times
+ */
+ rxi_MorePackets(rx_Window + 2); /* alloc more packets, too */
+ rxi_availProcs++; /*
+ * one more thread handling incoming
+ * calls
+ */
+#if defined(AFS_SGIMP_ENV)
+ USERPRI;
+#endif
+ for (;;) {
+
+ call = rx_GetCall();
+#ifdef KERNEL
+ if (afs_termState == AFSOP_STOP_RXCALLBACK) {
+ MUTEX_ENTER(&afs_termStateLock);
+ afs_termState = AFSOP_STOP_AFS;
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&afs_termStateCv);
+#else
+ osi_rxWakeup(&afs_termState);
+#endif
+ MUTEX_EXIT(&afs_termStateLock);
+ return;
+ }
+#endif
+ tservice = call->conn->service;
+#if defined(AFS_SGIMP_ENV)
+ AFS_GLOCK();
+#endif
+ if (tservice->beforeProc)
+ (*tservice->beforeProc) (call);
+
+ code = call->conn->service->executeRequestProc(call);
+
+ if (tservice->afterProc)
+ (*tservice->afterProc) (call, code);
+
+ rx_EndCall(call, code);
+ rxi_nCalls++;
+#if defined(AFS_SGIMP_ENV)
+ AFS_GUNLOCK();
+#endif
+ }
+}
+
+
+/*
+ * Sleep until a call arrives. Returns a pointer to the call, ready
+ * for an rx_Read.
+ */
+struct rx_call *
+rx_GetCall(void)
+{
+ struct rx_serverQueueEntry *sq;
+ struct rx_call *call = (struct rx_call *) 0;
+ struct rx_service *service = NULL;
+
+ SPLVAR;
+
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&freeSQEList_lock);
+
+ if ((sq = rx_FreeSQEList) != NULL) {
+ rx_FreeSQEList = *(struct rx_serverQueueEntry **) sq;
+ MUTEX_EXIT(&freeSQEList_lock);
+ } else { /* otherwise allocate a new one and
+ * return that */
+ MUTEX_EXIT(&freeSQEList_lock);
+ sq = (struct rx_serverQueueEntry *) rxi_Alloc(sizeof(struct rx_serverQueueEntry));
+#ifdef RX_ENABLE_LOCKS
+ LOCK_INIT(&sq->lock, "server Queue lock");
+#endif
+ }
+ MUTEX_ENTER(&sq->lock);
+#if defined(AFS_SGIMP_ENV)
+ ASSERT(!isafs_glock());
+#endif
+ NETPRI;
+
+ if (queue_IsNotEmpty(&rx_incomingCallQueue)) {
+ struct rx_call *tcall, *ncall;
+
+ /*
+ * Scan for eligible incoming calls. A call is not eligible
+ * if the maximum number of calls for its service type are
+ * already executing
+ */
+ for (queue_Scan(&rx_incomingCallQueue, tcall, ncall, rx_call)) {
+ service = tcall->conn->service;
+ if (QuotaOK(service)) {
+ call = tcall;
+ break;
+ }
+ }
+ }
+ if (call) {
+ queue_Remove(call);
+ call->flags &= (~RX_CALL_WAIT_PROC);
+ service->nRequestsRunning++;
+ /*
+ * just started call in minProcs pool, need fewer to maintain
+ * guarantee
+ */
+ if (service->nRequestsRunning <= service->minProcs)
+ rxi_minDeficit--;
+ rxi_availProcs--;
+ rx_nWaiting--;
+ } else {
+ /*
+ * If there are no eligible incoming calls, add this process
+ * to the idle server queue, to wait for one
+ */
+ sq->newcall = 0;
+ queue_Append(&rx_idleServerQueue, sq);
+ rx_waitForPacket = sq;
+ do {
+#ifdef RX_ENABLE_LOCKS
+ cv_wait(&sq->cv, &sq->lock);
+#else
+ osi_rxSleep(sq);
+#endif
+#ifdef KERNEL
+ if (afs_termState == AFSOP_STOP_RXCALLBACK) {
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return (struct rx_call *) 0;
+ }
+#endif
+ } while (!(call = sq->newcall));
+ }
+ MUTEX_EXIT(&sq->lock);
+
+ MUTEX_ENTER(&freeSQEList_lock);
+ *(struct rx_serverQueueEntry **) sq = rx_FreeSQEList;
+ rx_FreeSQEList = sq;
+ MUTEX_EXIT(&freeSQEList_lock);
+
+ call->state = RX_STATE_ACTIVE;
+ call->mode = RX_MODE_RECEIVING;
+ if (queue_IsEmpty(&call->rq)) {
+ /* we can't schedule a call if there's no data!!! */
+ rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_DELAY);
+ }
+ rxi_calltrace(RX_CALL_START, call);
+ dpf(("rx_GetCall(port=%d, service=%d) ==> call %x\n",
+ call->conn->service->servicePort,
+ call->conn->service->serviceId, call));
+
+ GLOBAL_UNLOCK();
+ USERPRI;
+
+ return call;
+}
+
+
+
+/*
+ * Establish a procedure to be called when a packet arrives for a
+ * call. This routine will be called at most once after each call,
+ * and will also be called if there is an error condition on the or
+ * the call is complete. Used by multi rx to build a selection
+ * function which determines which of several calls is likely to be a
+ * good one to read from.
+ * NOTE: the way this is currently implemented it is probably only a
+ * good idea to (1) use it immediately after a newcall (clients only)
+ * and (2) only use it once. Other uses currently void your warranty
+ */
+void
+rx_SetArrivalProc(struct rx_call * call, void (*proc) (),
+ void *handle, void *arg)
+{
+ call->arrivalProc = proc;
+ call->arrivalProcHandle = handle;
+ call->arrivalProcArg = arg;
+}
+
+/*
+ * Call is finished (possibly prematurely). Return rc to the peer, if
+ * appropriate, and return the final error code from the conversation
+ * to the caller
+ */
+long
+rx_EndCall(struct rx_call * call, long rc)
+{
+ struct rx_connection *conn = call->conn;
+ struct rx_service *service;
+ long error;
+
+ SPLVAR;
+#if defined(AFS_SGIMP_ENV)
+ GLOCKSTATE ms;
+
+#endif
+
+ dpf(("rx_EndCall(call %x)\n", call));
+
+#if defined(AFS_SGIMP_ENV)
+ AFS_GRELEASE(&ms);
+#endif
+ NETPRI;
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&call->lock);
+
+ call->arrivalProc = (void (*) ()) 0;
+ if (rc && call->error == 0) {
+ rxi_CallError(call, rc);
+ /*
+ * Send an abort message to the peer if this error code has
+ * only just been set. If it was set previously, assume the
+ * peer has already been sent the error code or will request it
+ */
+ rxi_SendCallAbort(call, (struct rx_packet *) 0);
+ }
+ if (conn->type == RX_SERVER_CONNECTION) {
+ /* Make sure reply or at least dummy reply is sent */
+ if (call->mode == RX_MODE_RECEIVING) {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+
+ rx_WriteProc(call, 0, 0);
+
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&call->lock);
+ }
+ if (call->mode == RX_MODE_SENDING) {
+ rx_FlushWrite(call);
+ }
+ service = conn->service;
+ service->nRequestsRunning--;
+ if (service->nRequestsRunning < service->minProcs)
+ rxi_minDeficit++;
+ rxi_availProcs++;
+ rxi_calltrace(RX_CALL_END, call);
+ } else { /* Client connection */
+ char dummy;
+
+ /*
+ * Make sure server receives input packets, in the case where
+ * no reply arguments are expected
+ */
+ if (call->mode == RX_MODE_SENDING) {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+
+ (void) rx_ReadProc(call, &dummy, 1);
+
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&call->lock);
+ }
+ if (conn->flags & RX_CONN_MAKECALL_WAITING) {
+ conn->flags &= (~RX_CONN_MAKECALL_WAITING);
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&conn->cv);
+#else
+ osi_rxWakeup(conn);
+#endif
+ }
+ }
+ call->state = RX_STATE_DALLY;
+ error = call->error;
+
+ /*
+ * currentPacket, nLeft, and NFree must be zeroed here, because
+ * ResetCall cannot: ResetCall may be called at splnet(), in the
+ * kernel version, and may interrupt the macros rx_Read or
+ * rx_Write, which run at normal priority for efficiency.
+ */
+ if (call->currentPacket) {
+ rxi_FreePacket(call->currentPacket);
+ call->currentPacket = (struct rx_packet *) 0;
+ call->nLeft = call->nFree = 0;
+ } else
+ call->nLeft = call->nFree = 0;
+
+
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+#if defined(AFS_SGIMP_ENV)
+ AFS_GACQUIRE(&ms);
+#endif
+ /*
+ * Map errors to the local host's errno.h format.
+ */
+ error = ntoh_syserr_conv(error);
+ return error;
+}
+
+/*
+ * Call this routine when shutting down a server or client (especially
+ * clients). This will allow Rx to gracefully garbage collect server
+ * connections, and reduce the number of retries that a server might
+ * make to a dead client
+ */
+void
+rx_Finalize(void)
+{
+ struct rx_connection **conn_ptr, **conn_end;
+
+ SPLVAR;
+ NETPRI;
+ if (rx_connHashTable)
+ for (conn_ptr = &rx_connHashTable[0],
+ conn_end = &rx_connHashTable[rx_hashTableSize];
+ conn_ptr < conn_end; conn_ptr++) {
+ struct rx_connection *conn, *next;
+
+ for (conn = *conn_ptr; conn; conn = next) {
+ next = conn->next;
+ if (conn->type == RX_CLIENT_CONNECTION)
+ rx_DestroyConnection(conn);
+ }
+ }
+
+ rxi_flushtrace();
+ USERPRI;
+}
+
+/*
+ * if we wakeup packet waiter too often, can get in loop with two
+ * AllocSendPackets each waking each other up (from ReclaimPacket calls)
+ */
+void
+rxi_PacketsUnWait(void)
+{
+
+ MUTEX_ENTER(&rx_waitingForPackets_lock);
+ if (!rx_waitingForPackets) {
+ MUTEX_EXIT(&rx_waitingForPackets_lock);
+ return;
+ }
+ if (rxi_OverQuota(RX_PACKET_CLASS_SEND)) {
+ MUTEX_EXIT(&rx_waitingForPackets_lock);
+ return; /* still over quota */
+ }
+ rx_waitingForPackets = 0;
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&rx_waitingForPackets_cv);
+#else
+ osi_rxWakeup(&rx_waitingForPackets);
+#endif
+ MUTEX_EXIT(&rx_waitingForPackets_lock);
+ return;
+}
+
+
+/* ------------------Internal interfaces------------------------- */
+
+/*
+ * Return this process's service structure for the
+ * specified socket and service
+ */
+struct rx_service *
+rxi_FindService(osi_socket socket, u_short serviceId)
+{
+ struct rx_service **sp;
+
+ for (sp = &rx_services[0]; *sp; sp++) {
+ if ((*sp)->serviceId == serviceId && (*sp)->socket == socket)
+ return *sp;
+ }
+ return 0;
+}
+
+/*
+ * Allocate a call structure, for the indicated channel of the
+ * supplied connection. The mode and state of the call must be set by
+ * the caller.
+ */
+struct rx_call *
+rxi_NewCall(struct rx_connection * conn, int channel)
+{
+ struct rx_call *call;
+
+ /*
+ * Grab an existing call structure, or allocate a new one.
+ * Existing call structures are assumed to have been left reset by
+ * rxi_FreeCall
+ */
+ MUTEX_ENTER(&rx_freeCallQueue_lock);
+
+ if (queue_IsNotEmpty(&rx_freeCallQueue)) {
+ call = queue_First(&rx_freeCallQueue, rx_call);
+ queue_Remove(call);
+ rx_stats.nFreeCallStructs--;
+ MUTEX_EXIT(&rx_freeCallQueue_lock);
+ MUTEX_ENTER(&call->lock);
+
+#ifdef ADAPT_PERF
+ /* Bind the call to its connection structure */
+ call->conn = conn;
+#endif
+ } else {
+ call = (struct rx_call *) rxi_Alloc(sizeof(struct rx_call));
+
+ MUTEX_EXIT(&rx_freeCallQueue_lock);
+ MUTEX_INIT(&call->lock, "call lock", MUTEX_DEFAULT, NULL);
+ MUTEX_INIT(&call->lockw, "call wlock", MUTEX_DEFAULT, NULL);
+ MUTEX_ENTER(&call->lock);
+
+ rx_stats.nCallStructs++;
+ /* Initialize once-only items */
+ queue_Init(&call->tq);
+ queue_Init(&call->rq);
+#ifdef ADAPT_PERF
+ /* Bind the call to its connection structure (prereq for reset) */
+ call->conn = conn;
+#endif
+ rxi_ResetCall(call);
+ }
+#ifndef ADAPT_PERF
+ /* Bind the call to its connection structure (prereq for reset) */
+ call->conn = conn;
+#endif
+ call->channel = channel;
+ call->callNumber = &conn->callNumber[channel];
+ /*
+ * Note that the next expected call number is retained (in
+ * conn->callNumber[i]), even if we reallocate the call structure
+ */
+ conn->call[channel] = call;
+ /*
+ * if the channel's never been used (== 0), we should start at 1, otherwise
+ * the call number is valid from the last time this channel was used
+ */
+ if (*call->callNumber == 0)
+ *call->callNumber = 1;
+
+ MUTEX_EXIT(&call->lock);
+ return call;
+}
+
+/*
+ * A call has been inactive long enough that so we can throw away
+ * state, including the call structure, which is placed on the call
+ * free list.
+ */
+void
+rxi_FreeCall(struct rx_call * call)
+{
+ int channel = call->channel;
+ struct rx_connection *conn = call->conn;
+
+
+ MUTEX_ENTER(&call->lock);
+
+ if (call->state == RX_STATE_DALLY)
+ (*call->callNumber)++;
+ rxi_ResetCall(call);
+ call->conn->call[channel] = (struct rx_call *) 0;
+
+ MUTEX_ENTER(&rx_freeCallQueue_lock);
+
+ queue_Append(&rx_freeCallQueue, call);
+ rx_stats.nFreeCallStructs++;
+
+ MUTEX_EXIT(&rx_freeCallQueue_lock);
+ MUTEX_EXIT(&call->lock);
+
+ /*
+ * Destroy the connection if it was previously slated for
+ * destruction, i.e. the Rx client code previously called
+ * rx_DestroyConnection (client connections), or
+ * rxi_ReapConnections called the same routine (server
+ * connections). Only do this, however, if there are no
+ * outstanding calls
+ */
+ if (conn->flags & RX_CONN_DESTROY_ME)
+ rx_DestroyConnection(conn);
+}
+
+
+long rxi_Alloccnt = 0, rxi_Allocsize = 0;
+char *
+rxi_Alloc(int size)
+{
+ char *p;
+
+ rxi_Alloccnt++;
+ rxi_Allocsize += size;
+#if (defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)) && defined(KERNEL)
+ p = (char *) osi_AllocSmall(size, 1);
+#else
+ p = (char *) osi_Alloc(size);
+#endif
+ if (!p)
+ osi_Panic("rxi_Alloc error");
+ memset(p, 0, size);
+ return p;
+}
+
+void
+rxi_Free(void *addr, int size)
+{
+ rxi_Alloccnt--;
+ rxi_Allocsize -= size;
+#if (defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)) && defined(KERNEL)
+ osi_FreeSmall(addr);
+#else
+ osi_Free(addr, size);
+#endif
+}
+
+/*
+ * Find the peer process represented by the supplied (host,port)
+ * combination. If there is no appropriate active peer structure, a
+ * new one will be allocated and initialized
+ */
+struct rx_peer *
+rxi_FindPeer(u_long host, u_short port)
+{
+ struct rx_peer *pp;
+ int hashIndex;
+
+ hashIndex = PEER_HASH(host, port);
+ for (pp = rx_peerHashTable[hashIndex]; pp; pp = pp->next) {
+ if ((pp->host == host) && (pp->port == port))
+ break;
+ }
+ if (!pp) {
+ pp = rxi_AllocPeer(); /*
+ * This bzero's *pp: anything not
+ * explicitly
+ */
+ pp->host = host; /*
+ * set here or in InitPeerParams is
+ * zero
+ */
+ pp->port = port;
+ queue_Init(&pp->congestionQueue);
+ pp->next = rx_peerHashTable[hashIndex];
+ rx_peerHashTable[hashIndex] = pp;
+ rxi_InitPeerParams(pp);
+ rx_stats.nPeerStructs++;
+ }
+ pp->refCount++;
+ return pp;
+}
+
+/*
+ * Destroy the specified peer structure, removing it from the peer hash
+ * table
+ */
+void
+rxi_DestroyPeer(struct rx_peer * peer)
+{
+ struct rx_peer **peer_ptr;
+
+ for (peer_ptr = &rx_peerHashTable[PEER_HASH(peer->host, peer->port)];
+ *peer_ptr; peer_ptr = &(*peer_ptr)->next) {
+ if (*peer_ptr == peer) {
+ *peer_ptr = peer->next;
+ rxi_FreePeer(peer);
+ rx_stats.nPeerStructs--;
+ return;
+ }
+ }
+}
+
+/*
+ * Find the connection at (host, port) started at epoch, and with the
+ * given connection id. Creates the server connection if necessary.
+ * The type specifies whether a client connection or a server
+ * connection is desired. In both cases, (host, port) specify the
+ * peer's (host, pair) pair. Client connections are not made
+ * automatically by this routine. The parameter socket gives the
+ * socket descriptor on which the packet was received. This is used,
+ * in the case of server connections, to check that *new* connections
+ * come via a valid (port, serviceId). Finally, the securityIndex
+ * parameter must match the existing index for the connection. If a
+ * server connection is created, it will be created using the supplied
+ * index, if the index is valid for this service
+ */
+struct rx_connection *
+rxi_FindConnection(osi_socket socket, long host,
+ u_short port, u_short serviceId, u_long cid,
+ u_long epoch, int type, u_int securityIndex)
+{
+ int hashindex;
+ struct rx_connection *conn;
+
+ hashindex = CONN_HASH(host, port, cid, epoch, type);
+ for (conn = rx_connHashTable[hashindex]; conn; conn = conn->next) {
+ if ((conn->type == type) && ((cid & RX_CIDMASK) == conn->cid) &&
+ (epoch == conn->epoch) &&
+ (securityIndex == conn->securityIndex)) {
+ struct rx_peer *pp = conn->peer;
+
+ /*
+ * epoch's high order bits mean route for security reasons only on
+ * the cid, not the host and port fields.
+ */
+ if (conn->epoch & 0x80000000)
+ break;
+ if (((type == RX_CLIENT_CONNECTION)
+ || (pp->host == host)) && (pp->port == port))
+ break;
+ }
+ }
+ if (!conn) {
+ struct rx_service *service;
+
+ if (type == RX_CLIENT_CONNECTION)
+ return (struct rx_connection *) 0;
+ service = rxi_FindService(socket, serviceId);
+ if (!service || (securityIndex >= service->nSecurityObjects)
+ || (service->securityObjects[securityIndex] == 0))
+ return (struct rx_connection *) 0;
+ conn = rxi_AllocConnection(); /* This bzero's the connection */
+#ifdef RX_ENABLE_LOCKS
+ LOCK_INIT(&conn->lock, "conn lock");
+#endif
+ conn->next = rx_connHashTable[hashindex];
+ rx_connHashTable[hashindex] = conn;
+ conn->peer = rxi_FindPeer(host, port);
+ conn->maxPacketSize = MIN(conn->peer->packetSize, OLD_MAX_PACKET_SIZE);
+ conn->type = RX_SERVER_CONNECTION;
+ conn->lastSendTime = clock_Sec(); /* don't GC immediately */
+ conn->epoch = epoch;
+ conn->cid = cid & RX_CIDMASK;
+ /* conn->serial = conn->lastSerial = 0; */
+ /* conn->rock = 0; */
+ /* conn->timeout = 0; */
+ conn->service = service;
+ conn->serviceId = serviceId;
+ conn->securityIndex = securityIndex;
+ conn->securityObject = service->securityObjects[securityIndex];
+ rx_SetConnDeadTime(conn, service->connDeadTime);
+ /* Notify security object of the new connection */
+ RXS_NewConnection(conn->securityObject, conn);
+ /* XXXX Connection timeout? */
+ if (service->newConnProc)
+ (*service->newConnProc) (conn);
+ rx_stats.nServerConns++;
+ }
+ conn->refCount++;
+ return conn;
+}
+
+/*
+ * There are two packet tracing routines available for testing and monitoring
+ * Rx. One is called just after every packet is received and the other is
+ * called just before every packet is sent. Received packets, have had their
+ * headers decoded, and packets to be sent have not yet had their headers
+ * encoded. Both take two parameters: a pointer to the packet and a sockaddr
+ * containing the network address. Both can be modified. The return value, if
+ * non-zero, indicates that the packet should be dropped.
+ */
+
+int (*rx_justReceived)() = NULL;
+int (*rx_almostSent)() = NULL;
+
+/*
+ * A packet has been received off the interface. Np is the packet, socket is
+ * the socket number it was received from (useful in determining which service
+ * this packet corresponds to), and (host, port) reflect the host,port of the
+ * sender. This call returns the packet to the caller if it is finished with
+ * it, rather than de-allocating it, just as a small performance hack
+ */
+
+struct rx_packet *
+rxi_ReceivePacket(struct rx_packet * np, osi_socket socket,
+ u_long host, u_short port)
+{
+ struct rx_call *call;
+ struct rx_connection *conn;
+ int channel;
+ unsigned long currentCallNumber;
+ int type;
+ int skew;
+
+#ifdef RXDEBUG
+ char *packetType;
+
+#endif
+ struct rx_packet *tnp;
+
+#ifdef RXDEBUG
+/*
+ * We don't print out the packet until now because (1) the time may not be
+ * accurate enough until now in the lwp implementation (rx_Listener only gets
+ * the time after the packet is read) and (2) from a protocol point of view,
+ * this is the first time the packet has been seen
+ */
+ packetType = (np->header.type > 0 && np->header.type < RX_N_PACKET_TYPES)
+ ? rx_packetTypes[np->header.type - 1] : "*UNKNOWN*";
+ dpf(("R %d %s: %x.%d.%d.%d.%d.%d.%d flags %d, packet %x",
+ np->header.serial, packetType, host, port, np->header.serviceId,
+ np->header.epoch, np->header.cid, np->header.callNumber,
+ np->header.seq, np->header.flags, np));
+#endif
+
+ if (np->header.type == RX_PACKET_TYPE_VERSION)
+ return rxi_ReceiveVersionPacket(np, socket, host, port);
+
+ if (np->header.type == RX_PACKET_TYPE_DEBUG)
+ return rxi_ReceiveDebugPacket(np, socket, host, port);
+
+#ifdef RXDEBUG
+
+ /*
+ * If an input tracer function is defined, call it with the packet and
+ * network address. Note this function may modify its arguments.
+ */
+ if (rx_justReceived) {
+ struct sockaddr_in addr;
+ int drop;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = port;
+ addr.sin_addr.s_addr = host;
+ drop = (*rx_justReceived) (np, &addr);
+ /* drop packet if return value is non-zero */
+ if (drop)
+ return np;
+ port = addr.sin_port; /* in case fcn changed addr */
+ host = addr.sin_addr.s_addr;
+ }
+#endif
+
+ /* If packet was not sent by the client, then *we* must be the client */
+ type = ((np->header.flags & RX_CLIENT_INITIATED) != RX_CLIENT_INITIATED)
+ ? RX_CLIENT_CONNECTION : RX_SERVER_CONNECTION;
+
+ /*
+ * Find the connection (or fabricate one, if we're the server & if
+ * necessary) associated with this packet
+ */
+ conn = rxi_FindConnection(socket, host, port, np->header.serviceId,
+ np->header.cid, np->header.epoch, type,
+ np->header.securityIndex);
+
+ if (!conn) {
+ /*
+ * If no connection found or fabricated, just ignore the packet.
+ * (An argument could be made for sending an abort packet for
+ * the conn)
+ */
+ return np;
+ }
+ /* compute the max serial number seen on this connection */
+ if (conn->maxSerial < np->header.serial)
+ conn->maxSerial = np->header.serial;
+
+ /*
+ * If the connection is in an error state, send an abort packet and
+ * ignore the incoming packet
+ */
+ if (conn->error) {
+ /* Don't respond to an abort packet--we don't want loops! */
+ if (np->header.type != RX_PACKET_TYPE_ABORT)
+ np = rxi_SendConnectionAbort(conn, np);
+ conn->refCount--;
+ return np;
+ }
+ /* Check for connection-only requests (i.e. not call specific). */
+ if (np->header.callNumber == 0) {
+ switch (np->header.type) {
+ case RX_PACKET_TYPE_ABORT:
+ /* What if the supplied error is zero? */
+ rxi_ConnectionError(conn, ntohl(rx_GetLong(np, 0)));
+ conn->refCount--;
+ return np;
+ case RX_PACKET_TYPE_CHALLENGE:
+ tnp = rxi_ReceiveChallengePacket(conn, np);
+ conn->refCount--;
+ return tnp;
+ case RX_PACKET_TYPE_RESPONSE:
+ tnp = rxi_ReceiveResponsePacket(conn, np);
+ conn->refCount--;
+ return tnp;
+ case RX_PACKET_TYPE_PARAMS:
+ case RX_PACKET_TYPE_PARAMS + 1:
+ case RX_PACKET_TYPE_PARAMS + 2:
+ /* ignore these packet types for now */
+ conn->refCount--;
+ return np;
+
+
+ default:
+ /*
+ * Should not reach here, unless the peer is broken: send an
+ * abort packet
+ */
+ rxi_ConnectionError(conn, RX_PROTOCOL_ERROR);
+ tnp = rxi_SendConnectionAbort(conn, np);
+ conn->refCount--;
+ return tnp;
+ }
+ }
+ channel = np->header.cid & RX_CHANNELMASK;
+ call = conn->call[channel];
+#ifdef RX_ENABLE_LOCKSX
+ if (call)
+ mutex_enter(&call->lock);
+#endif
+ currentCallNumber = conn->callNumber[channel];
+
+ if (type == RX_SERVER_CONNECTION) {/* We're the server */
+ if (np->header.callNumber < currentCallNumber) {
+ rx_stats.spuriousPacketsRead++;
+#ifdef RX_ENABLE_LOCKSX
+ if (call)
+ mutex_exit(&call->lock);
+#endif
+ conn->refCount--;
+ return np;
+ }
+ if (!call) {
+ call = rxi_NewCall(conn, channel);
+#ifdef RX_ENABLE_LOCKSX
+ mutex_enter(&call->lock);
+#endif
+ *call->callNumber = np->header.callNumber;
+ call->state = RX_STATE_PRECALL;
+ rxi_KeepAliveOn(call);
+ } else if (np->header.callNumber != currentCallNumber) {
+ /*
+ * If the new call cannot be taken right now send a busy and set
+ * the error condition in this call, so that it terminates as
+ * quickly as possible
+ */
+ if (call->state == RX_STATE_ACTIVE) {
+ struct rx_packet *tp;
+
+ rxi_CallError(call, RX_CALL_DEAD);
+ tp = rxi_SendSpecial(call, conn, np, RX_PACKET_TYPE_BUSY, (char *) 0, 0);
+#ifdef RX_ENABLE_LOCKSX
+ mutex_exit(&call->lock);
+#endif
+ conn->refCount--;
+ return tp;
+ }
+ /*
+ * If the new call can be taken right now (it's not busy) then
+ * accept it.
+ */
+ rxi_ResetCall(call);
+ *call->callNumber = np->header.callNumber;
+ call->state = RX_STATE_PRECALL;
+ rxi_KeepAliveOn(call);
+ } else {
+ /* Continuing call; do nothing here. */
+ }
+ } else { /* we're the client */
+
+ /*
+ * Ignore anything that's not relevant to the current call. If there
+ * isn't a current call, then no packet is relevant.
+ */
+ if (!call || (np->header.callNumber != currentCallNumber)) {
+ rx_stats.spuriousPacketsRead++;
+#ifdef RX_ENABLE_LOCKSX
+ if (call)
+ mutex_exit(&call->lock);
+#endif
+ conn->refCount--;
+ return np;
+ }
+ /*
+ * If the service security object index stamped in the packet does not
+ * match the connection's security index, ignore the packet
+ */
+ if (np->header.securityIndex != conn->securityIndex) {
+ conn->refCount--;
+#ifdef RX_ENABLE_LOCKSX
+ mutex_exit(&call->lock);
+#endif
+ return np;
+ }
+ /*
+ * If we're receiving the response, then all transmit packets are
+ * implicitly acknowledged. Get rid of them.
+ */
+ if (np->header.type == RX_PACKET_TYPE_DATA) {
+#ifdef AFS_SUN5_ENV
+ /*
+ * XXX Hack. Because we can't release the global rx lock when
+ * sending packets (osi_NetSend) we drop all acks while we're
+ * traversing the tq in rxi_Start sending packets out because
+ * packets may move to the freePacketQueue as result of being
+ * here! So we drop these packets until we're safely out of the
+ * traversing. Really ugly!
+ */
+ if (call->flags & RX_CALL_TQ_BUSY) {
+ rx_tq_dropped++;
+ return np; /* xmitting; drop packet */
+ }
+#endif
+ rxi_ClearTransmitQueue(call);
+ } else {
+ if (np->header.type == RX_PACKET_TYPE_ACK) {
+ /*
+ * now check to see if this is an ack packet acknowledging
+ * that the server actually *lost* some hard-acked data. If
+ * this happens we ignore this packet, as it may indicate that
+ * the server restarted in the middle of a call. It is also
+ * possible that this is an old ack packet. We don't abort
+ * the connection in this case, because this *might* just be
+ * an old ack packet. The right way to detect a server restart
+ * in the midst of a call is to notice that the server epoch
+ * changed, btw.
+ */
+ /*
+ * LWSXXX I'm not sure this is exactly right, since tfirst
+ * LWSXXX **IS** unacknowledged. I think that this is
+ * LWSXXX off-by-one, but I don't dare change it just yet,
+ * LWSXXX since it will interact badly with the
+ * LWSXXX server-restart detection code in receiveackpacket.
+ */
+ if (ntohl(rx_GetLong(np, FIRSTACKOFFSET)) < call->tfirst) {
+ rx_stats.spuriousPacketsRead++;
+#ifdef RX_ENABLE_LOCKSX
+ mutex_exit(&call->lock);
+#endif
+ conn->refCount--;
+ return np;
+ }
+ }
+ } /* else not a data packet */
+ }
+
+ /* Set remote user defined status from packet */
+ call->remoteStatus = np->header.userStatus;
+
+ /*
+ * Note the gap between the expected next packet and the actual packet
+ * that arrived, when the new packet has a smaller serial number than
+ * expected. Rioses frequently reorder packets all by themselves, so
+ * this will be quite important with very large window sizes. Skew is
+ * checked against 0 here to avoid any dependence on the type of
+ * inPacketSkew (which may be unsigned). In C, -1 > (unsigned) 0 is
+ * always true! The inPacketSkew should be a smoothed running value, not
+ * just a maximum. MTUXXX see CalculateRoundTripTime for an example of
+ * how to keep smoothed values. I think using a beta of 1/8 is probably
+ * appropriate. lws 93.04.21
+ */
+ skew = conn->lastSerial - np->header.serial;
+ conn->lastSerial = np->header.serial;
+ if (skew > 0) {
+ struct rx_peer *peer;
+
+ peer = conn->peer;
+ if (skew > peer->inPacketSkew) {
+ dpf(("*** In skew changed from %d to %d\n",
+ peer->inPacketSkew, skew));
+ peer->inPacketSkew = skew;
+ }
+ }
+ /* Now do packet type-specific processing */
+ switch (np->header.type) {
+ case RX_PACKET_TYPE_DATA:
+ np = rxi_ReceiveDataPacket(call, np);
+ break;
+ case RX_PACKET_TYPE_ACK:
+ /*
+ * Respond immediately to ack packets requesting acknowledgement
+ * (ping packets)
+ */
+ if (np->header.flags & RX_REQUEST_ACK) {
+ if (call->error)
+ (void) rxi_SendCallAbort(call, 0);
+ else
+ (void) rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_PING_RESPONSE);
+ }
+ np = rxi_ReceiveAckPacket(call, np);
+ break;
+ case RX_PACKET_TYPE_ABORT:
+ /*
+ * An abort packet: reset the connection, passing the error up to
+ * the user
+ */
+ /* What if error is zero? */
+ rxi_CallError(call, ntohl(*(long *) rx_DataOf(np)));
+ break;
+ case RX_PACKET_TYPE_BUSY:
+ /* XXXX */
+ break;
+ case RX_PACKET_TYPE_ACKALL:
+ /*
+ * All packets acknowledged, so we can drop all packets previously
+ * readied for sending
+ */
+#ifdef AFS_SUN5_ENV
+ /*
+ * XXX Hack. We because we can't release the global rx lock
+ * when sending packets (osi_NetSend) we drop all ack pkts while
+ * we're traversing the tq in rxi_Start sending packets out
+ * because packets may move to the freePacketQueue as result of
+ * being here! So we drop these packets until we're
+ * safely out of the traversing. Really ugly!
+ */
+ if (call->flags & RX_CALL_TQ_BUSY) {
+ rx_tq_dropped++;
+ return np; /* xmitting; drop packet */
+ }
+#endif
+ rxi_ClearTransmitQueue(call);
+ break;
+ default:
+ /*
+ * Should not reach here, unless the peer is broken: send an abort
+ * packet
+ */
+ rxi_CallError(call, RX_PROTOCOL_ERROR);
+ np = rxi_SendCallAbort(call, np);
+ break;
+ };
+ /*
+ * Note when this last legitimate packet was received, for keep-alive
+ * processing. Note, we delay getting the time until now in the hope that
+ * the packet will be delivered to the user before any get time is required
+ * (if not, then the time won't actually be re-evaluated here).
+ */
+ call->lastReceiveTime = clock_Sec();
+#ifdef RX_ENABLE_LOCKSX
+ mutex_exit(&call->lock);
+#endif
+ conn->refCount--;
+ return np;
+}
+
+/*
+ * return true if this is an "interesting" connection from the point of view
+ * of someone trying to debug the system
+ */
+int
+rxi_IsConnInteresting(struct rx_connection * aconn)
+{
+ int i;
+ struct rx_call *tcall;
+
+ if (aconn->flags & (RX_CONN_MAKECALL_WAITING | RX_CONN_DESTROY_ME))
+ return 1;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ tcall = aconn->call[i];
+ if (tcall) {
+ if ((tcall->state == RX_STATE_PRECALL) ||
+ (tcall->state == RX_STATE_ACTIVE))
+ return 1;
+ if ((tcall->mode == RX_MODE_SENDING) ||
+ (tcall->mode == RX_MODE_RECEIVING))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * if this is one of the last few packets AND it wouldn't be used by the
+ * receiving call to immediately satisfy a read request, then drop it on
+ * the floor, since accepting it might prevent a lock-holding thread from
+ * making progress in its reading
+ */
+
+static int
+TooLow(struct rx_packet * ap, struct rx_call * acall)
+{
+ if ((rx_nFreePackets < rxi_dataQuota + 2) &&
+ !((ap->header.seq == acall->rnext) &&
+ (acall->flags & RX_CALL_READER_WAIT))) {
+ return 1;
+ } else
+ return 0;
+}
+
+/* try to attach call, if authentication is complete */
+static void
+TryAttach(struct rx_call * acall)
+{
+ struct rx_connection *conn;
+
+ conn = acall->conn;
+ if ((conn->type == RX_SERVER_CONNECTION) &&
+ (acall->state == RX_STATE_PRECALL)) {
+ /* Don't attach until we have any req'd. authentication. */
+ if (RXS_CheckAuthentication(conn->securityObject, conn) == 0) {
+ rxi_AttachServerProc(acall);
+ /*
+ * Note: this does not necessarily succeed; there
+ * may not any proc available
+ */
+ } else {
+ rxi_ChallengeOn(acall->conn);
+ }
+ }
+}
+
+/*
+ * A data packet has been received off the interface. This packet is
+ * appropriate to the call (the call is in the right state, etc.). This
+ * routine can return a packet to the caller, for re-use
+ */
+struct rx_packet *
+rxi_ReceiveDataPacket(struct rx_call * call,
+ struct rx_packet * np)
+{
+ u_long seq, serial, flags;
+
+ seq = np->header.seq;
+ rx_stats.dataPacketsRead++;
+
+ /* If the call is in an error state, send an abort message */
+ /* XXXX this will send too many aborts for multi-packet calls */
+ if (call->error)
+ return rxi_SendCallAbort(call, np);
+
+ if (np->header.spare != 0)
+ call->conn->flags |= RX_CONN_USING_PACKET_CKSUM;
+
+ /*
+ * If there are no packet buffers, drop this new packet, unless we can find
+ * packet buffers from inactive calls
+ */
+ if (rxi_OverQuota(RX_PACKET_CLASS_RECEIVE) || TooLow(np, call)) {
+ rx_stats.noPacketBuffersOnRead++;
+ call->rprev = seq;
+ TryAttach(call);
+ rxi_calltrace(RX_TRACE_DROP, call);
+ return np;
+ }
+ /* The usual case is that this is the expected next packet */
+ if (np->header.seq == call->rnext) {
+
+ /* Check to make sure it is not a duplicate of one already queued */
+ if (queue_IsNotEmpty(&call->rq)
+ && queue_First(&call->rq, rx_packet)->header.seq == seq) {
+ rx_stats.dupPacketsRead++;
+ np = rxi_SendAck(call, np, seq, np->header.serial,
+ np->header.flags, RX_ACK_DUPLICATE);
+ call->rprev = seq;
+ return np;
+ }
+ /*
+ * It's the next packet. Stick it on the receive queue for this call
+ */
+ queue_Prepend(&call->rq, np);
+
+ /* I don't think these two variables are needed (lws) */
+ serial = np->header.serial;
+ flags = np->header.flags;
+#ifndef ADAPT_PERF
+ np = 0; /* We can't use this any more */
+
+ /*
+ * Provide asynchronous notification for those who want it
+ * (e.g. multi rx)
+ */
+ if (call->arrivalProc) {
+ (*call->arrivalProc) (call, call->arrivalProcHandle,
+ call->arrivalProcArg);
+ call->arrivalProc = (void (*) ()) 0;
+ }
+ /* Wakeup the reader, if any */
+ if (call->flags & RX_CALL_READER_WAIT) {
+ call->flags &= ~RX_CALL_READER_WAIT;
+ MUTEX_ENTER(&call->lockq);
+
+#ifdef RX_ENABLE_LOCKS
+ cv_broadcast(&call->cv_rq);
+#else
+ osi_rxWakeup(&call->rq);
+#endif
+ MUTEX_EXIT(&call->lockq);
+ }
+#endif
+
+ /*
+ * ACK packet right away, in order to keep the window going, and to
+ * reduce variability in round-trip-time estimates.
+ */
+
+ if (flags & RX_REQUEST_ACK) {
+
+ /*
+ * Acknowledge, if requested. Also take this opportunity to
+ * revise MTU estimate.
+ */
+#ifdef MISCMTU
+ /* Copy a lower estimate of the MTU from the other end. (cfe) */
+ /*
+ * We can figure out what the other end is using by checking out
+ * the size of its packets, and then adding back the header size.
+ * We don't count the last packet, since it might be partly empty.
+ * We shouldn't do this check on every packet, it's overkill.
+ * Perhaps it would be better done in
+ * ComputeRate if I decide it's ever worth doing. (lws)
+ */
+ if (!(np->header.flags & RX_LAST_PACKET) &&
+ call->conn && call->conn->peer) {
+ u_long length;
+ struct rx_peer *peer = call->conn->peer;
+
+ length = np->length + RX_HEADER_SIZE;
+ if (length < peer->packetSize) {
+ dpf(("CONG peer %lx/%u: packetsize %lu=>%lu (rtt %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->packetSize,
+ length, peer->rtt));
+ peer->packetSize = length;
+ }
+ }
+#endif /* MISCMTU */
+ np = rxi_SendAck(call, 0, seq, serial, flags, RX_ACK_REQUESTED);
+ } else if (flags & RX_LAST_PACKET) {
+ struct clock when;
+
+ /* Or schedule an acknowledgement later on. */
+ rxevent_Cancel(call->delayedAckEvent);
+ clock_GetTime(&when);
+ clock_Add(&when, &rx_lastAckDelay);
+ call->delayedAckEvent = rxevent_Post(&when, rxi_SendDelayedAck,
+ call, 0);
+ }
+#ifdef ADAPT_PERF
+ /*
+ * Provide asynchronous notification for those who want it
+ * (e.g. multi rx)
+ */
+ if (call->arrivalProc) {
+ (*call->arrivalProc) (call, call->arrivalProcHandle,
+ call->arrivalProcArg);
+ call->arrivalProc = (void (*) ()) 0;
+ }
+ /* Wakeup the reader, if any */
+ MUTEX_ENTER(&call->lockq);
+ if (call->flags & RX_CALL_READER_WAIT) {
+ call->flags &= ~RX_CALL_READER_WAIT;
+#ifdef RX_ENABLE_LOCKS
+/* cv_signal(&call->cv_rq);*/
+ cv_broadcast(&call->cv_rq);
+#else
+ osi_rxWakeup(&call->rq);
+#endif
+ }
+ MUTEX_EXIT(&call->lockq);
+
+ np = 0; /* We can't use this any more */
+#endif /* ADAPT_PERF */
+
+ /* Update last packet received */
+ call->rprev = seq;
+
+ /*
+ * If there is no server process serving this call, grab one, if
+ * available
+ */
+ TryAttach(call);
+ }
+ /* This is not the expected next packet */
+ else {
+ /*
+ * Determine whether this is a new or old packet, and if it's
+ * a new one, whether it fits into the current receive window.
+ * It's also useful to know if the packet arrived out of
+ * sequence, so that we can force an acknowledgement in that
+ * case. We have a slightly complex definition of
+ * out-of-sequence: the previous packet number received off
+ * the wire is remembered. If the new arrival's sequence
+ * number is less than previous, then previous is reset (to
+ * 0). MTUXXX This should change slightly if skew is taken into
+ * consideration. lws 93.04.20
+ * The new packet is then declared out-of-sequence if
+ * there are any packets missing between the "previous" packet
+ * and the one which just arrived (because the missing packets
+ * should have been filled in between the previous packet and
+ * the new arrival). This works regardless of whether the
+ * peer's retransmission algorithm has been invoked, or not
+ * (i.e. whether this is the first or subsequent pass over the
+ * sequence of packets). All this assumes that "most" of the
+ * time, packets are delivered in the same *order* as they are
+ * transmitted, with, possibly, some packets lost due to
+ * transmission errors along the way.
+ */
+
+ u_long prev; /* "Previous packet" sequence number */
+ struct rx_packet *tp; /* Temporary packet pointer */
+ struct rx_packet *nxp;/*
+ * Next packet pointer, for queue_Scan
+ */
+ int nTwixt; /*
+ * Number of packets between previous
+ * and new one
+ */
+
+ /*
+ * If the new packet's sequence number has been sent to the
+ * application already, then this is a duplicate
+ */
+ if (np->header.seq < call->rnext) {
+ rx_stats.dupPacketsRead++;
+ np = rxi_SendAck(call, np, seq, np->header.serial,
+ np->header.flags, RX_ACK_DUPLICATE);
+ call->rprev = seq;
+ return np;
+ }
+ /*
+ * If the sequence number is greater than what can be
+ * accomodated by the current window, then send a negative
+ * acknowledge and drop the packet
+ */
+ if ((call->rnext + call->rwind) <= np->header.seq) {
+ np = rxi_SendAck(call, np, seq, np->header.serial,
+ np->header.flags, RX_ACK_EXCEEDS_WINDOW);
+ call->rprev = seq;
+ return np;
+ }
+ /* Look for the packet in the queue of old received packets */
+ prev = call->rprev;
+ if (prev > np->header.seq)
+ prev = 0;
+ for (nTwixt = 0, queue_Scan(&call->rq, tp, nxp, rx_packet)) {
+ /* Check for duplicate packet */
+ if (np->header.seq == tp->header.seq) {
+ rx_stats.dupPacketsRead++;
+ np = rxi_SendAck(call, np, np->header.seq, np->header.serial,
+ np->header.flags, RX_ACK_DUPLICATE);
+ call->rprev = seq;
+ return np;
+ }
+
+ /*
+ * Count the number of packets received 'twixt the previous
+ * packet and the new packet
+ */
+ if (tp->header.seq > prev && tp->header.seq < np->header.seq)
+ nTwixt++;
+
+ /*
+ * If we find a higher sequence packet, break out and insert the
+ * new packet here.
+ */
+ if (np->header.seq < tp->header.seq)
+ break;
+ }
+
+ /*
+ * It's within the window: add it to the the receive queue.
+ * tp is left by the previous loop either pointing at the
+ * packet before which to insert the new packet, or at the
+ * queue head if the queue is empty or the packet should be
+ * appended.
+ */
+ queue_InsertBefore(tp, np);
+
+ /*
+ * Acknowledge the packet if it's out of sequence or if
+ * requested by peer
+ */
+ if (np->header.flags & RX_REQUEST_ACK) {
+ np = rxi_SendAck(call, 0, np->header.seq, np->header.serial,
+ np->header.flags, RX_ACK_REQUESTED);
+ call->rprev = seq;
+ return np;
+ }
+ call->rprev = seq;
+ np = 0;
+ }
+ return np;
+}
+
+#ifdef ADAPT_WINDOW
+static void rxi_ComputeRate();
+
+#endif
+
+/* The real smarts of the whole thing. Right now somewhat short-changed. */
+struct rx_packet *
+rxi_ReceiveAckPacket(struct rx_call * call, struct rx_packet * np)
+{
+ struct rx_ackPacket *ap;
+ int nAcks;
+ struct rx_packet *tp;
+ struct rx_packet *nxp; /*
+ * Next packet pointer for queue_Scan
+ */
+ struct rx_connection *conn = call->conn;
+ struct rx_peer *peer = conn->peer;
+ u_long first;
+ u_long serial;
+
+ /* because there are CM's that are bogus, sending weird values for this. */
+ u_long skew = 0;
+ int needRxStart = 0;
+ int nbytes;
+
+ rx_stats.ackPacketsRead++;
+ ap = (struct rx_ackPacket *) rx_DataOf(np);
+ nbytes = rx_Contiguous(np) - ((ap->acks) - (u_char *) ap);
+ if (nbytes < 0)
+ return np; /* truncated ack packet */
+
+ nAcks = MIN(nbytes, ap->nAcks); /* depends on ack packet struct */
+ first = ntohl(ap->firstPacket);
+ serial = ntohl(ap->serial);
+#ifdef notdef
+ skew = ntohs(ap->maxSkew);
+#endif
+
+
+#ifdef RXDEBUG
+ if (Log) {
+ fprintf(Log,
+ "RACK: reason %x previous %lu seq %lu serial %lu skew %lu "
+ "first %lu", ap->reason,
+ (unsigned long)ntohl(ap->previousPacket),
+ (unsigned long)np->header.seq,
+ (unsigned long)serial,
+ (unsigned long)skew,
+ (unsigned long)ntohl(ap->firstPacket));
+ if (nAcks) {
+ int offset;
+
+ for (offset = 0; offset < nAcks; offset++)
+ putc(ap->acks[offset] == RX_ACK_TYPE_NACK ? '-' : '*', Log);
+ }
+ putc('\n', Log);
+ }
+#endif
+
+ /*
+ * if a server connection has been re-created, it doesn't remember what
+ * serial # it was up to. An ack will tell us, since the serial field
+ * contains the largest serial received by the other side
+ */
+ if ((conn->type == RX_SERVER_CONNECTION) && (conn->serial < serial)) {
+ conn->serial = serial + 1;
+ }
+
+ /*
+ * Update the outgoing packet skew value to the latest value of the
+ * peer's incoming packet skew value. The ack packet, of course, could
+ * arrive out of order, but that won't affect things much
+ */
+ peer->outPacketSkew = skew;
+
+#ifdef AFS_SUN5_ENV
+ /*
+ * XXX Hack. Because we can't release the global rx lock when sending
+ * packets (osi_NetSend) we drop all acks while we're traversing the tq in
+ * rxi_Start sending packets out because packets
+ * may move to the freePacketQueue as result of being here! So we drop
+ * these packets until we're safely out of the traversing. Really ugly!
+ */
+ if (call->flags & RX_CALL_TQ_BUSY) {
+ rx_tq_dropped++;
+ return np; /* xmitting; drop packet */
+ }
+#endif
+ /*
+ * Check for packets that no longer need to be transmitted, and
+ * discard them. This only applies to packets positively
+ * acknowledged as having been sent to the peer's upper level.
+ * All other packets must be retained. So only packets with
+ * sequence numbers < ap->firstPacket are candidates.
+ */
+ while (queue_IsNotEmpty(&call->tq)) {
+ tp = queue_First(&call->tq, rx_packet);
+ if (tp->header.seq >= first)
+ break;
+ call->tfirst = tp->header.seq + 1;
+ if (tp->header.serial == serial) {
+#ifdef ADAPT_PERF
+ rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer);
+#else
+ rxi_ComputeRoundTripTime(tp, 0, 0);
+#endif
+#ifdef ADAPT_WINDOW
+ rxi_ComputeRate(peer, call, tp, np, ap->reason);
+#endif
+ }
+#ifdef ADAPT_PERF
+ else if ((tp->firstSerial == serial)) {
+ rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer);
+#ifdef ADAPT_WINDOW
+ rxi_ComputeRate(peer, call, tp, np, ap->reason);
+#endif
+ }
+#endif /* ADAPT_PERF */
+ queue_Remove(tp);
+ rxi_FreePacket(tp); /*
+ * rxi_FreePacket mustn't wake up anyone,
+ * preemptively.
+ */
+ }
+
+#ifdef ADAPT_WINDOW
+ /* Give rate detector a chance to respond to ping requests */
+ if (ap->reason == RX_ACK_PING_RESPONSE) {
+ rxi_ComputeRate(peer, call, 0, np, ap->reason);
+ }
+#endif
+
+ /*
+ * N.B. we don't turn off any timers here. They'll go away by themselves,
+ * anyway
+ */
+
+ /*
+ * Now go through explicit acks/nacks and record the results in
+ * the waiting packets. These are packets that can't be released
+ * yet, even with a positive acknowledge. This positive
+ * acknowledge only means the packet has been received by the
+ * peer, not that it will be retained long enough to be sent to
+ * the peer's upper level. In addition, reset the transmit timers
+ * of any missing packets (those packets that must be missing
+ * because this packet was out of sequence)
+ */
+
+ for (queue_Scan(&call->tq, tp, nxp, rx_packet)) {
+
+ /*
+ * Update round trip time if the ack was stimulated on receipt of
+ * this packet
+ */
+ if (tp->header.serial == serial) {
+#ifdef ADAPT_PERF
+ rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer);
+#else
+ rxi_ComputeRoundTripTime(tp, 0, 0);
+#endif
+#ifdef ADAPT_WINDOW
+ rxi_ComputeRate(peer, call, tp, np, ap->reason);
+#endif
+ }
+#ifdef ADAPT_PERF
+ else if ((tp->firstSerial == serial)) {
+ rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer);
+#ifdef ADAPT_WINDOW
+ rxi_ComputeRate(peer, call, tp, np, ap->reason);
+#endif
+ }
+#endif /* ADAPT_PERF */
+
+ /*
+ * Set the acknowledge flag per packet based on the
+ * information in the ack packet. It's possible for an
+ * acknowledged packet to be downgraded
+ */
+ if (tp->header.seq < first + nAcks) {
+ /* Explicit ack information: set it in the packet appropriately */
+ tp->acked = (ap->acks[tp->header.seq - first] == RX_ACK_TYPE_ACK);
+ } else {
+ /*
+ * No ack information: the packet may have been
+ * acknowledged previously, but that is now rescinded (the
+ * peer may have reduced the window size)
+ */
+ tp->acked = 0;
+ }
+
+
+#ifdef ADAPT_PERF
+ /*
+ * If packet isn't yet acked, and it has been transmitted at least
+ * once, reset retransmit time using latest timeout
+ * ie, this should readjust the retransmit timer for all outstanding
+ * packets... So we don't just retransmit when we should know better
+ */
+
+ if (!tp->acked && tp->header.serial) {
+ tp->retryTime = tp->timeSent;
+ clock_Add(&tp->retryTime, &peer->timeout);
+ /* shift by eight because one quarter-sec ~ 256 milliseconds */
+ clock_Addmsec(&(tp->retryTime), ((unsigned long) tp->backoff) << 8);
+ }
+#endif /* ADAPT_PERF */
+
+ /*
+ * If the packet isn't yet acked, and its serial number
+ * indicates that it was transmitted before the packet which
+ * prompted the acknowledge (that packet's serial number is
+ * supplied in the ack packet), then schedule the packet to be
+ * transmitted *soon*. This is done by resetting the
+ * retransmit time in the packet to the current time.
+ * Actually this is slightly more intelligent: to guard
+ * against packets that have been transmitted out-of-order by
+ * the network (this even happens on the local token ring with
+ * our IBM RT's!), the degree of out-of-orderness (skew) of
+ * the packet is compared against the maximum skew for this
+ * peer. If it is less, we don't retransmit yet. Note that
+ * we don't do this for packets with zero serial numbers: they
+ * never have been transmitted.
+ */
+
+ /*
+ * I don't know if we should add in the new retransmit backoff time
+ * here or not. I think that we should also consider reducing
+ * the "congestion window" size as an alternative. LWSXXX
+ */
+
+ if (!tp->acked && tp->header.serial
+ && ((tp->header.serial + skew) <= serial)) {
+ rx_stats.dataPacketsPushed++;
+ clock_GetTime(&tp->retryTime);
+ needRxStart = 1;
+
+ dpf(("Pushed packet seq %d serial %d, new time %d.%d\n",
+ tp->header.seq, tp->header.serial, tp->retryTime.sec,
+ tp->retryTime.usec / 1000));
+ }
+ }
+
+ /*
+ * If the window has been extended by this acknowledge packet,
+ * then wakeup a sender waiting in alloc for window space, or try
+ * sending packets now, if he's been sitting on packets due to
+ * lack of window space
+ */
+ if (call->tnext < (call->tfirst + call->twind)) {
+#ifdef RX_ENABLE_LOCKS
+ MUTEX_ENTER(&call->lockw);
+ cv_signal(&call->cv_twind);
+ MUTEX_EXIT(&call->lockw);
+#else
+ if (call->flags & RX_CALL_WAIT_WINDOW_ALLOC) {
+ call->flags &= ~RX_CALL_WAIT_WINDOW_ALLOC;
+ osi_rxWakeup(&call->twind);
+ }
+#endif
+ if (call->flags & RX_CALL_WAIT_WINDOW_SEND) {
+ call->flags &= ~RX_CALL_WAIT_WINDOW_SEND;
+ needRxStart = 1;
+ }
+ }
+ /*
+ * if the ack packet has a receivelen field hanging off it,
+ * update our state
+ */
+ if (np->length >= rx_AckDataSize(ap->nAcks) + 4) {
+ unsigned long maxPacketSize;
+
+ rx_packetread(np, rx_AckDataSize(ap->nAcks), 4, &maxPacketSize);
+ maxPacketSize = (unsigned long) ntohl(maxPacketSize);
+ dpf(("maxPacketSize=%ul\n", maxPacketSize));
+
+ /*
+ * sanity check - peer might have restarted with different params.
+ * If peer says "send less", dammit, send less... Peer should never
+ * be unable to accept packets of the size that prior AFS versions
+ * would send without asking.
+ */
+ if (OLD_MAX_PACKET_SIZE <= maxPacketSize)
+ conn->maxPacketSize = MIN(maxPacketSize, conn->peer->packetSize);
+ }
+ /* if (needRxStart) rxi_Start(0, call); */
+ rxi_Start(0, call); /* Force rxi_Restart for now: skew
+ * problems!!! */
+ return np;
+}
+
+/* Received a response to a challenge packet */
+struct rx_packet *
+rxi_ReceiveResponsePacket(struct rx_connection * conn,
+ struct rx_packet * np)
+{
+ int error;
+
+ /* Ignore the packet if we're the client */
+ if (conn->type == RX_CLIENT_CONNECTION)
+ return np;
+
+ /* If already authenticated, ignore the packet (it's probably a retry) */
+ if (RXS_CheckAuthentication(conn->securityObject, conn) == 0)
+ return np;
+
+ /* Otherwise, have the security object evaluate the response packet */
+ error = RXS_CheckResponse(conn->securityObject, conn, np);
+ if (error) {
+
+ /*
+ * If the response is invalid, reset the connection, sending an abort
+ * to the peer
+ */
+#ifndef KERNEL
+ IOMGR_Sleep(1);
+#endif
+ rxi_ConnectionError(conn, error);
+ return rxi_SendConnectionAbort(conn, np);
+ } else {
+
+ /*
+ * If the response is valid, any calls waiting to attach servers can
+ * now do so
+ */
+ int i;
+
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ struct rx_call *call = conn->call[i];
+
+ if (call && (call->state == RX_STATE_PRECALL))
+ rxi_AttachServerProc(call);
+ }
+ }
+ return np;
+}
+
+/*
+ * A client has received an authentication challenge: the security
+ * object is asked to cough up a respectable response packet to send
+ * back to the server. The server is responsible for retrying the
+ * challenge if it fails to get a response.
+ */
+
+struct rx_packet *
+rxi_ReceiveChallengePacket(struct rx_connection * conn,
+ struct rx_packet * np)
+{
+ int error;
+
+ /* Ignore the challenge if we're the server */
+ if (conn->type == RX_SERVER_CONNECTION)
+ return np;
+
+ /*
+ * Ignore the challenge if the connection is otherwise idle; someone's
+ * trying to use us as an oracle.
+ */
+ if (!rxi_HasActiveCalls(conn))
+ return np;
+
+ /*
+ * Send the security object the challenge packet. It is expected to fill
+ * in the response.
+ */
+ error = RXS_GetResponse(conn->securityObject, conn, np);
+
+ /*
+ * If the security object is unable to return a valid response, reset the
+ * connection and send an abort to the peer. Otherwise send the response
+ * packet to the peer connection.
+ */
+ if (error) {
+ rxi_ConnectionError(conn, error);
+ np = rxi_SendConnectionAbort(conn, np);
+ } else {
+ np = rxi_SendSpecial((struct rx_call *) 0, conn, np,
+ RX_PACKET_TYPE_RESPONSE, (char *) 0, -1);
+ }
+ return np;
+}
+
+
+/*
+ * Find an available server process to service the current request in
+ * the given call structure. If one isn't available, queue up this
+ * call so it eventually gets one
+ */
+void
+rxi_AttachServerProc(struct rx_call * call)
+{
+ struct rx_serverQueueEntry *sq;
+ struct rx_service *service = call->conn->service;
+
+ /* May already be attached */
+ if (call->state == RX_STATE_ACTIVE)
+ return;
+
+ if (!QuotaOK(service) || queue_IsEmpty(&rx_idleServerQueue)) {
+ /*
+ * If there are no processes available to service this call,
+ * put the call on the incoming call queue (unless it's
+ * already on the queue).
+ */
+ if (!(call->flags & RX_CALL_WAIT_PROC)) {
+ call->flags |= RX_CALL_WAIT_PROC;
+ rx_nWaiting++;
+ rxi_calltrace(RX_CALL_ARRIVAL, call);
+ queue_Append(&rx_incomingCallQueue, call);
+ }
+ } else {
+ sq = queue_First(&rx_idleServerQueue, rx_serverQueueEntry);
+
+ MUTEX_ENTER(&sq->lock);
+
+ queue_Remove(sq);
+ sq->newcall = call;
+ if (call->flags & RX_CALL_WAIT_PROC) {
+ /* Conservative: I don't think this should happen */
+ call->flags &= ~RX_CALL_WAIT_PROC;
+ rx_nWaiting--;
+ queue_Remove(call);
+ }
+ call->state = RX_STATE_ACTIVE;
+ call->mode = RX_MODE_RECEIVING;
+ if (call->flags & RX_CALL_CLEARED) {
+ /* send an ack now to start the packet flow up again */
+ call->flags &= ~RX_CALL_CLEARED;
+ rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_DELAY);
+ }
+ service->nRequestsRunning++;
+ if (service->nRequestsRunning <= service->minProcs)
+ rxi_minDeficit--;
+ rxi_availProcs--;
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&sq->cv);
+#else
+ osi_rxWakeup(sq);
+#endif
+ MUTEX_EXIT(&sq->lock);
+ }
+}
+
+/*
+ * Delay the sending of an acknowledge event for a short while, while
+ * a new call is being prepared (in the case of a client) or a reply
+ * is being prepared (in the case of a server). Rather than sending
+ * an ack packet, an ACKALL packet is sent.
+ */
+void
+rxi_AckAll(struct rxevent * event, struct rx_call * call, char *dummy)
+{
+ if (event)
+ call->delayedAckEvent = (struct rxevent *) 0;
+ rxi_SendSpecial(call, call->conn, (struct rx_packet *) 0,
+ RX_PACKET_TYPE_ACKALL, (char *) 0, 0);
+}
+
+void
+rxi_SendDelayedAck(struct rxevent * event, struct rx_call * call,
+ char *dummy)
+{
+ if (event)
+ call->delayedAckEvent = (struct rxevent *) 0;
+ (void) rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_DELAY);
+}
+
+/*
+ * Clear out the transmit queue for the current call (all packets have
+ * been received by peer)
+ */
+void
+rxi_ClearTransmitQueue(struct rx_call * call)
+{
+ struct rx_packet *p, *tp;
+
+ for (queue_Scan(&call->tq, p, tp, rx_packet)) {
+ queue_Remove(p);
+ rxi_FreePacket(p);
+ }
+
+ rxevent_Cancel(call->resendEvent);
+ call->tfirst = call->tnext; /*
+ * implicitly acknowledge all data already sent
+ */
+ MUTEX_ENTER(&call->lockw);
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&call->cv_twind);
+#else
+ osi_rxWakeup(&call->twind);
+#endif
+ MUTEX_EXIT(&call->lockw);
+}
+
+void
+rxi_ClearReceiveQueue(struct rx_call * call)
+{
+ struct rx_packet *p, *tp;
+
+ for (queue_Scan(&call->rq, p, tp, rx_packet)) {
+ queue_Remove(p);
+ rxi_FreePacket(p);
+ }
+ if (call->state == RX_STATE_PRECALL)
+ call->flags |= RX_CALL_CLEARED;
+}
+
+/* Send an abort packet for the specified call */
+struct rx_packet *
+rxi_SendCallAbort(struct rx_call * call, struct rx_packet * packet)
+{
+ if (call->error) {
+ long error;
+
+ error = htonl(call->error);
+ packet = rxi_SendSpecial(call, call->conn, packet, RX_PACKET_TYPE_ABORT,
+ (char *) &error, sizeof(error));
+ }
+ return packet;
+}
+
+/*
+ * Send an abort packet for the specified connection. Np is an
+ * optional packet that can be used to send the abort.
+ */
+struct rx_packet *
+rxi_SendConnectionAbort(struct rx_connection * conn,
+ struct rx_packet * packet)
+{
+ if (conn->error) {
+ long error;
+
+ error = htonl(conn->error);
+ packet = rxi_SendSpecial((struct rx_call *) 0, conn, packet,
+ RX_PACKET_TYPE_ABORT, (char *) &error, sizeof(error));
+ }
+ return packet;
+}
+
+/*
+ * Associate an error all of the calls owned by a connection. Called
+ * with error non-zero. This is only for really fatal things, like
+ * bad authentication responses. The connection itself is set in
+ * error at this point, so that future packets received will be
+ * rejected.
+ */
+void
+rxi_ConnectionError(struct rx_connection * conn, long error)
+{
+ if (error) {
+ int i;
+
+ if (conn->challengeEvent)
+ rxevent_Cancel(conn->challengeEvent);
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ struct rx_call *call = conn->call[i];
+
+ if (call)
+ rxi_CallError(call, error);
+ }
+ conn->error = error;
+ rx_stats.fatalErrors++;
+ }
+}
+
+/* Reset all of the calls associated with a connection. */
+void
+rxi_ResetConnection(struct rx_connection * conn)
+{
+ int i;
+
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ struct rx_call *call = conn->call[i];
+
+ if (call)
+ rxi_ResetCall(call);
+ }
+
+ /* get rid of pending events that could zap us later */
+ if (conn->challengeEvent)
+ rxevent_Cancel(conn->challengeEvent);
+}
+
+void
+rxi_CallError(struct rx_call * call, long error)
+{
+ if (call->error)
+ error = call->error;
+ rxi_ResetCall(call);
+ call->error = error;
+ call->mode = RX_MODE_ERROR;
+}
+
+/*
+ * Reset various fields in a call structure, and wakeup waiting
+ * processes. Some fields aren't changed: state & mode are not
+ * touched (these must be set by the caller), and bufptr, nLeft, and
+ * nFree are not reset, since these fields are manipulated by
+ * unprotected macros, and may only be reset by non-interrupting code.
+ */
+#ifdef ADAPT_WINDOW
+/* this code requires that call->conn be set properly as a pre-condition. */
+#endif /* ADAPT_WINDOW */
+
+void
+rxi_ResetCall(struct rx_call * call)
+{
+ int flags;
+
+ /* Notify anyone who is waiting for asynchronous packet arrival */
+ if (call->arrivalProc) {
+ (*call->arrivalProc) (call, call->arrivalProcHandle,
+ call->arrivalProcArg);
+ call->arrivalProc = (void (*) ()) 0;
+ }
+ flags = call->flags;
+ rxi_ClearReceiveQueue(call);
+ rxi_ClearTransmitQueue(call);
+ call->error = 0;
+ call->flags = 0;
+ call->rwind = rx_Window; /* XXXX */
+#ifdef ADAPT_WINDOW
+ call->twind = call->conn->peer->maxWindow; /* XXXX */
+#else
+ call->twind = rx_Window; /* XXXX */
+#endif
+ call->tfirst = call->rnext = call->tnext = 1;
+ call->rprev = 0;
+ call->lastAcked = 0;
+ call->localStatus = call->remoteStatus = 0;
+
+ MUTEX_ENTER(&call->lockq);
+ if (flags & RX_CALL_READER_WAIT) {
+#ifdef RX_ENABLE_LOCKS
+/* cv_signal(&call->cv_rq);*/
+ cv_broadcast(&call->cv_rq);
+#else
+ osi_rxWakeup(&call->rq);
+#endif
+ }
+ MUTEX_EXIT(&call->lockq);
+ if (flags & RX_CALL_WAIT_PACKETS)
+ rxi_PacketsUnWait(); /* XXX */
+ MUTEX_ENTER(&call->lockw);
+
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&call->cv_twind);
+#else
+ if (flags & RX_CALL_WAIT_WINDOW_ALLOC)
+ osi_rxWakeup(&call->twind);
+#endif
+ MUTEX_EXIT(&call->lockw);
+
+ if (queue_IsOnQueue(call)) {
+ queue_Remove(call);
+ if (flags & RX_CALL_WAIT_PROC)
+ rx_nWaiting--;
+ }
+ rxi_KeepAliveOff(call);
+ rxevent_Cancel(call->delayedAckEvent);
+}
+
+/*
+ * Send an acknowledge for the indicated packet (seq,serial) of the
+ * indicated call, for the indicated reason (reason). This
+ * acknowledge will specifically acknowledge receiving the packet, and
+ * will also specify which other packets for this call have been
+ * received. This routine returns the packet that was used to the
+ * caller. The caller is responsible for freeing it or re-using it.
+ * This acknowledgement also returns the highest sequence number
+ * actually read out by the higher level to the sender; the sender
+ * promises to keep around packets that have not been read by the
+ * higher level yet (unless, of course, the sender decides to abort
+ * the call altogether). Any of p, seq, serial, pflags, or reason may
+ * be set to zero without ill effect. That is, if they are zero, they
+ * will not convey any information.
+ * NOW there is a trailer field, after the ack where it will safely be
+ * ignored by mundanes, which indicates the maximum size packet this
+ * host can swallow.
+ */
+struct rx_packet *
+rxi_SendAck(struct rx_call * call,
+ struct rx_packet * optionalPacket, int seq, int serial,
+ int pflags, int reason)
+#if 0
+ struct rx_call *call;
+ struct rx_packet *optionalPacket; /* use to send ack (or null) */
+ int seq; /* Sequence number of the packet we
+ * are acking */
+ int serial; /* Serial number of the packet */
+ int pflags; /* Flags field from packet header */
+ int reason; /* Reason an acknowledge was prompted */
+
+#endif
+{
+ struct rx_ackPacket *ap;
+ struct rx_packet *rqp;
+ struct rx_packet *nxp; /* For queue_Scan */
+ struct rx_packet *p;
+ u_char offset;
+ long templ;
+
+ if (call->rnext > call->lastAcked)
+ call->lastAcked = call->rnext;
+ p = optionalPacket;
+
+ if (p) {
+ rx_computelen(p, p->length); /* reset length, you never know */
+ }
+ /* where that's been... */
+ else if (!(p = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL)))
+ osi_Panic("rxi_SendAck");
+
+ templ = rx_AckDataSize(call->rwind) + 4 - rx_GetDataSize(p);
+ if (templ > 0) {
+ if (rxi_AllocDataBuf(p, templ))
+ return optionalPacket;
+ templ = rx_AckDataSize(call->rwind) + 4;
+ if (rx_Contiguous(p) < templ)
+ return optionalPacket;
+ } /* MTUXXX failing to send an ack is
+ * very serious. We should */
+ /* try as hard as possible to send even a partial ack; it's */
+ /* better than nothing. */
+ ap = (struct rx_ackPacket *) rx_DataOf(p);
+ ap->bufferSpace = htonl(0); /* Something should go here, sometime */
+ ap->reason = reason;
+
+ /* The skew computation used to bullshit, I think it's better now. */
+ /* We should start paying attention to skew. XXX */
+ ap->serial = htonl(call->conn->maxSerial);
+ ap->maxSkew = 0; /* used to be peer->inPacketSkew */
+
+ ap->firstPacket = htonl(call->rnext); /*
+ * First packet not yet forwarded
+ * to reader
+ */
+ ap->previousPacket = htonl(call->rprev); /* Previous packet received */
+
+ /*
+ * No fear of running out of ack packet here because there can only be
+ * at most one window full of unacknowledged packets. The window size
+ * must be constrained to be less than the maximum ack size, of course.
+ * Also, an ack should always fit into a single packet -- it should not
+ * ever be fragmented.
+ */
+ for (offset = 0, queue_Scan(&call->rq, rqp, nxp, rx_packet)) {
+ while (rqp->header.seq > call->rnext + offset)
+ ap->acks[offset++] = RX_ACK_TYPE_NACK;
+ ap->acks[offset++] = RX_ACK_TYPE_ACK;
+ }
+ ap->nAcks = offset;
+ p->length = rx_AckDataSize(offset) + 4;
+ templ = htonl(rx_maxReceiveSize);
+ rx_packetwrite(p, rx_AckDataSize(offset), 4, &templ);
+ p->header.serviceId = call->conn->serviceId;
+ p->header.cid = (call->conn->cid | call->channel);
+ p->header.callNumber = *call->callNumber;
+ p->header.seq = seq;
+ p->header.securityIndex = call->conn->securityIndex;
+ p->header.epoch = call->conn->epoch;
+ p->header.type = RX_PACKET_TYPE_ACK;
+ p->header.flags = 0;
+ if (reason == RX_ACK_PING) {
+ p->header.flags |= RX_REQUEST_ACK;
+#ifdef ADAPT_WINDOW
+ clock_GetTime(&call->pingRequestTime);
+#endif
+ }
+ if (call->conn->type == RX_CLIENT_CONNECTION)
+ p->header.flags |= RX_CLIENT_INITIATED;
+
+
+#ifdef RXDEBUG
+ if (Log) {
+ fprintf(Log, "SACK: reason %x previous %lu seq %lu first %lu",
+ ap->reason,
+ (unsigned long)ntohl(ap->previousPacket),
+ (unsigned long)p->header.seq,
+ (unsigned long)ntohl(ap->firstPacket));
+ if (ap->nAcks) {
+ for (offset = 0; offset < ap->nAcks; offset++)
+ putc(ap->acks[offset] == RX_ACK_TYPE_NACK ? '-' : '*', Log);
+ }
+ putc('\n', Log);
+ }
+#endif
+
+ {
+ int i, nbytes = p->length;
+
+ for (i = 1; i < p->niovecs; i++) { /* vec 0 is ALWAYS header */
+ if (nbytes <= p->wirevec[i].iov_len) {
+ int savelen, saven;
+
+ savelen = p->wirevec[i].iov_len;
+ saven = p->niovecs;
+ p->wirevec[i].iov_len = nbytes;
+ p->niovecs = i + 1;
+ rxi_Send(call, p);
+ p->wirevec[i].iov_len = savelen;
+ p->niovecs = saven;
+ break;
+ } else
+ nbytes -= p->wirevec[i].iov_len;
+ }
+ }
+ rx_stats.ackPacketsSent++;
+ if (!optionalPacket)
+ rxi_FreePacket(p);
+ return optionalPacket; /* Return packet for re-use by caller */
+}
+
+
+/*
+ * This routine is called when new packets are readied for
+ * transmission and when retransmission may be necessary, or when the
+ * transmission window or burst count are favourable. This should be
+ * better optimized for new packets, the usual case, now that we've
+ * got rid of queues of send packets. XXXXXXXXXXX
+ */
+void
+rxi_Start(struct rxevent * event, struct rx_call * call)
+{
+ int nSent = 0;
+ struct rx_packet *p;
+ struct rx_packet *nxp; /* Next pointer for queue_Scan */
+ struct rx_packet *lastPacket;
+ struct rx_peer *peer = call->conn->peer;
+ struct clock now, retryTime;
+ int haveEvent;
+
+ /*
+ * If rxi_Start is being called as a result of a resend event,
+ * then make sure that the event pointer is removed from the call
+ * structure, since there is no longer a per-call retransmission
+ * event pending.
+ */
+ if (event && event == call->resendEvent)
+ call->resendEvent = 0;
+
+ if (queue_IsNotEmpty(&call->tq)) { /* If we have anything to send */
+ /*
+ * Get clock to compute the re-transmit time for any packets
+ * in this burst. Note, if we back off, it's reasonable to
+ * back off all of the packets in the same manner, even if
+ * some of them have been retransmitted more times than more
+ * recent additions
+ */
+ clock_GetTime(&now);
+ retryTime = now; /* initialize before use */
+ clock_Add(&retryTime, &peer->timeout);
+
+ /*
+ * Send (or resend) any packets that need it, subject to
+ * window restrictions and congestion burst control
+ * restrictions. Ask for an ack on the last packet sent in
+ * this burst. For now, we're relying upon the window being
+ * considerably bigger than the largest number of packets that
+ * are typically sent at once by one initial call to
+ * rxi_Start. This is probably bogus (perhaps we should ask
+ * for an ack when we're half way through the current
+ * window?). Also, for non file transfer applications, this
+ * may end up asking for an ack for every packet. Bogus. XXXX
+ */
+ call->flags |= RX_CALL_TQ_BUSY;
+ for (lastPacket = (struct rx_packet *) 0,
+ queue_Scan(&call->tq, p, nxp, rx_packet)) {
+ if (p->acked) {
+ rx_stats.ignoreAckedPacket++;
+ continue; /* Ignore this packet if it has been
+ * acknowledged */
+ }
+ /*
+ * Turn off all flags except these ones, which are the same
+ * on each transmission
+ */
+ p->header.flags &= RX_PRESET_FLAGS;
+
+ if (p->header.seq >= call->tfirst + call->twind) {
+ call->flags |= RX_CALL_WAIT_WINDOW_SEND; /*
+ * Wait for transmit
+ * window
+ */
+ /*
+ * Note: if we're waiting for more window space, we can
+ * still send retransmits; hence we don't return here, but
+ * break out to schedule a retransmit event
+ */
+ break;
+ }
+ /*
+ * If we're not allowed to send any more in the current
+ * burst, make sure we get scheduled later. Also schedule
+ * an event to "give back" the packets we've used, when the
+ * burst time has elapsed (if we used any packets at all).
+ */
+ if (peer->burstSize && !peer->burst) {
+ if (nSent) {
+ int foo; /* XXX - ugly */
+ /* Send off the prior packet */
+ /*
+ * Don't request an ack if it's a short packet, 'cuz the
+ * peer will cut down its MTU as a result.
+ */
+ if (((lastPacket->header.flags & RX_LAST_PACKET) == 0)) {
+ if ((lastPacket->length + RX_HEADER_SIZE +
+ call->conn->securityMaxTrailerSize) >= call->conn->maxPacketSize)
+ foo = ACKHACK(lastPacket);
+ else
+ Rx0++;
+ }
+ rxi_Send(call, lastPacket);
+ rxi_ScheduleDecongestionEvent(call, nSent);
+ }
+ rxi_CongestionWait(call);
+ /*
+ * Note: if we're waiting for congestion to ease, we can't
+ * send any packets, including retransmits. Hence we do
+ * not schedule a new retransmit event right now
+ */
+ call->flags &= ~RX_CALL_TQ_BUSY;
+ return;
+ }
+ /*
+ * Transmit the packet if it has never been sent, or
+ * retransmit it if the current timeout for this host for
+ * this packet has elapsed
+ */
+ if (!clock_IsZero(&p->retryTime)) {
+ if (clock_Lt(&now, &p->retryTime))
+ continue;
+
+ /*
+ * Always request an ack on a retransmitted packet; this
+ * will help to get the data moving again, especially if
+ * the packet is near the beginning of the window.
+ * Actually, XXXX, we may want to do just that: only
+ * request the acks if the packet is in, say, the first
+ * half of the window
+ */
+ p->header.flags |= RX_REQUEST_ACK;
+ peer->reSends++, rx_stats.dataPacketsReSent++;
+ p->retryTime = retryTime;
+
+ /*
+ * if a packet gets dropped, don't keep hammering on it --
+ * back off exponentially, at least up to a point. I had
+ * to trade off global congestion avoidance against individual
+ * performance. Note that most connections will time out
+ * after 20 - 60 seconds. In pathological cases, retransmits
+ * must still continue to disperse. For instance, there is
+ * a condition where the server discards received packets, but
+ * still sends keep-alives on the call, so the call may live
+ * much longer than 60 seconds.
+ */
+ if (p->backoff < MAXBACKOFF)
+ p->backoff = (p->backoff << 1) + 1; /* so it can't stay == 0 */
+ else
+ p->backoff++;
+ clock_Addmsec(&(p->retryTime), ((unsigned long) p->backoff) << 8);
+ /* consider shrinking the packet size? XXXX */
+ /* no, shrink the burst size. LWSXXX */
+ } else {
+ peer->nSent++, rx_stats.dataPacketsSent++;
+ p->firstSent = now; /* improved RTO calculation- not Karn */
+ p->retryTime = retryTime;
+ /*
+ * Ask for an ack for the first packet on a new
+ * connection, since it may carry some interesting info
+ * like maxReceiveSize. It will also help us train to a
+ * new estimate of RTT, for good or bad. This has one
+ * neat side effect: since the first call on a connection
+ * usually triggers a challenge/response exchange, the
+ * first packet was often retransmitted before the call
+ * could complete. Getting this ack prevents those
+ * retransmissions. Admittedly, this is straining at gnats.
+ */
+ if ((p->header.callNumber == 1) && (p->header.seq == 1) &&
+ (p->length >= call->conn->maxPacketSize)) {
+ p->header.flags |= RX_REQUEST_ACK;
+ }
+ }
+
+ /*
+ * Install the new retransmit time for the packet, and
+ * record the time sent
+ */
+ p->timeSent = now;
+
+ /*
+ * Send the previous packet, and remember this one--we don't
+ * send it immediately, so we can tag it as requiring an ack
+ * later, if necessary
+ */
+ if (peer->burstSize)
+ peer->burst--;
+ nSent++;
+ if (lastPacket) {
+ /*
+ * Tag this packet as not being the last in this group,
+ * for the receiver's benefit
+ */
+ lastPacket->header.flags |= RX_MORE_PACKETS;
+ rxi_Send(call, lastPacket);
+ }
+ lastPacket = p;
+ }
+ call->flags &= ~RX_CALL_TQ_BUSY;
+
+ /*
+ * If any packets are to be sent, send them and post a
+ * decongestion event to bump the burst count that we used up
+ * sending the packets
+ */
+ if (nSent) {
+
+ /*
+ * we don't ask for an ack on the final packet, since the
+ * response from the peer implicitly acks it, but we do wait a
+ * little longer for the ack on the last packet on server conns.
+ */
+ if (((lastPacket->header.flags & RX_LAST_PACKET) == 0)) {
+ int foo; /* XXX - ugly */
+ if ((lastPacket->length + RX_HEADER_SIZE +
+ call->conn->securityMaxTrailerSize) >=
+ call->conn->maxPacketSize)
+ foo = ACKHACK(lastPacket);
+ else
+ Rx1++;
+ } else if (!(lastPacket->header.flags & RX_CLIENT_INITIATED))
+ clock_Addmsec(&(lastPacket->retryTime), 400);
+
+ rxi_Send(call, lastPacket);
+ if (peer->burstSize)
+ rxi_ScheduleDecongestionEvent(call, nSent);
+ }
+
+ /*
+ * Always post a resend event, if there is anything in the queue, and
+ * resend is possible. There should be at least one unacknowledged
+ * packet in the queue ... otherwise none of these packets should be
+ * on the queue in the first place.
+ */
+ if (call->resendEvent) {
+
+ /*
+ * If there's an existing resend event, then if its expiry time
+ * is sooner than the new one, then it must be less than any
+ * possible expiry time (because it represents all previous
+ * packets sent that may still need retransmitting). In this
+ * case, just leave that event as scheduled
+ */
+ if (clock_Le(&call->resendEvent->eventTime, &retryTime))
+ return;
+ /* Otherwise, cancel the existing event and post a new one */
+ rxevent_Cancel(call->resendEvent);
+ }
+
+ /*
+ * Loop to find the earliest event. I *know* XXXX that this can be
+ * coded more elegantly (perhaps rolled into the above code)
+ */
+ for (haveEvent = 0, queue_Scan(&call->tq, p, nxp, rx_packet)) {
+ if (!p->acked && !clock_IsZero(&p->retryTime)) {
+ haveEvent = 1;
+ if (clock_Lt(&p->retryTime, &retryTime))
+ retryTime = p->retryTime;
+ }
+ }
+
+ /* Post a new event to re-run rxi_Start when retries may be needed */
+ if (haveEvent) {
+ call->resendEvent = rxevent_Post(&retryTime, rxi_Start, (char *) call, 0);
+ }
+ }
+}
+
+/*
+ * Also adjusts the keep alive parameters for the call, to reflect
+ * that we have just sent a packet (so keep alives aren't sent
+ * immediately)
+ */
+void
+rxi_Send(struct rx_call *call, struct rx_packet *p)
+{
+ struct rx_connection *conn = call->conn;
+
+ /* Stamp each packet with the user supplied status */
+ p->header.userStatus = call->localStatus;
+
+ /*
+ * Allow the security object controlling this call's security to make any
+ * last-minute changes to the packet
+ */
+ RXS_SendPacket(conn->securityObject, call, p);
+
+ /* Actually send the packet, filling in more connection-specific fields */
+ rxi_SendPacket(conn, p);
+
+ /*
+ * Update last send time for this call (for keep-alive processing), and
+ * for the connection (so that we can discover idle connections)
+ */
+ conn->lastSendTime = call->lastSendTime = clock_Sec();
+
+ /*
+ * Since we've just sent SOME sort of packet to the peer, it's safe to
+ * nuke any scheduled end-of-packets ack
+ */
+ rxevent_Cancel(call->delayedAckEvent);
+}
+
+
+/*
+ * Check if a call needs to be destroyed. Called by keep-alive code to ensure
+ * that things are fine. Also called periodically to guarantee that nothing
+ * falls through the cracks (e.g. (error + dally) connections have keepalive
+ * turned off. Returns 0 if conn is well, -1 otherwise. If otherwise, call
+ * may be freed!
+ */
+int
+rxi_CheckCall(struct rx_call *call)
+{
+ struct rx_connection *conn = call->conn;
+ struct rx_service *tservice;
+ u_long now;
+
+ now = clock_Sec();
+
+ /*
+ * These are computed to the second (+- 1 second). But that's good
+ * enough for these values, which should be a significant number of
+ * seconds.
+ */
+ if (now > (call->lastReceiveTime + conn->secondsUntilDead)) {
+ if (call->state == RX_STATE_ACTIVE)
+ rxi_CallError(call, RX_CALL_DEAD);
+ else
+ rxi_FreeCall(call);
+
+ /*
+ * Non-active calls are destroyed if they are not responding to
+ * pings; active calls are simply flagged in error, so the attached
+ * process can die reasonably gracefully.
+ */
+ return -1;
+ }
+ /* see if we have a non-activity timeout */
+ tservice = conn->service;
+ if ((conn->type == RX_SERVER_CONNECTION) && call->startWait
+ && tservice->idleDeadTime
+ && ((call->startWait + tservice->idleDeadTime) < now)) {
+ if (call->state == RX_STATE_ACTIVE) {
+ rxi_CallError(call, RX_CALL_TIMEOUT);
+ return -1;
+ }
+ }
+ /* see if we have a hard timeout */
+ if (conn->hardDeadTime && (now > (conn->hardDeadTime + call->startTime))) {
+ if (call->state == RX_STATE_ACTIVE)
+ rxi_CallError(call, RX_CALL_TIMEOUT);
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * When a call is in progress, this routine is called occasionally to
+ * make sure that some traffic has arrived (or been sent to) the peer.
+ * If nothing has arrived in a reasonable amount of time, the call is
+ * declared dead; if nothing has been sent for a while, we send a
+ * keep-alive packet (if we're actually trying to keep the call alive)
+ */
+void
+rxi_KeepAliveEvent(struct rxevent *event, struct rx_call *call,
+ char *dummy)
+{
+ struct rx_connection *conn = call->conn;
+ u_long now;
+
+ call->keepAliveEvent = (struct rxevent *) 0;
+ now = clock_Sec();
+
+ if (rxi_CheckCall(call))
+ return;
+
+ /* Don't try to keep alive dallying calls */
+ if ((call->state != RX_STATE_DALLY)
+ && ((now - call->lastSendTime) > conn->secondsUntilPing)) {
+ /* Don't try to send keepalives if there is unacknowledged data */
+
+ /*
+ * the rexmit code should be good enough, this little hack doesn't
+ * quite work LWSXXX
+ */
+ (void) rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_PING);
+ }
+ rxi_ScheduleKeepAliveEvent(call);
+}
+
+
+void
+rxi_ScheduleKeepAliveEvent(struct rx_call *call)
+{
+ if (!call->keepAliveEvent) {
+ struct clock when;
+
+ clock_GetTime(&when);
+ when.sec += call->conn->secondsUntilPing;
+ call->keepAliveEvent = rxevent_Post(&when, rxi_KeepAliveEvent, call, 0);
+ }
+}
+
+/* N.B. rxi_KeepAliveOff: is defined earlier as a macro */
+void
+rxi_KeepAliveOn(struct rx_call *call)
+{
+
+ /*
+ * Pretend last packet received was received now--i.e. if another packet
+ * isn't received within the keep alive time, then the call will die;
+ * Initialize last send time to the current time--even if a packet hasn't
+ * been sent yet. This will guarantee that a keep-alive is sent within
+ * the ping time
+ */
+ call->lastReceiveTime = call->lastSendTime = clock_Sec();
+ rxi_ScheduleKeepAliveEvent(call);
+}
+
+/*
+ * This routine is called periodically (every RX_AUTH_REQUEST_TIMEOUT
+ * seconds) to ask the client to authenticate itself. The routine
+ * issues a challenge to the client, which is obtained from the
+ * security object associated with the connection
+ */
+void
+rxi_ChallengeEvent(struct rxevent *event, struct rx_connection *conn,
+ char *dummy)
+{
+ conn->challengeEvent = (struct rxevent *) 0;
+ if (RXS_CheckAuthentication(conn->securityObject, conn) != 0) {
+ struct rx_packet *packet;
+ struct clock when;
+
+ packet = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
+ if (!packet)
+ osi_Panic("rxi_ChallengeEvent");
+ RXS_GetChallenge(conn->securityObject, conn, packet);
+ rxi_SendSpecial((struct rx_call *) 0, conn, packet,
+ RX_PACKET_TYPE_CHALLENGE, (char *) 0, -1);
+ rxi_FreePacket(packet);
+ clock_GetTime(&when);
+ when.sec += RX_CHALLENGE_TIMEOUT;
+ conn->challengeEvent = rxevent_Post(&when, rxi_ChallengeEvent,
+ conn, 0);
+ }
+}
+
+/*
+ * Call this routine to start requesting the client to authenticate
+ * itself. This will continue until authentication is established,
+ * the call times out, or an invalid response is returned. The
+ * security object associated with the connection is asked to create
+ * the challenge at this time. N.B. rxi_ChallengeOff is a macro,
+ * defined earlier.
+ */
+void
+rxi_ChallengeOn(struct rx_connection *conn)
+{
+ if (!conn->challengeEvent) {
+ RXS_CreateChallenge(conn->securityObject, conn);
+ rxi_ChallengeEvent((struct rxevent *) 0, conn, 0);
+ };
+}
+
+/*
+ * Called by event.c when a decongestion event (setup by
+ * rxi_CongestionWait) occurs. This adds back in to the burst count
+ * for the specified host the number of packets that were sent at the
+ * time the event was scheduled. It also calls rxi_Start on as many
+ * waiting calls as possible before the burst count goes down to zero,
+ * again.
+ */
+void
+rxi_DecongestionEvent(struct rxevent *event, struct rx_peer *peer,
+ int nPackets)
+{
+ struct rx_call *call;
+ struct rx_call *nxcall; /* Next pointer for queue_Scan */
+
+ peer->refCount--; /* It was bumped by the callee */
+ peer->burst += nPackets;
+ if (peer->burst > peer->burstSize)
+ peer->burst = peer->burstSize;
+ for (queue_Scan(&peer->congestionQueue, call, nxcall, rx_call)) {
+ queue_Remove(call);
+
+ /*
+ * The rxi_Start may put the call back on the congestion queue. In
+ * that case, peer->burst should be 0 (otherwise no congestion was
+ * encountered). It should go on the end of the queue, to allow
+ * other calls to proceed when the next burst is allowed
+ */
+ rxi_Start((struct rxevent *) 0, call);
+ if (!peer->burst)
+ return;
+ }
+}
+
+/*
+ * Schedule an event at a host-dependent time in the future which will
+ * add back nPackets to the current allowed burst window. Any number
+ * of these events may be scheduled.
+ */
+void
+rxi_ScheduleDecongestionEvent(struct rx_call *call, int nPackets)
+{
+ struct rx_peer *peer = call->conn->peer;
+ struct clock tmp;
+
+ clock_GetTime(&tmp);
+ clock_Add(&tmp, &peer->burstWait);
+ peer->refCount++; /* So it won't disappear underneath
+ * us! */
+ /* this is stupid - sending an int as a pointer is begging for trouble */
+ rxevent_Post(&tmp, rxi_DecongestionEvent, (void *) peer, (void *)nPackets);
+}
+
+/*
+ * The caller wishes to have rxi_Start called when the burst count has
+ * gone up, and more packets can therefore be sent. Add the caller to
+ * the end of the list of calls waiting for decongestion events to
+ * happen. It's important that it's added to the end so that the
+ * rxi_DecongestionEvent procedure always terminates (aside from
+ * matters of scheduling fairness).
+ */
+void
+rxi_CongestionWait(struct rx_call *call)
+{
+ if (queue_IsOnQueue(call))
+ return;
+ queue_Append(&call->conn->peer->congestionQueue, call);
+}
+
+/*
+ * Compute round trip time of the packet provided, in *rttp.
+ */
+#ifdef ADAPT_PERF
+#define ADAPT_RTO
+#endif
+
+void
+rxi_ComputeRoundTripTime(struct rx_packet *p,
+ struct clock *sentp,
+ struct rx_peer *peer)
+{
+ struct clock thisRtt, *rttp = &thisRtt;
+
+#ifdef ADAPT_RTO
+ int rtt_timeout;
+ static char id[] = "@(#)adaptive RTO";
+ *id = *id; /* so it won't complain about unsed variables */
+
+ clock_GetTime(rttp);
+ if (clock_Lt(rttp, sentp)) {
+ clock_Zero(rttp);
+ return; /* somebody set the clock back, don't
+ * count this time. */
+ }
+ clock_Sub(rttp, sentp);
+#else
+ clock_GetTime(rttp);
+ clock_Sub(rttp, &p->timeSent);
+#endif
+ if (clock_Lt(rttp, &rx_stats.minRtt))
+ rx_stats.minRtt = *rttp;
+ if (clock_Gt(rttp, &rx_stats.maxRtt)) {
+ if (rttp->sec > 110)
+ return; /* somebody set the clock ahead */
+ rx_stats.maxRtt = *rttp;
+ }
+ clock_Add(&rx_stats.totalRtt, rttp);
+ rx_stats.nRttSamples++;
+
+#ifdef ADAPT_RTO
+ /* better rtt calculation courtesy of UMich crew (dave,larry,peter,???) */
+
+ /* Apply VanJacobson round-trip estimations */
+ if (peer->rtt) {
+ int delta;
+
+ /*
+ * srtt (peer->rtt) is in units of one-eighth-milliseconds.
+ * srtt is stored as fixed point with 3 bits after the binary
+ * point (i.e., scaled by 8). The following magic is
+ * equivalent to the smoothing algorithm in rfc793 with an
+ * alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed point).
+ * srtt*8 = srtt*8 + rtt - srtt
+ * srtt = srtt + rtt/8 - srtt/8
+ */
+
+ delta = MSEC(rttp) - (peer->rtt >> 3);
+ peer->rtt += delta;
+
+ /*
+ * We accumulate a smoothed rtt variance (actually, a smoothed
+ * mean difference), then set the retransmit timer to smoothed
+ * rtt + 4 times the smoothed variance (was 2x in van's original
+ * paper, but 4x works better for me, and apparently for him as
+ * well).
+ * rttvar is stored as
+ * fixed point with 2 bits after the binary point (scaled by
+ * 4). The following is equivalent to rfc793 smoothing with
+ * an alpha of .75 (rttvar = rttvar*3/4 + |delta| / 4). This
+ * replaces rfc793's wired-in beta.
+ * dev*4 = dev*4 + (|actual - expected| - dev)
+ */
+
+ if (delta < 0)
+ delta = -delta;
+
+ delta -= (peer->rtt_dev >> 2);
+ peer->rtt_dev += delta;
+ } else {
+ peer->rtt = MSEC(rttp) << 3;
+ peer->rtt_dev = peer->rtt >> 2;/* rtt/2 */
+ }
+
+ /*
+ * the timeout is RTT + 4*MDEV + 0.4 sec This is because one end or the
+ * other of these connections is usually in a user process, and can be
+ * switched and/or swapped out. So on fast, reliable networks, the
+ * timeout would otherwise be too short.
+ */
+ rtt_timeout = (peer->rtt >> 3) + peer->rtt_dev + 400;
+ clock_Zero(&(peer->timeout));
+ clock_Addmsec(&(peer->timeout), rtt_timeout);
+
+ dpf(("rxi_ComputeRoundTripTime(rtt=%d ms, srtt=%d ms, rtt_dev=%d ms, timeout=%d.%0.3d sec)\n",
+ MSEC(rttp), peer->rtt >> 3, peer->rtt_dev >> 2,
+ (peer->timeout.sec), (peer->timeout.usec)));
+#endif /* ADAPT_RTO */
+}
+
+
+/*
+ * Find all server connections that have not been active for a long time,
+ * and toss them
+ */
+void
+rxi_ReapConnections(void)
+{
+ struct clock now;
+
+ clock_GetTime(&now);
+
+ /*
+ * Find server connection structures that haven't been used for greater
+ * than rx_idleConnectionTime
+ */
+ {
+ struct rx_connection **conn_ptr, **conn_end;
+ int i, havecalls = 0;
+
+ for (conn_ptr = &rx_connHashTable[0],
+ conn_end = &rx_connHashTable[rx_hashTableSize];
+ conn_ptr < conn_end; conn_ptr++) {
+ struct rx_connection *conn, *next;
+
+ for (conn = *conn_ptr; conn; conn = next) {
+ next = conn->next;
+ /* once a minute look at everything to see what's up */
+ havecalls = 0;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ if (conn->call[i]) {
+ havecalls = 1;
+ rxi_CheckCall(conn->call[i]);
+ }
+ }
+ if (conn->type == RX_SERVER_CONNECTION) {
+
+ /*
+ * This only actually destroys the connection if there
+ * are no outstanding calls
+ */
+ if (!havecalls && !conn->refCount &&
+ ((conn->lastSendTime + rx_idleConnectionTime) < now.sec)) {
+ conn->refCount++; /* it will be decr in
+ * rx_DestroyConn */
+ rx_DestroyConnection(conn);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Find any peer structures that haven't been used (haven't had an
+ * associated connection) for greater than rx_idlePeerTime
+ */
+ {
+ struct rx_peer **peer_ptr, **peer_end;
+
+ for (peer_ptr = &rx_peerHashTable[0],
+ peer_end = &rx_peerHashTable[rx_hashTableSize];
+ peer_ptr < peer_end; peer_ptr++) {
+ struct rx_peer *peer, *next;
+
+ for (peer = *peer_ptr; peer; peer = next) {
+ next = peer->next;
+ if (peer->refCount == 0
+ && ((peer->idleWhen + rx_idlePeerTime) < now.sec)) {
+ rxi_DestroyPeer(peer);
+ }
+ }
+ }
+ }
+
+ /*
+ * THIS HACK IS A TEMPORARY HACK. The idea is that the race condition in
+ * rxi_AllocSendPacket, if it hits, will be handled at the next conn GC,
+ * just below. Really, we shouldn't have to keep moving packets from one
+ * place to another, but instead ought to always know if we can afford to
+ * hold onto a packet in its particular use.
+ */
+ MUTEX_ENTER(&rx_waitingForPackets_lock);
+ if (rx_waitingForPackets) {
+ rx_waitingForPackets = 0;
+#ifdef RX_ENABLE_LOCKS
+ cv_signal(&rx_waitingForPackets_cv);
+#else
+ osi_rxWakeup(&rx_waitingForPackets);
+#endif
+ }
+ MUTEX_EXIT(&rx_waitingForPackets_lock);
+
+ now.sec += RX_REAP_TIME; /* Check every RX_REAP_TIME seconds */
+ rxevent_Post(&now, rxi_ReapConnections, 0, 0);
+}
+
+
+/*
+ * rxs_Release - This isn't strictly necessary but, since the macro name from
+ * rx.h is sort of strange this is better. This is called with a security
+ * object before it is discarded. Each connection using a security object has
+ * its own refcount to the object so it won't actually be freed until the last
+ * connection is destroyed.
+ *
+ * This is the only rxs module call. A hold could also be written but no one
+ * needs it.
+ */
+
+int
+rxs_Release(struct rx_securityClass *aobj)
+{
+ return RXS_Close(aobj);
+}
+
+#ifdef ADAPT_WINDOW
+#define RXRATE_PKT_OH (RX_HEADER_SIZE + RX_IPUDP_SIZE)
+#define RXRATE_SMALL_PKT (RXRATE_PKT_OH + sizeof(struct rx_ackPacket))
+#define RXRATE_AVG_SMALL_PKT (RXRATE_PKT_OH + (sizeof(struct rx_ackPacket)/2))
+#define RXRATE_LARGE_PKT (RXRATE_SMALL_PKT + 256)
+
+/*
+ * Adjust our estimate of the transmission rate to this peer, given
+ * that the packet p was just acked. We can adjust peer->timeout and
+ * call->twind (and peer->maxWindow). Pragmatically, this is called
+ * only with packets of maximal length.
+ */
+
+static void
+rxi_ComputeRate(struct rx_peer *peer, struct rx_call *call,
+ struct rx_packet *p, struct rx_packet *ackp, u_char ackReason)
+{
+ long xferSize, xferMs;
+ long minTime;
+ struct clock newTO;
+
+ /* Count down packets */
+ if (peer->rateFlag > 0)
+ peer->rateFlag--;
+ /* Do nothing until we're enabled */
+ if (peer->rateFlag != 0)
+ return;
+ if (!call->conn)
+ return;
+
+ /* Count only when the ack seems legitimate */
+ switch (ackReason) {
+ case RX_ACK_REQUESTED:
+ xferSize = p->length + RX_HEADER_SIZE +
+ call->conn->securityMaxTrailerSize;
+ xferMs = peer->rtt;
+ break;
+
+ case RX_ACK_PING_RESPONSE:
+ if (p) /* want the response to ping-request,
+ * not data send */
+ return;
+ clock_GetTime(&newTO);
+ if (clock_Gt(&newTO, &call->pingRequestTime)) {
+ clock_Sub(&newTO, &call->pingRequestTime);
+ xferMs = (newTO.sec * 1000) + (newTO.usec / 1000);
+ } else {
+ return;
+ }
+ xferSize = rx_AckDataSize(rx_Window) + RX_HEADER_SIZE;
+ break;
+
+ default:
+ return;
+ }
+
+ dpf(("CONG peer %lx/%u: sample (%s) size %ld, %ld ms (to %lu.%06lu, "
+ "rtt %u, win %u, ps %u)",
+ ntohl(peer->host), ntohs(peer->port),
+ (ackReason == RX_ACK_REQUESTED ? "dataack" : "pingack"),
+ xferSize, xferMs, peer->timeout.sec, peer->timeout.usec, peer->smRtt,
+ peer->maxWindow, peer->packetSize));
+
+ /* Track only packets that are big enough. */
+ if ((p->length + RX_HEADER_SIZE + call->conn->securityMaxTrailerSize) <
+ peer->packetSize)
+ return;
+
+ /* absorb RTT data (in milliseconds) for these big packets */
+ if (peer->smRtt == 0) {
+ peer->smRtt = xferMs;
+ } else {
+ peer->smRtt = ((peer->smRtt * 15) + xferMs + 4) >> 4;
+ if (!peer->smRtt)
+ peer->smRtt = 1;
+ }
+
+ if (peer->countDown) {
+ peer->countDown--;
+ return;
+ }
+ peer->countDown = 10; /* recalculate only every so often */
+
+#if 0
+
+ /*
+ * We here assume that we can approximate the total elapsed time for a
+ * window-full of full packets as: time = RTT + ((winSize *
+ * (packetSize+overhead)) - minPktSize) / byteRate
+ */
+ /* The RTT and byteRate numbers are what is measured above. */
+
+ /*
+ * In principle, we can change the other parameters: - winSize, the
+ * number of packets in the transmission window; - packetSize, the max
+ * size of a data packet; - the timeout, which must be larger than the
+ * expected time.
+ */
+
+ /*
+ * In practice, we do this in two steps: (a) ensure that the timeout is
+ * large enough for a single packet to get through; (b) ensure that the
+ * transmit-window is small enough to fit in the timeout.
+ */
+
+ /* First, an expression for the expected RTT for a full packet */
+ minTime = peer->smRtt + ((1000 * (peer->packetSize +
+ RX_HEADER_SIZE + RX_IPUDP_SIZE)) / peer->smBps);
+
+ /* Get a reasonable estimate for a timeout period */
+ minTime += minTime;
+ newTO.sec = minTime / 1000;
+ newTO.usec = (minTime - (newTO.sec * 1000)) * 1000;
+
+ /*
+ * Increase the timeout period so that we can always do at least one
+ * packet exchange
+ */
+ if (clock_Gt(&newTO, &peer->timeout)) {
+
+ dpf(("CONG peer %lx/%u: timeout %lu.%06lu ==> %lu.%06lu "
+ "(rtt %u, win %u, ps %u, Bps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->timeout.sec,
+ peer->timeout.usec, newTO.sec, newTO.usec, peer->smRtt,
+ peer->maxWindow, peer->packetSize, peer->smBps));
+
+ peer->timeout = newTO;
+ }
+ /* Now, get an estimate for the transmit window size. */
+ minTime = peer->timeout.sec * 1000 + (peer->timeout.usec / 1000);
+
+ /*
+ * Now, convert to the number of full packets that could fit in that
+ * interval
+ */
+ minTime = ((((minTime - peer->smRtt) * peer->smBps) / 1000) +
+ RXRATE_AVG_SMALL_PKT) /
+ (peer->packetSize + RX_HEADER_SIZE + RX_IPUDP_SIZE);
+ minTime >>= 1; /* Take half that many */
+ xferSize = minTime; /* (make a copy) */
+
+ /* Now clamp the size to reasonable bounds. */
+ if (minTime <= 1)
+ minTime = 1;
+ else if (minTime > rx_Window)
+ minTime = rx_Window;
+ if (minTime != peer->maxWindow) {
+ dpf(("CONG peer %lx/%u: windowsize %lu ==> %lu (to %lu.%06lu, "
+ "rtt %u, ps %u, Bps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->maxWindow, minTime,
+ peer->timeout.sec, peer->timeout.usec, peer->smRtt,
+ peer->packetSize, peer->smBps));
+
+ peer->maxWindow = minTime;
+ /* call->twind = minTime; */
+ }
+
+ /*
+ * Cut back on the peer timeout if it has grown unreasonably. Discern
+ * this by calculating the timeout necessary for rx_Window packets.
+ */
+ if ((xferSize > rx_Window) && (peer->timeout.sec >= 3)) {
+ /* calculate estimate for transmission interval in milliseconds */
+ minTime = (((1000 * rx_Window *
+ (peer->packetSize + RX_HEADER_SIZE + RX_IPUDP_SIZE))
+ - RXRATE_AVG_SMALL_PKT) / peer->smBps) + peer->smRtt;
+ if (minTime < 1000) {
+
+ dpf(("CONG peer %lx/%u: cut TO %lu.%06lu by 0.5 (rtt %u, "
+ "win %u, ps %u, Bps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->timeout.sec,
+ peer->timeout.usec, peer->smRtt, peer->maxWindow,
+ peer->packetSize, peer->smBps));
+
+ newTO.sec = 0; /* cut back on timeout by half a
+ * second */
+ newTO.usec = 500000;
+ clock_Sub(&peer->timeout, &newTO);
+ }
+ }
+#endif /* 0 */
+
+ /*
+ * In practice, we can measure only the RTT for full packets, because of
+ * the way Rx acks the data that it receives. (If it's smaller than a
+ * full packet, it often gets implicitly acked either by the call
+ * response (from a server) or by the next call (from a client), and
+ * either case confuses transmission times with processing times.)
+ * Therefore, replace the above more-sophisticated processing with a
+ * simpler version, where the smoothed RTT is kept for full-size packets,
+ * and the time to transmit a windowful of full-size packets is simply
+ * RTT * windowSize. Again, we take two steps: - ensure the timeout is
+ * large enough for a single packet's RTT; - ensure that the window is
+ * small enough to fit in the desired timeout.
+ */
+
+ /* First, the timeout check. */
+ minTime = peer->smRtt;
+ /* Get a reasonable estimate for a timeout period */
+ minTime += minTime;
+ newTO.sec = minTime / 1000;
+ newTO.usec = (minTime - (newTO.sec * 1000)) * 1000;
+
+ /*
+ * Increase the timeout period so that we can always do at least one
+ * packet exchange
+ */
+ if (clock_Gt(&newTO, &peer->timeout)) {
+
+ dpf(("CONG peer %lx/%u: timeout %lu.%06lu ==> %lu.%06lu (rtt %u, "
+ "win %u, ps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->timeout.sec,
+ peer->timeout.usec, newTO.sec, newTO.usec, peer->smRtt,
+ peer->maxWindow, peer->packetSize));
+
+ peer->timeout = newTO;
+ }
+ /* Now, get an estimate for the transmit window size. */
+ minTime = peer->timeout.sec * 1000 + (peer->timeout.usec / 1000);
+
+ /*
+ * Now, convert to the number of full packets that could fit in a
+ * reasonable fraction of that interval
+ */
+ minTime /= (peer->smRtt << 1);
+ xferSize = minTime; /* (make a copy) */
+
+ /* Now clamp the size to reasonable bounds. */
+ if (minTime <= 1)
+ minTime = 1;
+ else if (minTime > rx_Window)
+ minTime = rx_Window;
+ if (minTime != peer->maxWindow) {
+ dpf(("CONG peer %lx/%u: windowsize %lu ==> %lu (to %lu.%06lu, "
+ "rtt %u, ps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->maxWindow, minTime,
+ peer->timeout.sec, peer->timeout.usec, peer->smRtt,
+ peer->packetSize));
+ peer->maxWindow = minTime;
+ /* call->twind = minTime; */
+ }
+
+ /*
+ * Cut back on the peer timeout if it had earlier grown unreasonably.
+ * Discern this by calculating the timeout necessary for rx_Window
+ * packets.
+ */
+ if ((xferSize > rx_Window) && (peer->timeout.sec >= 3)) {
+ /* calculate estimate for transmission interval in milliseconds */
+ minTime = rx_Window * peer->smRtt;
+ if (minTime < 1000) {
+ dpf(("CONG peer %lx/%u: cut TO %lu.%06lu by 0.5 (rtt %u, "
+ "win %u, ps %u)",
+ ntohl(peer->host), ntohs(peer->port), peer->timeout.sec,
+ peer->timeout.usec, peer->smRtt, peer->maxWindow,
+ peer->packetSize));
+
+ newTO.sec = 0; /* cut back on timeout by half a
+ * second */
+ newTO.usec = 500000;
+ clock_Sub(&peer->timeout, &newTO);
+ }
+ }
+ return;
+} /* end of rxi_ComputeRate */
+
+#endif /* ADAPT_WINDOW */
+
+
+
+
+
+
+#ifdef RXDEBUG
+/* Don't call this debugging routine directly; use dpf */
+void
+rxi_DebugPrint(const char *fmt, ...)
+{
+ struct clock now;
+ va_list ap;
+
+ clock_GetTime(&now);
+
+ fprintf(Log, " %lu.%.3lu:", now.sec, now.usec / 1000);
+ va_start(ap, fmt);
+ vfprintf(Log, fmt, ap);
+ va_end(ap);
+ putc('\n', Log);
+}
+
+#endif
+
+#if defined(RXDEBUG)
+void
+rx_PrintTheseStats(FILE *file, struct rx_stats *s, int size)
+{
+ int i;
+
+ if (size != sizeof(struct rx_stats))
+ fprintf(file, "Unexpected size of stats structure: was %d, "
+ "expected %d\n",
+ size,
+ (int)sizeof(struct rx_stats));
+
+ fprintf(file,
+ "rx stats: free packets %d, allocs %d, "
+ "alloc-failures(rcv %d,send %d,ack %d)\n", rx_nFreePackets,
+ s->packetRequests, s->noPackets[0], s->noPackets[1],
+ s->noPackets[2]);
+ fprintf(file,
+ " greedy %d, bogusReads %d (last from host %x), "
+ "noPackets %d, noBuffers %d, selects %d, sendSelects %d\n",
+ s->socketGreedy, s->bogusPacketOnRead, s->bogusHost,
+ s->noPacketOnRead, s->noPacketBuffersOnRead, s->selects,
+ s->sendSelects);
+ fprintf(file, " packets read: ");
+ for (i = 0; i < RX_N_PACKET_TYPES; i++)
+ fprintf(file, "%s %d ", rx_packetTypes[i], s->packetsRead[i]);
+
+ fprintf(file, "\n");
+ fprintf(file,
+ " other read counters: data %d, ack %d, dup %d "
+ "spurious %d\n", s->dataPacketsRead, s->ackPacketsRead,
+ s->dupPacketsRead, s->spuriousPacketsRead);
+ fprintf(file, " packets sent: ");
+ for (i = 0; i < RX_N_PACKET_TYPES; i++)
+ fprintf(file, "%s %d ", rx_packetTypes[i], s->packetsSent[i]);
+ fprintf(file, "\n");
+ fprintf(file,
+ " other send counters: ack %d, data %d (not resends), "
+ "resends %d, pushed %d, acked&ignored %d\n", s->ackPacketsSent,
+ s->dataPacketsSent, s->dataPacketsReSent, s->dataPacketsPushed,
+ s->ignoreAckedPacket);
+ fprintf(file,
+ " \t(these should be small) sendFailed %d, "
+ "fatalErrors %ld\n",
+ s->netSendFailures, s->fatalErrors);
+ if (s->nRttSamples) {
+ fprintf(file, " Average rtt is %0.3f, with %d samples\n",
+ clock_Float(&s->totalRtt) / s->nRttSamples, s->nRttSamples);
+
+ fprintf(file, " Minimum rtt is %0.3f, maximum is %0.3f\n",
+ clock_Float(&s->minRtt), clock_Float(&s->maxRtt));
+ }
+ fprintf(file,
+ " %d server connections, %d client connections, %d "
+ "peer structs, %d call structs, %d free call structs\n",
+ s->nServerConns, s->nClientConns, s->nPeerStructs,
+ s->nCallStructs, s->nFreeCallStructs);
+ fprintf(file, " %d clock updates\n", clock_nUpdates);
+}
+
+/* for backward compatibility */
+void
+rx_PrintStats(FILE *file)
+{
+ rx_PrintTheseStats(file, &rx_stats, sizeof(rx_stats));
+}
+
+void
+rx_PrintPeerStats(FILE *file, struct rx_peer *peer)
+{
+ fprintf(file, "Peer %lx.%d. Burst size %d, burst wait %lu.%ld.\n",
+ (unsigned long)ntohl(peer->host),
+ peer->port,
+ peer->burstSize,
+ (unsigned long)peer->burstWait.sec,
+ (unsigned long)peer->burstWait.usec);
+ fprintf(file, " Rtt %d, retry time %lu.%06ld, total sent %d, resent %d\n",
+ peer->rtt,
+ (unsigned long)peer->timeout.sec,
+ (long)peer->timeout.usec,
+ peer->nSent,
+ peer->reSends);
+ fprintf(file,
+ " Packet size %d, max in packet skew %ld, max out packet "
+ "skew %ld\n", peer->packetSize, peer->inPacketSkew,
+ peer->outPacketSkew);
+}
+
+#endif /* RXDEBUG */
+
+void
+shutdown_rx(void)
+{
+ struct rx_serverQueueEntry *np;
+ int i, j;
+
+ rxinit_status = 0;
+ {
+ struct rx_peer **peer_ptr, **peer_end;
+
+ for (peer_ptr = &rx_peerHashTable[0],
+ peer_end = &rx_peerHashTable[rx_hashTableSize];
+ peer_ptr < peer_end; peer_ptr++) {
+ struct rx_peer *peer, *next;
+
+ for (peer = *peer_ptr; peer; peer = next) {
+ next = peer->next;
+ rxi_DestroyPeer(peer);
+ }
+ }
+ }
+ for (i = 0; i < RX_MAX_SERVICES; i++) {
+ if (rx_services[i])
+ rxi_Free(rx_services[i], sizeof(*rx_services));
+ }
+ for (i = 0; i < rx_hashTableSize; i++) {
+ struct rx_connection *tc, *ntc;
+
+ for (tc = rx_connHashTable[i]; tc; tc = ntc) {
+ ntc = tc->next;
+ for (j = 0; j < RX_MAXCALLS; j++) {
+ if (tc->call[j]) {
+ rxi_Free(tc->call[j], sizeof(*(tc->call)));
+ }
+ }
+ rxi_Free(tc, sizeof(tc));
+ }
+ }
+
+ MUTEX_ENTER(&freeSQEList_lock);
+
+ while ((np = rx_FreeSQEList) != NULL) {
+ rx_FreeSQEList = *(struct rx_serverQueueEntry **) np;
+ MUTEX_DESTROY(&np->lock);
+ rxi_Free(np, sizeof(np));
+ }
+
+ MUTEX_EXIT(&freeSQEList_lock);
+ MUTEX_DESTROY(&freeSQEList_lock);
+ MUTEX_DESTROY(&rx_waitingForPackets_lock);
+ MUTEX_DESTROY(&rx_freeCallQueue_lock);
+
+ osi_Free(rx_connHashTable,
+ rx_hashTableSize * sizeof(struct rx_connection *));
+ osi_Free(rx_peerHashTable, rx_hashTableSize * sizeof(struct rx_peer *));
+ osi_Free(rx_allocedP, sizeof(struct rx_packet) * rx_nPackets);
+
+ UNPIN(rx_connHashTable, rx_hashTableSize * sizeof(struct rx_connection *));
+ UNPIN(rx_peerHashTable, rx_hashTableSize * sizeof(struct rx_peer *));
+ UNPIN(rx_allocedP, sizeof(struct rx_packet) * rx_nPackets);
+
+ rxi_FreeAllPackets();
+
+ rxi_dataQuota = RX_MAX_QUOTA;
+ rxi_availProcs = rxi_totalMin = rxi_minDeficit = 0;
+}
diff --git a/usr.sbin/afs/src/rx/rx.h b/usr.sbin/afs/src/rx/rx.h
new file mode 100644
index 00000000000..bb46a439744
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx.h
@@ -0,0 +1,1065 @@
+/* $OpenBSD: rx.h,v 1.1.1.1 1998/09/14 21:53:14 art Exp $ */
+/* $KTH: rx.h,v 1.8 1998/03/01 15:26:57 assar Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#ifndef _RX_
+#define _RX_
+
+#ifdef KERNEL
+#include "../rx/rx_machdep.h"
+#include "../rx/rx_kernel.h"
+#include "../rx/rx_clock.h"
+#include "../rx/rx_event.h"
+#include "../rx/rx_queue.h"
+#include "../rx/rx_packet.h"
+#else /* KERNEL */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <atypes.h>
+#include <stdio.h>
+#include "rx_mach.h"
+#include "rx_user.h"
+#include "rx_clock.h"
+#include "rx_event.h"
+#include "rx_pkt.h"
+#endif /* KERNEL */
+
+
+/* Configurable parameters */
+#define RX_IDLE_DEAD_TIME 60 /* default idle dead time */
+#define RX_MAX_SERVICES 20 /* Maximum number of services that may
+ * be installed */
+#define RX_DEFAULT_STACK_SIZE 16000 /* Default process stack size;
+ * overriden by rx_SetStackSize */
+
+/* This parameter should not normally be changed */
+#define RX_PROCESS_PRIORITY LWP_NORMAL_PRIORITY
+
+/* backoff is fixed point binary. Ie, units of 1/4 seconds */
+#define MAXBACKOFF 0x1F
+
+struct rx_securityClass;
+
+/* Exported interfaces XXXX clean this up: not all of these are exported */
+int rx_Init(u_short);
+struct rx_service *rx_NewService(u_short, u_short, char *,
+ struct rx_securityClass **, int, long (*)());
+struct rx_connection *rx_NewConnection(register u_long, u_short, u_short,
+ register struct rx_securityClass *,
+ int);
+struct rx_call *rx_NewCall();
+struct rx_call *rx_GetCall(); /* Not normally used, but not obsolete */
+long rx_EndCall();
+int rx_AllocPackets();
+void rx_FreePackets();
+int rx_WriteProc();
+int rx_ReadProc();
+void rx_FlushWrite();
+#ifdef RXDEBUG
+void rx_PrintStats();
+#else
+#define rx_PrintStats(a)
+#endif
+void rx_PrintPeerStats();
+void rx_SetArrivalProc();
+void rx_Finalize();
+void rx_StartServer(int);
+void rx_DestroyConnection(struct rx_connection *);
+void rxi_Free(void *, register int);
+int rxi_GetCallNumberVector(const struct rx_connection *, int32_t *);
+int rxi_SetCallNumberVector(struct rx_connection *, int32_t *);
+void rx_SetEpoch(u_long);
+
+#define RX_WAIT 1
+#define RX_DONTWAIT 0
+
+#define rx_ConnectionOf(call) ((call)->conn)
+#define rx_PeerOf(conn) ((conn)->peer)
+#define rx_HostOf(peer) ((peer)->host)
+#define rx_PortOf(peer) ((peer)->port)
+#define rx_SetLocalStatus(call, status) ((call)->localStatus = (status))
+#define rx_GetLocalStatus(call, status) ((call)->localStatus)
+#define rx_GetRemoteStatus(call) ((call)->remoteStatus)
+#define rx_Error(call) ((call)->error)
+#define rx_ConnError(conn) ((conn)->error)
+#define rx_IsServerConn(conn) ((conn)->type == RX_SERVER_CONNECTION)
+#define rx_IsClientConn(conn) ((conn)->type == RX_CLIENT_CONNECTION)
+/* Don't use these; use the IsServerConn style */
+#define rx_ServerConn(conn) ((conn)->type == RX_SERVER_CONNECTION)
+#define rx_ClientConn(conn) ((conn)->type == RX_CLIENT_CONNECTION)
+#define rx_IsUsingPktCksum(conn) ((conn)->flags & \
+ RX_CONN_USING_PACKET_CKSUM)
+
+/*
+ * Set and get rock is applicable to both connections and calls.
+ * It's used by multi rx macros for calls.
+ */
+#define rx_SetRock(obj, newrock) ((obj)->rock = (void *)(newrock))
+#define rx_GetRock(obj, type) ((type)(obj)->rock)
+#define rx_ServiceIdOf(conn) ((conn)->serviceId)
+#define rx_SecurityClassOf(conn) ((conn)->securityIndex)
+#define rx_SecurityObjectOf(conn) ((conn)->securityObject)
+
+/*
+ * Macros callable by the user to further define attributes of a
+ * service. Must be called before rx_StartServer
+ */
+
+/*
+ * Set the service stack size. This currently just sets the stack
+ * size for all processes to be the maximum seen, so far
+ */
+#define rx_SetStackSize(service, stackSize) \
+ rx_stackSize = (((stackSize) > rx_stackSize)? stackSize: rx_stackSize)
+
+/*
+ * Set minimum number of processes guaranteed to be available for this
+ * service at all times
+ */
+#define rx_SetMinProcs(service, min) ((service)->minProcs = (min))
+
+/*
+ * Set maximum number of processes that will be made available to this
+ * service (also a guarantee that this number will be made available
+ * if there is no competition)
+ */
+#define rx_SetMaxProcs(service, max) ((service)->maxProcs = (max))
+
+/*
+ * Define a procedure to be called just before a server connection is
+ * destroyed
+ */
+#define rx_SetDestroyConnProc(service,proc) ((service)->destroyConnProc = (proc))
+
+/* Define procedure to set service dead time */
+#define rx_SetIdleDeadTime(service,time) ((service)->idleDeadTime = (time))
+
+/*
+ * Define procedures for getting and setting before and after execute-request
+ * procs
+ */
+#define rx_SetAfterProc(service,proc) ((service)->afterProc = (proc))
+#define rx_SetBeforeProc(service,proc) ((service)->beforeProc = (proc))
+#define rx_GetAfterProc(service) ((service)->afterProc)
+#define rx_GetBeforeProc(service) ((service)->beforeProc)
+
+/* Define a procedure to be called when a server connection is created */
+#define rx_SetNewConnProc(service, proc) ((service)->newConnProc = (proc))
+
+/*
+ * NOTE: We'll probably redefine the following three routines, again,
+ * sometime.
+ */
+
+/*
+ * Set the connection dead time for any connections created for this service
+ * (server only)
+ */
+#define rx_SetServiceDeadTime(service, seconds) ((service)->secondsUntilDead = (seconds))
+
+/* Set connection dead time, for a specific client or server connection */
+#define rx_SetConnDeadTime(conn, seconds) (rxi_SetConnDeadTime(conn, seconds))
+extern void rxi_SetConnDeadTime();
+
+/* Set connection hard timeout for a connection */
+#define rx_SetConnHardDeadTime(conn, seconds) ((conn)->hardDeadTime = (seconds))
+
+/*
+ * Set rx default connection dead time; set on both services and
+ * connections at creation time
+ */
+extern int rx_connDeadTime;
+
+#define rx_SetRxDeadTime(seconds) (rx_connDeadTime = (seconds))
+
+extern int rx_nPackets;
+
+#define cpspace(call) \
+ ((call)->currentPacket->wirevec[(call)->curvec].iov_len - (call)->curpos)
+#define cppos(call) \
+ ((call)->currentPacket->wirevec[(call)->curvec].iov_base + (call)->curpos)
+
+#ifndef AFS_SGIMP_ENV
+/* Write nbytes of data to the call. Returns the number of bytes written */
+/* If it returns 0, the call status should be checked with rx_Error. */
+#define rx_Write(call, buf, nbytes) rx_WriteProc((call), (buf), (nbytes))
+/* this shortcut is a good idea, but I don't trust it right now MTUXXX
+ (((call)->nFree > (nbytes)) && (cpspace(call) > (nbytes)) ? \
+ memcpy(cppos(call), (buf), (nbytes)), \
+ (call)->nFree -= (nbytes), \
+ (call)->currentPacket->wirevec[(call)->curvec].iov_base += (nbytes), \
+ (call)->curpos += (nbytes), \
+ (nbytes) \
+ : rx_WriteProc((call), (buf), (nbytes)))
+*/
+
+/*
+ * Read nbytes of data from the call. Returns the number of bytes read
+ */
+/*
+ * If it returns less than requested, the call status should be checked
+ * with rx_Error
+ */
+#define rx_Read(call, buf, nbytes) rx_ReadProc((call), (buf), (nbytes))
+/* this shortcut is a good idea, but I don't trust it right now MTUXXX
+ (((call)->nLeft > (nbytes)) && (cpspace(call) > (nbytes)) ? \
+ memcpy((buf), cppos(call), (nbytes)), \
+ (call)->nLeft -= (nbytes), \
+ (call)->currentPacket->wirevec[(call)->curvec].iov_base += (nbytes), \
+ (call)->curpos += (nbytes), \
+ (nbytes) \
+ : rx_ReadProc((call), (buf), (nbytes)))
+*/
+#endif /* AFS_SGIMP_ENV */
+
+/*
+ * This is the maximum size data packet that can be sent on this connection,
+ * accounting for security module-specific overheads.
+ */
+#define rx_MaxUserDataSize(conn) ((conn)->maxPacketSize - \
+ RX_HEADER_SIZE - \
+ (conn)->securityHeaderSize - \
+ (conn)->securityMaxTrailerSize)
+
+struct rx_securityObjectStats {
+ char type; /* 0:unk 1:null,2:vab 3:kad */
+ char level;
+ char sparec[10]; /* force correct alignment */
+ long flags; /* 1=>unalloc, 2=>auth, 4=>expired */
+ u_long expires;
+ u_long packetsReceived;
+ u_long packetsSent;
+ u_long bytesReceived;
+ u_long bytesSent;
+ short spares[4];
+ long sparel[8];
+};
+
+/*
+ * XXXX (rewrite this description) A security class object contains a set of
+ * procedures and some private data to implement a security model for rx
+ * connections. These routines are called by rx as appropriate. Rx knows
+ * nothing about the internal details of any particular security model, or
+ * about security state. Rx does maintain state per connection on behalf of
+ * the security class. Each security class implementation is also expected to
+ * provide routines to create these objects. Rx provides a basic routine to
+ * allocate one of these objects; this routine must be called by the class.
+ */
+struct rx_securityClass {
+ struct rx_securityOps {
+ int (*op_Close) ( /* obj */ );
+ int (*op_NewConnection) ( /* obj, conn */ );
+ int (*op_PreparePacket) ( /* obj, call, packet */ );
+ int (*op_SendPacket) ( /* obj, call, packet */ );
+ int (*op_CheckAuthentication) ( /* obj,conn */ );
+ int (*op_CreateChallenge) ( /* obj,conn */ );
+ int (*op_GetChallenge) ( /* obj,conn,packet */ );
+ int (*op_GetResponse) ( /* obj,conn,packet */ );
+ int (*op_CheckResponse) ( /* obj,conn,packet */ );
+ int (*op_CheckPacket) ( /* obj,call,packet */ );
+ int (*op_DestroyConnection) ( /* obj, conn */ );
+ int (*op_GetStats) ( /* obj, conn, stats */ );
+ int (*op_Spare1) ();
+ int (*op_Spare2) ();
+ int (*op_Spare3) ();
+ } *ops;
+ void *privateData;
+ int refCount;
+};
+
+#if defined(__STDC__) && !defined(__HIGHC__)
+#define RXS_OP(obj,op,args) ((obj->ops->op_ ## op) ? \
+ (*(obj)->ops->op_ ## op)args : 0)
+#else
+#define RXS_OP(obj,op,args) ((obj->ops->op_/**/op) ? \
+ (*(obj)->ops->op_/**/op)args : 0)
+#endif
+
+#define RXS_Close(obj) RXS_OP(obj,Close,(obj))
+#define RXS_NewConnection(obj,conn) RXS_OP(obj,NewConnection,(obj,conn))
+#define RXS_PreparePacket(obj,call,packet) RXS_OP(obj,PreparePacket,\
+ (obj,call,packet))
+#define RXS_SendPacket(obj,call,packet) RXS_OP(obj,SendPacket,\
+ (obj,call,packet))
+#define RXS_CheckAuthentication(obj,conn) RXS_OP(obj,CheckAuthentication,\
+ (obj,conn))
+#define RXS_CreateChallenge(obj,conn) RXS_OP(obj,CreateChallenge,\
+ (obj,conn))
+#define RXS_GetChallenge(obj,conn,packet) RXS_OP(obj,GetChallenge,\
+ (obj,conn,packet))
+#define RXS_GetResponse(obj,conn,packet) RXS_OP(obj,GetResponse,\
+ (obj,conn,packet))
+#define RXS_CheckResponse(obj,conn,packet) RXS_OP(obj,CheckResponse,\
+ (obj,conn,packet))
+#define RXS_CheckPacket(obj,call,packet) RXS_OP(obj,CheckPacket,\
+ (obj,call,packet))
+#define RXS_DestroyConnection(obj,conn) RXS_OP(obj,DestroyConnection,\
+ (obj,conn))
+#define RXS_GetStats(obj,conn,stats) RXS_OP(obj,GetStats,\
+ (obj,conn,stats))
+
+/*
+ * A service is installed by rx_NewService, and specifies a service type that
+ * is exported by this process. Incoming calls are stamped with the service
+ * type, and must match an installed service for the call to be accepted.
+ * Each service exported has a (port,serviceId) pair to uniquely identify it.
+ * It is also named: this is intended to allow a remote statistics gathering
+ * program to retrieve per service statistics without having to know the local
+ * service id's. Each service has a number of security objects (instances of
+ * security classes) which implement various types of end-to-end security
+ * protocols for connections made to this service. Finally, there are two
+ * parameters controlling the number of requests which may be executed in
+ * parallel by this service: minProcs is the number of requests to this
+ * service which are guaranteed to be able to run in parallel at any time;
+ * maxProcs has two meanings: it limits the total number of requests which may
+ * execute in parallel and it also guarantees that that many requests
+ * may be handled in parallel if no other service is handling any
+ * requests.
+ */
+
+struct rx_service {
+ u_short serviceId; /* Service number */
+ u_short servicePort; /* UDP port for this service */
+ char *serviceName; /* Name of the service */
+ osi_socket socket; /* socket struct or file descriptor */
+ u_short nRequestsRunning; /*
+ * Number of requests currently in
+ * progress
+ */
+ u_short nSecurityObjects; /* Number of entries in security
+ * objects array */
+ struct rx_securityClass **securityObjects; /*
+ * Array of security class
+ * objects
+ */
+ long (*executeRequestProc) (); /* Routine to call when an rpc request
+ * is received */
+ void (*destroyConnProc) (); /* Routine to call when a server
+ * connection is destroyed */
+ void (*newConnProc) (); /*
+ * Routine to call when a server
+ * connection is created
+ */
+ void (*beforeProc) (); /* routine to call before a call is
+ * executed */
+ void (*afterProc) (); /* routine to call after a call is
+ * executed */
+ u_short maxProcs; /* Maximum procs to be used for this
+ * service */
+ u_short minProcs; /* Minimum # of requests guaranteed
+ * executable simultaneously */
+ u_short connDeadTime; /*
+ * Secs until a client of this service
+ * will be declared dead, if it is not
+ * responding
+ */
+ u_short idleDeadTime; /*
+ * Time a server will wait for I/O to
+ * start up again
+ */
+};
+
+/*
+ * A server puts itself on an idle queue for a service using an
+ * instance of the following structure. When a call arrives, the call
+ * structure pointer is placed in "newcall", the routine to execute to
+ * service the request is placed in executeRequestProc, and the
+ * process is woken up. The queue entry's address is used for the
+ * sleep/wakeup.
+ */
+struct rx_serverQueueEntry {
+ struct rx_queue queueItemHeader;
+ struct rx_call *newcall;
+#ifdef RX_ENABLE_LOCKS
+ kmutex_t lock;
+ kcondvar_t cv;
+#endif
+};
+
+/* Bottom n-bits of the Call Identifier give the call number */
+#define RX_MAXCALLS 4 /* Power of 2; max async calls per
+ * connection */
+#define RX_CIDSHIFT 2 /* Log2(RX_MAXCALLS) */
+#define RX_CHANNELMASK (RX_MAXCALLS-1)
+#define RX_CIDMASK (~RX_CHANNELMASK)
+
+/*
+ * A peer refers to a peer process, specified by a (host,port) pair.
+ * There may be more than one peer on a given host.
+ */
+struct rx_peer {
+ struct rx_peer *next; /* Next in hash conflict or free list */
+ u_long host; /* Remote IP address, in net byte
+ * order */
+ u_short port; /* Remote UDP port, in net byte order */
+ u_short packetSize; /*
+ * Max packet size, if known, for this
+ * host
+ */
+
+ /* For garbage collection */
+ u_long idleWhen; /* When the refcountwent to zero */
+ short refCount; /* Reference count for this structure */
+
+ /* Congestion control parameters */
+ u_char burstSize; /*
+ * Reinitialization size for the burst
+ * parameter
+ */
+ u_char burst; /* Number of packets that can be
+ * transmitted right now, without
+ * pausing */
+ struct clock burstWait; /* Delay until new burst is allowed */
+ struct rx_queue congestionQueue; /*
+ * Calls that are waiting for non-zero
+ * burst value
+ */
+ int rtt; /*
+ * Round trip time, measured in
+ * milliseconds/8
+ */
+ int rtt_dev; /* rtt smoothed error, in
+ * milliseconds/4 */
+ struct clock timeout; /* Current retransmission delay */
+ int nSent; /*
+ * Total number of distinct data packets
+ * sent, not including retransmissions
+ */
+ int reSends; /*
+ * Total number of retransmissions for
+ * this peer, since this structure was
+ * created
+ */
+
+/*
+ * Skew: if a packet is received N packets later than expected (based
+ * on packet serial numbers), then we define it to have a skew of N.
+ * The maximum skew values allow us to decide when a packet hasn't
+ * been received yet because it is out-of-order, as opposed to when it
+ * is likely to have been dropped.
+ */
+ u_long inPacketSkew; /* Maximum skew on incoming packets */
+ u_long outPacketSkew; /* Peer-reported max skew on our sent
+ * packets */
+ int rateFlag; /* Flag for rate testing (-no 0yes
+ * +decrement) */
+ u_short maxWindow; /* Maximum window size (number of
+ * packets) */
+ u_short spare; /*
+ * we have to manually align things
+ * b/c 220s crash
+ */
+};
+
+/*
+ * A connection is an authenticated communication path, allowing
+ * limited multiple asynchronous conversations.
+ */
+struct rx_connection {
+ struct rx_connection *next; /* on hash chain _or_ free list */
+ struct rx_peer *peer;
+#ifdef RX_ENABLE_LOCKS
+ kmutex_t lock;
+ kcondvar_t cv;
+#endif
+ u_int32_t epoch; /* Process start time of client side
+ * of connection */
+ u_int32_t cid; /* Connection id (call channel is
+ * bottom bits) */
+ long error; /* If this connection is in error,
+ * this is it */
+ void *rock; /* User definable */
+ struct rx_call *call[RX_MAXCALLS];
+ u_int32_t callNumber[RX_MAXCALLS]; /* Current call numbers */
+ u_int32_t serial; /* Next outgoing packet serial number */
+ u_int32_t lastSerial; /* # of last packet received, for
+ * computing skew */
+ long maxSerial; /* largest serial number seen on
+ * incoming packets */
+ long maxPacketSize; /*
+ * max packet size should be
+ * per-connection since peer process
+ * could be restarted on us.
+ */
+ struct rxevent *challengeEvent; /* Scheduled when the server is
+ * challenging a client-- to
+ * retransmit the challenge */
+ struct rx_service *service; /* used by servers only */
+ u_short serviceId; /* To stamp on requests, clients only */
+ short refCount; /* Reference count */
+ u_char flags; /* Defined below */
+ u_char type; /* Type of connection, defined below */
+ u_char secondsUntilPing; /* how often to ping for each active
+ * call */
+ u_char securityIndex; /* corresponds to the security class
+ * of the */
+ /* securityObject for this conn */
+ struct rx_securityClass *securityObject; /*
+ * Security object for this
+ * connection
+ */
+ void *securityData; /* Private data for this conn's
+ * security class */
+ u_short securityHeaderSize; /*
+ * Length of security module's packet
+ * header data
+ */
+ u_short securityMaxTrailerSize; /*
+ * Length of security module's packet
+ * trailer data
+ */
+ int timeout; /*
+ * Overall timeout per call (seconds)
+ * for this conn
+ */
+ int lastSendTime; /* Last send time for this connection */
+ u_short secondsUntilDead; /*
+ * Maximum silence from peer before
+ * RX_CALL_DEAD
+ */
+ u_short hardDeadTime; /* hard max for call execution */
+};
+
+/* Flag bits for connection structure */
+#define RX_CONN_MAKECALL_WAITING 1 /* rx_MakeCall is waiting for a
+ * channel */
+#define RX_CONN_DESTROY_ME 2 /*
+ * Destroy *client* connection after
+ * last call
+ */
+#define RX_CONN_USING_PACKET_CKSUM 4 /* non-zero header.spare field seen */
+#define RX_CONN_BIG_ONES 8 /*
+ * may use packets > 1500 bytes
+ * (compatibility)
+ */
+
+
+/* Type of connection, client or server */
+#define RX_CLIENT_CONNECTION 0
+#define RX_SERVER_CONNECTION 1
+
+/*
+ * Call structure: only instantiated for active calls and dallying server
+ * calls. The permanent call state (i.e. the call number as well as state
+ * shared with other calls associated with this connection) is maintained
+ * in the connection structure.
+ */
+struct rx_call {
+ struct rx_queue queue_item_header; /*
+ * Call can be on various queues
+ * (one-at-a-time)
+ */
+ struct rx_queue tq; /* Transmit packet queue */
+ struct rx_queue rq; /* Receive packet queue */
+#ifdef RX_ENABLE_LOCKS
+ kmutex_t lock;
+ kmutex_t lockw;
+ kcondvar_t cv_twind;
+ kmutex_t lockq;
+ kcondvar_t cv_rq;
+#endif
+ struct rx_connection *conn; /* Parent connection for this call */
+ u_int32_t *callNumber; /*
+ * Pointer to call number field
+ * within connection
+ */
+#if 0
+ char *bufPtr; /*
+ * Next byte to fill or read in current
+ * send/read packet
+ */
+#endif
+ u_short nLeft; /*
+ * Number of bytes left in first receive
+ * queue packet
+ */
+ struct rx_packet *currentPacket; /*
+ * Current packet being assembled or
+ * being read
+ */
+ u_short curvec; /* current iovec in currentPacket */
+ u_short curpos; /* current position within curvec */
+ u_short nFree; /* Number of bytes free in last send
+ * packet */
+ u_char channel; /* Index of call, within connection */
+ u_char state; /* Current call state as defined below */
+ u_char mode; /* Current mode of a call in ACTIVE
+ * state */
+ u_char flags; /* Some random flags */
+ u_char localStatus; /* Local user status sent out of band */
+ u_char remoteStatus; /* Remote user status received out of
+ * band */
+ long error; /* Error condition for this call */
+ u_long timeout; /* High level timeout for this call */
+ u_long rnext; /*
+ * Next sequence number expected to be
+ * read by rx_ReadData
+ */
+ u_long rprev; /*
+ * Previous packet received; used for
+ * deciding what the next packet to be
+ * received should be in order to decide
+ * whether a negative acknowledge should
+ * be sent
+ */
+ u_long rwind; /*
+ * The receive window: the peer must
+ * not send packets with sequence
+ * numbers >= rnext+rwind
+ */
+ u_long tfirst; /*
+ * First unacknowledged transmit packet
+ * number
+ */
+ u_long tnext; /* Next transmit sequence number to
+ * use */
+ u_long twind; /*
+ * The transmit window: we cannot
+ * assign a sequence number to a
+ * packet >= tfirst + twind
+ */
+ struct rxevent *resendEvent; /*
+ * If this is non-Null, there is a
+ * retransmission event pending
+ */
+ struct rxevent *timeoutEvent; /*
+ * If this is non-Null, then there is an
+ * overall timeout for this call
+ */
+ struct rxevent *keepAliveEvent; /*
+ * Scheduled periodically in active
+ * calls to keep call alive
+ */
+ struct rxevent *delayedAckEvent; /*
+ * Scheduled after all packets are
+ * received to send an ack if a reply
+ * or new call is not generated soon
+ */
+ int lastSendTime; /* Last time a packet was sent on this
+ * call */
+ int lastReceiveTime; /* Last time a packet was received for
+ * this call */
+ void (*arrivalProc) (); /* Procedure to call when reply is
+ * received */
+ void *arrivalProcHandle; /* Handle to pass to replyFunc */
+ void *arrivalProcArg; /* Additional arg to pass to reply
+ * Proc */
+ u_long lastAcked; /* last packet "hard" acked by
+ * receiver */
+ u_long startTime; /* time the call started running */
+ u_long startWait; /*
+ * time server began waiting for
+ * input data/send quota
+ */
+ struct clock traceWait; /*
+ * time server began waiting for input
+ * data/send quota
+ */
+ struct clock traceStart; /* time the call started running */
+};
+
+/* Major call states */
+#define RX_STATE_NOTINIT 0 /* Call structure has never been
+ * initialized */
+#define RX_STATE_PRECALL 1 /*
+ * Server-only: call is not in
+ * progress, but packets have arrived
+ */
+#define RX_STATE_ACTIVE 2 /*
+ * An active call; a process is dealing
+ * with this call
+ */
+#define RX_STATE_DALLY 3 /* Dallying after process is done with
+ * call */
+
+/*
+ * Call modes: the modes of a call in RX_STATE_ACTIVE state (process attached)
+ */
+#define RX_MODE_SENDING 1 /* Sending or ready to send */
+#define RX_MODE_RECEIVING 2 /* Receiving or ready to receive */
+#define RX_MODE_ERROR 3 /* Something in error for current
+ * conversation */
+#define RX_MODE_EOF 4 /*
+ * Server has flushed (or client has
+ * read) last reply packet
+ */
+
+/* Flags */
+#define RX_CALL_READER_WAIT 1 /* Reader is waiting for next packet */
+#define RX_CALL_WAIT_WINDOW_ALLOC 2 /*
+ * Sender is waiting for window to
+ * allocate buffers
+ */
+#define RX_CALL_WAIT_WINDOW_SEND 4 /*
+ * Sender is waiting for window to
+ * send buffers
+ */
+#define RX_CALL_WAIT_PACKETS 8 /*
+ * Sender is waiting for packet buffers
+ */
+#define RX_CALL_WAIT_PROC 16 /*
+ * Waiting for a process to be assigned
+ */
+#define RX_CALL_RECEIVE_DONE 32 /* All packets received on this call */
+#define RX_CALL_CLEARED 64 /*
+ * Receive queue cleared in precall
+ * state
+ */
+#define RX_CALL_TQ_BUSY 128 /*
+ * Call's Xmit Queue is busy;
+ * don't modify
+ */
+
+/* Maximum number of acknowledgements in an acknowledge packet */
+#define RX_MAXACKS 255
+
+/*
+ * The structure of the data portion of an acknowledge packet: An acknowledge
+ * packet is in network byte order at all times. An acknowledgement is always
+ * prompted for a specific reason by a specific incoming packet. This reason
+ * is reported in "reason" and the packet's sequence number in the packet
+ * header.seq. In addition to this information, all of the current
+ * acknowledgement information about this call is placed in the packet.
+ * "FirstPacket" is the sequence number of the first packet represented in an
+ * array of bytes, "acks", containing acknowledgement information for a number
+ * of consecutive packets. All packets prior to FirstPacket are implicitly
+ * acknowledged: the sender need no longer be concerned about them. Packets
+ * from firstPacket+nAcks and on are not acknowledged. Packets in the range
+ * [firstPacket,firstPacket+nAcks) are each acknowledged explicitly. The
+ * acknowledgement may be RX_NACK if the packet is not (currently) at the
+ * receiver (it may have never been received, or received and then later
+ * dropped), or it may be RX_ACK if the packet is queued up waiting to be read
+ * by the upper level software. RX_ACK does not imply that the packet may not
+ * be dropped before it is read; it does imply that the sender should stop
+ * retransmitting the packet until notified otherwise. The field
+ * previousPacket identifies the previous packet received by the peer. This
+ * was used in a previous version of this software, and could be used in the
+ * future. The serial number in the data part of the ack packet corresponds to
+ * the serial number oof the packet which prompted the acknowledge. Any
+ * packets which are explicitly not acknowledged, and which were last
+ * transmitted with a serial number less than the provided serial number,
+ * should be retransmitted immediately. Actually, this is slightly inaccurate:
+ * packets are not necessarily received in order. When packets are habitually
+ * transmitted out of order, this is allowed for in the retransmission
+ * algorithm by introducing the notion of maximum packet skew: the degree of
+ * out-of-orderness of the packets received on the wire. This number is
+ * communicated from the receiver to the sender in ack packets.
+ */
+
+struct rx_ackPacket {
+ u_short bufferSpace; /*
+ * Number of packet buffers available.
+ * That is: the number of buffers that
+ * the sender of the ack packet is
+ * willing to provide for data,
+ * on this or subsequent calls. Lying is
+ * permissable.
+ */
+ u_short maxSkew; /*
+ * Maximum difference between serial# of
+ * packet acknowledged and highest
+ * packet yet received
+ */
+ u_long firstPacket; /*
+ * The first packet in the list of
+ * acknowledged packets
+ */
+ u_long previousPacket; /*
+ * The previous packet number received
+ * (obsolete?)
+ */
+ u_long serial; /*
+ * Serial number of the packet which
+ * prompted the acknowledge
+ */
+ u_char reason; /*
+ * Reason for the acknowledge of
+ * ackPacket, defined below
+ */
+ u_char nAcks; /* Number of acknowledgements */
+ u_char acks[RX_MAXACKS]; /*
+ * Up to RX_MAXACKS packet ack's,
+ * defined below
+ */
+ /*
+ * Packets <firstPacket are implicitly acknowledged and may be discarded
+ * by the sender. Packets >= firstPacket+nAcks are implicitly NOT
+ * acknowledged. No packets with sequence numbers >= firstPacket should
+ * be discarded by the sender (they may thrown out at any time by the
+ * receiver)
+ */
+};
+
+#define FIRSTACKOFFSET 4
+
+/* Reason for acknowledge message */
+#define RX_ACK_REQUESTED 1 /* Peer requested an ack on this
+ * packet */
+#define RX_ACK_DUPLICATE 2 /* Duplicate packet */
+#define RX_ACK_OUT_OF_SEQUENCE 3 /* Packet out of sequence */
+#define RX_ACK_EXCEEDS_WINDOW 4 /*
+ * Packet sequence number higher than
+ * window; discarded
+ */
+#define RX_ACK_NOSPACE 5 /* No buffer space at all */
+#define RX_ACK_PING 6 /* This is a keep-alive ack */
+#define RX_ACK_PING_RESPONSE 7 /* Ack'ing because we were pinged */
+#define RX_ACK_DELAY 8 /*
+ * Ack generated since nothing has
+ * happened since receiving packet
+ */
+
+/* Packet acknowledgement type */
+#define RX_ACK_TYPE_NACK 0 /* I Don't have this packet */
+#define RX_ACK_TYPE_ACK 1 /*
+ * I have this packet, although I may
+ * discard it later
+ */
+
+/*
+ * The packet size transmitted for an acknowledge is adjusted to reflect the
+ * actual size of the acks array. This macro defines the size
+ */
+#define rx_AckDataSize(nAcks) (18 + (nAcks))
+
+#define RX_CHALLENGE_TIMEOUT 2 /*
+ * Number of seconds before another
+ * authentication request packet is
+ * generated
+ */
+
+/*
+ * RX error codes. RX uses error codes from -1 to -64. Rxgen may use other
+ * error codes < -64; user programs are expected to return positive error
+ * codes
+ */
+
+/* Something bad happened to the connection; temporary loss of communication */
+#define RX_CALL_DEAD (-1)
+
+/*
+ * An invalid operation, such as a client attempting to send data after
+ * having received the beginning of a reply from the server
+ */
+#define RX_INVALID_OPERATION (-2)
+
+/* An optional timeout per call may be specified */
+#define RX_CALL_TIMEOUT (-3)
+
+/* End of data on a read */
+#define RX_EOF (-4)
+
+/* Some sort of low-level protocol error */
+#define RX_PROTOCOL_ERROR (-5)
+
+/*
+ * Generic user abort code; used when no more specific error code needs to
+ * be communicated. For example, multi rx clients use this code to abort a
+ * multi rx call
+ */
+#define RX_USER_ABORT (-6)
+
+/* Port already in use (from rx_Init) */
+#define RX_ADDRINUSE (-7)
+
+/* EMSGSIZE returned from network. Packet too big, must fragment */
+#define RX_MSGSIZE (-8)
+
+/*
+ * Structure for keeping rx statistics. Note that this structure is returned
+ * by rxdebug, so, for compatibility reasons, new fields should be appended (or
+ * spares used), the rxdebug protocol checked, if necessary, and the PrintStats
+ * code should be updated as well.
+ *
+ * Clearly we assume that ntohl will work on these structures so sizeof(int)
+ * must equal sizeof(long).
+ */
+
+struct rx_stats { /* General rx statistics */
+ int packetRequests; /* Number of packet allocation
+ * requests */
+ int noPackets[RX_N_PACKET_CLASSES];/*
+ * Number of failed packet requests,
+ * per allocation class
+ */
+ int socketGreedy; /* Whether SO_GREEDY succeeded */
+ int bogusPacketOnRead; /*
+ * Number of inappropriately short
+ * packets received
+ */
+ int bogusHost; /* Host address from bogus packets */
+ int noPacketOnRead; /*
+ * Number of read packets attempted
+ * when there was actually no packet
+ * to read off the wire
+ */
+ int noPacketBuffersOnRead; /*
+ * Number of dropped data packets due
+ * to lack of packet buffers
+ */
+ int selects; /*
+ * Number of selects waiting for packet
+ * or timeout
+ */
+ int sendSelects; /*
+ * Number of selects forced when
+ * sending packet
+ */
+ int packetsRead[RX_N_PACKET_TYPES];/*
+ * Total number of packets read, per
+ * type
+ */
+ int dataPacketsRead; /*
+ * Number of unique data packets read
+ * off the wire
+ */
+ int ackPacketsRead; /* Number of ack packets read */
+ int dupPacketsRead; /* Number of duplicate data packets
+ * read */
+ int spuriousPacketsRead; /* Number of inappropriate data
+ * packets */
+ int packetsSent[RX_N_PACKET_TYPES];/*
+ * Number of rxi_Sends: packets sent
+ * over the wire, per type
+ */
+ int ackPacketsSent; /* Number of acks sent */
+ int pingPacketsSent; /* Total number of ping packets sent */
+ int abortPacketsSent; /* Total number of aborts */
+ int busyPacketsSent; /* Total number of busies sent
+ * received */
+ int dataPacketsSent; /* Number of unique data packets sent */
+ int dataPacketsReSent; /* Number of retransmissions */
+ int dataPacketsPushed; /*
+ * Number of retransmissions pushed early by
+ * a NACK
+ */
+ int ignoreAckedPacket; /*
+ * Number of packets with acked flag,
+ * on rxi_Start
+ */
+ struct clock totalRtt; /*
+ * Total round trip time measured
+ * (use to compute average)
+ */
+ struct clock minRtt; /* Minimum round trip time measured */
+ struct clock maxRtt; /* Maximum round trip time measured */
+ int nRttSamples; /* Total number of round trip samples */
+ int nServerConns; /* Total number of server connections */
+ int nClientConns; /* Total number of client connections */
+ int nPeerStructs; /* Total number of peer structures */
+ int nCallStructs; /* Total number of call structures
+ * allocated */
+ int nFreeCallStructs; /*
+ * Total number of previously allocated
+ * free call structures
+ */
+ int netSendFailures;
+ long fatalErrors;
+ int spares[8];
+};
+
+/* structures for debug input and output packets */
+
+/* debug input types */
+struct rx_debugIn {
+ long type;
+ long index;
+};
+
+/* Invalid rx debug package type */
+#define RX_DEBUGI_BADTYPE (-8)
+
+#define RX_DEBUGI_VERSION_MINIMUM ('L')/* earliest real version */
+#define RX_DEBUGI_VERSION ('N') /* Latest version */
+ /* first version w/ secStats */
+#define RX_DEBUGI_VERSION_W_SECSTATS ('L')
+ /* version M is first supporting GETALLCONN and RXSTATS type */
+#define RX_DEBUGI_VERSION_W_GETALLCONN ('M')
+#define RX_DEBUGI_VERSION_W_RXSTATS ('M')
+ /* last version with unaligned debugConn */
+#define RX_DEBUGI_VERSION_W_UNALIGNED_CONN ('L')
+#define RX_DEBUGI_VERSION_W_WAITERS ('N')
+
+#define RX_DEBUGI_GETSTATS 1 /* get basic rx stats */
+#define RX_DEBUGI_GETCONN 2 /* get connection info */
+#define RX_DEBUGI_GETALLCONN 3 /* get even uninteresting conns */
+#define RX_DEBUGI_RXSTATS 4 /* get all rx stats */
+
+struct rx_debugStats {
+ long nFreePackets;
+ long packetReclaims;
+ long callsExecuted;
+ char waitingForPackets;
+ char usedFDs;
+ char version;
+ char spare1;
+ long nWaiting;
+ long spare2[9];
+};
+
+struct rx_debugConn_vL {
+ long host;
+ long cid;
+ long serial;
+ long callNumber[RX_MAXCALLS];
+ long error;
+ short port;
+ char flags;
+ char type;
+ char securityIndex;
+ char callState[RX_MAXCALLS];
+ char callMode[RX_MAXCALLS];
+ char callFlags[RX_MAXCALLS];
+ char callOther[RX_MAXCALLS];
+ /* old style getconn stops here */
+ struct rx_securityObjectStats secStats;
+ long sparel[10];
+};
+
+struct rx_debugConn {
+ long host;
+ long cid;
+ long serial;
+ long callNumber[RX_MAXCALLS];
+ long error;
+ short port;
+ char flags;
+ char type;
+ char securityIndex;
+ char sparec[3]; /* force correct alignment */
+ char callState[RX_MAXCALLS];
+ char callMode[RX_MAXCALLS];
+ char callFlags[RX_MAXCALLS];
+ char callOther[RX_MAXCALLS];
+ /* old style getconn stops here */
+ struct rx_securityObjectStats secStats;
+ long epoch;
+ long maxPacketSize;
+ long sparel[9];
+};
+
+#define RX_OTHER_IN 1 /* packets avail in in queue */
+#define RX_OTHER_OUT 2 /* packets avail in out queue */
+
+#endif /* _RX_ End of rx.h */
diff --git a/usr.sbin/afs/src/rx/rx_clock.c b/usr.sbin/afs/src/rx/rx_clock.c
new file mode 100644
index 00000000000..ecc93700132
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_clock.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: rx_clock.c,v 1.1.1.1 1998/09/14 21:53:14 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* Elapsed time package */
+/* See rx_clock.h for calling conventions */
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_clock.c,v 1.4 1998/03/13 01:10:57 art Exp $");
+
+#ifndef KERNEL
+
+#if defined(AGS_GFS_ENV)
+#define STARTVALUE 8000000 /* Ultrix bounds smaller, too small
+ * for general use */
+#else
+#ifdef AFS_SUN5_ENV
+#define STARTVALUE 10000000 /* Max number of seconds setitimer
+ * allows, for some reason */
+#else
+#define STARTVALUE 100000000 /* Max number of seconds setitimer
+ * allows, for some reason */
+#endif
+#endif
+
+struct clock clock_now; /* The last elapsed time ready by
+ * clock_GetTimer */
+
+/*
+ * This is set to 1 whenever the time is read, and reset to 0 whenever
+ * clock_NewTime is called. This is to allow the caller to control the
+ * frequency with which the actual time is re-evaluated (an expensive
+ * operation)
+ */
+int clock_haveCurrentTime;
+
+int clock_nUpdates; /* The actual number of clock updates */
+
+/* Initialize the clock */
+void
+clock_Init(void)
+{
+ static int initialized = 0;
+ struct itimerval itimer, otimer;
+
+ if (!initialized) {
+ itimer.it_value.tv_sec = STARTVALUE;
+ itimer.it_value.tv_usec = 0;
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+
+ if (setitimer(ITIMER_REAL, &itimer, &otimer) != 0) {
+ fprintf(stderr, "clock: could not set interval timer; aborted\n");
+ fflush(stderr);
+ exit(1);
+ }
+ initialized = 1;
+ }
+ clock_UpdateTime();
+}
+
+/*
+ * Compute the current time. The timer gets the current total elapsed
+ * time since startup, expressed in seconds and microseconds. This call
+ * is almost 200 usec on an APC RT
+ */
+void
+clock_UpdateTime(void)
+{
+ struct itimerval itimer;
+
+ getitimer(ITIMER_REAL, &itimer);
+
+ clock_now.sec = STARTVALUE - 1 - itimer.it_value.tv_sec;
+ /* The "-1" makes up for adding 1000000 usec, on the next line */
+
+ clock_now.usec = 1000000 - itimer.it_value.tv_usec;
+ if (clock_now.usec == 1000000)
+ clock_now.usec = 0, clock_now.sec++;
+ clock_haveCurrentTime = 1;
+ clock_nUpdates++;
+}
+
+#else /* KERNEL */
+#endif /* KERNEL */
diff --git a/usr.sbin/afs/src/rx/rx_clock.h b/usr.sbin/afs/src/rx/rx_clock.h
new file mode 100644
index 00000000000..99d46f715b0
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_clock.h
@@ -0,0 +1,154 @@
+/* $OpenBSD: rx_clock.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/* $KTH: rx_clock.h,v 1.3 1998/02/22 19:43:17 joda Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* Elapsed time package */
+/* This package maintains a clock which is independent of the time of day. It uses the 4.3BSD interval timer (getitimer/setitimer) in TIMER_REAL mode. Any other use of the timer voids this package's warranty. */
+
+#ifndef _CLOCK_
+#define _CLOCK_
+
+#ifdef KERNEL
+#if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV)
+#include "../h/systm.h"
+#include "../h/time.h"
+#endif /* System V */
+#else /* KERNEL */
+#ifndef ITIMER_REAL
+#include <sys/time.h>
+#endif /* ITIMER_REAL */
+#endif /* KERNEL */
+
+/* Some macros to make macros more reasonable (this allows a block to be used within a macro which does not cause if statements to screw up). That is, you can use "if (...) macro_name(); else ...;" without having things blow up on the semi-colon. */
+
+#ifndef BEGIN
+#define BEGIN do {
+#define END } while(0)
+#endif
+
+/* A clock value is the number of seconds and microseconds that have elapsed since calling clock_Init. */
+struct clock {
+ long sec; /* Seconds since clock_Init */
+ long usec; /* Microseconds since clock_Init */
+};
+
+#ifndef KERNEL
+
+/* For internal use. The last value returned from clock_GetTime() */
+extern struct clock clock_now;
+
+/* For internal use: this flag, if set, indicates a new time should be read by clock_getTime() */
+
+extern int clock_haveCurrentTime;
+
+/* For external use: the number of times the clock value is actually updated */
+extern int clock_nUpdates;
+
+/* Initialize the clock package */
+void clock_Init (void);
+
+#define clock_NewTime() (clock_haveCurrentTime = 0)
+
+/* Update the value to be returned by gettime */
+void clock_UpdateTime (void);
+
+/* Return the current clock time. If the clock value has not been updated since the last call to clock_NewTime, it is updated now */
+#define clock_GetTime(cv) \
+ BEGIN \
+ if (!clock_haveCurrentTime) clock_UpdateTime(); \
+ (cv)->sec = clock_now.sec; \
+ (cv)->usec = clock_now.usec; \
+ END
+
+/* Current clock time, truncated to seconds */
+#define clock_Sec() ((!clock_haveCurrentTime)? clock_UpdateTime(), clock_now.sec:clock_now.sec)
+
+#else /* KERNEL */
+
+#define clock_Init()
+#define clock_GetTime(cv) osi_GetTime((struct timeval *)cv) /* Bogus--uses TOD clock */
+#define clock_Sec() osi_Time()
+#define clock_NewTime() /* don't do anything; clock is fast
+ * enough in kernel */
+#endif /* KERNEL */
+
+/* Returns the elapsed time in milliseconds between clock values (*cv1) and (*cv2) */
+#define clock_ElapsedTime(cv1, cv2) \
+ (((cv2)->sec - (cv1)->sec)*1000 + ((cv2)->usec - (cv1)->usec)/1000)
+
+/* Advance the known value of the current clock time (clock_now) by the specified clock value */
+#define clock_Advance(cv) clock_Add(&clock_now, cv)
+
+/* Some comparison operators for clock values */
+#define clock_Gt(a, b) ((a)->sec>(b)->sec || ((a)->sec==(b)->sec && (a)->usec>(b)->usec))
+#define clock_Ge(a, b) ((a)->sec>(b)->sec || ((a)->sec==(b)->sec && (a)->usec>=(b)->usec))
+#define clock_Eq(a, b) ((a)->sec==(b)->sec && (a)->usec==(b)->usec)
+#define clock_Le(a, b) ((a)->sec<(b)->sec || ((a)->sec==(b)->sec && (a)->usec<=(b)->usec))
+#define clock_Lt(a, b) ((a)->sec<(b)->sec || ((a)->sec==(b)->sec && (a)->usec<(b)->usec))
+
+/* Is the clock value zero? */
+#define clock_IsZero(c) ((c)->sec == 0 && (c)->usec == 0)
+
+/* Set the clock value to zero */
+#define clock_Zero(c) ((c)->sec = (c)->usec = 0)
+
+/* Add time c2 to time c1. Both c2 and c1 must be positive times. */
+#define clock_Add(c1, c2) \
+ BEGIN \
+ if (((c1)->usec += (c2)->usec) >= 1000000) { \
+ (c1)->usec -= 1000000; \
+ (c1)->sec++; \
+ } \
+ (c1)->sec += (c2)->sec; \
+ END
+
+#define MSEC(cp) ((cp->sec * 1000) + (cp->usec / 1000))
+
+/* Add ms milliseconds to time c1. Both ms and c1 must be positive */
+/* optimized for ms << 1000 */
+#define clock_Addmsec(c1, ms) \
+ BEGIN \
+ (c1)->usec += ((unsigned long) (ms)) * 1000; \
+ while ((c1)->usec >= 1000000) { \
+ (c1)->usec -= 1000000; \
+ (c1)->sec++; \
+ } \
+ END
+
+/* Subtract time c2 from time c1. c2 should be less than c1 */
+#define clock_Sub(c1, c2) \
+ BEGIN \
+ if (((c1)->usec -= (c2)->usec) < 0) { \
+ (c1)->usec += 1000000; \
+ (c1)->sec--; \
+ } \
+ (c1)->sec -= (c2)->sec; \
+ END
+
+#define clock_Float(c) ((c)->sec + (c)->usec/1e6)
+
+void clock_Init(void);
+void clock_UpdateTime(void);
+
+
+#endif /* _CLOCK_ */
diff --git a/usr.sbin/afs/src/rx/rx_event.c b/usr.sbin/afs/src/rx/rx_event.c
new file mode 100644
index 00000000000..42411c149d1
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_event.c
@@ -0,0 +1,230 @@
+/* $OpenBSD: rx_event.c,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_event.c,v 1.3 1998/02/22 19:43:59 joda Exp $");
+
+/*
+ * All event processing is relative to the apparent current time
+ * given by clock_GetTime
+ */
+
+/* This should be static, but event_test wants to look at the free list... */
+struct rx_queue rxevent_free; /* It's somewhat bogus to use a
+ * doubly-linked queue for the free
+ * list */
+static struct rx_queue rxevent_queue; /* The list of waiting events */
+static int rxevent_allocUnit = 10; /* Allocation unit (number of event
+ * records to allocate at one time) */
+int rxevent_nFree; /* Number of free event records */
+int rxevent_nPosted; /* Current number of posted events */
+static void (*rxevent_ScheduledEarlierEvent) ();/* Proc to call when an event
+ * is scheduled that is
+ * earlier than all other
+ * events */
+static struct xfreelist {
+ struct xfreelist *next;
+} *xfreemallocs = 0, *xsp = 0;
+
+#ifdef RXDEBUG
+FILE *rxevent_debugFile; /* Set to an stdio descriptor for
+ * event logging to that file */
+#endif
+
+/* Pass in the number of events to allocate at a time */
+static int initialized = 0;
+
+void
+rxevent_Init(int nEvents, void (*scheduler) ())
+{
+ if (initialized)
+ return;
+ clock_Init();
+ if (nEvents)
+ rxevent_allocUnit = nEvents;
+ queue_Init(&rxevent_free);
+ queue_Init(&rxevent_queue);
+ rxevent_nFree = rxevent_nPosted = 0;
+ rxevent_ScheduledEarlierEvent = scheduler;
+ initialized = 1;
+}
+
+/* Add the indicated event (function, arg) at the specified clock time */
+struct rxevent *
+rxevent_Post(struct clock * when, void (*func)(), void *arg, void *arg1)
+/* when - When event should happen, in clock (clock.h) units */
+{
+ register struct rxevent *ev, *qe, *qpr;
+
+#ifdef RXDEBUG
+ if (Log) {
+ struct clock now;
+
+ clock_GetTime(&now);
+ fprintf(Log, "%ld.%ld: rxevent_Post(%ld.%ld, %p, %p)\n",
+ now.sec, now.usec, when->sec, when->usec, func, arg);
+ }
+#endif
+#if defined(AFS_SGIMP_ENV)
+ ASSERT(osi_rxislocked());
+#endif
+
+ /*
+ * If we're short on free event entries, create a block of new ones and
+ * add them to the free queue
+ */
+ if (queue_IsEmpty(&rxevent_free)) {
+ register int i;
+
+#if defined(AFS_AIX32_ENV) && defined(KERNEL)
+ ev = (struct rxevent *) rxi_Alloc(sizeof(struct rxevent));
+ queue_Append(&rxevent_free, &ev[0]), rxevent_nFree++;
+#else
+ ev = (struct rxevent *) osi_Alloc(sizeof(struct rxevent) *
+ rxevent_allocUnit);
+ xsp = xfreemallocs;
+ xfreemallocs = (struct xfreelist *) ev;
+ xfreemallocs->next = xsp;
+ for (i = 0; i < rxevent_allocUnit; i++)
+ queue_Append(&rxevent_free, &ev[i]), rxevent_nFree++;
+#endif
+ }
+ /* Grab and initialize a new rxevent structure */
+ ev = queue_First(&rxevent_free, rxevent);
+ queue_Remove(ev);
+ rxevent_nFree--;
+
+ /* Record user defined event state */
+ ev->eventTime = *when;
+ ev->func = func;
+ ev->arg = arg;
+ ev->arg1 = arg1;
+ rxevent_nPosted += 1; /* Rather than ++, to shut high-C up
+ * regarding never-set variables */
+
+ /*
+ * Locate a slot for the new entry. The queue is ordered by time, and we
+ * assume that a new entry is likely to be greater than a majority of the
+ * entries already on the queue (unless there's very few entries on the
+ * queue), so we scan it backwards
+ */
+ for (queue_ScanBackwards(&rxevent_queue, qe, qpr, rxevent)) {
+ if (clock_Ge(when, &qe->eventTime)) {
+ queue_InsertAfter(qe, ev);
+ return ev;
+ }
+ }
+ /* The event is to expire earlier than any existing events */
+ queue_Prepend(&rxevent_queue, ev);
+ if (rxevent_ScheduledEarlierEvent)
+ (*rxevent_ScheduledEarlierEvent) (); /* Notify our external
+ * scheduler */
+ return ev;
+}
+
+/*
+ * Cancel an event by moving it from the event queue to the free list.
+ * Warning, the event must be on the event queue! If not, this should core
+ * dump (reference through 0). This routine should be called using the macro
+ * event_Cancel, which checks for a null event and also nulls the caller's
+ * event pointer after cancelling the event.
+ */
+void
+rxevent_Cancel_1(register struct rxevent * ev)
+{
+#ifdef RXDEBUG
+ if (Log) {
+ struct clock now;
+
+ clock_GetTime(&now);
+ fprintf(Log, "%ld.%ld: rxevent_Cancel_1(%ld.%ld, %p, %p)\n",
+ now.sec, now.usec, ev->eventTime.sec, ev->eventTime.usec,
+ ev->func, ev->arg);
+ }
+#endif
+ /*
+ * Append it to the free list (rather than prepending) to keep
+ * the free list hot so nothing pages out
+ */
+#if defined(AFS_SGIMP_ENV)
+ ASSERT(osi_rxislocked());
+#endif
+ queue_MoveAppend(&rxevent_free, ev);
+ rxevent_nPosted--;
+ rxevent_nFree++;
+}
+
+/*
+ * Process all events that have expired relative to the current clock time
+ * (which is not re-evaluated unless clock_NewTime has been called).
+ * The relative time to the next event is returned in the output parameter
+ * next and the function returns 1. If there are is no next event,
+ * the function returns 0.
+ */
+int
+rxevent_RaiseEvents(struct clock * next)
+{
+ register struct rxevent *qe;
+ struct clock now;
+
+#ifdef RXDEBUG
+ if (Log)
+ fprintf(Log, "rxevent_RaiseEvents(%ld.%ld)\n", now.sec, now.usec);
+#endif
+
+ /*
+ * Events are sorted by time, so only scan until an event is found that
+ * has not yet timed out
+ */
+ while (queue_IsNotEmpty(&rxevent_queue)) {
+ clock_GetTime(&now);
+ qe = queue_First(&rxevent_queue, rxevent);
+ if (clock_Lt(&now, &qe->eventTime)) {
+ *next = qe->eventTime;
+ clock_Sub(next, &now);
+ return 1;
+ }
+ queue_Remove(qe);
+ rxevent_nPosted--;
+ qe->func(qe, qe->arg, qe->arg1);
+ queue_Append(&rxevent_free, qe);
+ rxevent_nFree++;
+ }
+ return 0;
+}
+
+void
+shutdown_rxevent()
+{
+ struct xfreelist *xp, *nxp;
+
+ initialized = 0;
+#if defined(AFS_AIX32_ENV) && defined(KERNEL)
+ /* Everything is freed in afs_osinet.c */
+#else
+ while ((xp = xfreemallocs) != NULL) {
+ nxp = xp->next;
+ osi_Free((char *) xp, sizeof(struct rxevent) * rxevent_allocUnit);
+ }
+#endif
+}
diff --git a/usr.sbin/afs/src/rx/rx_event.h b/usr.sbin/afs/src/rx/rx_event.h
new file mode 100644
index 00000000000..33e564d007a
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_event.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: rx_event.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* Event package */
+
+#ifndef _EVENT_
+#define _EVENT_
+
+#ifdef KERNEL
+#include "../rx/rx_queue.h"
+#include "../rx/rx_clock.h"
+#else /* KERNEL */
+#include "rx_queue.h"
+#include "rx_clock.h"
+#endif /* KERNEL */
+
+/*
+ * An event is something that will happen at (or after) a specified clock
+ * time, unless cancelled prematurely. The user routine (*func)() is called
+ * with arguments (event, arg, arg1) when the event occurs. Warnings:
+ * (1) The user supplied routine should NOT cause process preemption.
+ * (2) The event passed to the user is still on the event queue at that time.
+ * The user must not remove (event_Cancel) it explicitly, but the user may
+ * remove or schedule any OTHER event at this time.
+ */
+
+struct rxevent {
+ struct rx_queue junk; /* Events are queued */
+ struct clock eventTime; /* When this event times out (in
+ * clock.c units) */
+ void (*func)(); /* Function to call when this expires */
+ void *arg; /* Argument to the function */
+ void *arg1; /* Another argument */
+};
+
+/*
+ * Some macros to make macros more reasonable (this allows a block to be
+ * used within a macro which does not cause if statements to screw up).
+ * That is, you can use "if (...) macro_name(); else ...;" without having
+ * things blow up on the semi-colon.
+ */
+
+#ifndef BEGIN
+#define BEGIN do {
+#define END } while(0)
+#endif
+
+/*
+ * This routine must be called to initialize the event package.
+ * nEvents is the number of events to allocate in a batch whenever more
+ * are needed. If this is 0, a default number (10) will be allocated.
+ */
+void rxevent_Init(int, void (*)());
+
+/*
+ * Arrange for the indicated event at the appointed time. When is a
+ * "struct clock", in the clock.c time base
+ */
+struct rxevent *rxevent_Post(struct clock*, void (*)(), void*, void*);
+
+/*
+ * Remove the indicated event from the event queue. The event must be
+ * pending. Also see the warning, above. The event pointer supplied is
+ * zeroed.
+ */
+void rxevent_Cancel_1(register struct rxevent *);
+
+#define rxevent_Cancel(event_ptr) \
+ BEGIN \
+ if (event_ptr) { \
+ rxevent_Cancel_1(event_ptr); \
+ event_ptr = (struct rxevent *) 0; \
+ } \
+ END
+
+/*
+ * The actions specified for each event that has reached the current clock
+ * time will be taken. The current time returned by GetTime is used
+ * (warning: this may be an old time if the user has not called clock_NewTime)
+ */
+int rxevent_RaiseEvents(struct clock *);
+
+#endif /* _EVENT_ */
diff --git a/usr.sbin/afs/src/rx/rx_globs.c b/usr.sbin/afs/src/rx/rx_globs.c
new file mode 100644
index 00000000000..01e4e1e8d38
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_globs.c
@@ -0,0 +1,31 @@
+/* $OpenBSD: rx_globs.c,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* RX: Globals for internal use, basically */
+
+/* Enable data initialization when the header file is included */
+#define INIT(stuff) = stuff
+#define EXT
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_globs.c,v 1.5 1998/02/26 14:38:27 art Exp $");
diff --git a/usr.sbin/afs/src/rx/rx_globs.h b/usr.sbin/afs/src/rx/rx_globs.h
new file mode 100644
index 00000000000..6fd04cf0ed3
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_globs.h
@@ -0,0 +1,290 @@
+/* $OpenBSD: rx_globs.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/* $KTH: rx_globs.h,v 1.4 1998/02/22 19:46:16 joda Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* RX: Globals for internal use, basically */
+
+#ifdef KERNEL
+#include "../rx/rx.h"
+#else /* KERNEL */
+#include "rx.h"
+#endif /* KERNEL */
+
+#ifndef INIT
+#define INIT(x)
+#define EXT extern
+#endif /* INIT */
+
+/* The array of installed services. Null terminated. */
+EXT struct rx_service *rx_services[RX_MAX_SERVICES + 1];
+
+/* Incoming calls wait on this queue when there are no available server processes */
+EXT struct rx_queue rx_incomingCallQueue;
+
+/* Server processes wait on this queue when there are no appropriate calls to process */
+EXT struct rx_queue rx_idleServerQueue;
+
+/* Constant delay time before sending an acknowledge of the last packet received. This is to avoid sending an extra acknowledge when the client is about to make another call, anyway, or the server is about to respond. */
+EXT struct clock rx_lastAckDelay;
+
+/* Variable to allow introduction of network unreliability */
+#ifdef RXDEBUG
+EXT int rx_intentionallyDroppedPacketsPer100 INIT(0); /* Dropped on Send */
+
+#endif
+
+EXT int rx_extraQuota INIT(0); /* extra packets to add to the quota */
+EXT int rx_extraPackets INIT(32); /* extra packets to alloc (2 windows
+ * by deflt) */
+
+EXT int rx_stackSize INIT(RX_DEFAULT_STACK_SIZE);
+
+EXT int rx_connDeadTime INIT(12); /* Time until an unresponsive
+ * connection is declared dead */
+EXT int rx_idleConnectionTime INIT(700); /* Time until we toss an idle
+ * connection */
+EXT int rx_idlePeerTime INIT(60); /* Time until we toss a peer
+ * structure, after all connections
+ * using it have disappeared */
+
+/* These definitions should be in one place */
+#ifdef AFS_SUN5_ENV
+#define RX_CBUF_TIME 180 /* Check for cbuf deficit */
+#define RX_REAP_TIME 90 /* Check for tossable connections
+ * every 90 seconds */
+#else
+#define RX_CBUF_TIME 120 /* Check for cbuf deficit */
+#define RX_REAP_TIME 60 /* Check for tossable connections
+ * every 60 seconds */
+#endif
+
+EXT int rx_Window INIT(15); /* Temporary HACK: transmit/receive
+ * window */
+EXT int rx_ACKHACK INIT(4); /* Temporary HACK: how often to send
+ * request for acknowledge */
+
+#define ACKHACK(p) ((((p)->header.seq & 3)==0) && ((p)->header.flags |= RX_REQUEST_ACK))
+
+EXT int rx_nPackets INIT(100); /* obsolete; use rx_extraPackets now */
+
+/* List of free packets */
+EXT struct rx_queue rx_freePacketQueue;
+EXT struct rx_queue rx_freeCbufQueue;
+
+#ifdef RX_ENABLE_LOCKS
+EXT afs_lock_t rx_freePktQ_lock;
+
+#endif
+
+/* Number of free packets */
+EXT int rx_nFreePackets INIT(0);
+EXT int rx_nFreeCbufs INIT(0);
+EXT int rx_nCbufs INIT(0);
+EXT int rxi_NeedMoreCbufs INIT(0);
+EXT int rx_nWaiting INIT(0);
+
+/* largest packet which we can safely receive, initialized to AFS 3.2 value
+ * This is provided for backward compatibility with peers which may be unable
+ * to swallow anything larger. THIS MUST NEVER DECREASE WHILE AN APPLICATION
+ * IS RUNNING! */
+EXT u_long rx_maxReceiveSize INIT(OLD_MAX_PACKET_SIZE);
+
+#if (defined(AFS_SUN5_ENV) || defined(AFS_AOS_ENV)) && defined(KERNEL)
+EXT u_long rx_MyMaxSendSize INIT(OLD_MAX_PACKET_SIZE - RX_HEADER_SIZE);
+
+#else
+EXT u_long rx_MyMaxSendSize INIT(RX_MAX_PACKET_DATA_SIZE);
+
+#endif
+
+
+/* List of free queue entries */
+EXT struct rx_serverQueueEntry *rx_FreeSQEList INIT(0);
+
+#ifdef RX_ENABLE_LOCKS
+EXT kmutex_t freeSQEList_lock;
+
+#endif
+
+/* List of free call structures */
+EXT struct rx_queue rx_freeCallQueue;
+
+#ifdef RX_ENABLE_LOCKS
+EXT kmutex_t rx_freeCallQueue_lock;
+
+#endif
+EXT long rxi_nCalls INIT(0);
+
+/* Basic socket for client requests; other sockets (for receiving server requests) are in the service structures */
+EXT osi_socket rx_socket;
+
+/* Port requested at rx_Init. If this is zero, the actual port used will be different--but it will only be used for client operations. If non-zero, server provided services may use the same port. */
+EXT u_short rx_port;
+
+/* 32-bit select Mask for rx_Listener. We use 32 bits because IOMGR_Select only supports 32 */
+EXT fd_set rx_selectMask;
+EXT int rx_maxSocketNumber; /* Maximum socket number represented
+ * in the select mask */
+
+/* This is actually the minimum number of packets that must remain free,
+ overall, immediately after a packet of the requested class has been
+ allocated. *WARNING* These must be assigned with a great deal of care.
+ In order, these are receive quota, send quota and special quota */
+#define RX_PACKET_QUOTAS {1, 10, 0}
+/* value large enough to guarantee that no allocation fails due to RX_PACKET_QUOTAS.
+ Make it a little bigger, just for fun */
+#define RX_MAX_QUOTA 15 /* part of min packet computation */
+EXT int rx_packetQuota[RX_N_PACKET_CLASSES] INIT(RX_PACKET_QUOTAS);
+
+EXT int rx_nextCid; /* Next connection call id */
+EXT int rx_epoch; /* Initialization time of rx */
+
+#ifdef RX_ENABLE_LOCKS
+EXT kmutex_t rx_waitingForPackets_lock;
+EXT kcondvar_t rx_waitingForPackets_cv;
+
+#endif
+EXT char rx_waitingForPackets; /* Processes set and wait on this
+ * variable when waiting for packet
+ * buffers */
+
+EXT struct rx_stats rx_stats;
+
+EXT struct rx_peer **rx_peerHashTable;
+EXT struct rx_connection **rx_connHashTable;
+EXT u_long rx_hashTableSize INIT(256); /* Power of 2 */
+EXT u_long rx_hashTableMask INIT(255); /* One less than rx_hashTableSize */
+
+#define CONN_HASH(host, port, cid, epoch, type) ((((cid)>>RX_CIDSHIFT)&rx_hashTableMask))
+
+#define PEER_HASH(host, port) ((host ^ port) & rx_hashTableMask)
+
+#ifdef notdef /* Use a func for now to measure
+ * allocated structs */
+#define rxi_Free(addr, size) osi_Free(addr, size)
+#endif /* notdef */
+
+#define rxi_AllocSecurityObject() (struct rx_securityClass *) rxi_Alloc(sizeof(struct rx_securityClass))
+#define rxi_FreeSecurityObject(obj) rxi_Free(obj, sizeof(struct rx_securityClass))
+#define rxi_AllocService() (struct rx_service *) rxi_Alloc(sizeof(struct rx_service))
+#define rxi_FreeService(obj) rxi_Free(obj, sizeof(struct rx_service))
+#define rxi_AllocPeer() (struct rx_peer *) rxi_Alloc(sizeof(struct rx_peer))
+#define rxi_FreePeer(peer) rxi_Free(peer, sizeof(struct rx_peer))
+#define rxi_AllocConnection() (struct rx_connection *) rxi_Alloc(sizeof(struct rx_connection))
+#define rxi_FreeConnection(conn) (rxi_Free(conn, sizeof(struct rx_connection)))
+
+/* Forward definitions of internal procedures */
+struct rx_packet *rxi_AllocPacket(int);
+struct rx_packet *rxi_AllocSendPacket(struct rx_call *, int);
+char *rxi_Alloc(int);
+struct rx_peer *rxi_FindPeer(u_long, u_short);
+struct rx_call *rxi_NewCall(struct rx_connection *, int);
+void rxi_FreeCall(struct rx_call *);
+void rxi_Listener(void);
+int rxi_ReadPacket(int, struct rx_packet *, u_long *, u_short *);
+struct rx_packet *rxi_ReceivePacket(struct rx_packet *, osi_socket,
+ u_long, u_short);
+struct rx_packet *rxi_ReceiveDataPacket(struct rx_call *,
+ struct rx_packet *);
+struct rx_packet *rxi_ReceiveAckPacket(struct rx_call *,
+ struct rx_packet *);
+struct rx_packet *rxi_ReceiveResponsePacket(struct rx_connection *,
+ struct rx_packet *);
+struct rx_packet *rxi_ReceiveChallengePacket(struct rx_connection *,
+ struct rx_packet *);
+void rx_ServerProc(void);
+void rxi_AttachServerProc(struct rx_call *);
+void rxi_ChallengeOn(struct rx_connection *);
+void rxi_InitPeerParams(struct rx_peer *);
+
+
+#define rxi_ChallengeOff(conn) rxevent_Cancel((conn)->challengeEvent);
+void rxi_ChallengeEvent(struct rxevent*, struct rx_connection *,
+ char *);
+struct rx_packet *rxi_SendAck(struct rx_call *,
+ struct rx_packet *, int, int, int, int);
+void rxi_ClearTransmitQueue(struct rx_call *);
+void rxi_ClearReceiveQueue(struct rx_call *);
+void rxi_ResetConnection(struct rx_connection *);
+void rxi_InitCall(void); /* obsolete ? */
+void rxi_ResetCall(struct rx_call *);
+void rxi_CallError(struct rx_call *, long);
+void rxi_ConnectionError(struct rx_connection *, long);
+void rxi_QueuePackets(void); /* obsolete ? */
+void rxi_Start(struct rxevent *, struct rx_call *);
+void rxi_CallIsIdle(void); /* obsolete ? */
+void rxi_CallTimedOut(void); /* obsolete ? */
+void rxi_ComputeRoundTripTime(struct rx_packet *,
+ struct clock *,
+ struct rx_peer *);
+void rxi_ScheduleKeepAliveEvent(struct rx_call *);
+void rxi_KeepAliveEvent(struct rxevent *, struct rx_call *, char *);
+void rxi_KeepAliveOn(struct rx_call *);
+
+#define rxi_KeepAliveOff(call) rxevent_Cancel((call)->keepAliveEvent)
+void rxi_AckAll(struct rxevent *, struct rx_call *, char *);
+void rxi_SendDelayedAck(struct rxevent *, struct rx_call *, char *);
+struct rx_packet *rxi_SendSpecial(struct rx_call *,
+ struct rx_connection *,
+ struct rx_packet *, int, char *, int);
+struct rx_packet *rxi_SendCallAbort(struct rx_call *,
+ struct rx_packet *);
+struct rx_packet *rxi_SendConnectionAbort(struct rx_connection *,
+ struct rx_packet *);
+void rxi_ScheduleDecongestionEvent(struct rx_call *, int);
+void rxi_CongestionWait(struct rx_call *);
+void rxi_ReapConnections(void);
+void rxi_EncodePacketHeader(struct rx_packet *);
+void rxi_DecodePacketHeader(struct rx_packet *);
+void rxi_DebugPrint(const char *, ...);
+void rxi_PrepareSendPacket(struct rx_call *,
+ struct rx_packet *, int);
+void rxi_MoreCbufs(int);
+long rx_SlowGetLong(struct rx_packet *, int);
+
+void rxi_Send(struct rx_call *, struct rx_packet *);
+void rxi_FreeAllPackets(void);
+void rxi_SendPacket(struct rx_connection *,
+ struct rx_packet *);
+int rxi_IsConnInteresting(struct rx_connection *);
+struct rx_packet *rxi_ReceiveDebugPacket(struct rx_packet *, osi_socket,
+ long, short);
+struct rx_packet *rxi_ReceiveVersionPacket(struct rx_packet *, osi_socket,
+ long, short);
+void rxi_SendDebugPacket(struct rx_packet *, osi_socket, long, short);
+
+
+#ifdef RXDEBUG
+/* Some debugging stuff */
+EXT FILE *rx_debugFile; /* Set by the user to a stdio file for
+ * debugging output */
+
+#define Log rx_debugFile
+#define dpf(args) if (rx_debugFile) rxi_DebugPrint args; else
+
+EXT char *rx_packetTypes[RX_N_PACKET_TYPES] INIT(RX_PACKET_TYPES); /* Strings defined in
+ * rx.h */
+
+#else
+#define dpf(args)
+#endif /* RXDEBUG */
diff --git a/usr.sbin/afs/src/rx/rx_kern.h b/usr.sbin/afs/src/rx/rx_kern.h
new file mode 100644
index 00000000000..4c5fcc3c737
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_kern.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: rx_kern.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/* $KTH: rx_kern.h,v 1.3 1998/02/22 19:46:53 joda Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* Definitions specific to the in-kernel implementation of Rx, for in-kernel clients */
+
+#ifndef __RX_KERNEL_INCL_
+#define __RX_KERNEL_INCL_ 1
+
+#ifdef AFS_AIX32_ENV
+/*
+ * vrmix has some rather peculiar ideas about vax-style processor levels,
+ * as evidenced in "net/spl.h".
+ */
+#include "net/spl.h"
+#endif
+
+extern int (*rxk_GetPacketProc) (); /* set to packet allocation procedure */
+extern int (*rxk_PacketArrivalProc) ();
+
+#ifdef AFS_SUN5_ENV
+#define SPLVAR
+#define NETPRI
+#define USERPRI
+#else
+#define SPLVAR register int splvar
+#define NETPRI splvar=splnet()
+#define USERPRI splx(splvar)
+#endif
+
+rxi_StartListener(void);
+
+#define rxi_ReScheduleEvents 0 /* Not needed by kernel */
+
+/* This is a no-op, because the kernel server procs are pre-allocated */
+#define rxi_StartServerProcs(x)
+
+/* Socket stuff */
+typedef struct socket *osi_socket;
+
+#define OSI_NULLSOCKET ((osi_socket) 0)
+
+extern rx_ReScheduleEvents();
+extern osi_socket rxi_GetUDPSocket();
+
+#define osi_Msg printf)(
+#if !defined(AFS_SGI_ENV) && !defined(AFS_SUN5_ENV)
+#define osi_rxSleep(a) osi_Sleep(a)
+#define osi_rxWakeup(a) osi_Wakeup(a)
+#endif
+#if !defined(AFS_SGI_ENV)
+extern int printf();
+
+#endif
+
+#define osi_YieldIfPossible()
+#define osi_WakeupAndYieldIfPossible(x) rx_Wakeup(x)
+
+#include "../afs/longc_procs.h"
+
+#endif /* __RX_KERNEL_INCL_ */
diff --git a/usr.sbin/afs/src/rx/rx_locl.h b/usr.sbin/afs/src/rx/rx_locl.h
new file mode 100644
index 00000000000..00fd0b02d1b
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_locl.h
@@ -0,0 +1,104 @@
+/* $OpenBSD: rx_locl.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: rx_locl.h,v 1.4 1998/03/28 16:35:46 lha Exp $ */
+
+#ifndef __RX_LOCL_H__
+#define __RX_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <signal.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/param.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <atypes.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <netinet/in.h>
+#include <sys/time.h>
+#ifdef __osf__ /* brain damage */
+struct mbuf;
+struct ifaddr;
+struct ifmulti;
+struct rtentry;
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <lwp.h>
+#include <unistd.h>
+#ifdef AFS_SUN5_ENV
+#include <sys/sysmacros.h> /* ??? */
+#endif
+
+#ifdef USE_MMAPTIME
+#include <mmaptime.h>
+#endif
+
+#include <roken.h>
+
+#include "rx_mach.h"
+#include "rx_user.h"
+#include "rx_clock.h"
+#include "rx_queue.h"
+#include "rx.h"
+#include "rx_globs.h"
+#include "rx_clock.h"
+#include "rx_trace.h"
+#include "rx_misc.h"
+#include "rx_multi.h"
+
+#endif /* __RX_LOCL_H__ */
diff --git a/usr.sbin/afs/src/rx/rx_mach.h b/usr.sbin/afs/src/rx/rx_mach.h
new file mode 100644
index 00000000000..4d23b80319f
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_mach.h
@@ -0,0 +1,93 @@
+/* $OpenBSD: rx_mach.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+#ifndef _RX_MACHDEP_
+#define _RX_MACHDEP_
+
+/* $Header: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_mach.h,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
+* Copyright Transarc Corporation 1993 - 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 neither the name of IBM nor the name *
+* of Transarc be used in advertising or publicity pertaining to *
+* distribution of the software without specific, written prior permission. *
+* *
+* IBM AND TRANSARC DISCLAIM 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. *
+****************************************************************************
+*/
+
+
+#if defined(AFS_SUN5_ENV) && defined(KERNEL)
+#if defined(AFS_FINEGR_SUNLOCK)
+#define RX_ENABLE_LOCKS 1
+#else
+#undef RX_ENABLE_LOCKS
+#endif
+#include <sys/tiuser.h>
+#include <sys/t_lock.h>
+#include <sys/mutex.h>
+#endif
+
+#ifndef AFS_AOS_ENV
+#define ADAPT_PERF
+#ifndef AFS_SUN5_ENV
+#define MISCMTU
+#ifndef __CYGWIN32__
+#define ADAPT_MTU
+#endif
+#endif
+#endif
+
+#if defined(AFS_AIX32_ENV) && defined(KERNEL)
+#define PIN(a, b) pin(a, b);
+#define UNPIN(a, b) unpin(a, b);
+#else
+#define PIN(a, b) ;
+#define UNPIN(a, b) ;
+#endif
+
+#if defined(AFS_GLOBAL_SUNLOCK) && defined(KERNEL)
+extern kmutex_t afs_rxglobal_lock;
+
+#define GLOBAL_LOCK() mutex_enter(&afs_rxglobal_lock)
+#define GLOBAL_UNLOCK() mutex_exit(&afs_rxglobal_lock)
+#else
+#define GLOBAL_LOCK()
+#define GLOBAL_UNLOCK()
+#endif
+
+#ifdef RX_ENABLE_LOCKS
+extern kmutex_t afs_termStateLock;
+extern kcondvar_t afs_termStateCv;
+
+#define MUTEX_DESTROY(a) mutex_destroy(a)
+#define MUTEX_ENTER(a) mutex_enter(a)
+#define MUTEX_EXIT(a) mutex_exit(a)
+#define MUTEX_INIT(a,b,c,d) mutex_init(a,b,c,d)
+#else
+#define MObtainWriteLock(a)
+#define MReleaseWriteLock(a)
+#define MUTEX_DESTROY(a)
+#define MUTEX_ENTER(a)
+#define MUTEX_EXIT(a)
+#define MUTEX_INIT(a,b,c,d)
+#endif
+
+#ifndef AFS_AIX32_ENV
+#define IFADDR2SA(f) (&((f)->ifa_addr))
+#else /* AFS_AIX32_ENV */
+#define IFADDR2SA(f) ((f)->ifa_addr)
+#endif
+
+
+#endif /* _RX_MACHDEP_ */
diff --git a/usr.sbin/afs/src/rx/rx_misc.c b/usr.sbin/afs/src/rx/rx_misc.c
new file mode 100644
index 00000000000..a407813c6ca
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_misc.c
@@ -0,0 +1,92 @@
+/* $OpenBSD: rx_misc.c,v 1.1.1.1 1998/09/14 21:53:15 art Exp $ */
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_misc.c,v 1.4 1998/02/22 19:47:15 joda Exp $");
+
+/*
+ * We currently only include below the errors that
+ * affect us the most. We should add to this list
+ * more code mappings, as necessary.
+ */
+
+/*
+ * Convert from the local (host) to the standard
+ * (network) system error code.
+ */
+int
+hton_syserr_conv(long code)
+{
+ register long err;
+
+#if 0
+ if (code == ENOSPC)
+ err = VDISKFULL;
+#ifndef AFS_SUN5_ENV
+ /* EDQUOT doesn't exist on solaris */
+ else if (code == EDQUOT)
+ err = VOVERQUOTA;
+#endif
+ else
+#endif
+ err = code;
+ return err;
+}
+
+
+/*
+ * Convert from the standard (Network) format to the
+ * local (host) system error code.
+ */
+int
+ntoh_syserr_conv(long code)
+{
+ register long err;
+
+#if 0
+ if (code == VDISKFULL)
+ err = ENOSPC;
+ else if (code == VOVERQUOTA)
+#ifdef AFS_SUN5_ENV
+ err = ENOSPC;
+#else
+ err = EDQUOT;
+#endif
+ else
+#endif
+ err = code;
+ return err;
+}
+
+
+#ifndef KERNEL
+/*
+ * We provide the following because some systems (like aix) would fail if we
+ * pass 0 as length.
+ */
+
+#ifndef osi_alloc
+static char memZero;
+
+char *
+osi_alloc(long x)
+{
+
+ /*
+ * 0-length allocs may return NULL ptr from osi_kalloc, so we
+ * special-case things so that NULL returned iff an error occurred
+ */
+ if (x == 0)
+ return &memZero;
+ return (char *) malloc(x);
+}
+
+void
+osi_free(char *x, long size)
+{
+ if (x == &memZero)
+ return;
+ free(x);
+}
+
+#endif
+#endif /* KERNEL */
diff --git a/usr.sbin/afs/src/rx/rx_misc.h b/usr.sbin/afs/src/rx/rx_misc.h
new file mode 100644
index 00000000000..d576741e547
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_misc.h
@@ -0,0 +1,49 @@
+/* $OpenBSD: rx_misc.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: rx_misc.h,v 1.1 1998/01/28 04:54:16 art Exp $ */
+
+#ifndef __RX_MISC_H
+#define __RX_MISC_H
+int ntoh_syserr_conv(register long code);
+int hton_syserr_conv(register long code);
+
+char *osi_alloc(long);
+void osi_free(char *, long);
+#endif /* __RX_MISC_H */
diff --git a/usr.sbin/afs/src/rx/rx_multi.c b/usr.sbin/afs/src/rx/rx_multi.c
new file mode 100644
index 00000000000..11c918bcb4f
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_multi.c
@@ -0,0 +1,112 @@
+/* $OpenBSD: rx_multi.c,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_multi.c,v 1.3 1998/02/22 19:47:42 joda Exp $");
+
+/* multi.c and multi.h, together with some rxgen hooks, provide a way of making multiple, but similar, rx calls to multiple hosts simultaneously */
+
+struct multi_handle *
+multi_Init(struct rx_connection **conns, int nConns)
+{
+ void multi_Ready();
+ struct rx_call **calls;
+ short *ready;
+ struct multi_handle *mh;
+ int i;
+
+ /*
+ * Note: all structures that are possibly referenced by other processes
+ * must be allocated. In some kernels variables allocated on a process
+ * stack will not be accessible to other processes
+ */
+ calls = (struct rx_call **) osi_Alloc(sizeof(struct rx_call *) * nConns);
+ ready = (short *) osi_Alloc(sizeof(short *) * nConns);
+ mh = (struct multi_handle *) osi_Alloc(sizeof(struct multi_handle));
+ if (!calls || !ready || !mh)
+ osi_Panic("multi_Rx: no mem\n");
+ mh->calls = calls;
+ mh->nextReady = mh->firstNotReady = mh->ready = ready;
+ mh->nReady = 0;
+ mh->nConns = nConns;
+ for (i = 0; i < nConns; i++) {
+ struct rx_call *call;
+
+ call = mh->calls[i] = rx_NewCall(conns[i]);
+ rx_SetArrivalProc(call, multi_Ready, (void *) mh, (void *) i);
+ }
+ return mh;
+}
+
+/*
+ * Return the user's connection index of the most recently ready call; that
+ * is, a call that has received at least one reply packet
+ */
+int
+multi_Select(struct multi_handle *mh)
+{
+ SPLVAR;
+ NETPRI;
+ if (mh->nextReady == mh->firstNotReady) {
+ if (mh->nReady == mh->nConns) {
+ USERPRI;
+ return -1;
+ }
+ osi_rxSleep(mh);
+ }
+ USERPRI;
+ return *mh->nextReady++;
+}
+
+/*
+ * Called by Rx when the first reply packet of a call is received, or the
+ * call is aborted.
+ */
+void
+multi_Ready(struct rx_call *call, struct multi_handle *mh,
+ int index)
+{
+ *mh->firstNotReady++ = index;
+ mh->nReady++;
+ osi_rxWakeup(mh);
+}
+
+/*
+ * Called when the multi rx call is over, or when the user aborts it
+ * (by using the macro multi_Abort)
+ */
+void
+multi_Finalize(struct multi_handle *mh)
+{
+ int i;
+ int nCalls = mh->nConns;
+
+ for (i = 0; i < nCalls; i++) {
+ struct rx_call *call = mh->calls[i];
+
+ if (call)
+ rx_EndCall(call, RX_USER_ABORT);
+ }
+ osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
+ osi_Free(mh->ready, sizeof(short *) * nCalls);
+}
diff --git a/usr.sbin/afs/src/rx/rx_multi.h b/usr.sbin/afs/src/rx/rx_multi.h
new file mode 100644
index 00000000000..557f4208b00
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_multi.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: rx_multi.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/* $KTH: rx_multi.h,v 1.3 1998/02/22 19:48:23 joda Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#ifndef _RX_MULTI_
+#define _RX_MULTI_
+
+#ifdef KERNEL
+#include "../rx/rx.h"
+#else /* KERNEL */
+#include "rx.h"
+#endif /* KERNEL */
+
+struct multi_handle {
+ int nConns;
+ struct rx_call **calls;
+ short *ready;
+ short nReady; /* XXX UNALIGNED */
+ short *nextReady;
+ short *firstNotReady;
+};
+
+void
+multi_Finalize (struct multi_handle*);
+
+struct multi_handle *
+multi_Init (struct rx_connection **, int);
+
+void
+multi_Ready (struct rx_call*, struct multi_handle*, int);
+
+int
+multi_Select (struct multi_handle *);
+
+#define multi_Rx(conns, nConns) \
+ do {\
+ register struct multi_handle *multi_h;\
+ register int multi_i;\
+ register struct rx_call *multi_call;\
+ multi_h = multi_Init(conns, nConns);\
+ for (multi_i = 0; multi_i < nConns; multi_i++)
+
+#define multi_Body(startProc, endProc)\
+ multi_call = multi_h->calls[multi_i];\
+ startProc;\
+ rx_FlushWrite(multi_call);\
+ }\
+ while ((multi_i = multi_Select(multi_h)) >= 0) {\
+ register long multi_error;\
+ multi_call = multi_h->calls[multi_i];\
+ multi_error = rx_EndCall(multi_call, endProc);\
+ multi_h->calls[multi_i] = (struct rx_call *) 0
+
+#define multi_Abort break
+
+#define multi_End\
+ multi_Finalize(multi_h);\
+ } while (0)
+
+
+#endif /* _RX_MULTI_ End of rx_multi.h */
diff --git a/usr.sbin/afs/src/rx/rx_null.c b/usr.sbin/afs/src/rx/rx_null.c
new file mode 100644
index 00000000000..3f05dea401f
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_null.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: rx_null.c,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_null.c,v 1.3 1998/02/22 19:48:47 joda Exp $");
+
+/* The null security object. No authentication, no nothing. */
+
+static struct rx_securityOps null_ops;
+static struct rx_securityClass null_object;
+
+struct rx_securityClass *
+rxnull_NewServerSecurityObject()
+{
+ null_object.ops = &null_ops;
+ return &null_object;
+}
+
+struct rx_securityClass *
+rxnull_NewClientSecurityObject()
+{
+ null_object.ops = &null_ops;
+ return &null_object;
+}
diff --git a/usr.sbin/afs/src/rx/rx_null.h b/usr.sbin/afs/src/rx/rx_null.h
new file mode 100644
index 00000000000..6211b2abe38
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_null.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: rx_null.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_null.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_null.h,v $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#ifndef RX_NULL_HEADER
+#define RX_NULL_HEADER
+
+#ifdef KERNEL
+#include "../rx/rx.h"
+#else /* KERNEL */
+#include "rx.h"
+#endif /* KERNEL */
+
+/* The null security object. No authentication, no nothing. */
+
+extern struct rx_securityClass *rxnull_NewServerSecurityObject(void);
+extern struct rx_securityClass *rxnull_NewClientSecurityObject(void);
+
+#endif /* RX_NULL_HEADER */
diff --git a/usr.sbin/afs/src/rx/rx_pkt.c b/usr.sbin/afs/src/rx/rx_pkt.c
new file mode 100644
index 00000000000..30df91d56c7
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_pkt.c
@@ -0,0 +1,1329 @@
+/* $OpenBSD: rx_pkt.c,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_pkt.c,v 1.9 1998/03/14 13:40:22 assar Exp $");
+
+struct rx_packet *rx_mallocedP = 0;
+struct rx_cbuf *rx_mallocedC = 0;
+
+char cml_version_number[4711]; /* XXX - What is this? */
+extern int (*rx_almostSent) ();
+
+/*
+ * some rules about packets:
+ * 1. When a packet is allocated, the final iov_buf contains room for
+ * a security trailer, but iov_len masks that fact. If the security
+ * package wants to add the trailer, it may do so, and then extend
+ * iov_len appropriately. For this reason, packet's niovecs and
+ * iov_len fields should be accurate before calling PreparePacket.
+ */
+
+/*
+ * Preconditions:
+ * all packet buffers (iov_base) are integral multiples of
+ * the word size.
+ * offset is an integral multiple of the word size.
+ */
+
+long
+rx_SlowGetLong(struct rx_packet *packet, int offset)
+{
+ int i, l;
+
+ for (l = 0, i = 1; i < packet->niovecs; i++) {
+ if (l + packet->wirevec[i].iov_len > offset) {
+ return *((u_int32_t *)
+ ((char *)packet->wirevec[i].iov_base + (offset - l)));
+ }
+ l += packet->wirevec[i].iov_len;
+ }
+
+ return 0;
+}
+
+/* Preconditions:
+ * all packet buffers (iov_base) are integral multiples of the word
+ * size.
+ * offset is an integral multiple of the word size.
+ */
+long
+rx_SlowPutLong(struct rx_packet *packet, int offset, long data)
+{
+ int i, l;
+
+ for (l = 0, i = 1; i < packet->niovecs; i++) {
+ if (l + packet->wirevec[i].iov_len > offset) {
+ *((u_int32_t *) ((char *)packet->wirevec[i].iov_base + (offset - l))) = data;
+ return 0;
+ }
+ l += packet->wirevec[i].iov_len;
+ }
+
+ return 0;
+}
+
+/*
+ * Preconditions:
+ * all packet buffers (iov_base) are integral multiples of the
+ * word size.
+ * offset is an integral multiple of the word size.
+ * Packet Invariants:
+ * all buffers are contiguously arrayed in the iovec from 0..niovecs-1
+ */
+size_t
+rx_SlowReadPacket(struct rx_packet *packet, int offset, int resid, void *out)
+{
+ int i;
+ unsigned char *p = out;
+ size_t bytes;
+
+ for(i = 1; (i < packet->niovecs) && (offset + (ssize_t)resid > 0); i++) {
+ if(offset < packet->wirevec[i].iov_len) {
+ /* at this point the intersection of this iovec and
+ [offset, offset+resid) is non-empty, so we can copy
+ min(base + len, base + offset + resid) -
+ max(base, base + offset) bytes
+ */
+ bytes = min(packet->wirevec[i].iov_len, offset + resid) -
+ max(offset, 0);
+ memcpy(p,
+ (char *)packet->wirevec[i].iov_base + max(offset, 0),
+ bytes);
+ p += bytes;
+ }
+ offset -= packet->wirevec[i].iov_len;
+ }
+ return p - (unsigned char *)out;
+}
+
+
+/*
+ * Preconditions:
+ * all packet buffers (iov_base) are integral multiples of the
+ * word size.
+ * offset is an integral multiple of the word size.
+ */
+size_t
+rx_SlowWritePacket(struct rx_packet *packet, int offset, int resid, void *in)
+{
+ int i;
+ unsigned char *p = in;
+ size_t bytes;
+
+ for(i = 1; i < RX_MAXWVECS && offset + resid > 0; i++) {
+ if(i >= packet->niovecs)
+ if(rxi_AllocDataBuf(packet, resid))
+ break;
+ if(offset < packet->wirevec[i].iov_len) {
+ /* at this point the intersection of this iovec and
+ [offset, offset+resid) is non-empty, so we can copy
+ min(base + len, base + offset + resid) -
+ max(base, base + offset) bytes
+ */
+ bytes = min(packet->wirevec[i].iov_len, offset + resid) -
+ max(offset, 0);
+ memcpy((char *)(packet->wirevec[i].iov_base) + max(offset, 0),
+ p, bytes);
+ p += bytes;
+ }
+ offset -= packet->wirevec[i].iov_len;
+ }
+ return p - (unsigned char *)in;
+}
+
+
+static void
+freeCBuf(struct rx_cbuf *c)
+{
+ SPLVAR;
+
+ dpf(("Free cbuf %x\n", c));
+ NETPRI;
+
+ MObtainWriteLock(&rx_freePktQ_lock);
+
+ queue_Append(&rx_freeCbufQueue, c);
+ rx_nFreeCbufs++;
+
+ MReleaseWriteLock(&rx_freePktQ_lock);
+ USERPRI;
+
+ return;
+}
+
+static struct rx_cbuf *
+allocCBuf(void)
+{
+ struct rx_cbuf *c;
+
+ SPLVAR;
+
+ NETPRI;
+ MObtainWriteLock(&rx_freePktQ_lock);
+
+ if (queue_IsEmpty(&rx_freeCbufQueue)) {
+ c = NULL;
+ rxi_NeedMoreCbufs = TRUE;
+ goto done;
+ }
+ rx_nFreeCbufs--;
+ c = queue_First(&rx_freeCbufQueue, rx_cbuf);
+
+ dpf(("Alloc cb %x\n", c));
+
+ queue_Remove(c);
+
+done:
+ MReleaseWriteLock(&rx_freePktQ_lock);
+
+ USERPRI;
+ return c;
+}
+
+/* Allocate more CBufs iff we need them */
+/*
+ * In kernel, can't page in memory with interrupts disabled, so we
+ * don't use the event mechanism.
+ */
+void
+rx_CheckCbufs(unsigned long when)
+/* time when I should be called next */
+{
+ struct clock now;
+
+ clock_GetTime(&now);
+
+ if (rxi_NeedMoreCbufs) {
+ rxi_MoreCbufs(rx_Window);
+ }
+#ifndef KERNEL
+ now.sec += RX_CBUF_TIME;
+ rxevent_Post(&now, rx_CheckCbufs, (void *)now.sec, NULL);
+#endif
+}
+
+/*
+ * this one is kind of awful.
+ * In rxkad, the packet has been all shortened, and everything, ready for
+ * sending. All of a sudden, we discover we need some of that space back.
+ * This isn't terribly general, because it knows that the packets are only
+ * rounded up to the EBS (userdata + security header).
+ */
+int
+rxi_RoundUpPacket(struct rx_packet *p, unsigned int nb)
+{
+ int i;
+
+ i = p->niovecs - 1;
+ if (p->wirevec[i].iov_base == (caddr_t) p->localdata) {
+ if (p->wirevec[i].iov_len <= RX_FIRSTBUFFERSIZE - nb) {
+ p->wirevec[i].iov_len += nb;
+ return 0;
+ }
+ } else {
+ if (p->wirevec[i].iov_len <= RX_CBUFFERSIZE - nb) {
+ p->wirevec[i].iov_len += nb;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/* get sufficient space to store nb bytes of data (or more), and hook
+ * it into the supplied packet. Return nbytes<=0 if successful, otherwise
+ * returns the number of bytes >0 which it failed to come up with.
+ * Don't need to worry about locking on packet, since only
+ * one thread can manipulate one at a time. Locking on cbufs is handled
+ * by allocCBuf */
+/* MTUXXX don't need to go throught the for loop if we can trust niovecs */
+int
+rxi_AllocDataBuf(struct rx_packet *p, int nb)
+{
+ int i;
+
+ for (i = 0; nb > 0 && i < RX_MAXWVECS; i++) {
+ if (p->wirevec[i].iov_base)
+ continue;
+
+ switch (i) {
+ case 1:
+ p->wirevec[i].iov_len = RX_FIRSTBUFFERSIZE;
+ p->wirevec[i].iov_base = (caddr_t) p->localdata;
+ nb -= RX_FIRSTBUFFERSIZE;
+ p->length += RX_FIRSTBUFFERSIZE;
+ break;
+ default:
+ {
+ struct rx_cbuf *cb;
+
+ if ((cb = allocCBuf()) != NULL) {
+ p->wirevec[i].iov_base = (caddr_t) cb->data;
+ p->wirevec[i].iov_len = RX_CBUFFERSIZE;
+ nb -= RX_CBUFFERSIZE;
+ p->length += RX_CBUFFERSIZE;
+ p->niovecs++;
+ } else
+ i = RX_MAXWVECS;
+ }
+ break;
+ }
+ }
+
+ return nb;
+}
+
+int
+rxi_FreeDataBufs(struct rx_packet *p, int first)
+{
+ int i;
+
+ if (first != 1) /* MTUXXX */
+ osi_Panic("FreeDataBufs 1: first must be 1");
+
+ for (i = first; i < RX_MAXWVECS; i++) {
+ if (p->wirevec[i].iov_base) {
+ if (p->wirevec[i].iov_base != (caddr_t) p->localdata) {
+ freeCBuf((struct rx_cbuf *)((char *)p->wirevec[i].iov_base -
+ sizeof(struct rx_queue)));
+ }
+ p->wirevec[i].iov_base = NULL;
+ } else if (i == 1) /* MTUXXX */
+ osi_Panic("FreeDataBufs 4: vec 1 must not be NULL");
+
+ p->wirevec[i].iov_len = 0;
+ }
+ p->length = 0;
+
+ return 0;
+}
+
+/*
+ * add n more fragment buffers (continuation buffers)
+ * Must be called at user priority or will crash RS/6000s
+ */
+void
+rxi_MoreCbufs(int n)
+{
+ struct rx_cbuf *c, *e;
+ int getme;
+
+ SPLVAR;
+
+ if (!n)
+ return;
+
+ getme = n * sizeof(struct rx_cbuf);
+ c = rx_mallocedC = (struct rx_cbuf *) osi_Alloc(getme);
+ if (!c)
+ return;
+
+ memset(c, 0, getme);
+
+ PIN(c, getme); /* XXXXX */
+ NETPRI;
+ MObtainWriteLock(&rx_freePktQ_lock);
+
+ for (e = c + n; c < e; c++) {
+ queue_Append(&rx_freeCbufQueue, c);
+ }
+ rxi_NeedMoreCbufs = FALSE;
+ rx_nFreeCbufs += n;
+ rx_nCbufs += n;
+
+ MReleaseWriteLock(&rx_freePktQ_lock);
+ USERPRI;
+
+ return;
+}
+
+/* Add more packet buffers */
+void
+rxi_MorePackets(int apackets)
+{
+ struct rx_packet *p, *e;
+ int getme;
+
+ SPLVAR;
+
+ getme = apackets * sizeof(struct rx_packet);
+ p = rx_mallocedP = (struct rx_packet *) osi_Alloc(getme);
+
+ PIN(p, getme); /* XXXXX */
+ memset((char *) p, 0, getme);
+ NETPRI;
+ MObtainWriteLock(&rx_freePktQ_lock);
+
+ for (e = p + apackets; p < e; p++) {
+ p->wirevec[0].iov_base = (char *) (p->wirehead);
+ p->wirevec[0].iov_len = RX_HEADER_SIZE;
+ p->wirevec[1].iov_base = (char *) (p->localdata);
+ p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
+ p->niovecs = 2;
+
+ queue_Append(&rx_freePacketQueue, p);
+ }
+ rx_nFreePackets += apackets;
+
+ MReleaseWriteLock(&rx_freePktQ_lock);
+ USERPRI;
+
+ /*
+ * allocate enough cbufs that 1/4 of the packets will be able to hold
+ * maximal amounts of data
+ */
+/* MTUXXX enable this -- currently disabled for testing
+ rxi_MoreCbufs((apackets/4)*(rx_maxReceiveSize - RX_FIRSTBUFFERSIZE)/RX_CBUFFERSIZE);
+*/
+
+}
+
+void
+rxi_FreeAllPackets(void)
+{
+ /* must be called at proper interrupt level, etcetera */
+ /* MTUXXX need to free all Cbufs */
+ osi_Free(rx_mallocedP, (rx_Window + 2) * sizeof(struct rx_packet));
+ UNPIN(rx_mallocedP, (rx_Window + 2) * sizeof(struct rx_packet));
+
+ return;
+}
+
+
+/*
+ * In the packet freeing routine below, the assumption is that
+ * we want all of the packets to be used equally frequently, so that we
+ * don't get packet buffers paging out. It would be just as valid to
+ * assume that we DO want them to page out if not many are being used.
+ * In any event, we assume the former, and append the packets to the end
+ * of the free list.
+ */
+/*
+ * This explanation is bogus. The free list doesn't remain in any kind of
+ * useful order for long: the packets in use get pretty much randomly scattered
+ * across all the pages. In order to permit unused {packets,bufs} to page
+ * out, they must be stored so that packets which are adjacent in memory are
+ * adjacent in the free list. An array springs rapidly to mind.
+ */
+
+/*
+ * Free the packet p. P is assumed not to be on any queue, i.e.
+ * remove it yourself first if you call this routine.
+ */
+void
+rxi_FreePacket(struct rx_packet *p)
+{
+ SPLVAR;
+ dpf(("Free %x\n", p));
+
+ rxi_FreeDataBufs(p, 1); /* this gets the locks below, so must
+ * call it first */
+
+ NETPRI;
+
+ MObtainWriteLock(&rx_freePktQ_lock);
+
+ rx_nFreePackets++;
+ queue_Append(&rx_freePacketQueue, p);
+ /* Wakeup anyone waiting for packets */
+ rxi_PacketsUnWait();
+
+ MReleaseWriteLock(&rx_freePktQ_lock);
+ USERPRI;
+}
+
+
+
+/*
+ * rxi_AllocPacket sets up p->length so it reflects the number of
+ * bytes in the packet at this point, **not including** the header.
+ * The header is absolutely necessary, besides, this is the way the
+ * length field is usually used
+ */
+struct rx_packet *
+rxi_AllocPacket(int class)
+{
+ struct rx_packet *p;
+
+ if (rxi_OverQuota(class)) {
+ rx_stats.noPackets[class]++;
+ return NULL;
+ }
+ rx_stats.packetRequests++;
+
+ MObtainWriteLock(&rx_freePktQ_lock);
+ rx_nFreePackets--;
+ if (queue_IsEmpty(&rx_freePacketQueue))
+ osi_Panic("rxi_AllocPacket error");
+
+ p = queue_First(&rx_freePacketQueue, rx_packet);
+
+ dpf(("Alloc %x, class %d\n",
+ queue_First(&rx_freePacketQueue, rx_packet), class));
+
+ queue_Remove(p);
+ MReleaseWriteLock(&rx_freePktQ_lock);
+
+ /*
+ * have to do this here because rx_FlushWrite fiddles with the iovs in
+ * order to truncate outbound packets. In the near future, may need to
+ * allocate bufs from a static pool here, and/or in AllocSendPacket
+ */
+ p->wirevec[0].iov_base = (char *) (p->wirehead);
+ p->wirevec[0].iov_len = RX_HEADER_SIZE;
+ p->wirevec[1].iov_base = (char *) (p->localdata);
+ p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
+ p->niovecs = 2;
+ p->length = RX_FIRSTBUFFERSIZE;
+ return p;
+}
+
+
+/*
+ * This guy comes up with as many buffers as it {takes,can get} given
+ * the MTU for this call. It also sets the packet length before
+ * returning. caution: this is often called at NETPRI
+ */
+struct rx_packet *
+rxi_AllocSendPacket(struct rx_call *call, int want)
+{
+ struct rx_packet *p = (struct rx_packet *) 0;
+ int mud;
+
+ SPLVAR;
+ mud = call->conn->maxPacketSize - RX_HEADER_SIZE;
+
+ while (!(call->error)) {
+ /* if an error occurred, or we get the packet we want, we're done */
+ if ((p = rxi_AllocPacket(RX_PACKET_CLASS_SEND)) != NULL) {
+
+ want += rx_GetSecurityHeaderSize(rx_ConnectionOf(call)) +
+ rx_GetSecurityMaxTrailerSize(rx_ConnectionOf(call));
+ want = MIN(want, mud);
+
+ if (want > p->length)
+ (void) rxi_AllocDataBuf(p, (want - p->length));
+
+ if (p->length > mud)
+ p->length = mud;
+
+ p->length -= rx_GetSecurityHeaderSize(rx_ConnectionOf(call)) +
+ rx_GetSecurityMaxTrailerSize(rx_ConnectionOf(call));
+
+ if (p->length <= 0) {
+ rxi_FreePacket(p);
+ p = NULL;
+ }
+ break;
+ }
+
+ /*
+ * no error occurred, and we didn't get a packet, so we sleep. At
+ * this point, we assume that packets will be returned sooner or
+ * later, as packets are acknowledged, and so we just wait.
+ */
+ NETPRI;
+ MUTEX_ENTER(&rx_waitingForPackets_lock);
+ rx_waitingForPackets = 1;
+ call->flags |= RX_CALL_WAIT_PACKETS;
+
+#ifdef RX_ENABLE_LOCKS
+ cv_wait(&rx_waitingForPackets_cv, &rx_waitingForPackets_lock);
+#else
+ osi_rxSleep(&rx_waitingForPackets);
+#endif
+ call->flags &= ~RX_CALL_WAIT_PACKETS;
+ MUTEX_EXIT(&rx_waitingForPackets_lock);
+ USERPRI;
+ }
+
+ return p;
+}
+
+
+#ifndef KERNEL
+/* count the number of used FDs */
+static int
+CountFDs(int amax)
+{
+ struct stat tstat;
+ int i, code;
+ int count;
+
+ count = 0;
+ for (i = 0; i < amax; i++) {
+ code = fstat(i, &tstat);
+ if (code == 0)
+ count++;
+ }
+ return count;
+}
+
+/*
+ * This function reads a single packet from the interface into the
+ * supplied packet buffer (*p). Return 0 if the packet is bogus. The
+ * (host,port) of the sender are stored in the supplied variables, and
+ * the data length of the packet is stored in the packet structure.
+ * The header is decoded.
+ */
+int
+rxi_ReadPacket(int socket, struct rx_packet *p,
+ u_long *host, u_short *port)
+{
+ struct sockaddr_in from;
+ int nbytes;
+ long rlen;
+ long tlen;
+ long _tlen;
+ struct msghdr msg;
+ u_int32_t dummy; /* was using rlen but had aliasing
+ * problems */
+
+ rx_computelen(p, tlen);
+ rx_SetDataSize(p, tlen); /* this is the size of the user data
+ * area */
+
+ tlen += RX_HEADER_SIZE; /* now this is the size of the entire
+ * packet */
+ rlen = rx_maxReceiveSize; /* this is what I am advertising.
+ * Only check it once in order to
+ * avoid races. */
+ _tlen = rlen - tlen;
+ if (_tlen > 0) {
+ _tlen = rxi_AllocDataBuf(p, _tlen);
+ if (_tlen >0) {
+ _tlen = rlen - _tlen;
+ }
+ else _tlen = rlen;
+ }
+ else _tlen = rlen;
+ tlen=(tlen>_tlen)?tlen:_tlen;
+
+ /*
+ * set up this one iovec for padding, it's just to make sure that the
+ * read doesn't return more data than we expect, and is done to get
+ * around our problems caused by the lack of a length field in the rx
+ * header.
+ */
+ p->wirevec[p->niovecs].iov_base = (caddr_t) & dummy;
+ p->wirevec[p->niovecs++].iov_len = 4;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = (char *) &from;
+ msg.msg_namelen = sizeof(struct sockaddr_in);
+ msg.msg_iov = p->wirevec;
+ msg.msg_iovlen = p->niovecs;
+#if 0
+ msg.msg_accrights = NULL;
+ msg.msg_accrightslen = 0;
+#endif
+ nbytes = recvmsg(socket, &msg, 0);
+
+ /* restore the vec to its correct state */
+ p->wirevec[--p->niovecs].iov_base = NULL;
+ p->wirevec[p->niovecs].iov_len = 0;
+
+ p->length = (nbytes - RX_HEADER_SIZE);
+ if ((nbytes > tlen) || (nbytes < (int)RX_HEADER_SIZE)) { /* Bogus packet */
+ if (nbytes > 0)
+ rxi_MoreCbufs(rx_Window);
+ if (nbytes > tlen)
+ rxi_AllocDataBuf(p, nbytes - tlen);
+ else if (nbytes < 0 && errno == EWOULDBLOCK)
+ rx_stats.noPacketOnRead++;
+ else {
+ rx_stats.bogusPacketOnRead++;
+ rx_stats.bogusHost = from.sin_addr.s_addr;
+ dpf(("B: bogus packet from [%x,%d] nb=%d", from.sin_addr.s_addr,
+ from.sin_port, nbytes));
+ }
+ return 0;
+ } else {
+ /* Extract packet header. */
+ rxi_DecodePacketHeader(p);
+
+ *host = from.sin_addr.s_addr;
+ *port = from.sin_port;
+ if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES)
+ rx_stats.packetsRead[p->header.type - 1]++;
+
+ return 1;
+ }
+}
+
+/* Send a udp datagram */
+int
+osi_NetSend(osi_socket socket, char *addr, struct iovec *dvec,
+ int nvecs, int length)
+{
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = dvec;
+ msg.msg_iovlen = nvecs;
+
+ msg.msg_name = addr;
+ msg.msg_namelen = sizeof(struct sockaddr_in);
+#if 0
+ msg.msg_accrights = NULL;
+ msg.msg_accrightslen = 0;
+#endif
+
+ while (sendmsg(socket, &msg, 0) == -1) {
+ int err;
+ fd_set sfds;
+
+ rx_stats.sendSelects++;
+ if (errno != EWOULDBLOCK && errno != ENOBUFS) {
+ (osi_Msg "rx failed to send packet: ");
+ perror("rx_send"); /* translates the message to English */
+ return 3;
+ }
+
+ FD_ZERO(&sfds);
+ FD_SET(socket, &sfds);
+ while ((err = select(socket + 1, 0, &sfds, 0, 0)) != 1) {
+ if (err >= 0 || errno != EINTR)
+ osi_Panic("osi_NetSend: select error %d.%d", err, errno);
+ }
+ }
+
+ return 0;
+}
+
+#else /* KERNEL */
+/*
+ * osi_NetSend is defined in afs/afs_osinet.c
+ * message receipt is done in rxk_input or rx_put.
+ */
+
+#ifdef AFS_SUN5_ENV
+/*
+ * Copy an mblock to the contiguous area pointed to by cp.
+ * MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
+ * but it doesn't really.
+ * Returns the number of bytes not transferred.
+ * The message is NOT changed.
+ */
+static int
+cpytoc(mblk_t *mp, int off, int len, char *cp)
+{
+ int n;
+
+ for (; mp && len > 0; mp = mp->b_cont) {
+ if (mp->b_datap->db_type != M_DATA) {
+ return -1;
+ }
+ n = MIN(len, (mp->b_wptr - mp->b_rptr));
+ memcpy(cp, mp->b_rptr, n);
+ cp += n;
+ len -= n;
+ mp->b_rptr += n;
+ }
+ return (len);
+}
+
+/*
+ * MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
+ * but it doesn't really.
+ * This sucks, anyway, do it like m_cpy.... below
+ */
+static int
+cpytoiovec(mblk_t *mp, int off, int len,
+ struct iovec *iovs, int niovs)
+{
+ int m, n, o, t, i;
+
+ for (i = -1, t = 0; i < niovs && mp && len > 0; mp = mp->b_cont) {
+ if (mp->b_datap->db_type != M_DATA) {
+ return -1;
+ }
+ n = MIN(len, (mp->b_wptr - mp->b_rptr));
+ len -= n;
+ while (n) {
+ if (!t) {
+ o = 0;
+ i++;
+ t = iovs[i].iov_len;
+ }
+ m = MIN(n, t);
+ memcpy(iovs[i].iov_base + o, mp->b_rptr, m);
+ mp->b_rptr += m;
+ o += m;
+ t -= m;
+ n -= m;
+ }
+ }
+ return (len);
+}
+
+#define m_cpytoc(a, b, c, d) cpytoc(a, b, c, d)
+#define m_cpytoiovec(a, b, c, d, e) cpytoiovec(a, b, c, d, e)
+#else
+
+static int
+m_cpytoiovec(struct mbuf *m, int off, int len, struct iovec iovs[], int niovs)
+{
+ caddr_t p1, p2;
+ unsigned int l1, l2, i, t;
+
+ if (m == NULL || off < 0 || len < 0 || iovs == NULL)
+ panic("m_cpytoiovec"); /* MTUXXX probably don't need this
+ * check */
+
+ while (off && m)
+ if (m->m_len <= off) {
+ off -= m->m_len;
+ m = m->m_next;
+ continue;
+ } else
+ break;
+
+ if (m == NULL)
+ return len;
+
+ p1 = mtod(m, caddr_t) + off;
+ l1 = m->m_len - off;
+ i = 0;
+ p2 = iovs[0].iov_base;
+ l2 = iovs[0].iov_len;
+
+ while (len) {
+ t = MIN(l1, MIN(l2, (unsigned int) len));
+ memcpy(p2, p1, t);
+ p1 += t;
+ p2 += t;
+ l1 -= t;
+ l2 -= t;
+ len -= t;
+ if (!l1) {
+ m = m->m_next;
+ if (!m)
+ break;
+ p1 = mtod(m, caddr_t);
+ l1 = m->m_len;
+ }
+ if (!l2) {
+ if (++i >= niovs)
+ break;
+ p2 = iovs[i].iov_base;
+ l2 = iovs[i].iov_len;
+ }
+ }
+
+ return len;
+}
+
+#endif /* AFS_SUN5_ENV */
+
+int
+rx_mb_to_packet(char *amb, void (*free)(), int hdr_len, int data_len,
+ struct rx_packet *phandle)
+{
+ int code;
+
+ code = m_cpytoiovec(amb, hdr_len, data_len, phandle->wirevec,
+ phandle->niovecs);
+ (*free) (amb);
+
+ return code;
+}
+
+#define CountFDs(amax) amax
+
+#endif /* KERNEL */
+
+
+/* send a response to a debug packet */
+
+struct rx_packet *
+rxi_ReceiveDebugPacket(struct rx_packet *ap, osi_socket asocket,
+ long ahost, short aport)
+{
+ struct rx_debugIn tin;
+ long tl;
+
+ rx_packetread(ap, 0, sizeof(struct rx_debugIn), (char *) &tin);
+
+ /*
+ * all done with packet, now set length to the truth, so we can reuse
+ * this packet
+ */
+ rx_computelen(ap, ap->length);
+
+ tin.type = ntohl(tin.type);
+ tin.index = ntohl(tin.index);
+ switch (tin.type) {
+ case RX_DEBUGI_GETSTATS:{
+ struct rx_debugStats tstat;
+
+ /* get basic stats */
+ memset((char *) &tstat, 0, sizeof(tstat)); /* make sure spares are
+ * zero */
+ tstat.version = RX_DEBUGI_VERSION;
+#ifndef RX_ENABLE_LOCKS
+ tstat.waitingForPackets = rx_waitingForPackets;
+#endif
+ tstat.nFreePackets = htonl(rx_nFreePackets);
+ tstat.callsExecuted = htonl(rxi_nCalls);
+ tstat.packetReclaims = htonl(0);
+ tstat.usedFDs = CountFDs(64);
+ tstat.nWaiting = htonl(rx_nWaiting);
+
+
+ tl = sizeof(struct rx_debugStats) - ap->length;
+ if (tl > 0)
+ tl = rxi_AllocDataBuf(ap, tl);
+
+ if (tl <= 0) {
+ rx_packetwrite(ap, 0, sizeof(struct rx_debugStats), (char *) &tstat);
+ ap->length = sizeof(struct rx_debugStats);
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ rx_computelen(ap, ap->length);
+ }
+ break;
+ }
+
+ case RX_DEBUGI_GETALLCONN:
+ case RX_DEBUGI_GETCONN:{
+ int i, j;
+ struct rx_connection *tc;
+ struct rx_call *tcall;
+ struct rx_debugConn tconn;
+ int all = (tin.type == RX_DEBUGI_GETALLCONN);
+
+
+ tl = sizeof(struct rx_debugConn) - ap->length;
+ if (tl > 0)
+ tl = rxi_AllocDataBuf(ap, tl);
+ if (tl > 0)
+ return ap;
+
+ memset((char *) &tconn, 0, sizeof(tconn)); /* make sure spares are
+ * zero */
+ /* get N'th (maybe) "interesting" connection info */
+ for (i = 0; i < rx_hashTableSize; i++) {
+ for (tc = rx_connHashTable[i]; tc; tc = tc->next) {
+ if ((all || rxi_IsConnInteresting(tc)) && tin.index-- <= 0) {
+ tconn.host = tc->peer->host;
+ tconn.port = tc->peer->port;
+ tconn.cid = htonl(tc->cid);
+ tconn.epoch = htonl(tc->epoch);
+ tconn.serial = htonl(tc->serial);
+ for (j = 0; j < RX_MAXCALLS; j++) {
+ tconn.callNumber[j] = htonl(tc->callNumber[j]);
+ if ((tcall = tc->call[j]) != NULL) {
+ tconn.callState[j] = tcall->state;
+ tconn.callMode[j] = tcall->mode;
+ tconn.callFlags[j] = tcall->flags;
+ if (queue_IsNotEmpty(&tcall->rq))
+ tconn.callOther[j] |= RX_OTHER_IN;
+ if (queue_IsNotEmpty(&tcall->tq))
+ tconn.callOther[j] |= RX_OTHER_OUT;
+ } else
+ tconn.callState[j] = RX_STATE_NOTINIT;
+ }
+
+ tconn.maxPacketSize = htonl(tc->maxPacketSize);
+ tconn.error = htonl(tc->error);
+ tconn.flags = tc->flags;
+ tconn.type = tc->type;
+ tconn.securityIndex = tc->securityIndex;
+ if (tc->securityObject) {
+ RXS_GetStats(tc->securityObject, tc,
+ &tconn.secStats);
+#define DOHTONL(a) (tconn.secStats.a = htonl(tconn.secStats.a))
+#define DOHTONS(a) (tconn.secStats.a = htons(tconn.secStats.a))
+ DOHTONL(flags);
+ DOHTONL(expires);
+ DOHTONL(packetsReceived);
+ DOHTONL(packetsSent);
+ DOHTONL(bytesReceived);
+ DOHTONL(bytesSent);
+ for (i = 0;
+ i < sizeof(tconn.secStats.spares) / sizeof(short);
+ i++)
+ DOHTONS(spares[i]);
+ for (i = 0;
+ i < sizeof(tconn.secStats.sparel) / 4;
+ i++)
+ DOHTONL(sparel[i]);
+ }
+ rx_packetwrite(ap, 0, sizeof(struct rx_debugConn), (char *) &tconn);
+ tl = ap->length;
+ ap->length = sizeof(struct rx_debugConn);
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ ap->length = tl;
+ return ap;
+ }
+ }
+ }
+ /* if we make it here, there are no interesting packets */
+ tconn.cid = htonl(0xffffffff); /* means end */
+ rx_packetwrite(ap, 0, sizeof(struct rx_debugConn), &tconn);
+ tl = ap->length;
+ ap->length = sizeof(struct rx_debugConn);
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ ap->length = tl;
+ break;
+ }
+
+ case RX_DEBUGI_RXSTATS:{
+ int i;
+ long *s;
+
+ tl = sizeof(rx_stats) - ap->length;
+ if (tl > 0)
+ tl = rxi_AllocDataBuf(ap, tl);
+ if (tl > 0)
+ return ap;
+
+ /* Since its all longs convert to network order with a loop. */
+ s = (long *) &rx_stats;
+ for (i = 0; i < sizeof(rx_stats) / 4; i++, s++)
+ rx_PutLong(ap, i * 4, htonl(*s));
+
+ tl = ap->length;
+ ap->length = sizeof(rx_stats);
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ ap->length = tl;
+ break;
+ }
+
+ default:
+ /* error response packet */
+ tin.type = htonl(RX_DEBUGI_BADTYPE);
+ tin.index = tin.type;
+ rx_packetwrite(ap, 0, sizeof(struct rx_debugIn), &tin);
+ tl = ap->length;
+ ap->length = sizeof(struct rx_debugIn);
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ ap->length = tl;
+ break;
+ }
+ return ap;
+}
+
+struct rx_packet *
+rxi_ReceiveVersionPacket(struct rx_packet *ap, osi_socket asocket,
+ long ahost, short aport)
+{
+ long tl;
+
+ rx_packetwrite(ap, 0, 65, cml_version_number + 4);
+ tl = ap->length;
+ ap->length = 65;
+ rxi_SendDebugPacket(ap, asocket, ahost, aport);
+ ap->length = tl;
+ return ap;
+}
+
+
+/* send a debug packet back to the sender */
+void
+rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
+ long ahost, short aport)
+{
+ struct sockaddr_in taddr;
+
+ taddr.sin_family = AF_INET;
+ taddr.sin_port = aport;
+ taddr.sin_addr.s_addr = ahost;
+
+ GLOBAL_UNLOCK();
+ /* debug packets are not reliably delivered, hence the cast below. */
+ /* MTUXXX need to adjust lengths as in sendSpecial */
+ (void) osi_NetSend(asocket, (char *)&taddr, apacket->wirevec,
+ apacket->niovecs, apacket->length + RX_HEADER_SIZE);
+ GLOBAL_LOCK();
+}
+
+/*
+ * Send the packet to appropriate destination for the specified
+ * connection. The header is first encoded and placed in the packet.
+ */
+void
+rxi_SendPacket(struct rx_connection *conn,
+ struct rx_packet *p)
+{
+ struct sockaddr_in addr;
+ struct rx_peer *peer = conn->peer;
+ osi_socket socket;
+
+#ifdef RXDEBUG
+ char deliveryType = 'S';
+
+#endif
+
+ memset(&addr, 0, sizeof(addr));
+
+ /* The address we're sending the packet to */
+ addr.sin_family = AF_INET;
+ addr.sin_port = peer->port;
+ addr.sin_addr.s_addr = peer->host;
+
+ /*
+ * This stuff should be revamped, I think, so that most, if not all, of
+ * the header stuff is always added here. We could probably do away with
+ * the encode/decode routines. XXXXX
+ */
+
+ /*
+ * Stamp each packet with a unique serial number. The serial number is
+ * maintained on a connection basis because some types of security may be
+ * based on the serial number of the packet, and security is handled on a
+ * per authenticated-connection basis.
+ */
+
+ /*
+ * Pre-increment, to guarantee no zero serial number; a zero serial
+ * number means the packet was never sent.
+ */
+ p->header.serial = ++conn->serial;
+
+ /*
+ * This is so we can adjust retransmit time-outs better in the face of
+ * rapidly changing round-trip times. RTO estimation is not a la Karn.
+ */
+ if (p->firstSerial == 0) {
+ p->firstSerial = p->header.serial;
+ }
+#ifdef RXDEBUG
+
+ /*
+ * If an output tracer function is defined, call it with the packet and
+ * network address. Note this function may modify its arguments.
+ */
+ if (rx_almostSent) {
+ int drop = (*rx_almostSent) (p, &addr);
+
+ /* drop packet if return value is non-zero? */
+ if (drop)
+ deliveryType = 'D'; /* Drop the packet */
+ }
+#endif
+
+ /* Get network byte order header */
+ rxi_EncodePacketHeader(p); /* XXX in the event of rexmit, etc,
+ * don't need to touch ALL the fields */
+
+ /*
+ * Send the packet out on the same socket that related packets are being
+ * received on
+ */
+ socket = (conn->type == RX_CLIENT_CONNECTION
+ ? rx_socket : conn->service->socket);
+
+#ifdef RXDEBUG
+ /* Possibly drop this packet, for testing purposes */
+ if ((deliveryType == 'D') ||
+ ((rx_intentionallyDroppedPacketsPer100 > 0) &&
+ (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
+ deliveryType = 'D'; /* Drop the packet */
+ } else {
+ deliveryType = 'S'; /* Send the packet */
+#endif /* RXDEBUG */
+
+ /*
+ * Loop until the packet is sent. We'd prefer just to use a blocking
+ * socket, but unfortunately the interface doesn't allow us to have
+ * the socket block in send mode, and not block in receive mode
+ */
+ GLOBAL_UNLOCK();
+ if (osi_NetSend(socket, (char *)&addr, p->wirevec,
+ p->niovecs, p->length + RX_HEADER_SIZE)) {
+ /* send failed, so let's hurry up the resend, eh? */
+ rx_stats.netSendFailures++;
+ clock_Zero(&p->retryTime);
+ p->header.serial = 0; /* Another way of saying never
+ * transmitted... */
+ }
+ GLOBAL_LOCK();
+#ifdef RXDEBUG
+ }
+ dpf(("%c %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %x resend %d.%0.3d",
+ deliveryType, p->header.serial, rx_packetTypes[p->header.type - 1],
+ peer->host, peer->port, p->header.serial, p->header.epoch,
+ p->header.cid, p->header.callNumber, p->header.seq, p->header.flags,
+ p, p->retryTime.sec, p->retryTime.usec / 1000));
+#endif
+ rx_stats.packetsSent[p->header.type - 1]++;
+}
+
+
+/*
+ * Send a "special" packet to the peer connection. If call is
+ * specified, then the packet is directed to a specific call channel
+ * associated with the connection, otherwise it is directed to the
+ * connection only. Uses optionalPacket if it is supplied, rather than
+ * allocating a new packet buffer. Nbytes is the length of the data
+ * portion of the packet. If data is non-null, nbytes of data are
+ * copied into the packet. Type is the type of the packet, as defined
+ * in rx.h. Bug: there's a lot of duplication between this and other
+ * routines. This needs to be cleaned up.
+ */
+struct rx_packet *
+rxi_SendSpecial(struct rx_call *call,
+ struct rx_connection *conn,
+ struct rx_packet *optionalPacket, int type, char *data,
+ int nbytes)
+{
+
+ /*
+ * Some of the following stuff should be common code for all packet sends
+ * (it's repeated elsewhere)
+ */
+ struct rx_packet *p;
+ int i = 0;
+ int savelen = 0;
+ int saven = 0;
+ int channel, callNumber;
+
+ if (call) {
+ channel = call->channel;
+ callNumber = *call->callNumber;
+ } else {
+ channel = 0;
+ callNumber = 0;
+ }
+ p = optionalPacket;
+ if (!p) {
+ p = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
+ if (!p)
+ osi_Panic("rxi_SendSpecial failure");
+ }
+ if (nbytes != -1)
+ p->length = nbytes;
+ else
+ nbytes = p->length;
+ p->header.serviceId = conn->serviceId;
+ p->header.securityIndex = conn->securityIndex;
+ p->header.cid = (conn->cid | channel);
+ p->header.callNumber = callNumber;
+ p->header.seq = 0;
+ p->header.epoch = conn->epoch;
+ p->header.type = type;
+ p->header.flags = 0;
+ if (conn->type == RX_CLIENT_CONNECTION)
+ p->header.flags |= RX_CLIENT_INITIATED;
+ if (data)
+ rx_packetwrite(p, 0, nbytes, data);
+
+ for (i = 1; i < p->niovecs; i++) {
+ if (nbytes <= p->wirevec[i].iov_len) {
+ savelen = p->wirevec[i].iov_len;
+ saven = p->niovecs;
+ p->wirevec[i].iov_len = nbytes;
+ p->niovecs = i + 1; /* so condition fails because i ==
+ * niovecs */
+ } else
+ nbytes -= p->wirevec[i].iov_len;
+ }
+
+ if (call)
+ rxi_Send(call, p);
+ else
+ rxi_SendPacket(conn, p);
+ if (saven) { /* means we truncated the packet
+ * above. We probably don't */
+ /* really need to do this, but it seems safer this way, given that */
+ /* sneaky optionalPacket... */
+ p->wirevec[i - 1].iov_len = savelen;
+ p->niovecs = saven;
+ }
+ if (!optionalPacket)
+ rxi_FreePacket(p);
+ return optionalPacket;
+}
+
+
+/* Encode the packet's header (from the struct header in the packet to
+ * the net byte order representation in the wire representation of the
+ * packet, which is what is actually sent out on the wire) */
+void
+rxi_EncodePacketHeader(struct rx_packet *p)
+{
+ u_int32_t *buf = (u_int32_t *) (p->wirevec[0].iov_base); /* MTUXXX */
+
+ memset((char *) buf, 0, RX_HEADER_SIZE);
+ *buf++ = htonl(p->header.epoch);
+ *buf++ = htonl(p->header.cid);
+ *buf++ = htonl(p->header.callNumber);
+ *buf++ = htonl(p->header.seq);
+ *buf++ = htonl(p->header.serial);
+ *buf++ = htonl((((unsigned long) p->header.type) << 24)
+ | (((unsigned long) p->header.flags) << 16)
+ | (p->header.userStatus << 8) | p->header.securityIndex);
+ /* Note: top 16 bits of this next word were reserved */
+ *buf++ = htonl((p->header.spare << 16) | (p->header.serviceId & 0xffff));
+}
+
+/* Decode the packet's header (from net byte order to a struct header) */
+void
+rxi_DecodePacketHeader(struct rx_packet *p)
+{
+ u_int32_t *buf = (u_int32_t *) (p->wirevec[0].iov_base); /* MTUXXX */
+ u_int32_t temp;
+
+ p->header.epoch = ntohl(*buf++);
+ p->header.cid = ntohl(*buf++);
+ p->header.callNumber = ntohl(*buf++);
+ p->header.seq = ntohl(*buf++);
+ p->header.serial = ntohl(*buf++);
+ temp = ntohl(*buf++);
+ /* C will truncate byte fields to bytes for me */
+ p->header.type = temp >> 24;
+ p->header.flags = temp >> 16;
+ p->header.userStatus = temp >> 8;
+ p->header.securityIndex = temp >> 0;
+ temp = ntohl(*buf++);
+ p->header.serviceId = (temp & 0xffff);
+ p->header.spare = temp >> 16;
+ /* Note: top 16 bits of this last word are the security checksum */
+}
+
+void
+rxi_PrepareSendPacket(struct rx_call *call,
+ struct rx_packet *p, int last)
+{
+ struct rx_connection *conn = call->conn;
+ int len, i;
+
+ p->acked = 0;
+ p->header.cid = (conn->cid | call->channel);
+ p->header.serviceId = conn->serviceId;
+ p->header.securityIndex = conn->securityIndex;
+ p->header.callNumber = *call->callNumber;
+ p->header.seq = call->tnext++;
+ p->header.epoch = conn->epoch;
+ p->header.type = RX_PACKET_TYPE_DATA;
+ p->header.flags = 0;
+ p->header.spare = 0;
+ if (conn->type == RX_CLIENT_CONNECTION)
+ p->header.flags |= RX_CLIENT_INITIATED;
+
+ if (last)
+ p->header.flags |= RX_LAST_PACKET;
+
+ clock_Zero(&p->retryTime); /* Never yet transmitted */
+ p->header.serial = 0; /* Another way of saying never
+ * transmitted... */
+ p->backoff = 0;
+
+ /*
+ * Now that we're sure this is the last data on the call, make sure that
+ * the "length" and the sum of the iov_lens matches.
+ */
+ len = p->length + call->conn->securityHeaderSize;
+
+ for (i = 1; i < p->niovecs && len > 0; i++) {
+ len -= p->wirevec[i].iov_len;
+ }
+ if (len > 0) {
+ osi_Panic("PrepareSendPacket 1\n"); /* MTUXXX */
+ } else {
+ p->niovecs = i;
+ p->wirevec[i - 1].iov_len += len;
+ }
+ RXS_PreparePacket(conn->securityObject, call, p);
+}
diff --git a/usr.sbin/afs/src/rx/rx_pkt.h b/usr.sbin/afs/src/rx/rx_pkt.h
new file mode 100644
index 00000000000..8b7d50baef8
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_pkt.h
@@ -0,0 +1,291 @@
+/* $OpenBSD: rx_pkt.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+#ifndef _RX_PACKET_
+#define _RX_PACKET_
+#include "sys/uio.h"
+/*
+ * this file includes the macros and decls which depend on packet
+ * format, and related packet manipulation macros. Note that code
+ * which runs at NETPRI should not sleep, or AIX will panic
+ */
+/*
+ * There are some assumptions that various code makes -- I'll try to
+ * express them all here:
+ * 1. rx_ReceiveAckPacket assumes that it can get an entire ack
+ * contiguous in the first iovec. As a result, the iovec buffers must
+ * be >= sizeof (struct rx_ackpacket)
+ * 2. All callers of rx_Pullup besides rx_ReceiveAckPacket try to pull
+ * up less data than rx_ReceiveAckPacket does.
+ * 3. rx_GetLong and rx_PutLong (and the slow versions of same) assume
+ * that the iovec buffers are all integral multiples of the word size,
+ * and that the offsets are as well.
+ */
+
+#include <sys/param.h>
+
+#define RX_IPUDP_SIZE 28
+
+/*
+ * REMOTE_PACKET_SIZE is currently the same as local. This is because REMOTE
+ * is defined much too generally for my tastes, and includes the case of
+ * multiple class C nets connected with a router within one campus or MAN.
+ * I don't want to make local performance suffer just because of some
+ * out-dated protocol that used to be in use on the NSFANET that's
+ * practically unused anymore. Any modern IP implementation will be
+ * using MTU discovery, and even old routers shouldn't frag packets
+ * when sending from one connected network directly to another. Maybe
+ * the next release of RX will do MTU discovery.
+ */
+
+/*
+ * MTUXXX the various "MAX" params here must be rationalized. From now on,
+ * the MAX packet size will be the maximum receive size, but the maximum send
+ * size will be larger than that.
+ */
+
+#ifdef notdef
+/* some sample MTUs
+ 4352 what FDDI(RFC1188) uses... Larger?
+ 4096 VJ's recommendation for FDDI
+ 17914 what IBM 16MB TR uses
+ 8166 IEEE 802.4
+ 4464 IEEE 802.5 MAX
+ 2002 IEEE 802.5 Recommended
+ 1500 what Ethernet uses
+ 1492 what 802.3 uses ( 8 bytes for 802.2 SAP )
+*/
+
+/* * * * these are the old defines
+*/
+#define RX_MAX_PACKET_SIZE (RX_MAX_DL_MTU -RX_IPUDP_SIZE)
+
+#define RX_MAX_PACKET_DATA_SIZE (RX_MAX_PACKET_SIZE-RX_HEADER_SIZE)
+#ifdef AFS_HPUX_ENV
+/* HPUX by default uses an 802.3 size, and it's not evident from SIOCGIFCONF */
+#define RX_LOCAL_PACKET_SIZE (1492 - RX_IPUDP_SIZE)
+#define RX_REMOTE_PACKET_SIZE (1492 - RX_IPUDP_SIZE)
+#else
+#define RX_LOCAL_PACKET_SIZE RX_MAX_PACKET_SIZE /* For hosts on same net */
+#define RX_REMOTE_PACKET_SIZE RX_MAX_PACKET_SIZE /* see note above */
+#endif
+
+#endif /* notdef */
+
+/* These are the new, streamlined ones.
+ */
+#define RX_HEADER_SIZE 28
+
+#define OLD_MAX_PACKET_SIZE (1500 -RX_IPUDP_SIZE)
+#define RX_PP_PACKET_SIZE (576 +RX_HEADER_SIZE)
+
+/* if the other guy is not on the local net, use this size */
+#define RX_REMOTE_PACKET_SIZE (1500 - RX_IPUDP_SIZE)
+
+/* for now, never send more data than this */
+#define RX_MAX_PACKET_SIZE (16384 + RX_HEADER_SIZE)
+#define RX_MAX_PACKET_DATA_SIZE 16384
+
+
+/* Packet types, for rx_packet.type */
+#define RX_PACKET_TYPE_DATA 1 /* A vanilla data packet */
+#define RX_PACKET_TYPE_ACK 2 /* Acknowledge packet */
+#define RX_PACKET_TYPE_BUSY 3 /* Busy: can't accept call
+ * immediately; try later */
+#define RX_PACKET_TYPE_ABORT 4 /* Abort packet. No response needed. */
+#define RX_PACKET_TYPE_ACKALL 5 /* Acknowledges receipt of all packets */
+#define RX_PACKET_TYPE_CHALLENGE 6 /* Challenge client's identity:
+ * request credentials */
+#define RX_PACKET_TYPE_RESPONSE 7 /* Respond to challenge packet */
+#define RX_PACKET_TYPE_DEBUG 8 /* Get debug information */
+
+#define RX_PACKET_TYPE_PARAMS 9 /* exchange size params (showUmine) */
+#define RX_PACKET_TYPE_VERSION 13 /* get AFS version */
+
+
+#define RX_PACKET_TYPES {"data", "ack", "busy", "abort", "ackall", "challenge", "response", "debug", "params", "unused", "unused", "unused", "version"}
+#define RX_N_PACKET_TYPES 13 /* Must agree with above list; counts
+ * 0 */
+
+/* Packet classes, for rx_AllocPacket */
+#define RX_PACKET_CLASS_RECEIVE 0
+#define RX_PACKET_CLASS_SEND 1
+#define RX_PACKET_CLASS_SPECIAL 2
+
+#define RX_N_PACKET_CLASSES 3 /* Must agree with above list */
+
+/* Flags for rx_header flags field */
+#define RX_CLIENT_INITIATED 1 /* Packet is sent/received from client
+ * side of call */
+#define RX_REQUEST_ACK 2 /* Peer requests acknowledgement */
+#define RX_LAST_PACKET 4 /* This is the last packet from this
+ * side of the call */
+#define RX_MORE_PACKETS 8 /* There are more packets following
+ * this, i.e. the next sequence number
+ * seen by the receiver should be
+ * greater than this one, rather than
+ * a resend of an earlier sequence
+ * number */
+
+/* The following flags are preset per packet, i.e. they don't change
+ * on retransmission of the packet */
+#define RX_PRESET_FLAGS (RX_CLIENT_INITIATED | RX_LAST_PACKET)
+
+
+/* The rx part of the header of a packet, in host form */
+struct rx_header {
+ u_int32_t epoch; /* Start time of client process */
+ u_int32_t cid; /* Connection id (defined by client) */
+ u_int32_t callNumber; /* Current call number */
+ u_int32_t seq; /* Sequence number of this packet,
+ * within this call */
+ u_int32_t serial; /* Serial number of this packet: a new
+ * serial number is stamped on each
+ * packet sent out */
+ u_char type; /* RX packet type */
+ u_char flags; /* Flags, defined below */
+ u_char userStatus; /* User defined status information,
+ * returned/set by macros
+ * rx_Get/SetLocal/RemoteStatus */
+ u_char securityIndex; /* Which service-defined security
+ * method to use */
+ u_short serviceId; /* service this packet is directed
+ * _to_ */
+
+ /*
+ * This spare is now used for packet header checkksum. see
+ * rxi_ReceiveDataPacket and packet cksum macros above for details.
+ */
+ u_short spare;
+};
+
+#define RX_MAXWVECS 10 /* most Unixes max is 16, so never let
+ * this > 15 */
+/*
+ * RX_FIRSTBUFFERSIZE must be larger than the largest ack packet,
+ * the largest possible challenge or response packet.
+ * Both Firstbuffersize and cbuffersize must be integral multiples of 8,
+ * so the security header and trailer stuff works for rxkad_crypt. yuck.
+ */
+#if defined(AFS_SUN5_ENV) || defined(AFS_AOS_ENV)
+#define RX_FIRSTBUFFERSIZE (OLD_MAX_PACKET_SIZE - RX_HEADER_SIZE)
+#define RX_CBUFFERSIZE 1012
+#else
+#define RX_FIRSTBUFFERSIZE 480 /* MTUXXX should be 1444 */
+#define RX_CBUFFERSIZE 504 /* MTUXXX change this to 1024 or 1012 */
+#endif /* AFS_SUN5_ENV */
+struct rx_packet {
+ struct rx_queue queueItemHeader; /* Packets are chained using the
+ * queue.h package */
+ struct clock retryTime; /* When this packet should NEXT be
+ * re-transmitted */
+ struct clock timeSent; /* When this packet was transmitted
+ * last */
+ u_int32_t firstSerial; /* Original serial number of this
+ * packet */
+ struct clock firstSent; /* When this packet was transmitted
+ * first */
+ struct rx_header header; /* The internal packet header */
+ int niovecs;
+ struct iovec wirevec[RX_MAXWVECS + 1]; /* the new form of the packet */
+ /* should be `u_long' here /joda */
+ u_long wirehead[RX_HEADER_SIZE / sizeof(u_long)+1 ];
+ u_long localdata[RX_FIRSTBUFFERSIZE / sizeof(u_long)+1];
+ u_int32_t dummy;
+ u_char acked; /* This packet has been *tentatively*
+ * acknowledged */
+ u_char backoff; /* for multiple re-sends */
+ u_short length; /* Data length */
+};
+
+struct rx_cbuf {
+ struct rx_queue queueItemHeader;
+ /* `u_long' is correct /joda */
+ u_long data[(RX_CBUFFERSIZE / sizeof(u_long)) + 1];
+};
+
+/* Macros callable by security modules, to set header/trailer lengths,
+ * set actual packet size, and find the beginning of the security
+ * header (or data) */
+#define rx_SetSecurityHeaderSize(conn, length) ((conn)->securityHeaderSize = (length))
+#define rx_SetSecurityMaxTrailerSize(conn, length) ((conn)->securityMaxTrailerSize = (length))
+#define rx_GetSecurityHeaderSize(conn) ((conn)->securityHeaderSize)
+#define rx_GetSecurityMaxTrailerSize(conn) ((conn)->securityMaxTrailerSize)
+
+/* This is the address of the data portion of the packet. Any encryption
+ * headers will be at this address, the actual data, for a data packet, will
+ * start at this address + the connection's security header size. */
+#define rx_DataOf(packet) ((char *) (packet)->wirevec[1].iov_base)
+#define rx_GetDataSize(packet) ((packet)->length)
+#define rx_SetDataSize(packet, size) ((packet)->length = (size))
+
+/* These macros used in conjunction with reuse of packet header spare as a
+ * packet cksum for rxkad security module. */
+#define rx_GetPacketCksum(packet) ((packet)->header.spare)
+#define rx_SetPacketCksum(packet, cksum) ((packet)->header.spare = (cksum))
+
+#define rxi_OverQuota(packetclass) (rx_nFreePackets - 1 < rx_packetQuota[packetclass])
+
+/* this returns a long from byte offset o in packet p. offset must
+ * always be aligned properly for a long, I'm leaving this up to the
+ * caller. */
+#define rx_GetLong(p,off) (( (off) >= (p)->wirevec[1].iov_len) ? \
+ rx_SlowGetLong((p), (off)) : \
+ *((long *)((char *)(p)->wirevec[1].iov_base + (off))))
+
+#define rx_PutLong(p,off,b) { \
+ if ((off) >= (p)->wirevec[1].iov_len) \
+ rx_SlowPutLong((p), (off), (b)); \
+ else *((long *)((char *)(p)->wirevec[1].iov_base + (off))) = b; }
+
+#define rx_data(p, o, l) ((l=((struct rx_packet*)(p))->wirevec[(o+1)].iov_len),\
+ (((struct rx_packet*)(p))->wirevec[(o+1)].iov_base))
+
+
+struct rx_packet *rx_AllocPacket(void);
+void rxi_MorePackets(int);
+void rx_CheckCbufs(unsigned long);
+void rxi_FreePacket(register struct rx_packet *);
+int rxi_AllocDataBuf(struct rx_packet *, int);
+size_t rx_SlowReadPacket(struct rx_packet*, int, int, void*);
+size_t rx_SlowWritePacket(struct rx_packet*, int, int, void*);
+int rxi_RoundUpPacket(struct rx_packet *, unsigned int);
+
+/* copy data into an RX packet */
+#define rx_packetwrite(p, off, len, in) \
+ ( (off) + (len) > (p)->wirevec[1].iov_len ? \
+ rx_SlowWritePacket(p, off, len, in) : \
+ ((memcpy((char *)((p)->wirevec[1].iov_base)+(off), (in), (len))),0))
+
+/* copy data from an RX packet */
+#define rx_packetread(p, off, len, out) \
+ ( (off) + (len) > (p)->wirevec[1].iov_len ? \
+ rx_SlowReadPacket(p, off, len, out) : \
+ ((memcpy((out), (char *)((p)->wirevec[1].iov_base)+(off), len)),0))
+
+#define rx_computelen(p,l) { register int i; \
+ for (l=0, i=1; i < p->niovecs; i++ ) l += p->wirevec[i].iov_len; }
+
+/* return what the actual contiguous space is: should be min(length,size) */
+/* The things that call this really want something like ...pullup MTUXXX */
+#define rx_Contiguous(p) MIN((p)->length,((p)->wirevec[1].iov_len))
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/* === packet-ized down to here, the following macros work temporarily */
+/* Unfortunately, they know that the cbuf stuff isn't there. */
+
+/* try to ensure that rx_DataOf will return a contiguous space at
+ * least size bytes long */
+/* return what the actual contiguous space is: should be min(length,size) */
+#define rx_Pullup(p,size) /* this idea here is that this will
+ * make a guarantee */
+
+
+/* The offset of the actual user's data in the packet, skipping any
+ * security header */
+/* DEPRECATED: DON'T USE THIS! [ 93.05.03 lws ] */
+#define rx_UserDataOf(conn, packet) (((char *) (packet)->wirevec[1].iov_base) + (conn)->securityHeaderSize)
+
+#endif /* _RX_PACKET_ */
diff --git a/usr.sbin/afs/src/rx/rx_queue.h b/usr.sbin/afs/src/rx/rx_queue.h
new file mode 100644
index 00000000000..f9ece2710b3
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_queue.h
@@ -0,0 +1,186 @@
+/* $OpenBSD: rx_queue.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_queue.h,v 1.1.1.1 1998/09/14 21:53:16 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_queue.h,v $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* queue.h: Simple double linked queue package */
+
+/* It's simple, but, I think, it's pretty nice to use, and it's *very* efficient (especially so with a good optimizing compiler). WARNING: Since these functions are implemented as macros, it is best to use only *VERY* simple expressions for all parameters. Double warning: this uses a lot of type coercion, so you have to be *REAL* careful. But C doesn't give me a reasonable alternative (i.e.. in-line expanded functions). */
+
+/* Author: Bob Sidebotham, ITC */
+
+#ifndef _RX_QUEUE_
+#define _RX_QUEUE_
+
+/* A queue head is simply a queue element linked to itself (i.e. the null queue is a queue with exactly one element). Queue elements can be prepended to any structure: these macros assume that the structure passed is coercible to a (struct q). Since all of these operations are implemented as macros, the user should beware of side-effects in macro parameters. Also beware that implicit casting of queue types occurs, so be careful to supply the right parameters at the right times! */
+#undef queue /* Since some OS (ultrix, etc) have
+ * their own */
+struct rx_queue {
+ struct rx_queue *prev;
+ struct rx_queue *next;
+};
+
+/* Sample usages:
+
+(*A queue head:*)
+struct rx_queue myqueue;
+
+(*An element for my queue type:*)
+struct myelement {
+ struct rx_queue queue_header;
+ int mydata;
+};
+
+(*Initialize the queue:*)
+queue_Init(&myqueue);
+
+(*Append a bunch of items to the queue:*)
+for (i=0; i<20; i++) {
+ struct myelement *item = (struct myelement *) malloc(sizeof *item);
+ item->mydata = i;
+ queue_Append(&myqueue, item);
+}
+
+(*Scan a queue, incrementing the mydata field in each element, and removing any entries for which mydata>MAX. Nqe is used by the scan to hold the next queue element, so the current queue element may be removed safely. *)
+struct myelement *qe, *nqe;
+for (queue_Scan(&myqueue, qe, nqe, myelement)) {
+ if (++qe->mydata > MAX) queue_Remove(qe);
+}
+
+(* Count the number of elements in myqueue. The queue_Scan macro specifies all three elements of the for loop, but an additional initializer and an additional incrementor can be added *)
+struct myelement *qe, *nqe;
+int n;
+for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
+
+*/
+
+/* INTERNAL macros */
+
+/* This one coerces the user's structure to a queue element (or queue head) */
+#define _RX_QUEUE(x) ((struct rx_queue *)(x))
+
+/* This one adds a queue element (i) before or after another queue element (or queue head) (q), doubly linking everything together. It's called by the user usable macros, below. If (a,b) is (next,prev) then the element i is linked after q; if it is (prev,next) then it is linked before q */
+/* N.B. I don't think it is possible to write this expression, correctly, with less than one comma (you can easily write an alternative expression with no commas that works with most or all compilers, but it's not clear that it really is un-ambiguous, legal C-code). */
+#define _QA(q,i,a,b) (((i->a=q->a)->b=i)->b=q, q->a=i)
+
+/* These ones splice two queues together. If (a,b) is (next,prev) then (*q2) is appended to (*q1), otherwise (*q2) is prepended to (*q1). */
+#define _QS(q1,q2,a,b) if (queue_IsEmpty(q2)); else \
+ ((((q2->a->b=q1)->a->b=q2->b)->a=q1->a, q1->a=q2->a), queue_Init(q2))
+
+/* Basic remove operation. Doesn't update the queue item to indicate it's been removed */
+#define _QR(i) ((_RX_QUEUE(i)->prev->next=_RX_QUEUE(i)->next)->prev=_RX_QUEUE(i)->prev)
+
+/* EXPORTED macros */
+
+/* Initialize a queue head (*q). A queue head is just a queue element */
+#define queue_Init(q) (_RX_QUEUE(q))->prev = (_RX_QUEUE(q))->next = (_RX_QUEUE(q))
+
+/* Prepend a queue element (*i) to the head of the queue, after the queue head (*q). The new queue element should not currently be on any list. */
+#define queue_Prepend(q,i) _QA(_RX_QUEUE(q),_RX_QUEUE(i),next,prev)
+
+/* Append a queue element (*i) to the end of the queue, before the queue head (*q). The new queue element should not currently be on any list. */
+#define queue_Append(q,i) _QA(_RX_QUEUE(q),_RX_QUEUE(i),prev,next)
+
+/* Insert a queue element (*i2) before another element (*i1) in the queue. The new queue element should not currently be on any list. */
+#define queue_InsertBefore(i1,i2) _QA(_RX_QUEUE(i1),_RX_QUEUE(i2),prev,next)
+
+/* Insert a queue element (*i2) after another element (*i1) in the queue. The new queue element should not currently be on any list. */
+#define queue_InsertAfter(i1,i2) _QA(_RX_QUEUE(i1),_RX_QUEUE(i2),next,prev)
+
+/* Spice the members of (*q2) to the beginning of (*q1), re-initialize (*q2) */
+#define queue_SplicePrepend(q1,q2) _QS(_RX_QUEUE(q1),_RX_QUEUE(q2),next,prev)
+
+/* Splice the members of queue (*q2) to the end of (*q1), re-initialize (*q2) */
+#define queue_SpliceAppend(q1,q2) _QS(_RX_QUEUE(q1),_RX_QUEUE(q2),prev,next)
+
+/* Replace the queue (*q1) with the contents of the queue (*q2), re-initialize (*q2) */
+#define queue_Replace(q1,q2) if (queue_IsEmpty(q2)) queue_Init(q1); else \
+ (*_RX_QUEUE(q1) = *_RX_QUEUE(q2), _RX_QUEUE(q1)->next->prev = _RX_QUEUE(q1)->prev->next = _RX_QUEUE(q1), queue_Init(q2))
+
+/* Remove a queue element (*i) from it's queue. The next field is 0'd, so that any further use of this q entry will hopefully cause a core dump. Multiple removes of the same queue item are not supported */
+#define queue_Remove(i) (_QR(i), _RX_QUEUE(i)->next = 0)
+
+/* Move the queue element (*i) from it's queue to the end of the queue (*q) */
+#define queue_MoveAppend(q,i) (_QR(i), queue_Append(q,i))
+
+/* Move the queue element (*i) from it's queue to the head of the queue (*q) */
+#define queue_MovePrepend(q,i) (_QR(i), queue_Prepend(q,i))
+
+/* Return the first element of a queue, coerced too the specified structure s */
+/* Warning: this returns the queue head, if the queue is empty */
+#define queue_First(q,s) ((struct s *)_RX_QUEUE(q)->next)
+
+/* Return the last element of a queue, coerced to the specified structure s */
+/* Warning: this returns the queue head, if the queue is empty */
+#define queue_Last(q,s) ((struct s *)_RX_QUEUE(q)->prev)
+
+/* Return the next element in a queue, beyond the specified item, coerced to the specified structure s */
+/* Warning: this returns the queue head, if the item specified is the last in the queue */
+#define queue_Next(i,s) ((struct s *)_RX_QUEUE(i)->next)
+
+/* Return the previous element to a specified element of a queue, coerced to the specified structure s */
+/* Warning: this returns the queue head, if the item specified is the first in the queue */
+#define queue_Prev(i,s) ((struct s *)_RX_QUEUE(i)->prev)
+
+/* Return true if the queue is empty, i.e. just consists of a queue head. The queue head must have been initialized some time prior to this call */
+#define queue_IsEmpty(q) (_RX_QUEUE(q)->next == _RX_QUEUE(q))
+
+/* Return true if the queue is non-empty, i.e. consists of a queue head plus at least one queue item */
+#define queue_IsNotEmpty(q) (_RX_QUEUE(q)->next != _RX_QUEUE(q))
+
+/* Return true if the queue item is currently in a queue */
+/* Returns false if the item was removed from a queue OR is uninitialized (zero) */
+#define queue_IsOnQueue(i) (_RX_QUEUE(i)->next != 0)
+
+/* Returns true if the queue item (i) is the first element of the queue (q) */
+#define queue_IsFirst(q,i) (_RX_QUEUE(q)->first == _RX_QUEUE(i))
+
+/* Returns true if the queue item (i) is the last element of the queue (q) */
+#define queue_IsLast(q,i) (_RX_QUEUE(q)->prev == _RX_QUEUE(i))
+
+/* Returns true if the queue item (i) is the end of the queue (q), that is, i is the head of the queue */
+#define queue_IsEnd(q,i) (_RX_QUEUE(q) == _RX_QUEUE(i))
+
+/* Prototypical loop to scan an entire queue forwards. q is the queue
+ * head, qe is the loop variable, next is a variable used to store the
+ * queue entry for the next iteration of the loop, s is the user's
+ * queue structure name. Called using "for (queue_Scan(...)) {...}".
+ * Note that extra initializers can be added before the queue_Scan,
+ * and additional expressions afterwards. So "for (sum=0,
+ * queue_Scan(...), sum += value) {value = qe->value}" is possible.
+ * If the current queue entry is deleted, the loop will work
+ * correctly. Care must be taken if other elements are deleted or
+ * inserted. Next may be updated within the loop to alter the item
+ * used in the next iteration. */
+#define queue_Scan(q, qe, next, s) \
+ (qe) = queue_First(q, s), next = queue_Next(qe, s); \
+ !queue_IsEnd(q, qe); \
+ (qe) = (next), next = queue_Next(qe, s)
+
+/* This is similar to queue_Scan, but scans from the end of the queue to the beginning. Next is the previous queue entry. */
+#define queue_ScanBackwards(q, qe, prev, s) \
+ (qe) = queue_Last(q, s), prev = queue_Prev(qe, s); \
+ !queue_IsEnd(q, qe); \
+ (qe) = prev, prev = queue_Prev(qe, s)
+
+#endif /* _RX_QUEUE_ */
diff --git a/usr.sbin/afs/src/rx/rx_rdwr.c b/usr.sbin/afs/src/rx/rx_rdwr.c
new file mode 100644
index 00000000000..55b15741bf7
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_rdwr.c
@@ -0,0 +1,465 @@
+/* $OpenBSD: rx_rdwr.c,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_rdwr.c,v 1.4 1998/02/22 19:53:57 joda Exp $");
+
+#ifdef AFS_SGIMP_ENV
+int
+rx_Read(struct rx_call *call, char *buf, int nbytes)
+{
+ int rv;
+
+ SPLVAR;
+ GLOCKSTATE ms;
+
+ NETPRI;
+ AFS_GRELEASE(&ms);
+ rv = rx_ReadProc(call, buf, nbytes);
+ AFS_GACQUIRE(&ms);
+ USERPRI;
+ return rv;
+}
+
+int
+rx_Write(struct rx_call *call, char *buf, int nbytes)
+{
+ int rv;
+
+ SPLVAR;
+ GLOCKSTATE ms;
+
+ NETPRI;
+ AFS_GRELEASE(&ms);
+ rv = rx_WriteProc(call, buf, nbytes);
+ AFS_GACQUIRE(&ms);
+ USERPRI;
+ return rv;
+}
+
+#endif
+
+int
+rx_ReadProc(struct rx_call *call, char *buf, int nbytes)
+{
+ struct rx_packet *rp;
+ int requestCount;
+
+ SPLVAR;
+/* XXXX took out clock_NewTime from here. Was it needed? */
+ requestCount = nbytes;
+
+ NETPRI;
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&call->lock);
+
+ while (nbytes) {
+ if (call->nLeft == 0) {
+ /* Get next packet */
+ for (;;) {
+ if (call->error || (call->mode != RX_MODE_RECEIVING)) {
+ if (call->error) {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return 0;
+ }
+ if (call->mode == RX_MODE_SENDING) {
+ rx_FlushWrite(call);
+ continue;
+ }
+ }
+ if (queue_IsNotEmpty(&call->rq)) {
+ /* Check that next packet available is next in sequence */
+ rp = queue_First(&call->rq, rx_packet);
+ if (rp->header.seq == call->rnext) {
+ long error;
+ struct rx_connection *conn = call->conn;
+
+ queue_Remove(rp);
+
+ /*
+ * RXS_CheckPacket called to undo RXS_PreparePacket's
+ * work. It may reduce the length of the packet by
+ * up to conn->maxTrailerSize, to reflect the length
+ * of the data + the header.
+ */
+ if ((error = RXS_CheckPacket(conn->securityObject,
+ call, rp)) != 0) {
+
+ /*
+ * Used to merely shut down the call, but now we
+ * shut down the whole connection since this may
+ * indicate an attempt to hijack it
+ */
+ rxi_ConnectionError(conn, error);
+ rp = rxi_SendConnectionAbort(conn, rp);
+ rxi_FreePacket(rp);
+
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return 0;
+ }
+ call->rnext++;
+ call->currentPacket = rp;
+ call->curvec = 1; /* 0th vec is always header */
+
+ /*
+ * begin at the beginning [ more or less ], continue
+ * on until the end, then stop.
+ */
+ call->curpos = call->conn->securityHeaderSize;
+
+ /*
+ * Notice that this code works correctly if the data
+ * size is 0 (which it may be--no reply arguments
+ * from server, for example). This relies heavily on
+ * the fact that the code below immediately frees the
+ * packet (no yields, etc.). If it didn't, this
+ * would be a problem because a value of zero for
+ * call->nLeft normally means that there is no read
+ * packet
+ */
+ call->nLeft = rp->length;
+ if (rp->header.flags & RX_LAST_PACKET)
+ call->flags |= RX_CALL_RECEIVE_DONE;
+
+ /*
+ * now, if we haven't send a hard ack for window/2
+ * packets we spontaneously generate one, to take
+ * care of the case where (most likely in the kernel)
+ * we receive a window-full of packets, and ack all
+ * of them before any are read by the user, thus not
+ * hard-acking any of them. The sender retransmits
+ * in this case only under a timer, which is a real
+ * loser
+ */
+
+#ifndef ADAPT_WINDOW
+ if (call->rnext > (call->lastAcked + (rx_Window >> 1)))
+#else /* ADAPT_WINDOW */
+ if (call->rnext > (call->lastAcked +
+ (call->conn->peer->maxWindow >> 1)))
+#endif /* ADAPT_WINDOW */
+ {
+ rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_DELAY);
+ }
+ break;
+ }
+ }
+/*
+MTUXXX doesn't there need to be an "else" here ???
+*/
+ /* Are there ever going to be any more packets? */
+ if (call->flags & RX_CALL_RECEIVE_DONE) {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return requestCount - nbytes;
+ }
+ /* Wait for in-sequence packet */
+ call->flags |= RX_CALL_READER_WAIT;
+ clock_NewTime();
+ call->startWait = clock_Sec();
+
+ MUTEX_EXIT(&call->lock);
+ MUTEX_ENTER(&call->lockq);
+#ifdef RX_ENABLE_LOCKS
+ while (call->flags & RX_CALL_READER_WAIT)
+ cv_wait(&call->cv_rq, &call->lockq);
+#else
+ osi_rxSleep(&call->rq);
+#endif
+ MUTEX_EXIT(&call->lockq);
+ MUTEX_ENTER(&call->lock);
+
+ call->startWait = 0;
+ }
+ } else { /* assert(call->currentPacket); */
+ /*
+ * MTUXXX this should be replaced by
+ * some error-recovery code before
+ * shipping
+ */
+ /*
+ * It's possible for call->nLeft to be smaller than
+ * any particular iov_len. Usually, recvmsg doesn't change the
+ * iov_len, since it reflects the size of the buffer. We have to
+ * keep track of the number of bytes read in the length field of
+ * the packet struct. On the final portion of a received packet,
+ * it's almost certain that call->nLeft will be smaller than the
+ * final buffer.
+ */
+ unsigned int t, l1;
+ caddr_t p1;
+
+ while (nbytes && call->currentPacket) {
+ p1 = (char*)call->currentPacket->wirevec[call->curvec].iov_base +
+ call->curpos;
+ l1 = call->currentPacket->wirevec[call->curvec].iov_len -
+ call->curpos;
+
+ t = MIN(l1, nbytes);
+ t = MIN(t, call->nLeft);
+ memcpy(buf, p1, t);
+ p1 += t;
+ buf += t;
+ l1 -= t;
+ nbytes -= t;
+ call->curpos += t;
+ call->nLeft -= t;
+
+ if (call->nLeft == 0) {
+ /* out of packet. Get another one. */
+ rxi_FreePacket(call->currentPacket);
+ call->currentPacket = NULL;
+ } else if (l1 == 0) {
+ /* need to get another struct iov */
+ if (++call->curvec > call->currentPacket->niovecs) {
+ /*
+ * current packet is exhausted, get ready for another
+ */
+
+ /*
+ * don't worry about curvec and stuff, they get set
+ * somewhere else
+ */
+ rxi_FreePacket(call->currentPacket);
+ call->currentPacket = NULL;
+ call->nLeft = 0;
+ } else
+ call->curpos = 0;
+ }
+ }
+ if (nbytes == 0) {
+ /* user buffer is full, return */
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return requestCount;
+ }
+ }
+
+ } /* while (nbytes) ... */
+
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return requestCount;
+}
+
+int
+rx_WriteProc(struct rx_call *call, char *buf, int nbytes)
+{
+ struct rx_connection *conn = call->conn;
+ int requestCount = nbytes;
+
+ SPLVAR;
+
+ GLOBAL_LOCK();
+ MUTEX_ENTER(&call->lock);
+ NETPRI;
+ if (call->mode != RX_MODE_SENDING) {
+ if ((conn->type == RX_SERVER_CONNECTION)
+ && (call->mode == RX_MODE_RECEIVING)) {
+ call->mode = RX_MODE_SENDING;
+ if (call->currentPacket) {
+ rxi_FreePacket(call->currentPacket);
+ call->currentPacket = NULL;
+ call->nLeft = 0;
+ call->nFree = 0;
+ }
+ } else {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return 0;
+ }
+ }
+
+ /*
+ * Loop condition is checked at end, so that a write of 0 bytes will
+ * force a packet to be created--specially for the case where there are 0
+ * bytes on the stream, but we must send a packet anyway.
+ */
+ do {
+ if (call->nFree == 0) {
+ struct rx_packet *cp = call->currentPacket;
+
+ if (!call->error && call->currentPacket) {
+ clock_NewTime(); /* Bogus: need new time package */
+
+ /*
+ * The 0, below, specifies that it is not the last packet:
+ * there will be others. PrepareSendPacket may alter the
+ * packet length by up to conn->securityMaxTrailerSize
+ */
+ rxi_PrepareSendPacket(call, cp, 0);
+ queue_Append(&call->tq, cp);
+ rxi_Start(0, call);
+ }
+ /* Wait for transmit window to open up */
+ while (!call->error &&
+ call->tnext + 1 > call->tfirst + call->twind) {
+ clock_NewTime();
+ call->startWait = clock_Sec();
+
+ MUTEX_EXIT(&call->lock);
+ MUTEX_ENTER(&call->lockw);
+
+#ifdef RX_ENABLE_LOCKS
+ cv_wait(&call->cv_twind, &call->lockw);
+#else
+ call->flags |= RX_CALL_WAIT_WINDOW_ALLOC;
+ osi_rxSleep(&call->twind);
+#endif
+ MUTEX_EXIT(&call->lockw);
+ MUTEX_ENTER(&call->lock);
+
+ call->startWait = 0;
+ }
+ if ((call->currentPacket = rxi_AllocSendPacket(call,
+ nbytes)) != 0) {
+ call->nFree = call->currentPacket->length;
+ call->curvec = 1; /* 0th vec is always header */
+
+ /*
+ * begin at the beginning [ more or less ], continue on until
+ * the end, then stop.
+ */
+ call->curpos = call->conn->securityHeaderSize;
+ }
+ if (call->error) {
+ if (call->currentPacket) {
+ rxi_FreePacket(call->currentPacket);
+ call->currentPacket = NULL;
+ }
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return 0;
+ }
+ }
+
+ /*
+ * If the remaining bytes fit in the buffer, then store them and
+ * return. Don't ship a buffer that's full immediately to the
+ * peer--we don't know if it's the last buffer yet
+ */
+
+ if (!(call->currentPacket)) {
+ call->nFree = 0;
+ }
+ {
+ struct rx_packet *cp = call->currentPacket;
+ unsigned int t, l1;
+ caddr_t p1;
+
+ while (nbytes && call->nFree) {
+ p1 = (char *)cp->wirevec[call->curvec].iov_base + call->curpos;
+ l1 = cp->wirevec[call->curvec].iov_len - call->curpos;
+
+ t = MIN(call->nFree, MIN(l1, nbytes));
+ memcpy(p1, buf, t);
+ p1 += t;
+ buf += t;
+ l1 -= t;
+ nbytes -= t;
+ call->curpos += t;
+ call->nFree -= t;
+
+ if (!l1) {
+ call->curpos = 0;
+ /* need to get another struct iov */
+ if (++call->curvec >= cp->niovecs) {
+ /* current packet is full, extend or send it */
+ call->nFree = 0;
+ }
+ }
+ if (!call->nFree) {
+ int len, mud;
+
+ len = cp->length;
+ mud = rx_MaxUserDataSize(conn);
+ if (mud > len) {
+ int want;
+
+ want = MIN(nbytes, mud - len);
+ rxi_AllocDataBuf(cp, want);
+ if (cp->length > mud)
+ cp->length = mud;
+ call->nFree += (cp->length - len);
+ }
+ }
+ } /*
+ * while bytes to send and room to
+ * send them
+ */
+ /* might be out of space now */
+ if (!nbytes) {
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return requestCount;
+ } else; /*
+ * more data to send, so get another
+ * packet and keep going
+ */
+ }
+ } while (nbytes);
+
+ MUTEX_EXIT(&call->lock);
+ GLOBAL_UNLOCK();
+ USERPRI;
+ return requestCount - nbytes;
+}
+
+/*
+ * Flush any buffered data to the stream, switch to read mode
+ * (clients) or to EOF mode (servers)
+ */
+void
+rx_FlushWrite(struct rx_call *call)
+{
+ SPLVAR;
+ NETPRI;
+ if (call->mode == RX_MODE_SENDING) {
+ struct rx_packet *cp;
+
+ call->mode = (call->conn->type == RX_CLIENT_CONNECTION ?
+ RX_MODE_RECEIVING : RX_MODE_EOF);
+
+ if (call->currentPacket) {
+
+ /* cp->length is only supposed to be the user's data */
+
+ cp = call->currentPacket;
+
+ /*
+ * cp->length was already set to (then-current) MaxUserDataSize
+ * or less.
+ */
+ cp->length -= call->nFree;
+ call->currentPacket = (struct rx_packet *) 0;
+ call->nFree = 0;
+
+
+ } else {
+ cp = rxi_AllocSendPacket(call, 0);
+ if (!cp) {
+ /* Mode can no longer be MODE_SENDING */
+ USERPRI;
+ return;
+ }
+ cp->length = 0;
+ cp->niovecs = 1; /* just the header */
+ call->nFree = 0;
+ }
+
+ /* The 1 specifies that this is the last packet */
+ rxi_PrepareSendPacket(call, cp, 1);
+ queue_Append(&call->tq, cp);
+ rxi_Start(0, call);
+ }
+ USERPRI;
+}
diff --git a/usr.sbin/afs/src/rx/rx_strm.h b/usr.sbin/afs/src/rx/rx_strm.h
new file mode 100644
index 00000000000..68680e0f16c
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_strm.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: rx_strm.h,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_strm.h,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+/* $Source: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_strm.h,v $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/* rx_stream.h: the stream I/O layer for RX */
+
+This file is now obsolete.
+
+
+
+#ifndef _RX_STREAM_
+#define _RX_STREAM_
+
+#ifdef KERNEL
+#include "../rx/rx.h"
+#else /* KERNEL */
+#include <sys/types.h>
+#include <sys/uio.h>
+#include "rx.h"
+#endif /* KERNEL */
+
+/* Write descriptor */
+struct rx_stream_wd {
+ char *freePtr; /* Pointer to bytes in first packet */
+ int nFree; /* Number of bytes free in first
+ * packet */
+ struct rx_call *call; /* The call this stream is attached to */
+ struct rx_queue wq; /* Currently allocated packets for
+ * this stream */
+ int packetSize; /* Data size used in each packet */
+};
+
+/* Read descriptor */
+struct rx_stream_rd {
+ struct rx_packet *packet; /* The current packet */
+ char *nextByte; /* Pointer to bytes in current packet */
+ int nLeft; /* Number of bytes free in current
+ * packet */
+ struct rx_call *call; /* The call this stream is attached to */
+ struct rx_queue rq; /* Currently allocated packets for
+ * this stream */
+ struct rx_queue freeTheseQ; /* These packets should be freed on
+ * the next operation */
+};
+
+/* Composite stream descriptor */
+struct rx_stream {
+ union {
+ struct rx_stream_rd rd;
+ struct rx_stream_wd wd;
+ } sd;
+};
+
+/* Externals */
+void rx_stream_InitWrite();
+void rx_stream_InitRead();
+void rx_stream_FinishWrite();
+void rx_stream_FinishRead();
+int rx_stream_Read();
+int rx_stream_Write();
+int rx_stream_AllocIov();
+
+/* Write nbytes of data to the write stream. Returns the number of bytes written */
+/* If it returns 0, the call status should be checked with rx_Error. */
+#define rx_stream_Write(iod, buf, nbytes) \
+ (iod)->sd.wd.nFree > (nbytes) ? \
+ (buf) && memcpy((iod)->sd.wd.freePtr, (buf), (nbytes)), \
+ (iod)->sd.wd.nFree -= (nbytes), \
+ (iod)->sd.wd.freePtr += (nbytes), (nbytes) \
+ : rx_stream_WriteProc((iod), (buf), (nbytes))
+
+
+/* Read nbytes of data from the read stream. Returns the number of bytes read */
+/* If it returns less than requested, the call status should be checked with rx_Error */
+#define rx_stream_Read(iod, buf, nbytes) \
+ (iod)->sd.rd.nLeft > (nbytes) ? \
+ memcpy((buf), (iod)->sd.rd.nextByte, (nbytes)), \
+ (iod)->sd.rd.nLeft -= (nbytes), (iod)->sd.rd.nextByte += (nbytes), (nbytes) \
+ : rx_stream_ReadProc((iod), (buf), (nbytes))
+
+#endif /* _RX_STREAM_ End of rx_stream.h */
diff --git a/usr.sbin/afs/src/rx/rx_trace.c b/usr.sbin/afs/src/rx/rx_trace.c
new file mode 100644
index 00000000000..9ad2fbff8de
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_trace.c
@@ -0,0 +1,159 @@
+/* $OpenBSD: rx_trace.c,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_trace.c,v 1.4 1998/02/22 19:55:04 joda Exp $");
+
+#ifdef RXTRACEON
+char rxi_tracename[80] = "/tmp/rxcalltrace";
+
+#else
+char rxi_tracename[80] = "\0Change This pathname (and preceding NUL) to initiate tracing";
+
+#endif
+int rxi_logfd = 0;
+char rxi_tracebuf[4096];
+unsigned long rxi_tracepos = 0;
+
+struct rx_trace {
+ unsigned long cid;
+ unsigned short call;
+ unsigned short qlen;
+ unsigned long now;
+ unsigned long waittime;
+ unsigned long servicetime;
+ unsigned long event;
+};
+
+struct rx_trace rxtinfo;
+
+#ifdef RXDEBUG
+void
+rxi_flushtrace(void)
+{
+ write(rxi_logfd, rxi_tracebuf, rxi_tracepos);
+ rxi_tracepos = 0;
+}
+
+void
+rxi_calltrace(unsigned int event, struct rx_call *call)
+{
+ struct clock now;
+
+ if (!rxi_tracename[0])
+ return;
+
+ if (!rxi_logfd) {
+ rxi_logfd = open(rxi_tracename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+ if (!rxi_logfd)
+ rxi_tracename[0] = '\0';
+ }
+ clock_GetTime(&now);
+
+ rxtinfo.event = event;
+ rxtinfo.now = now.sec * 1000 + now.usec / 1000;
+ rxtinfo.cid = call->conn->cid;
+ rxtinfo.call = *(call->callNumber);
+ rxtinfo.qlen = rx_nWaiting;
+ rxtinfo.servicetime = 0;
+ rxtinfo.waittime = 0;
+
+ switch (event) {
+ case RX_CALL_END:
+ clock_Sub(&now, &(call->traceStart));
+ rxtinfo.servicetime = now.sec * 10000 + now.usec / 100;
+ if (call->traceWait.sec) {
+ now = call->traceStart;
+ clock_Sub(&now, &(call->traceWait));
+ rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
+ } else
+ rxtinfo.waittime = 0;
+ call->traceWait.sec = call->traceWait.usec =
+ call->traceStart.sec = call->traceStart.usec = 0;
+ break;
+
+ case RX_CALL_START:
+ call->traceStart = now;
+ if (call->traceWait.sec) {
+ clock_Sub(&now, &(call->traceWait));
+ rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
+ } else
+ rxtinfo.waittime = 0;
+ break;
+
+ case RX_TRACE_DROP:
+ if (call->traceWait.sec) {
+ clock_Sub(&now, &(call->traceWait));
+ rxtinfo.waittime = now.sec * 10000 + now.usec / 100;
+ } else
+ rxtinfo.waittime = 0;
+ break;
+
+ case RX_CALL_ARRIVAL:
+ call->traceWait = now;
+ default:
+ break;
+ }
+
+ memcpy(rxi_tracebuf + rxi_tracepos, &rxtinfo, sizeof(struct rx_trace));
+ rxi_tracepos += sizeof(struct rx_trace);
+ if (rxi_tracepos >= (4096 - sizeof(struct rx_trace)))
+ rxi_flushtrace();
+}
+#endif
+
+#ifdef DUMPTRACE
+
+void
+main(int argc, char **argv)
+{
+ struct rx_trace ip;
+ int err = 0;
+
+ setlinebuf(stdout);
+ argv++;
+ argc--;
+ while (argc && **argv == '-') {
+ if (strcmp(*argv, "-trace") == 0) {
+ strcpy(rxi_tracename, *(++argv));
+ argc--;
+ } else {
+ err++;
+ break;
+ }
+ argv++, argc--;
+ }
+ if (err || argc != 0) {
+ printf("usage: dumptrace [-trace pathname]");
+ exit(1);
+ }
+ rxi_logfd = open(rxi_tracename, O_RDONLY);
+ if (!rxi_logfd) {
+ perror("");
+ exit(errno);
+ }
+ while (read(rxi_logfd, &ip, sizeof(struct rx_trace))) {
+ printf("%9u ", ip.now);
+ switch (ip.event) {
+ case RX_CALL_END:
+ putchar('E');
+ break;
+ case RX_CALL_START:
+ putchar('S');
+ break;
+ case RX_CALL_ARRIVAL:
+ putchar('A');
+ break;
+ case RX_TRACE_DROP:
+ putchar('D');
+ break;
+ default:
+ putchar('U');
+ break;
+ }
+ printf(" %3u %7u %7u %x.%x\n",
+ ip.qlen, ip.servicetime, ip.waittime, ip.cid, ip.call);
+ }
+}
+
+#endif /* DUMPTRACE */
+
diff --git a/usr.sbin/afs/src/rx/rx_trace.h b/usr.sbin/afs/src/rx/rx_trace.h
new file mode 100644
index 00000000000..51c0963e6bc
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_trace.h
@@ -0,0 +1,21 @@
+/* $OpenBSD: rx_trace.h,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+/* $Header: /home/cvs/src/usr.sbin/afs/src/rx/Attic/rx_trace.h,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+
+#ifndef _RX_TRACE
+#define _RX_TRACE
+
+#ifndef RXDEBUG
+#define rxi_calltrace(a,b)
+#define rxi_flushtrace()
+#else
+void rxi_calltrace(unsigned int, struct rx_call*);
+void rxi_flushtrace(void);
+
+#define RX_CALL_ARRIVAL 0
+#define RX_CALL_START 1
+#define RX_CALL_END 2
+#define RX_TRACE_DROP 3
+
+#endif /* RXDEBUG */
+
+#endif /* _RX_TRACE */
diff --git a/usr.sbin/afs/src/rx/rx_user.c b/usr.sbin/afs/src/rx/rx_user.c
new file mode 100644
index 00000000000..b443cbb6c19
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_user.c
@@ -0,0 +1,600 @@
+/* $OpenBSD: rx_user.c,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+/*
+ * rx_user.c contains routines specific to the user space UNIX
+ * implementation of rx
+ */
+
+#include "rx_locl.h"
+
+RCSID("$KTH: rx_user.c,v 1.10 1998/04/08 05:19:34 lha Exp $");
+
+#ifndef IPPORT_USERRESERVED
+/*
+ * If in.h doesn't define this, define it anyway. Unfortunately, defining
+ * this doesn't put the code into the kernel to restrict kernel assigned
+ * port numbers to numbers below IPPORT_USERRESERVED...
+ */
+#define IPPORT_USERRESERVED 5000
+#endif
+
+/* Don't set this to anything else right now; it is currently broken */
+int (*rx_select) (int, fd_set *, fd_set *,
+ fd_set *, struct timeval *) = IOMGR_Select;
+ /*
+ * Can be set to "select", in some
+ * cases
+ */
+
+fd_set rx_selectMask = { {0,0,0,0,0,0,0,0} }; /* XXX */
+
+PROCESS rx_listenerPid; /* LWP process id of socket listener
+ * process */
+void rxi_Listener(void);
+
+/*
+ * This routine will get called by the event package whenever a new,
+ * earlier than others, event is posted. If the Listener process
+ * is blocked in selects, this will unblock it. It also can be called
+ * to force a new trip through the rxi_Listener select loop when the set
+ * of file descriptors it should be listening to changes...
+ */
+void
+rxi_ReScheduleEvents(void)
+{
+ if (rx_listenerPid)
+ IOMGR_Cancel(rx_listenerPid);
+}
+
+void
+rxi_StartListener(void)
+{
+ /* Initialize LWP & IOMGR in case no one else has */
+ PROCESS junk;
+
+ LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
+ IOMGR_Initialize();
+
+ /* Priority of listener should be high, so it can keep conns alive */
+#define RX_LIST_STACK 24000
+ LWP_CreateProcess(rxi_Listener, RX_LIST_STACK, LWP_MAX_PRIORITY, 0,
+ "rx_Listener", &rx_listenerPid);
+}
+
+/*
+ * Called by rx_StartServer to start up lwp's to service calls.
+ * NExistingProcs gives the number of procs already existing, and which
+ * therefore needn't be created.
+ */
+void
+rxi_StartServerProcs(int nExistingProcs)
+{
+ register struct rx_service *service;
+ register int i;
+ int maxdiff = 0;
+ int nProcs = 0;
+ PROCESS scratchPid;
+
+ /*
+ * For each service, reserve N processes, where N is the "minimum" number
+ * of processes that MUST be able to execute a request in parallel, at
+ * any time, for that process. Also compute the maximum difference
+ * between any service's maximum number of processes that can run (i.e.
+ * the maximum number that ever will be run, and a guarantee that this
+ * number will run if other services aren't running), and its minimum
+ * number. The result is the extra number of processes that we need in
+ * order to provide the latter guarantee
+ */
+ for (i = 0; i < RX_MAX_SERVICES; i++) {
+ int diff;
+
+ service = rx_services[i];
+ if (service == (struct rx_service *) 0)
+ break;
+ nProcs += service->minProcs;
+ diff = service->maxProcs - service->minProcs;
+ if (diff > maxdiff)
+ maxdiff = diff;
+ }
+ nProcs += maxdiff; /* Extra processes needed to allow max
+ * number requested to run in any
+ * given service, under good
+ * conditions */
+ nProcs -= nExistingProcs; /* Subtract the number of procs that
+ * were previously created for use as
+ * server procs */
+ for (i = 0; i < nProcs; i++) {
+ LWP_CreateProcess(rx_ServerProc, rx_stackSize, RX_PROCESS_PRIORITY, 0,
+ "rx_ServerProc", &scratchPid);
+ }
+}
+
+/*
+ * Make a socket for receiving/sending IP packets. Set it into non-blocking
+ * and large buffering modes. If port isn't specified, the kernel will pick
+ * one. Returns the socket (>= 0) on success. Returns OSI_NULLSOCKET on
+ * failure.
+ *
+ * Port must be in network byte order.
+ */
+
+osi_socket
+rxi_GetUDPSocket(u_short port)
+{
+ int binds, code;
+ register int socketFd = OSI_NULLSOCKET;
+ struct sockaddr_in taddr;
+ char *name = "rxi_GetUDPSocket: ";
+
+#if 0 /* We dont want to have this error
+ * message, don't bother us */
+ if (port >= IPPORT_RESERVED && port < IPPORT_USERRESERVED) {
+ (osi_Msg "%s*WARNING* port number %d is not a reserved port number."
+ "Use port numbers above %d\n",
+ name, port, IPPORT_USERRESERVED);
+ }
+#endif /* 0 */
+
+ if (port > 0 && port < IPPORT_RESERVED && geteuid() != 0) {
+ (osi_Msg "%sport number %d is a reserved port number which may only"
+ " be used by root. Use port numbers above %d\n",
+ name, port, IPPORT_USERRESERVED);
+ goto error;
+ }
+ socketFd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ /* IOMGR_Select doesn't deal with arbitrarily large select masks */
+ if (socketFd > 31) {
+ (osi_Msg "%ssocket descriptor > 31\n", name);
+ goto error;
+ }
+ FD_SET(socketFd, &rx_selectMask);
+ if (socketFd > rx_maxSocketNumber)
+ rx_maxSocketNumber = socketFd;
+
+ taddr.sin_addr.s_addr = 0;
+ taddr.sin_family = AF_INET;
+ taddr.sin_port = port;
+#define MAX_RX_BINDS 10
+ for (binds = 0; binds < MAX_RX_BINDS; binds++) {
+ code = bind(socketFd, (const struct sockaddr *) & taddr, sizeof(taddr));
+ if (!code)
+ break;
+ sleep(10);
+ }
+ if (code) {
+ perror("bind");
+ (osi_Msg "%sbind failed\n", name);
+ goto error;
+ }
+
+ /*
+ * Use one of three different ways of getting a socket buffer expanded to
+ * a reasonable size
+ */
+ {
+ int len1, len2;
+
+ len1 = len2 = 32766;
+
+ rx_stats.socketGreedy =
+ (setsockopt(socketFd, SOL_SOCKET, SO_SNDBUF,
+ &len1, sizeof(len1)) >= 0) &&
+ (setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF,
+ &len2, sizeof(len2)) >= 0);
+ }
+
+/*#ifdef notdef*/
+ if (!rx_stats.socketGreedy)
+ (osi_Msg "%s*WARNING* Unable to increase buffering on socket\n", name);
+/*#endif*/
+
+ /*
+ * Put it into non-blocking mode so that rx_Listener can do a polling
+ * read before entering select
+ */
+ if (fcntl(socketFd, F_SETFL, FNDELAY) == -1) {
+ perror("fcntl");
+ (osi_Msg "%sunable to set non-blocking mode on socket\n", name);
+ goto error;
+ }
+ return socketFd;
+
+error:
+ if (socketFd >= 0)
+ close(socketFd);
+ return OSI_NULLSOCKET;
+}
+
+/*
+ * The main loop which listens to the net for datagrams, and handles timeouts
+ * and retransmissions, etc. It also is responsible for scheduling the
+ * execution of pending events (in conjunction with event.c).
+ *
+ * Note interaction of nextPollTime and lastPollWorked. The idea is that
+ * if rx is not keeping up with the incoming stream of packets (because
+ * there are threads that are interfering with its running sufficiently
+ * often), rx does a polling select before doing a real IOMGR_Select system
+ * call. Doing a real select means that we don't have to let other processes
+ * run before processing more packets.
+ *
+ * So, our algorithm is that if the last poll on the file descriptor found
+ * useful data, or we're at the time nextPollTime (which is advanced so that
+ * it occurs every 3 or 4 seconds),
+ * then we try the polling select before the IOMGR_Select. If we eventually
+ * catch up (which we can tell by the polling select returning no input
+ * packets ready), then we don't do a polling select again until several
+ * seconds later (via nextPollTime mechanism).
+ */
+
+#ifndef FD_COPY
+#define FD_COPY(f, t) memcpy((t), (f), sizeof(*(f)))
+#endif
+
+void
+rxi_Listener(void)
+{
+ u_long host;
+ u_short port;
+ register struct rx_packet *p = (struct rx_packet *) 0;
+ fd_set rfds;
+ int socket;
+ int fds;
+ struct clock cv;
+ long nextPollTime; /* time to next poll FD before
+ * sleeping */
+ int lastPollWorked, doingPoll; /* true iff last poll was useful */
+ struct timeval tv, *tvp;
+
+ clock_NewTime();
+ lastPollWorked = 0;
+ nextPollTime = 0;
+ for (;;) {
+
+ /*
+ * Grab a new packet only if necessary (otherwise re-use the old one)
+ */
+ if (!p) {
+ if (!(p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE)))
+ osi_Panic("rxi_Listener: no packets!"); /* Shouldn't happen */
+ }
+ /* Wait for the next event time or a packet to arrive. */
+ /*
+ * event_RaiseEvents schedules any events whose time has come and
+ * then atomically computes the time to the next event, guaranteeing
+ * that this is positive. If there is no next event, it returns 0
+ */
+ if (!rxevent_RaiseEvents(&cv))
+ tvp = (struct timeval *) 0;
+ else {
+
+ /*
+ * It's important to copy cv to tv, because the 4.3 documentation
+ * for select threatens that *tv may be updated after a select,
+ * in future editions of the system, to indicate how much of the
+ * time period has elapsed. So we shouldn't rely on tv not being
+ * altered.
+ */
+ tv.tv_sec = cv.sec; /* Time to next event */
+ tv.tv_usec = cv.usec;
+ tvp = &tv;
+ }
+ rx_stats.selects++;
+ FD_COPY(&rx_selectMask, &rfds);
+ if (lastPollWorked || nextPollTime < clock_Sec()) {
+ /* we're catching up, or haven't tried to for a few seconds */
+ rx_select = select;
+ doingPoll = 1;
+ nextPollTime = clock_Sec() + 4; /* try again in 4 seconds no
+ * matter what */
+ tv.tv_sec = tv.tv_usec = 0;/* make sure we poll */
+ tvp = &tv;
+ } else {
+ rx_select = IOMGR_Select;
+ doingPoll = 0;
+ }
+ lastPollWorked = 0; /* default is that it didn't find
+ * anything */
+
+ fds = (*rx_select) (FD_SETSIZE, &rfds, 0, 0, tvp);
+ clock_NewTime();
+ if (fds > 0) {
+ if (doingPoll)
+ lastPollWorked = 1;
+ for(socket = 0; socket < FD_SETSIZE; ++socket) {
+ if(p == NULL)
+ break;
+ if(FD_ISSET(socket, &rfds) &&
+ rxi_ReadPacket(socket, p, &host, &port)) {
+ p = rxi_ReceivePacket(p, socket, host, port);
+ }
+ }
+ }
+ }
+ /* NOTREACHED */
+}
+
+
+void
+osi_Panic(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "Fatal Rx error: ");
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fflush(stderr);
+ fflush(stdout);
+ abort();
+}
+
+#ifdef AFS_AIX32_ENV
+#ifndef osi_Alloc
+static char memZero;
+char *
+osi_Alloc(long x)
+{
+
+ /*
+ * 0-length allocs may return NULL ptr from osi_kalloc, so we
+ * special-case things so that NULL returned iff an error occurred
+ */
+ if (x == 0)
+ return &memZero;
+ return ((char *) malloc(x));
+}
+
+void
+osi_Free(char *x, long size)
+{
+ if (x == &memZero)
+ return;
+ free((char *) x);
+}
+
+#endif
+#endif /* AFS_AIX32_ENV */
+
+#define ADDRSPERSITE 16
+
+#ifdef ADAPT_MTU
+
+static u_long myNetAddrs[ADDRSPERSITE];
+static int myNetMTUs[ADDRSPERSITE];
+static int myNetFlags[ADDRSPERSITE];
+static int numMyNetAddrs;
+
+static void
+GetIFInfo(void)
+{
+ int s;
+ int len, res;
+ struct ifconf ifc;
+ struct ifreq ifs[ADDRSPERSITE];
+ struct sockaddr_in *a;
+ char *p;
+ struct ifreq ifreq;
+ size_t sz = 0;
+
+ numMyNetAddrs = 0;
+ memset(myNetAddrs, 0, sizeof(myNetAddrs));
+ memset(myNetMTUs, 0, sizeof(myNetMTUs));
+ memset(myNetFlags, 0, sizeof(myNetFlags));
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return;
+
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_buf = (caddr_t) & ifs[0];
+ memset(&ifs[0], 0, sizeof(ifs));
+
+ res = ioctl(s, SIOCGIFCONF, &ifc);
+ if (res < 0) {
+ close(s);
+ return;
+ }
+ len = ifc.ifc_len / sizeof(struct ifreq);
+ if (len > ADDRSPERSITE)
+ len = ADDRSPERSITE;
+
+ ifreq.ifr_name[0] = '\0';
+ for (p = ifc.ifc_buf; p < ifc.ifc_buf + ifc.ifc_len; p += sz) {
+ struct ifreq *ifr = (struct ifreq *)p;
+
+ sz = sizeof(*ifr);
+#ifdef SOCKADDR_HAS_SA_LEN
+ sz = max(sz, sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len);
+#endif
+ if (strncmp (ifreq.ifr_name,
+ ifr->ifr_name,
+ sizeof(ifr->ifr_name))) {
+ res = ioctl(s, SIOCGIFFLAGS, ifr);
+ if (res < 0)
+ continue;
+ if (!(ifr->ifr_flags & IFF_UP))
+ continue;
+ myNetFlags[numMyNetAddrs] = ifr->ifr_flags;
+
+ res = ioctl(s, SIOCGIFADDR, ifr);
+ if (res < 0)
+ continue;
+ a = (struct sockaddr_in *)&ifr->ifr_addr;
+ if (a->sin_family != AF_INET)
+ continue;
+ myNetAddrs[numMyNetAddrs] = ntohl(a->sin_addr.s_addr);
+
+ res = -1;
+#ifdef SIOCGIFMTU
+ res = ioctl(s, SIOCGIFMTU, ifr);
+#elif SIOCRIFMTU
+ res = ioctl(s, SIOCRIFMTU, ifr);
+#else
+ res = -1;
+#endif
+ if (res == 0) {
+ myNetMTUs[numMyNetAddrs] = ifr->ifr_metric;
+ if (rx_maxReceiveSize < (myNetMTUs[numMyNetAddrs]
+ - RX_IPUDP_SIZE))
+ rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE,
+ (myNetMTUs[numMyNetAddrs]
+ - RX_IPUDP_SIZE));
+ } else {
+ myNetMTUs[numMyNetAddrs] = OLD_MAX_PACKET_SIZE;
+ res = 0;
+ }
+ ++numMyNetAddrs;
+ ifreq = *ifr;
+ }
+ }
+
+ {
+#if 0
+ RETSIGTYPE (*old)(int);
+
+ old = signal(SIGSYS, SIG_IGN);
+ if (syscall(31 /* AFS_SYSCALL */ , 28 /* AFSCALL_CALL */ ,
+ 20 /* AFSOP_GETMTU */ , myNetAddrs[numMyNetAddrs],
+ &(myNetMTUs[numMyNetAddrs])));
+ myNetMTUs[numMyNetAddrs] = OLD_MAX_PACKET_SIZE;
+ signal(SIGSYS, old);
+#endif
+ }
+
+ close(s);
+
+ /*
+ * have to allocate at least enough to allow a single packet to reach its
+ * maximum size, so ReadPacket will work. Allocate enough for a couple
+ * of packets to do so, for good measure
+ */
+ /* MTUXXX before shipping, change this 8 to a 4 */
+ {
+ int npackets, ncbufs;
+
+ ncbufs = (rx_maxReceiveSize - RX_FIRSTBUFFERSIZE);
+ if (ncbufs > 0) {
+ ncbufs = ncbufs / RX_CBUFFERSIZE;
+ npackets = (rx_Window / 8);
+ npackets = (npackets > 2 ? npackets : 2);
+ rxi_MoreCbufs(npackets * (ncbufs + 1));
+ }
+ }
+}
+
+#endif /* ADAPT_MTU */
+
+/*
+ * Called from rxi_FindPeer, when initializing a clear rx_peer structure,
+ * to get interesting information.
+ */
+
+void
+rxi_InitPeerParams(register struct rx_peer * pp)
+{
+ register u_long ppaddr, msk, net;
+ u_short rxmtu;
+ int ix, nlix = 0, nlcount;
+ static int Inited = 0;
+
+#ifdef ADAPT_MTU
+
+ if (!Inited) {
+ GetIFInfo();
+ Inited = 1;
+ }
+ /*
+ * try to second-guess IP, and identify which link is most likely to
+ * be used for traffic to/from this host.
+ */
+ ppaddr = ntohl(pp->host);
+ if (IN_CLASSA(ppaddr))
+ msk = IN_CLASSA_NET;
+ else if (IN_CLASSB(ppaddr))
+ msk = IN_CLASSB_NET;
+ else if (IN_CLASSC(ppaddr))
+ msk = IN_CLASSC_NET;
+ else
+ msk = 0;
+ net = ppaddr & msk;
+
+ for (nlcount = 0, ix = 0; ix < numMyNetAddrs; ++ix) {
+#ifdef IFF_LOOPBACK
+ if (!(myNetFlags[ix] & IFF_LOOPBACK)) {
+ nlix = ix;
+ ++nlcount;
+ }
+#endif /* IFF_LOOPBACK */
+ if ((myNetAddrs[ix] & msk) == net)
+ break;
+ }
+
+ pp->rateFlag = 2; /* start timing after two full packets */
+ /*
+ * I don't initialize these, because I presume they are bzero'd...
+ * pp->burstSize pp->burst pp->burstWait.sec pp->burstWait.usec
+ * pp->timeout.usec
+ */
+
+ pp->maxWindow = rx_Window;
+ if (ix >= numMyNetAddrs) { /* not local */
+ pp->timeout.sec = 3;
+ pp->packetSize = RX_REMOTE_PACKET_SIZE;
+ } else {
+ pp->timeout.sec = 2;
+ pp->packetSize = MIN(RX_MAX_PACKET_SIZE,
+ (rx_MyMaxSendSize + RX_HEADER_SIZE));
+ }
+
+ /* Now, maybe get routing interface and override parameters. */
+ if (ix >= numMyNetAddrs && nlcount == 1)
+ ix = nlix;
+
+ if (ix < numMyNetAddrs) {
+#ifdef IFF_POINTOPOINT
+ if (myNetFlags[ix] & IFF_POINTOPOINT) {
+ /* wish we knew the bit rate and the chunk size, sigh. */
+ pp->maxWindow = 10;
+ pp->timeout.sec = 4;
+ /* pp->timeout.usec = 0; */
+ pp->packetSize = RX_PP_PACKET_SIZE;
+ }
+#endif /* IFF_POINTOPOINT */
+
+ /*
+ * Reduce the packet size to one based on the MTU given by the
+ * interface.
+ */
+ if (myNetMTUs[ix] > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
+ rxmtu = myNetMTUs[ix] - RX_IPUDP_SIZE;
+ if (rxmtu < pp->packetSize)
+ pp->packetSize = rxmtu;
+ }
+ }
+#else /* ADAPT_MTU */
+ pp->rateFlag = 2; /* start timing after two full packets */
+ pp->maxWindow = rx_Window;
+ pp->timeout.sec = 2;
+ pp->packetSize = OLD_MAX_PACKET_SIZE;
+#endif /* ADAPT_MTU */
+}
diff --git a/usr.sbin/afs/src/rx/rx_user.h b/usr.sbin/afs/src/rx/rx_user.h
new file mode 100644
index 00000000000..d1857897ca8
--- /dev/null
+++ b/usr.sbin/afs/src/rx/rx_user.h
@@ -0,0 +1,106 @@
+/* $OpenBSD: rx_user.h,v 1.1.1.1 1998/09/14 21:53:17 art Exp $ */
+/* $KTH: rx_user.h,v 1.5 1998/03/28 16:35:47 lha Exp $ */
+
+/*
+****************************************************************************
+* Copyright IBM Corporation 1988, 1989 - 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. *
+****************************************************************************
+*/
+
+#ifdef VALIDATE
+error - foo error - foo error - foo
+#endif /* VALIDATE */
+#ifndef RX_USER_INCLUDE
+#define RX_USER_INCLUDE
+
+/* rx_user.h: definitions specific to the user-level implementation of Rx */
+
+#include <stdio.h>
+#include <lwp.h>
+
+#ifdef RXDEBUG
+extern FILE *rx_debugFile;
+
+#endif
+
+/* These routines are no-ops in the user level implementation */
+#define SPLVAR
+#define NETPRI
+#define USERPRI
+#if defined(AFS_SGIMP_ENV)
+#define AFS_GLOCK()
+#define AFS_GUNLOCK()
+#define ISAFS_GLOCK()
+#endif
+
+extern PROCESS rx_listenerPid; /* LWP process id of socket listener
+ * process */
+void rxi_StartListener(void);
+void rxi_StartServerProcs(int);
+void rxi_ReScheduleEvents(void);
+
+void rxi_PacketsUnWait(void);
+
+/*
+ *Some "operating-system independent" stuff, for the user mode implementation
+ */
+typedef short osi_socket;
+
+osi_socket rxi_GetUDPSocket(u_short);
+
+#define OSI_NULLSOCKET ((osi_socket) -1)
+
+#define rx_Sleep(x) osi_Sleep(x)
+#define rx_Wakeup(x) osi_Wakeup(x)
+#define osi_rxSleep(x) osi_Sleep(x)
+#define osi_rxWakeup(x) osi_Wakeup(x)
+#define osi_Sleep(x) LWP_WaitProcess(x)
+#define osi_Wakeup(x) LWP_NoYieldSignal(x)
+/* osi_WakeupAndYieldIfPossible doesn't actually have to yield, but its better if it does */
+#define osi_WakeupAndYieldIfPossible(x) LWP_SignalProcess(x)
+#define osi_YieldIfPossible() LWP_DispatchProcess();
+
+#ifndef AFS_AIX32_ENV
+
+#ifndef osi_Alloc
+#define osi_Alloc(size) ((char *) malloc(size))
+#endif
+
+#ifndef osi_Free
+#define osi_Free(ptr, size) free((char *)(ptr))
+#endif
+
+#endif
+
+#ifdef USE_MMAPTIME
+#define osi_GetTime(timevalptr) mmaptime_gettimeofday(timevalptr, 0)
+#else
+#define osi_GetTime(timevalptr) gettimeofday(timevalptr, 0)
+#endif
+
+/* Just in case it's possible to distinguish between relatively long-lived stuff and stuff which will be freed very soon, but which needs quick allocation (e.g. dynamically allocated xdr things) */
+#define osi_QuickFree(ptr, size) osi_Free(ptr, size)
+#define osi_QuickAlloc(size) osi_Alloc(size)
+
+void osi_Panic(const char *fmt, ...);
+
+int fprintf(FILE *, const char *, ...);
+
+#define osi_Msg fprintf)(stderr,
+
+#endif /* RX_USER_INCLUDE */
diff --git a/usr.sbin/afs/src/rx/transarc b/usr.sbin/afs/src/rx/transarc
new file mode 100644
index 00000000000..d2ade14194c
--- /dev/null
+++ b/usr.sbin/afs/src/rx/transarc
@@ -0,0 +1,135 @@
+From Tony_Mauro@transarc.com Wed Nov 20 22:08:16 1996
+Date: Wed, 17 Jul 1996 15:35:18 -0400 (EDT)
+From: Tony_Mauro@transarc.com
+To: shadow@dementia.org
+Cc: Ken_Ziolkowski@transarc.com, Kathleen_Rizzuti@transarc.com
+Subject: answer on TR-20916
+
+Dear Derrick:
+
+Transarc's licensing coordinator, Ken Ziolkowski, asked me to write to you
+about TR-20916, to share what he learned at a recent IBM seminar on
+export controls in Washington DC.
+
+While at the seminar, he discussed with several IBM experts on US
+export regulations your proposed mechanisms for protecting the
+"DES-contaminated" parts of Rx. Unfortunately, they do not feel that
+your proposals are sufficient. I'm referring specifically to the
+possibilities you described in your mail of 6-21-96:
+
+ 2) Create a patch and do one of:
+
+ a) place it in a hidden directory on an ftp server, forcing users who
+ wish to fetch it to telnet to the machine and log in as
+ "getrx". (telnet to bitsy.mit.edu and log in as getpgp, for
+ instance) The directory is moved every 30 minutes.
+
+ b) have users send me email certifying that they are U.S. citizens, at
+ which point they will be given a pointer to the hidden
+ directory. The directory would be moved daily, like getting Kerberos
+ from Cygnus.
+
+Possibility (b) is more secure than (a), but it still falls short in
+two respects:
+
+ - email certification of US citizenship is not sufficient. It is
+ not that hard to masquerade as someone other than your true
+ identity, and even (I believe) to fake a US/Canada origination
+ address when outside those countries. You need to get written
+ certification, as I'll detail below.
+
+ - in addition to certification of citizenship, requesters need to
+ certify that they will not redistribute the software to anyone
+ ineligible to receive it.
+
+Transarc could approve your third possibility
+
+ c) I have contacted people at MIT to see if they would be interested
+ in doing distribution; It may be possible to arrange with someone
+ there to do distribution using their existing channels.
+
+on the assurance that MIT's channels would control access to DES
+as strictly as Transarc must do when it distributes software.
+
+The forms of redistribution that Transarc can approve are:
+
+First, you may redistribute the Rx source code that does not "contain any
+DES algorithms which can be used to encrypt data." In other words,
+you may implement the following part of your 6-21-96 mail:
+
+ 1) Strip away anything which might possibly be export-controlled, and
+ create a "clean" version, which will be advertised, and put in a
+ public place. Presumably removing des and rxkad, plus possibly a bit
+ more (I haven't looked yet) will be sufficient for this purpose.
+
+The US Government classifies such software as "GDTA" (I don't know
+what that stands for). Here are some guidelines that Ken picked up at
+the seminar about distributing it:
+
+ When providing GTDA software over the network (whether
+ by FTP, Web Site or other electronic means):
+
+ 1. software must be provided on a 'no charge' basis.
+
+ 2. the provider may not impose limitations or constraints on
+ the use of the software; e.g. no 'license or use' provisions are
+ applicable. The software is truly 'publicly' available.
+
+ 3. generally, it should be made available on an anonymous basis; that
+ is, you aren't collecting names and addresses. While we may be able to
+ preserve the characteristics of GTDA if we collect names and addresses
+ e.g. for future marketing purposes, I think it's much easier to
+ reconcile when we don't collect the names.
+
+Second, for your own protection against prosecution, we must strongly
+recommend that you drop the idea of distributing the DES source
+version of Rx. The US Government classifies software that uses the DES
+algorithms to encrypt data as a ``munition'' and imposes strict
+penalties for non-authorized distribution. If you use mechanism (a) or
+(b) from above, you would be in violation of Federal law.
+
+To comply with the law, you would need to have requestors sign a
+written copy of something like the following, which is taken from the
+AFS License Agreement:
+
+ The End-user hereby agrees and acknowledges that any technology and
+ technical data obtained by the end-user, including the
+ ___________________ software, are under the jurisdiction of the export
+ control laws and regulations of the United States and that any direct
+ or indirect export, re-export, license, sale or other transfer of such
+ technology may require the prior authorization of the United States
+ government. The end-user expressly warrants that in its activities
+ under this Agreement it will comply with all applicable laws and
+ regulations of the United States and its departments and agencies
+ relating to the export of technical data. In the event of any breach
+ of the foregoing warranty, the end-user hereby indemnifies
+ _________________(the parties providing the technology/technical
+ data/software) and agrees to hold such parties harmless from and
+ against any loss, liability, cost, damage or expense that such parties
+ incurs or suffers as a result in any way of the end-user's failure to
+ comply with such United States laws and regulations.
+
+Obviously, you would need to protect the software against access by
+anyone who had not signed such a statement.
+
+The US Government's attitude toward this issue is serious enough that
+Transarc would be liable for prosecution if we were aware you were
+planning to (or actually did) go ahead and use one of your proposed
+mechanisms, and did not try to get you to stop. Therefore, Ken will
+be sending you a written confirmation basically repeating what I've
+said here.
+
+Ken and I would both like to apologize for any damper this puts on our
+plans. We recognize that you are trying to do a service to the
+software community, but unfortunately the export laws do not take good
+intentions into consideration. Further, we appreciate very much that
+you asked us about redistributing Rx before actually doing it. I'm
+sorry if you feel penalized for being honest.
+
+Please feel free to call or write me (mauro@transarc.com; 281-5852
+x7376) or Ken (kenz@transarc.com; 338-4480) if you have any further
+questions.
+
+
+Tony Mauro
+Transarc AFS Support
diff --git a/usr.sbin/afs/src/rxdef/cb.xg b/usr.sbin/afs/src/rxdef/cb.xg
new file mode 100644
index 00000000000..7613145da44
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/cb.xg
@@ -0,0 +1,33 @@
+/* This is -*-c-*- */
+
+/*
+ * Interface to CM
+ */
+
+package RXAFSCB_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+/*%#include "fs.h"*/
+
+/*
+ * Interface
+ */
+
+#include "common.h"
+
+#if 0
+const AFSCBMAX = 50;
+
+typedef AFSCallBack AFSCBs<AFSCBMAX>;
+
+typedef AFSFid AFSCBFids<AFSCBMAX>;
+#endif
+
+CallBack (IN AFSCBFids *a_fidArrayP,
+ IN AFSCBs *a_callBackArrayP) = 204;
+
+InitCallBackState () = 205;
+
+Probe () = 206;
diff --git a/usr.sbin/afs/src/rxdef/common.h b/usr.sbin/afs/src/rxdef/common.h
new file mode 100644
index 00000000000..8e817555a57
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/common.h
@@ -0,0 +1,166 @@
+/* $OpenBSD: common.h,v 1.1.1.1 1998/09/14 21:53:18 art Exp $ */
+/*
+ * Common defintions for cb.xg and fs.xg
+ */
+
+/* $KTH: common.h,v 1.8 1998/09/03 18:47:29 lha Exp $ */
+
+%#ifndef _COMMON_
+%#define _COMMON_
+
+const LockRead = 0;
+const LockWrite = 1;
+const LockExtend = 2;
+const LockRelease = 3;
+
+const AFSNAMEMAX = 256;
+
+struct AFSFid {
+ unsigned long Volume;
+ unsigned long Vnode;
+ unsigned long Unique;
+};
+
+struct VenusFid {
+ long Cell;
+ AFSFid fid;
+};
+
+struct AFSCallBack {
+ unsigned long CallBackVersion;
+ unsigned long ExpirationTime;
+ unsigned long CallBackType;
+};
+
+enum CallBackType { CBEXCLUSIVE = 1, CBSHARED = 2, CBDROPPED = 3};
+
+struct AFSVolSync {
+ unsigned spare1;
+ unsigned spare2;
+ unsigned spare3;
+ unsigned spare4;
+ unsigned spare5;
+ unsigned spare6;
+};
+
+const TYPE_FILE = 1;
+const TYPE_DIR = 2;
+const TYPE_LINK = 3;
+
+struct AFSFetchStatus {
+ unsigned long InterfaceVersion;
+ unsigned long FileType;
+ unsigned long LinkCount;
+ unsigned long Length;
+ unsigned long DataVersion;
+ unsigned long Author;
+ unsigned long Owner;
+ unsigned long CallerAccess;
+ unsigned long AnonymousAccess;
+ unsigned long UnixModeBits;
+ unsigned long ParentVnode;
+ unsigned long ParentUnique;
+ unsigned long SegSize;
+ unsigned long ClientModTime;
+ unsigned long ServerModTime;
+ unsigned long Group;
+ unsigned long SyncCount;
+ unsigned spare1;
+ unsigned spare2;
+ unsigned spare3;
+ unsigned spare4;
+};
+
+/*
+ * Things in AFSStoreStatus.mask
+ */
+
+const SS_MODTIME = 0x01 ;
+const SS_OWNER = 0x02 ;
+const SS_GROUP = 0x04 ;
+const SS_MODEBITS = 0x08 ;
+const SS_SEGSIZE = 0x0F ;
+
+struct AFSStoreStatus {
+ unsigned long Mask;
+ unsigned long ClientModTime;
+ unsigned long Owner;
+ unsigned long Group;
+ unsigned long UnixModeBits;
+ unsigned long SegSize;
+};
+
+struct AFSFetchVolumeStatus {
+ int32_t Vid;
+ int32_t ParentId;
+ char Online;
+ char InService;
+ char Blessed;
+ char NeedsSalvage;
+ int32_t Type;
+ int32_t MinQuota;
+ int32_t MaxQuota;
+ int32_t BlocksInUse;
+ int32_t PartBlocksAvail;
+ int32_t PartMaxBlocks;
+};
+
+struct AFSStoreVolumeStatus {
+ int32_t Mask;
+ int32_t MinQuota;
+ int32_t MaxQuota;
+};
+
+const AFSOPAQUEMAX = 1024;
+
+typedef opaque AFSOpaque<AFSOPAQUEMAX>;
+
+typedef long ViceLockType;
+
+const AFSCBMAX = 50;
+
+typedef AFSCallBack AFSCBs<AFSCBMAX>;
+typedef AFSFetchStatus AFSBulkStats<AFSCBMAX>;
+typedef AFSFid AFSCBFids<AFSCBMAX>;
+
+/* Definitions for ACLs */
+
+const PRSFS_READ = 1 ; /* Read files */
+const PRSFS_WRITE = 2 ; /* Write files & write-lock existing files */
+const PRSFS_INSERT = 4 ; /* Insert & write-lock new files */
+const PRSFS_LOOKUP = 8 ; /* Enumerate files and examine ACL */
+const PRSFS_DELETE = 16 ; /* Remove files */
+const PRSFS_LOCK = 32 ; /* Read-lock files */
+const PRSFS_ADMINISTER = 64 ; /* Set access list of directory */
+
+struct AFSVolumeInfo {
+ u_long Vid;
+ long Type;
+ u_long Type0;
+ u_long Type1;
+ u_long Type2;
+ u_long Type3;
+ u_long Type4;
+ u_long ServerCount;
+ u_long Server0;
+ u_long Server1;
+ u_long Server2;
+ u_long Server3;
+ u_long Server4;
+ u_long Server5;
+ u_long Server6;
+ u_long Server7;
+ unsigned short Port0;
+ unsigned short Port1;
+ unsigned short Port2;
+ unsigned short Port3;
+ unsigned short Port4;
+ unsigned short Port5;
+ unsigned short Port6;
+ unsigned short Port7;
+};
+
+
+
+
+%#endif /* _COMMON_ */
diff --git a/usr.sbin/afs/src/rxdef/fs.xg b/usr.sbin/afs/src/rxdef/fs.xg
new file mode 100644
index 00000000000..ee7136042a3
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/fs.xg
@@ -0,0 +1,146 @@
+/* This is -*-c-*- */
+
+/*
+ * Interface to FS
+ */
+
+package RXAFS_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+
+#include "common.h"
+
+/*
+ * Interface
+ */
+
+FetchData (IN AFSFid *a_fidToFetchP,
+ IN long a_offset,
+ IN long a_lenInBytes,
+ OUT AFSFetchStatus *a_fidStatP,
+ OUT AFSCallBack *a_callBackP,
+ OUT AFSVolSync *a_volSyncP) split = 130;
+
+FetchACL (IN AFSFid *a_dirFidP,
+ OUT AFSOpaque *a_ACLP,
+ OUT AFSFetchStatus *a_dirNewStatP,
+ OUT AFSVolSync *a_volSyncP) = 131;
+
+FetchStatus (IN AFSFid *a_fidToStatP,
+ OUT AFSFetchStatus *a_currStatP,
+ OUT AFSCallBack *a_callBackP,
+ OUT AFSVolSync *a_volSyncP) = 132;
+
+StoreData (IN AFSFid *a_fidToStoreP,
+ IN AFSStoreStatus *a_fidStatusP,
+ IN long a_offset,
+ IN long a_lenInBytes,
+ IN long a_fileLenInBytes,
+ OUT AFSFetchStatus *a_fidStatP,
+ OUT AFSCallBack *a_callBackP,
+ OUT AFSVolSync *a_volSyncP) split = 133;
+
+/*
+ * Correct documentation wouldn't make this fun enough. Gaah.
+ */
+StoreACL (IN AFSFid *a_dirFidP,
+ IN AFSOpaque *a_ACLToStoreP,
+ OUT AFSFetchStatus *a_dirNewStatP,
+ OUT AFSVolSync *a_volSyncP) = 134;
+
+StoreStatus (IN AFSFid *a_fidP,
+ IN AFSStoreStatus *a_currStatusP,
+ OUT AFSFetchStatus *a_srStatusP,
+ OUT AFSVolSync *a_volSyncP) = 135;
+
+RemoveFile (IN AFSFid *a_dirFidP,
+ IN string a_name<AFSNAMEMAX>,
+ OUT AFSFetchStatus *a_srvStatusP,
+ OUT AFSVolSync *a_volSyncP) = 136;
+
+CreateFile (IN AFSFid *DirFid,
+ IN string Name<AFSNAMEMAX>,
+ IN AFSStoreStatus *InStatus,
+ OUT AFSFid *OutFid,
+ OUT AFSFetchStatus *OutFidStatus,
+ OUT AFSFetchStatus *OutDirStatus,
+ OUT AFSCallBack *CallBack,
+ OUT AFSVolSync *a_volSyncP) = 137;
+
+Rename (IN AFSFid *a_origDirFidP,
+ IN string a_origNameP<AFSNAMEMAX>,
+ IN AFSFid *a_newDirFidP,
+ IN string a_newNameP<AFSNAMEMAX>,
+ OUT AFSFetchStatus *a_origDirStatusP,
+ OUT AFSFetchStatus *a_newDirStatusP,
+ OUT AFSVolSync *a_volSyncP) = 138;
+
+Symlink (IN AFSFid *a_dirFidP,
+ IN string a_nameP<AFSNAMEMAX>,
+ IN string a_linkContentsP<AFSNAMEMAX>,
+ IN AFSStoreStatus *a_origDirStatP,
+ OUT AFSFid *a_newFidP,
+ OUT AFSFetchStatus *a_newFidStatP,
+ OUT AFSFetchStatus *a_newDirStatP,
+ OUT AFSVolSync *a_volSyncP) = 139;
+
+Link (IN AFSFid *a_dirFidP,
+ IN string a_nameP<AFSNAMEMAX>,
+ IN AFSFid *a_existingFidP,
+ OUT AFSFetchStatus *a_newFidStatP,
+ OUT AFSFetchStatus *a_newDirStatP,
+ OUT AFSVolSync *a_volSyncP) = 140;
+
+MakeDir (IN AFSFid *a_parentDirFidP,
+ IN string a_newDirNameP<AFSNAMEMAX>,
+ IN AFSStoreStatus *a_currStatP,
+ OUT AFSFid *a_newDirFidP,
+ OUT AFSFetchStatus *a_dirFidStatP,
+ OUT AFSFetchStatus *a_parentDirStatP,
+ OUT AFSCallBack *a_newDirCallBackP,
+ OUT AFSVolSync *a_volSyncP) = 141;
+
+RemoveDir (IN AFSFid *a_parentDirStatP,
+ IN string a_dirNameP<AFSNAMEMAX>,
+ OUT AFSFetchStatus *a_newParentDirStatP,
+ OUT AFSVolSync *a_volSyncP) = 142;
+
+GiveUpCallBacks (IN AFSCBFids *a_fidArrayP,
+ IN AFSCBs *a_callBackArrayP) = 147;
+
+GetVolumeStatus (IN long a_volIDP,
+ OUT AFSFetchVolumeStatus *a_volFetchStatP,
+ OUT string a_volNameP<AFSNAMEMAX>,
+ OUT string a_offLineMsgP<AFSOPAQUEMAX>,
+ OUT string a_motdP<AFSOPAQUEMAX>) = 149;
+
+SetVolumeStatus (IN long a_volIDP,
+ IN AFSStoreVolumeStatus *a_volStoreStatP,
+ IN string a_volNameP<AFSNAMEMAX>,
+ IN string a_offLineMsgP<AFSOPAQUEMAX>,
+ IN string a_motdP<AFSOPAQUEMAX>) = 150;
+
+GetRootVolume (OUT string a_rootVolNameP<AFSNAMEMAX>) = 151;
+
+GetTime (OUT unsigned long *a_secondsP,
+ OUT unsigned long *a_uSecondsP) = 153;
+
+NGetVolumeInfo (IN string VolumeName<AFSNAMEMAX>,
+ OUT AFSVolumeInfo *stuff) = 154;
+
+BulkStatus (IN AFSCBFids *FidsArray,
+ OUT AFSBulkStats *StatArray,
+ OUT AFSCBs *CBArray,
+ OUT AFSVolSync *Sync) = 155;
+
+SetLock (IN AFSFid *Fid,
+ IN ViceLockType Type,
+ OUT AFSVolSync *Sync) = 156;
+
+ExtendLock (IN AFSFid *Fid,
+ OUT AFSVolSync *Sync) = 157;
+
+ReleaseLock (IN AFSFid *Fid,
+ OUT AFSVolSync *Sync) = 158;
diff --git a/usr.sbin/afs/src/rxdef/pts.xg b/usr.sbin/afs/src/rxdef/pts.xg
new file mode 100644
index 00000000000..510294a8aa7
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/pts.xg
@@ -0,0 +1,303 @@
+/* This is -*-c-*- */
+
+/*
+ * Interface to PTS
+ */
+
+package PR_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+
+
+/*
+ * Interface
+ */
+
+
+/* Opcodes */
+
+const PRINEWUSER = 500;
+const PRWHEREISIT = 501;
+const PRDUMPENTRY = 502;
+const PRADDTOGROUP = 503;
+const PRNAMETOUID = 504;
+const PRIDTONAME = 505;
+const PRDELETE = 506;
+const PRREMOVEFROMGROUP = 507;
+const PRGETCPS = 508;
+const PRNEWENTRY = 509;
+const PRLISTMAX = 510;
+const PRSETMAX = 511;
+const PRLISTENTRY = 512;
+const PRCHANGEENTRY = 513;
+const PRLISTELEMENTS = 514;
+const PROSAMEMBEROF = 515;
+const PRSETFIELDSENTRY = 516;
+const PRLISTOWNED = 517;
+
+/* Constants */
+
+const PR_MAXNAMELEN = 64;
+const PR_MAXGROUPS = 5000;
+const PR_MAXLIST = 5000;
+const PRSIZE = 10;
+const COSIZE = 39;
+const PRSRV = 73;
+const ENTRYSIZE = 192;
+const HASHSIZE = 8191;
+
+const PRDBVERSION = 0;
+
+/* Bits for PR_SetFieldsEntry() */
+
+const PR_SF_NGROUPS = 0x80000000;
+const PR_SF_NUSERS = 0x40000000;
+const PR_SF_ALLBITS = 0xff;
+
+/* Reserved IDs */
+const SYSADMINID = -204;
+const ANYUSERID = -101;
+const AUTHUSERID = -102;
+const ANONYMOUSID = 32766;
+const PRBADID = 0x80000000;
+
+/* Bits for struct prentry flags */
+const PRTYPE = 0x3f;
+const PRFREE = 1;
+const PRGRP = 2;
+const PRCONT = 4;
+const PRCELL = 8;
+const PRFOREIGN = 16;
+const PRINST = 32;
+const PRUSER = 0;
+
+const PRACCESS = 0x40;
+const PRQUOTA = 0x80;
+
+/* Privacy Bits */
+
+const PRP_REMOVE_MEM = 0x010000;
+const PRP_ADD_MEM = 0x020000;
+const PRP_ADD_ANY = 0x040000;
+const PRP_MEMBER_MEM = 0x080000;
+const PRP_MEMBER_ANY = 0x100000;
+const PRP_OWNED_ANY = 0x200000;
+const PRP_STATUS_MEM = 0x400000;
+const PRP_STATUS_ANY = 0x800000;
+
+/* Misc */
+const PRSUCCESS = 0;
+const PR_REMEMBER_TIMES = 1;
+
+
+struct prheader {
+ long version;
+ long headerSize;
+ long freePtr;
+ long eofPtr;
+ long maxGroup;
+ long maxID;
+ long maxForeign;
+ long maxInst;
+ long orphan;
+ long usercount;
+ long groupcount;
+ long foreigncount;
+ long instcount;
+ long reserved[5];
+ long nameHash[HASHSIZE];
+ long idHash[HASHSIZE];
+};
+
+struct prentry {
+ long flags;
+ long id;
+ long cellid;
+ long next;
+ long reserved[5];
+ long entries[PRSIZE];
+ long nextID;
+ long nextName;
+ long owner;
+ long creator;
+ long ngroups;
+ long nusers;
+ long count;
+ long instance;
+ long owned;
+ long nextOwned;
+ long parent;
+ long sibling;
+ long child;
+ char name[PR_MAXNAMELEN];
+};
+
+struct prentry_disk {
+ long flags;
+ long id;
+ long cellid;
+ long next;
+ long reserved[5];
+ long entries[PRSIZE];
+ long nextID;
+ long nextName;
+ long owner;
+ long creator;
+ long ngroups;
+ long nusers;
+ long count;
+ long instance;
+ long owned;
+ long nextOwned;
+ long parent;
+ long sibling;
+ long child;
+ string name<PR_MAXNAMELEN>;
+};
+
+struct contentry {
+ long flags;
+ long id;
+ long cellid;
+ long next;
+ long reserved[5];
+ long entries[COSIZE];
+};
+
+struct prdebugentry {
+ long flags;
+ long id;
+ long cellid;
+ long next;
+ long reserved[5];
+ long entries[PRSIZE];
+ long nextID;
+ long nextname;
+ long owner;
+ long creator;
+ long ngroups;
+ long nusers;
+ long count;
+ long instance;
+ long owned;
+ long nextOwned;
+ long parent;
+ long sibling;
+ long child;
+ char name[PR_MAXNAMELEN];
+};
+
+struct prcheckentry {
+ long flags;
+ long id;
+ long owner;
+ long creator;
+ long ngroups;
+ long nusers;
+ long count;
+ long reserved[5];
+ char name[PR_MAXNAMELEN];
+};
+
+
+typedef char prname[PR_MAXNAMELEN];
+
+typedef prname namelist<PR_MAXLIST>;
+
+typedef long idlist<PR_MAXLIST>;
+
+typedef long prlist<PR_MAXGROUPS>;
+
+
+/* Error codes */
+
+const PREXIST = 267264 ;
+const PRIDEXIST = 267265 ;
+const PRNOIDS = 267266 ;
+const PRDBFAIL = 267267 ;
+const PRNOENT = 267268 ;
+const PRPERM = 267269 ;
+const PRNOTGROUP = 267270 ;
+const PRNOTUSER = 267271 ;
+const PRBADNAM = 267272 ;
+const PRBADARG = 267273 ;
+const PRNOMORE = 267274 ;
+const PRDBBAD = 267275 ;
+const PRGROUPEMPTY = 267276 ;
+const PRINCONSISTENT = 267277 ;
+const PRBADDR = 267278 ;
+const PRTOOMANY = 267279 ;
+
+
+NameToID(IN namelist *nlist,
+ OUT idlist *ilist) = 504;
+
+IDToName(IN idlist *ilist,
+ OUT namelist *nlist) = 505;
+
+NewEntry(IN char name[PR_MAXNAMELEN],
+ IN long flag,
+ IN long oid,
+ OUT long *id) = 509;
+
+INewEntry(IN char name[PR_MAXNAMELEN],
+ IN long id,
+ IN long oid) = 500;
+
+ListEntry(IN long id,
+ OUT struct prcheckentry *entry) = 512;
+
+DumpEntry(IN long pos,
+ OUT struct prdebugentry *entry) = 502;
+
+ChangeEntry(IN long id,
+ IN char name[PR_MAXNAMELEN],
+ IN long oid,
+ IN long newid) = 513;
+
+SetFieldesEntry(IN long id,
+ IN long mask,
+ IN long flags,
+ IN long ngroups,
+ IN long nusers,
+ IN long spare1,
+ IN long spare2) = 516;
+
+Delete(IN long id) = 506;
+
+WhereIsIt(IN long id,
+ OUT long *ps) = 501;
+
+AddToGroup(IN long uid,
+ IN long gid) = 503;
+
+RemoveFromGroup(IN long id,
+ IN long gid) = 507;
+
+ListMax(OUT long *uid,
+ OUT long *gid) = 510;
+
+SetMax(IN long uid,
+ IN long gflag) = 511;
+
+ListElements(IN long id,
+ OUT prlist *elist,
+ OUT long *over) = 514;
+
+GetCPS(IN long id,
+ OUT prlist *elist,
+ OUT long *over) = 508;
+
+ListOwned(IN long id,
+ OUT prlist *elist,
+ OUT long *over) = 517;
+
+IsAMemberOf(IN long uid,
+ IN long gid,
+ OUT long *flag) = 515;
+
+
+
+/* the end */
diff --git a/usr.sbin/afs/src/rxdef/ubik.xg b/usr.sbin/afs/src/rxdef/ubik.xg
new file mode 100644
index 00000000000..78eecc0f6d5
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/ubik.xg
@@ -0,0 +1,88 @@
+/* -*- C -*- */
+
+/*
+ * $Id: ubik.xg,v 1.1.1.1 1998/09/14 21:53:18 art Exp $
+ */
+
+package Ubik_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+
+/*
+ * Interface
+ */
+
+struct net_tid {
+ long epoch;
+ long counter;
+};
+
+typedef net_tid net_version;
+
+struct ubik_debug {
+ long now;
+ long lastYesTime;
+ long lastYesHost;
+ long lastYesState;
+ long lastYesClaim;
+ long lowestHost;
+ long lowestTime;
+ long syncHost;
+ long syncTime;
+ struct net_version syncVersion;
+ struct net_tid syncTid;
+ long amSyncSite;
+ long syncSiteUntil;
+ long nServers;
+ long lockedPages;
+ long writeLockedPages;
+ struct net_version localVersion;
+ long activeWrite;
+ long tidCounter;
+ long anyReadLocks;
+ long anyWriteLocks;
+ long recoveryState;
+ long currentTrans;
+ long writeTrans;
+ long epochTime;
+};
+
+struct ubik_sdebug {
+ long addr;
+ long lastVoteTime;
+ long lastBeaconSent;
+ long lastVote;
+ struct net_version remoteVersion;
+ long currentDB;
+ long beaconSinceDown;
+ long up;
+};
+
+
+
+/* Opcodes */
+
+const VOTE_BEACON = 10000 ;
+const VOTE_DEBUG = 10001 ;
+const VOTE_SDEBUG = 10002 ;
+const VOTE_GETSYNCSITE = 10003 ;
+
+/* Error codes */
+
+/* XXX */
+
+
+/* The rpc calls */
+
+Beacon (IN long state,
+ IN long voteStart,
+ IN net_version *Version,
+ IN net_tid *tid) multi = 10000;
+
+Debug (OUT ubik_debug *db) = 10001 ;
+
+SDebug (IN long which, OUT ubik_sdebug *db) = 10002 ;
+
+GetSyncSite (OUT long *site) = 10003 ;
diff --git a/usr.sbin/afs/src/rxdef/vldb.xg b/usr.sbin/afs/src/rxdef/vldb.xg
new file mode 100644
index 00000000000..23eb49c9dee
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/vldb.xg
@@ -0,0 +1,265 @@
+/* This is -*-c-*- */
+
+/*
+ * Interface to VLDB
+ */
+
+package VL_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+
+/*
+ * Structures and defines for vldb data
+ */
+
+const VLDB_MAXNAMELEN=65;
+
+const MAXNSERVERS=8;
+const NMAXNSERVERS=13;
+
+const MAX_NUMBER_OPCODES=30;
+
+const MAXTYPES=3;
+
+const MAXSERVERID=30;
+
+const HASHSIZE=8191;
+
+const DEFAULTBULK=10000;
+
+typedef opaque bulk<DEFAULTBULK>;
+
+#if 0
+typedef struct single_vldbentry *vldblist;
+#endif
+
+const RWVOL = 0;
+const ROVOL = 1;
+const BACKVOL = 2;
+
+const VLSF_NEWREPSITE = 0x01;
+const VLSF_ROVOL = 0x02;
+const VLSF_RWVOL = 0x04;
+const VLSF_BACKVOL = 0x08;
+
+const VLF_RWEXISTS = 0x1000;
+const VLF_ROEXISTS = 0x2000;
+const VLF_BOEXISTS = 0x4000;
+const VLF_BACKEXISTS = 0x4000;
+
+const VL_IDEXIST = 363520;
+const VL_IO = 363521;
+const VL_NAMEEXIST = 363522;
+const VL_CREATEFAIL = 363523;
+const VL_NOENT = 363524;
+const VL_EMPTY = 363525;
+const VL_ENTDELETED = 363526;
+const VL_BADNAME = 363527;
+const VL_BADINDEX = 363528;
+const VL_BADVOLTYPE = 363529;
+const VL_BADPARTITION = 363530;
+const VL_BADSERVER = 363531;
+const VL_REPSFULL = 363532;
+const VL_NOREPSERVER = 363533;
+const VL_DUPREPSERVER = 363534;
+const VL_RWNOTFOUND = 363535;
+const VL_BADREFCOUNT = 363536;
+const VL_SIZEEXCEEDED = 363537;
+const VL_BADENTRY = 363538;
+const VL_BADVOLIDBUMP = 363539;
+const VL_IDALREADHASED = 363540;
+const VL_ENTRYLOCKED = 363541;
+const VL_BADVOLOPER = 363542;
+const VL_BADRELLOCKTYPE= 363543;
+const VL_RERELEASE = 363544;
+const VL_BADSERVERFLAG = 363545;
+const VL_PERM = 363546;
+const VL_NOMEM = 363547;
+
+
+struct vldbentry {
+ char name[VLDB_MAXNAMELEN];
+ long volumeType;
+ long nServers;
+ long serverNumber[MAXNSERVERS];
+ long serverPartition[MAXNSERVERS];
+ long serverFlags[MAXNSERVERS];
+ u_long volumeId[MAXTYPES];
+ long cloneId;
+ long flags;
+};
+
+struct nvldbentry {
+ char name[VLDB_MAXNAMELEN];
+ long nServers;
+ long serverNumber[NMAXNSERVERS];
+ long serverPartition[NMAXNSERVERS];
+ long serverFlags[NMAXNSERVERS];
+ u_long volumeId[MAXTYPES];
+ long cloneId;
+ long flags;
+ long spares1;
+ long spares2;
+ long spares3;
+ long spares4;
+ long spares5;
+ long spares6;
+ long spares7;
+ long spares8;
+ long spares9;
+};
+
+
+struct vital_vlheader {
+ long vldbversion;
+ long headersize;
+ long feePtr;
+ long eofPtr;
+ long allocs;
+ long frees;
+ long MaxVolumeId;
+ long totalEntries[MAXTYPES];
+};
+
+struct VldbUpdateEntry {
+ u_long Mask;
+ char name[VLDB_MAXNAMELEN];
+ long volumeType;
+ long flags;
+ u_long ReadOnlyId;
+ u_long BackupId;
+ long cloneid;
+ long nModifiedRepsites;
+ u_long RepsitesMask[MAXNSERVERS];
+ long RepsitesTargetServer[MAXNSERVERS];
+ long RepsitesTargetPart[MAXNSERVERS];
+ long RepsitesNewServer[MAXNSERVERS];
+ long RepsitesNewPart[MAXNSERVERS];
+ long RepsitesNewFlags[MAXNSERVERS];
+};
+
+struct VldbListByAttributes {
+ u_long Mask;
+ long server;
+ long partition;
+ long volumetype;
+ long volumeid;
+ long flag;
+};
+
+struct afsUUID {
+ u_long time_low;
+ u_short time_mid;
+ u_short time_hi_and_version;
+ char clock_seq_hi_and_reserved;
+ char clock_seq_low;
+ char node[6];
+};
+
+struct uvldbentry {
+ char name[VLDB_MAXNAMELEN];
+ long nServers;
+ afsUUID serverNumber[NMAXNSERVERS];
+ long serverUnique[NMAXNSERVERS];
+ long serverPartition[NMAXNSERVERS];
+ long serverFlags[NMAXNSERVERS];
+ u_long volumeId[MAXTYPES];
+ long cloneId;
+ long flags;
+ long spares1;
+ long spares2;
+ long spares3;
+ long spares4;
+ long spares5;
+ long spares6;
+ long spares7;
+ long spares8;
+ long spares9;
+};
+
+
+#if 0
+struct single_vldbentry {
+ vldbentry VldbEntry;
+ vldblist next_vldb;
+};
+
+struct vldb_list {
+ vldblist node;
+};
+#endif
+
+struct vldstats {
+ unsigned long start_time;
+ long requests[MAX_NUMBER_OPCODES];
+ long aborts[MAX_NUMBER_OPCODES];
+ long reserved[5];
+};
+
+typedef vldbentry bulkentries<>;
+
+/*
+ * Interface
+ */
+
+CreateEntry (IN vldbentry *newentry) = 501;
+
+DeleteEntry (IN long Volid,
+ IN long voltype) = 502;
+
+GetEntryByID (IN long Volid,
+ IN long voltype,
+ OUT vldbentry *entry) = 503;
+
+GetEntryByName (IN string volumename<VLDB_MAXNAMELEN>,
+ OUT vldbentry *entry) = 504;
+
+GetNewVolumeId (IN long bumpcount,
+ OUT long *newvolumid) = 505;
+
+ReplaceEntry (IN long Volid,
+ IN long voltype,
+ IN vldbentry *newentry,
+ IN long ReleaseType) = 506;
+
+UpdateEntry (IN long Volid,
+ IN long voltype,
+ IN VldbUpdateEntry *UpdateEntry,
+ IN long ReleaseType) = 507;
+
+SetLock (IN long Volid,
+ IN long voltype,
+ IN long voloper) = 508;
+
+ReleaseLock (IN long volid,
+ IN long voltype,
+ IN long ReleaseType) = 509;
+
+ListEntry (IN long previous_index,
+ OUT long *count,
+ OUT long *next_index,
+ OUT vldbentry *entry) = 510;
+
+ListAttributes (IN VldbListByAttributes *attributes,
+ OUT long *nentries,
+ OUT bulkentries *blkentries) = 511;
+
+#if 0
+LinkedList (IN VldbListByAttributes *attributes,
+ OUT long *nentries,
+ OUT vldb_list *linkedentries) = 512;
+#endif
+
+GetStats (OUT vldstats *stats,
+ OUT vital_vlheader *vital_header) = 513;
+
+Probe () = 514;
+
+GetEntryByNameN(IN string volumename<VLDB_MAXNAMELEN>,
+ OUT nvldbentry *entry) = 519;
+
+
+GetEntryByNameU (IN string volumename<VLDB_MAXNAMELEN>,
+ OUT struct uvldbentry *entry) = 527;
diff --git a/usr.sbin/afs/src/rxdef/volumeserver.xg b/usr.sbin/afs/src/rxdef/volumeserver.xg
new file mode 100644
index 00000000000..07313e084c0
--- /dev/null
+++ b/usr.sbin/afs/src/rxdef/volumeserver.xg
@@ -0,0 +1,239 @@
+/*
+ * Interface to Volumeserver,
+ * reference /afs/nada.kth.se/misc/reference/programming/afs/shadow/
+ *
+ * $Id: volumeserver.xg,v 1.1.1.1 1998/09/14 21:53:18 art Exp $
+ */
+
+package VOLSER_
+
+%#include <atypes.h>
+%#include <rx/rx.h>
+%#include <rx/rx_null.h>
+
+const VLDB_MAXSERVER = 80;
+const VOLSERVICE_PORT = 7005;
+const VOLSERVICE_ID = 4;
+const INVALID_BID = 0;
+const VOLSER_MAXVOLNAME = 65;
+const VOLSER_OLDMAXVOLNAME = 32;
+const VOLSER_MAX_REPSITES = 7;
+const VNAMESIZE = 32;
+
+
+const VOLCREATEVOLUME = 100;
+const VOLDELETEVOLUME = 101;
+const VOLRESTORE = 102;
+const VOLFORWARD = 103;
+const VOLENDTRANS = 104;
+const VOLCLONE = 105;
+const VOLSETFLAGS = 106;
+const VOLGETFLAGS = 107;
+const VOLTRANSCREATE = 108;
+const VOLDUMP = 109;
+const VOLGETNTHVOLUME = 110;
+const VOLSETFORWARDING = 111;
+const VOLGETNAME = 112;
+const VOLGETSTATUS = 113;
+const VOLSIGRESTORE = 114;
+const VOLLISTPARTITIONS = 115;
+const VOLLISTVOLS = 116;
+const VOLSETIDTYPES = 117;
+const VOLMONITOR = 118;
+const VOLDISKPART = 119;
+const VOLRECLOSE = 120;
+const VOLLISTONEVOL = 121;
+const VOLNUKE = 122;
+const VOLSETDATE = 123;
+
+const PARTVALID = 0x01;
+const VOK = 0x02;
+const VBUSY = 110;
+
+const VOLSERTRELE_ERROR = 1492325120 ;
+const VOLSERNO_OP = 1492325121 ;
+const VOLSERREAD_DUMPERROR = 1492325122 ;
+const VOLSERDUMPERROR = 1492325123 ;
+const VOLSERATTACH_ERROR = 1492325124 ;
+const VOLSERILLEGAL_PARTITION = 1492325125 ;
+const VOLSERDETACH_ERROR = 1492325126 ;
+const VOLSERBAD_ACCESS = 1492325127 ;
+const VOLSERVLDB_ERROR = 1492325128 ;
+const VOLSERBADNAME = 1492325129 ;
+const VOLSERVOLMOVED = 1492325130 ;
+const VOLSERBADOP = 1492325131 ;
+const VOLSERBADRELEASE = 1492325132 ;
+const VOLSERVOLBUSY = 1492325133 ;
+const VOLSERNO_MEMORY = 1492325134 ;
+const VOLSERNOVOL = 1492325135 ;
+const VOLSERMULTIRWVOL = 1492325136 ;
+const VOLSERFAILEDOP = 1492325137 ;
+
+struct volser_trans {
+ volser_trans *next;
+ long tid;
+ long time;
+ long creationTime;
+ long returnCode;
+ long volid;
+ long partition;
+ long dumpTransId;
+ long dumpSeq; /* Not used */
+ short refCount;
+ short iflags;
+ char vflags;
+ char tflags;
+ char incremental;
+ char lastProcName[30];
+/* struct rx_call *rxCallPtr; XXXXXXX BROKEN /lha */
+};
+
+struct volDescription {
+ char volName[VOLSER_MAXVOLNAME];
+ long volId;
+ long volSize;
+ long volFlags;
+ long volCloneId;
+};
+
+struct partList {
+ int partId[26];
+ long partFlags[26];
+};
+
+struct volser_status {
+ long volID;
+ long nextUnique;
+ long type;
+ long parentID;
+ long cloneID;
+ long backupID;
+ long restoredFromID;
+ long maxQuota;
+ long minQuota;
+ long owner;
+ long creationDate;
+ long accessDate;
+ long updateDate;
+ long exprirationDate;
+ long backupDate;
+ long copyDate;
+};
+
+struct destServer {
+ long destHost;
+ long destPort;
+ long destSSID; /* currently allways set to 1 */
+};
+
+struct volintInfo {
+ char name[VNAMESIZE];
+ long volid;
+ long type;
+ long backupID;
+ long parentID;
+ long cloneID;
+ long status;
+ long copyDate;
+ char inUse;
+ char needsSalvaged;
+ char destroyMe;
+ long creationDate;
+ long accessDate;
+ long updateDate;
+ long backupDate;
+ long dayUse;
+ long filecount;
+ long maxquota;
+ long size;
+ long flags;
+ long spare0;
+ long spare1;
+ long spare2;
+ long spare3;
+};
+
+struct transDebugInfo {
+ long tid;
+ long time;
+ long creationTime;
+ long returnCode;
+ long volid ;
+ long partition;
+ short iflags;
+ char vflags;
+ char tflags;
+ char lastProcName[30];
+ long callValid;
+ long readNext;
+ long transmitNext;
+ long lastSendTime;
+ long lastReceiveTime;
+};
+
+struct pIDs {
+ long partIds[26];
+};
+
+struct diskPartition {
+ char name[32];
+ char devName[32];
+ long lock_fd;
+ long totalUsable;
+ long free;
+ long minFree;
+};
+
+struct restoreCookie {
+ char name[32];
+ long type;
+ long clone;
+ long parent;
+};
+
+typedef transDebugInfo transDebugEntries<>;
+typedef volintInfo volEntries<>;
+
+
+AFSVolCreateVolume(IN long partition,
+ IN char *name,
+ IN long type,
+ IN long parent,
+ INOUT long *volid,
+ OUT long *trans) = 100 ;
+
+AFSVolTransCreate(IN long volume,
+ IN long partition,
+ IN long flags,
+ OUT long *trans) = 108 ;
+
+AFSVolEndTrans(IN long trans,
+ OUT long *rcode) = 104 ;
+
+AFSVolGetFlags(IN long trans,
+ OUT long *flags) = 107 ;
+
+AFSVolSetFlags(IN long trans,
+ IN long flags) = 106 ;
+
+AFSVolGetName(IN long tid,
+ OUT string tname<256>) = 112 ;
+
+AFSVolSetDate(IN long tid,
+ IN long newDate) = 123 ;
+
+AFSVolListPartitions(OUT struct pIDs *partIDs) = 115 ;
+
+AFSVolPartitionInfo(IN string name<>,
+ OUT struct diskPartition *partition) = 119 ;
+
+AFSVolListVolumes(IN long partID,
+ IN long flags,
+ OUT struct volEntries *resultEntries) = 116 ;
+
+AFSVolListOneVolume(IN long partID,
+ IN long volid,
+ OUT struct volEntries *resultEntries) = 121 ;
+
+AFSVolMonitor(OUT transDebugEntries *result) = 118 ;
+
diff --git a/usr.sbin/afs/src/rxkad/compat.c b/usr.sbin/afs/src/rxkad/compat.c
new file mode 100644
index 00000000000..878414a8b5f
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/compat.c
@@ -0,0 +1,177 @@
+/* $OpenBSD: compat.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: compat.c,v 1.2 1998/04/05 10:58:16 assar Exp $");
+
+void
+initialize_rxk_error_table(void)
+{
+ /* A no op, our com_err is not compatible anyways. */
+}
+
+u_int32
+life_to_time(u_int32 start, int life_)
+{
+ return krb_life_to_time(start, life_);
+}
+
+int
+time_to_life(u_int32 start, u_int32 end)
+{
+ return krb_time_to_life(start, end);
+}
+
+/* function returns:
+ *
+ * -2 if zero or negative lifetime, or start time is more than now plus time
+ * uncertainty plus max ticket lifetime, or if there is an end time, it's
+ * before now minus uncertainty, the start time is non-zero, and now minus
+ * the start time is greater than the max ticket lifetime plus 24 hours
+ *
+ * -1 if there is an end time, it's before now minus uncertainty, and the
+ * start time is not non-zero or now minus the start time is not greater
+ * than the max ticket lifetime plus 24 hours
+ *
+ * 0 if the times are consistent (not covered by above) but start time is
+ * less than now plus uncertainty
+ *
+ * 1 if the start time is in the past and the end time is infinity.
+ *
+ * 2 if the start time is past and the end time is in the future
+ * and the lifetime is within the legal limit.
+ */
+int
+tkt_CheckTimes(int32 begin, int32 end, int32 now)
+{
+ if (end <= begin
+ || begin > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME
+ || (end
+ && end < now - KTC_TIME_UNCERTAINTY
+ && now - begin > MAXKTCTICKETLIFETIME + MAXKTCTICKETLIFETIME))
+ return -2;
+ if (end
+ && end < now - KTC_TIME_UNCERTAINTY
+ && (begin == 0 || now - begin <= 2 * MAXKTCTICKETLIFETIME))
+ return -1;
+ if (begin < now + KTC_TIME_UNCERTAINTY)
+ return 0;
+ if (begin < now && end == 0)
+ return 1;
+ if (begin < now
+ && end > now
+ && (end - begin) < MAXKTCTICKETLIFETIME)
+ return 2;
+ return 2;
+}
+
+
+int
+tkt_MakeTicket(char *ticket,
+ int *ticketLen,
+ struct ktc_encryptionKey *key,
+ char *name, char *inst, char *cell,
+ u_int32 start, u_int32 end,
+ struct ktc_encryptionKey *sessionKey,
+ u_int32 host,
+ char *sname, char *sinst)
+{
+ int code;
+ KTEXT_ST tkt;
+
+ /* This routine will probably never be called, only kaserver needs it */
+
+ code = krb_create_ticket(&tkt,
+ 0, /*flags*/
+ name, inst, cell,
+ host,
+ sessionKey,
+ krb_time_to_life(start, end), start,
+ sname, sinst,
+ (des_cblock *)key);
+ if (code != KSUCCESS)
+ return code;
+
+ *ticketLen = tkt.length;
+ memcpy(ticket, tkt.dat, tkt.length);
+ return code;
+}
+
+int
+tkt_DecodeTicket (char *asecret,
+ int32 ticketLen,
+ struct ktc_encryptionKey *key_,
+ char *name,
+ char *inst,
+ char *cell,
+ char *sessionKey,
+ int32 *host,
+ int32 *start,
+ int32 *end)
+{
+ des_cblock *key = (des_cblock *)key_;
+ des_key_schedule sched;
+ KTEXT_ST txt;
+ int ret;
+ unsigned char flags;
+ int life;
+ char sname[ANAME_SZ];
+ char sinst[INST_SZ];
+
+ des_key_sched(key, sched);
+ txt.length = ticketLen;
+ memcpy (txt.dat, asecret, ticketLen);
+ ret = decomp_ticket (&txt,
+ &flags,
+ name,
+ inst,
+ cell,
+ host,
+ sessionKey,
+ &life,
+ start,
+ sname,
+ sinst,
+ key,
+ sched);
+ if (ret == KSUCCESS)
+ *end = krb_life_to_time(*start, life);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/rxkad/osi_alloc.c b/usr.sbin/afs/src/rxkad/osi_alloc.c
new file mode 100644
index 00000000000..8b447933a71
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/osi_alloc.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: osi_alloc.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: osi_alloc.c,v 1.2 1997/11/09 23:48:40 assar Exp $");
+
+#undef osi_Alloc
+#undef osi_Free
+
+static char zero_malloc;
+
+char *
+osi_Alloc(int32 size)
+{
+ if (size == 0)
+ return &zero_malloc;
+ return malloc(size);
+}
+
+void
+osi_Free(void *p, int32 size)
+{
+ if (p == &zero_malloc)
+ return;
+ free(p);
+}
diff --git a/usr.sbin/afs/src/rxkad/rxk_clnt.c b/usr.sbin/afs/src/rxkad/rxk_clnt.c
new file mode 100644
index 00000000000..c8d536145b5
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxk_clnt.c
@@ -0,0 +1,355 @@
+/* $OpenBSD: rxk_clnt.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: rxk_clnt.c,v 1.4 1998/02/22 21:12:25 lha Exp $");
+
+/* This code also links into the kernel so we need to use osi_Alloc()
+ * to avoid calling malloc(). Similar trick with memcpy() */
+
+#undef osi_Alloc
+#undef osi_Free
+char *osi_Alloc(int32 size);
+void osi_Free(void *p, int32 size);
+
+#undef memcpy
+#define memcpy(to, from, len) bcopy1((from), (to), (len))
+
+static
+void
+bcopy1(const void *from_, void *to_, size_t n)
+{
+ char *to = to_;
+ const char *from = from_;
+ for (; n > 0; n--)
+ {
+ *to = *from;
+ to++;
+ from++;
+ }
+}
+
+/* Security object specific client data */
+typedef struct rxkad_clnt_class {
+ struct rx_securityClass klass;
+ rxkad_level level;
+ key_stuff k;
+ int32 kvno;
+ int32 ticket_len;
+ char *ticket;
+} rxkad_clnt_class;
+
+/* Per connection specific client data */
+typedef struct clnt_con_data {
+ end_stuff e;
+} clnt_con_data;
+
+static
+int
+client_NewConnection(struct rx_securityClass *obj_, struct rx_connection *con)
+{
+ rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_;
+ clnt_con_data *cdat;
+
+ assert(con->securityData == 0);
+ obj->klass.refCount++;
+ cdat = (clnt_con_data *) osi_Alloc(sizeof(clnt_con_data));
+ cdat->e.bytesReceived = cdat->e.packetsReceived = 0;
+ cdat->e.bytesSent = cdat->e.packetsSent = 0;
+
+ con->securityData = (char *) cdat;
+ rx_nextCid += RX_MAXCALLS;
+ con->epoch = rx_epoch;
+ con->cid = rx_nextCid;
+ /* We don't use trailers but the transarc implementation breaks when
+ * we don't set the trailer size, packets get to large */
+ switch (obj->level) {
+ case rxkad_clear:
+ /* nichts */
+ break;
+ case rxkad_auth:
+ rx_SetSecurityHeaderSize(con, 4);
+ rx_SetSecurityMaxTrailerSize(con, 4);
+ break;
+ case rxkad_crypt:
+ rx_SetSecurityHeaderSize(con, 8);
+ rx_SetSecurityMaxTrailerSize(con, 8);
+ break;
+ default:
+ assert(0);
+ }
+ rxkad_calc_header_iv(con, obj->k.keysched,
+ (const des_cblock *)&obj->k.key, cdat->e.header_iv);
+ return 0;
+}
+
+static
+int
+client_Close(struct rx_securityClass *obj_)
+{
+ rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_;
+ obj->klass.refCount--;
+ if (obj->klass.refCount <= 0)
+ {
+ osi_Free(obj->ticket, obj->ticket_len);
+ osi_Free(obj, sizeof(rxkad_clnt_class));
+ }
+ return 0;
+}
+
+static
+int
+client_DestroyConnection(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ clnt_con_data *cdat = (clnt_con_data *)con->securityData;
+
+ if (cdat)
+ osi_Free(cdat, sizeof(clnt_con_data));
+ return client_Close(obj);
+}
+
+/*
+ * Receive a challange and respond.
+ */
+static
+int
+client_GetResponse(const struct rx_securityClass *obj_,
+ const struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_;
+ rxkad_challenge c;
+ rxkad_response r;
+
+ /* Get challenge */
+ if (rx_SlowReadPacket(pkt, 0, sizeof(c), &c) != sizeof(c))
+ return RXKADPACKETSHORT;
+
+ if (ntohl(c.version) != RXKAD_VERSION)
+ return RXKADINCONSISTENCY;
+
+ if (ntohl(c.min_level) > obj->level)
+ return RXKADLEVELFAIL;
+
+ /* Make response */
+ r.version = htonl(RXKAD_VERSION);
+ r.unused = 0;
+ r.encrypted.epoch = htonl(con->epoch);
+ r.encrypted.cid = htonl(con->cid & RX_CIDMASK);
+ r.encrypted.cksum = 0;
+ r.encrypted.security_index = htonl(con->securityIndex);
+ {
+ int i;
+ /* Get and fixup call number vector */
+ rxi_GetCallNumberVector(con, r.encrypted.call_numbers);
+ for (i = 0; i < RX_MAXCALLS; i++)
+ {
+ if (r.encrypted.call_numbers[i] < 0)
+ return RXKADINCONSISTENCY;
+ r.encrypted.call_numbers[i] = htonl(r.encrypted.call_numbers[i]);
+ }
+ }
+ r.encrypted.inc_nonce = htonl(ntohl(c.nonce) + 1);
+ r.encrypted.level = htonl((int32)obj->level);
+ r.kvno = htonl(obj->kvno);
+ r.ticket_len = htonl(obj->ticket_len);
+ /* Make checksum before we seal r.encrypted */
+ r.encrypted.cksum = rxkad_cksum_response(&r);
+ /* Seal r.encrypted */
+ fc_cbc_enc2(&r.encrypted, &r.encrypted, sizeof(r.encrypted),
+ obj->k.keysched, (u_int32*)obj->k.key, ENCRYPT);
+
+ /* Stuff response and kerberos ticket into packet */
+ if (rx_SlowWritePacket(pkt, 0, sizeof(r), &r) != sizeof(r))
+ return RXKADPACKETSHORT;
+ if (rx_SlowWritePacket(pkt, sizeof(r), obj->ticket_len, obj->ticket) != obj->ticket_len)
+ return RXKADPACKETSHORT;
+ rx_SetDataSize(pkt, sizeof(r) + obj->ticket_len);
+ return 0;
+}
+
+/*
+ * Checksum and/or encrypt packet.
+ */
+static
+int
+client_PreparePacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_;
+ key_stuff *k = &obj->k;
+ struct rx_connection *con = rx_ConnectionOf(call);
+ end_stuff *e = &((clnt_con_data *) con->securityData)->e;
+
+ return rxkad_prepare_packet(pkt, con, obj->level, k, e);
+}
+
+/*
+ * Verify checksums and/or decrypt packet.
+ */
+static
+int
+client_CheckPacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_;
+ key_stuff *k = &obj->k;
+ struct rx_connection *con = rx_ConnectionOf(call);
+ end_stuff *e = &((clnt_con_data *) con->securityData)->e;
+
+ return rxkad_check_packet(pkt, con, obj->level, k, e);
+}
+
+static
+int
+client_GetStats(const struct rx_securityClass *obj,
+ const struct rx_connection *con,
+ struct rx_securityObjectStats *st)
+{
+ clnt_con_data *cdat = (clnt_con_data *) con->securityData;
+
+ st->type = rxkad_disipline;
+ st->level = ((rxkad_clnt_class *)obj)->level;
+ st->flags = rxkad_checksummed;
+ if (cdat == 0)
+ st->flags |= rxkad_unallocated;
+ {
+ st->bytesReceived = cdat->e.bytesReceived;
+ st->packetsReceived = cdat->e.packetsReceived;
+ st->bytesSent = cdat->e.bytesSent;
+ st->packetsSent = cdat->e.packetsSent;
+ }
+ return 0;
+}
+
+static
+struct rx_securityOps client_ops = {
+ client_Close,
+ client_NewConnection,
+ client_PreparePacket,
+ 0,
+ 0,
+ 0,
+ 0,
+ client_GetResponse,
+ 0,
+ client_CheckPacket,
+ client_DestroyConnection,
+ client_GetStats,
+ 0,
+ 0,
+ 0,
+};
+
+int rxkad_EpochWasSet = 0;
+
+int rxkad_min_level = rxkad_clear; /* rxkad_{clear, auth, crypt} */
+
+struct rx_securityClass *
+rxkad_NewClientSecurityObject(/*rxkad_level*/ int level,
+ void *sessionkey,
+ int32 kvno,
+ int ticket_len,
+ char *ticket)
+{
+ rxkad_clnt_class *obj;
+ static int inited = 0;
+
+ if (level < rxkad_min_level)
+ level = rxkad_min_level; /* Boost security level */
+
+ if (!inited)
+ {
+ /* Any good random numbers will do, no real need to use
+ * cryptographic techniques here */
+ union {
+ u_int32 rnd[2];
+ des_cblock k;
+ } u;
+ int32 sched[ROUNDS];
+
+ u.rnd[0] = rx_nextCid;
+ u.rnd[1] = rx_epoch;
+ fc_keysched(sessionkey, sched);
+ fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT);
+
+ /* Some paranoia so we won't reveal the key */
+ /*des_set_odd_parity(&u.k);*/
+ fc_keysched(&u.k, sched);
+ fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT);
+
+ /* Some paranoia so we won't reveal the key */
+ /*des_set_odd_parity(&u.k);*/
+ fc_keysched(&u.k, sched);
+ fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT);
+
+ /* Set new cid and epoch generator */
+ rx_nextCid = u.rnd[0] << RX_CIDSHIFT;
+ rx_SetEpoch(u.rnd[0] ^ u.rnd[1]);
+ rxkad_EpochWasSet = 1;
+ inited = 1;
+ }
+
+#if 0
+ /* If we are passed a to large kerberos 5 ticket hope for the best */
+ if (ticket_len > MAXKRB5TICKETLEN)
+ ticket_len = MAXKRB5TICKETLEN;
+#endif
+
+ obj = (rxkad_clnt_class *) osi_Alloc(sizeof(rxkad_clnt_class));
+ obj->klass.refCount = 1;
+ obj->klass.ops = &client_ops;
+
+ obj->klass.privateData = (char *) obj;
+
+ obj->level = level;
+ fc_keysched(sessionkey, obj->k.keysched);
+ memcpy(obj->k.key, sessionkey, sizeof(des_cblock));
+ obj->kvno = kvno;
+
+ obj->ticket_len = ticket_len;
+ obj->ticket = osi_Alloc(ticket_len);
+ memcpy(obj->ticket, ticket, ticket_len);
+
+ return &obj->klass;
+}
diff --git a/usr.sbin/afs/src/rxkad/rxk_crpt.c b/usr.sbin/afs/src/rxkad/rxk_crpt.c
new file mode 100644
index 00000000000..42b104c274c
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxk_crpt.c
@@ -0,0 +1,767 @@
+/* $OpenBSD: rxk_crpt.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: rxk_crpt.c,v 1.8 1998/07/12 14:38:58 joda Exp $");
+
+/*
+ * Unrolling of the inner loops helps the most on pentium chips
+ * (ca 18%). On risc machines only expect a modest improvement (ca 5%).
+ * The cost for this is rougly 4k bytes.
+ */
+#define UNROLL_LOOPS 1
+/*
+ * Inline assembler gives a boost only to fc_keysched.
+ * On the pentium expect ca 28%.
+ */
+/*#define GNU_ASM 1 (now autoconfed) */
+
+#if !defined(inline) && !defined(__GNUC__)
+#define inline
+#endif
+
+#ifdef MANGLE_NAMES
+#define fc_keysched _afs_QTKrFdpoFL
+#define fc_ecb_encrypt _afs_sDLThwNLok
+#define fc_cbc_encrypt _afs_fkyCWTvfRS
+#define rxkad_DecryptPacket _afs_SRWEeqTXrS
+#define rxkad_EncryptPacket _afs_bpwQbdoghO
+#endif
+
+/*
+ * There is usually no memcpy in kernels but gcc will inline all
+ * calls to memcpy in this code anyway.
+ */
+#if defined(KERNEL) && !defined(__GNUC__)
+#define memcpy(to, from, n) bcopy((from), (to), (n))
+#endif
+
+/* Rotate 32 bit word left */
+#define ROT32L(x, n) ((((u_int32) x) << (n)) | (((u_int32) x) >> (32-(n))))
+#define bswap32(x) (((ROT32L(x, 16) & 0x00ff00ff)<<8) | ((ROT32L(x, 16)>>8) & 0x00ff00ff))
+
+#if defined(__alpha) || defined(i386) || defined(MIPSEL)
+#define NTOH(x) bswap32(x)
+#else
+#define NTOH(x) (x)
+#endif
+
+/*
+ * Try to use a good function for ntohl-ing.
+ *
+ * The choice is done by autoconf setting EFF_NTOHL to one of:
+ * CPU function
+ * i386 ntohl
+ * i[4-9]86 bswap
+ * alpha bswap32
+ * all else ntohl
+ */
+
+#if defined(__GNUC__) && defined(i386)
+static inline
+u_int32
+bswap(u_int32 x)
+{
+ asm("bswap %0" : "=r" (x) : "0" (x));
+ return x;
+}
+#endif
+
+/*
+ * Sboxes for Feistel network derived from
+ * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
+ */
+
+#undef Z
+#define Z(x) NTOH(x << 3)
+static const u_int32 sbox0[256] = {
+ Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11), Z(0xcd), Z(0x86), Z(0x86),
+ Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06), Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5),
+ Z(0x28), Z(0x60), Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3), Z(0xd2),
+ Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a), Z(0x35), Z(0xac), Z(0xaa), Z(0x5f),
+ Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53), Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32),
+ Z(0x10), Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd), Z(0x3b), Z(0x95),
+ Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80), Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f),
+ Z(0x26), Z(0x76), Z(0x15), Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
+ Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24), Z(0x0b), Z(0x8a), Z(0x83),
+ Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8), Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64),
+ Z(0xf0), Z(0x51), Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef), Z(0x10),
+ Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44), Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b),
+ Z(0xae), Z(0xd5), Z(0xad), Z(0x1d), Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2),
+ Z(0xb7), Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44), Z(0xb6), Z(0x69),
+ Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0), Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f),
+ Z(0x36), Z(0xba), Z(0x71), Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
+ Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95), Z(0x22), Z(0x99), Z(0xfd),
+ Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1), Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70),
+ Z(0xff), Z(0xc6), Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5), Z(0x36),
+ Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6), Z(0x93), Z(0xc4), Z(0xaa), Z(0x26),
+ Z(0x49), Z(0xe0), Z(0x21), Z(0x64), Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9),
+ Z(0xd1), Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03), Z(0xe4), Z(0xb0),
+ Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39), Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c),
+ Z(0x0d), Z(0x42), Z(0x2e)};
+
+#undef Z
+#define Z(x) NTOH((x << 27) | (x >> 5))
+static const u_int32 sbox1[256] = {
+ Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e), Z(0x67), Z(0x6c), Z(0xa1),
+ Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85), Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3),
+ Z(0xf2), Z(0x89), Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39), Z(0x31),
+ Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6), Z(0x23), Z(0x83), Z(0x98), Z(0x7d),
+ Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99), Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f),
+ Z(0xad), Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6), Z(0xb8), Z(0xa1),
+ Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b), Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23),
+ Z(0x17), Z(0x04), Z(0xfa), Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
+ Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc), Z(0xe2), Z(0xaf), Z(0x45),
+ Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd), Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18),
+ Z(0x60), Z(0x3d), Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b), Z(0x06),
+ Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17), Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1),
+ Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5), Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28),
+ Z(0x0a), Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a), Z(0x31), Z(0xf7),
+ Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5), Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57),
+ Z(0x25), Z(0xbe), Z(0x89), Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
+ Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8), Z(0x69), Z(0x10), Z(0x9d),
+ Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30), Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19),
+ Z(0xbd), Z(0x45), Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96), Z(0xef),
+ Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad), Z(0x80), Z(0x48), Z(0x81), Z(0xb7),
+ Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7), Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57),
+ Z(0xc1), Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78), Z(0x16), Z(0x06),
+ Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4), Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96),
+ Z(0x91), Z(0x82), Z(0x80)};
+
+#undef Z
+#define Z(x) NTOH(x << 11)
+static const u_int32 sbox2[256] = {
+ Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86), Z(0xd1), Z(0xec), Z(0x50),
+ Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d), Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2),
+ Z(0xc5), Z(0x5d), Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24), Z(0xc8),
+ Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9), Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9),
+ Z(0x45), Z(0x20), Z(0x1b), Z(0xce), Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3),
+ Z(0xa9), Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68), Z(0x84), Z(0xbc),
+ Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6), Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95),
+ Z(0x02), Z(0xc0), Z(0xd0), Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
+ Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d), Z(0x6d), Z(0x1c), Z(0x6c),
+ Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e), Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12),
+ Z(0x19), Z(0x34), Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae), Z(0x2a),
+ Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc), Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b),
+ Z(0xb1), Z(0x85), Z(0x59), Z(0x80), Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48),
+ Z(0x40), Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e), Z(0xb7), Z(0x5e),
+ Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15), Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9),
+ Z(0xc7), Z(0x40), Z(0x45), Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
+ Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f), Z(0xdc), Z(0xff), Z(0xfd),
+ Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a), Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e),
+ Z(0x3d), Z(0xfd), Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f), Z(0x56),
+ Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5), Z(0xf3), Z(0x8e), Z(0xde), Z(0xae),
+ Z(0x37), Z(0x49), Z(0xb7), Z(0xfa), Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15),
+ Z(0xd1), Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59), Z(0x56), Z(0x68),
+ Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f), Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76),
+ Z(0xb4), Z(0x10), Z(0x86)};
+
+#undef Z
+#define Z(x) NTOH(x << 19)
+static const u_int32 sbox3[256] = {
+ Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2), Z(0xb5), Z(0xb7), Z(0x42),
+ Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12), Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20),
+ Z(0x6d), Z(0x57), Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b), Z(0x53),
+ Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66), Z(0xa1), Z(0x01), Z(0xa5), Z(0x41),
+ Z(0x97), Z(0x41), Z(0x31), Z(0x82), Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10),
+ Z(0xcc), Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16), Z(0x47), Z(0xf6),
+ Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a), Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01),
+ Z(0x54), Z(0x70), Z(0xa4), Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
+ Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2), Z(0x2a), Z(0x41), Z(0xb2),
+ Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d), Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc),
+ Z(0x60), Z(0x65), Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87), Z(0x96),
+ Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4), Z(0x5a), Z(0x83), Z(0xbf), Z(0x92),
+ Z(0x1b), Z(0x94), Z(0x00), Z(0x42), Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76),
+ Z(0x5f), Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95), Z(0x17), Z(0xe4),
+ Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85), Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b),
+ Z(0x66), Z(0xa1), Z(0x34), Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
+ Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a), Z(0x19), Z(0xf1), Z(0xa1),
+ Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0), Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a),
+ Z(0x2d), Z(0x20), Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f), Z(0x47),
+ Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79), Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd),
+ Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3), Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0),
+ Z(0x11), Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f), Z(0xd8), Z(0xe1),
+ Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9), Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba),
+ Z(0xfc), Z(0x0e), Z(0x25)};
+
+/*
+ * This is a 16 round Feistel network with permutation F_ENCRYPT
+ */
+
+#define F_ENCRYPT(R, L, sched) { \
+ union lc4 { u_int32 l; unsigned char c[4]; } u; \
+ u.l = sched ^ R; \
+ L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; }
+
+#if defined(i386) || defined(__alpha)
+/* BEWARE: this code is endian dependent.
+ * This should really be inline assembler on the x86.
+ */
+#undef F_ENCRYPT
+#define FF(y, shiftN) (((y) >> shiftN) & 0xFF)
+#define F_ENCRYPT(R, L, sched) { \
+ u_int32 u; \
+ u = sched ^ R; \
+ L ^= sbox0[FF(u, 0)] ^ sbox1[FF(u, 8)] ^ sbox2[FF(u, 16)] ^ sbox3[FF(u, 24)];}
+#endif
+
+static inline
+void
+fc_ecb_enc(u_int32 l,
+ u_int32 r,
+ u_int32 out[2],
+ const int32 sched[ROUNDS])
+{
+#if !defined(UNROLL_LOOPS)
+ {
+ int i;
+ for (i = 0; i < (ROUNDS/4); i++)
+ {
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ }
+ }
+#else
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+ F_ENCRYPT(r, l, *sched++);
+ F_ENCRYPT(l, r, *sched++);
+#endif /* UNROLL_LOOPS */
+
+ out[0] = l;
+ out[1] = r;
+}
+
+static inline
+void
+fc_ecb_dec(u_int32 l,
+ u_int32 r,
+ u_int32 out[2],
+ const int32 sched[ROUNDS])
+{
+ sched = &sched[ROUNDS-1];
+
+#if !defined(UNROLL_LOOPS)
+ {
+ int i;
+ for (i = 0; i < (ROUNDS/4); i++)
+ {
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ }
+ }
+#else
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+ F_ENCRYPT(l, r, *sched--);
+ F_ENCRYPT(r, l, *sched--);
+#endif /* UNROLL_LOOPS */
+
+ out[0] = l;
+ out[1] = r;
+}
+
+static inline
+void
+fc_cbc_enc(const u_int32 *in,
+ u_int32 *out,
+ int32 length,
+ const int32 sched[ROUNDS],
+ u_int32 iv[2])
+{
+ int32 xor0 = iv[0], xor1 = iv[1];
+
+ for (; length > 0; length -= 8)
+ {
+ u_int32 b8[2];
+ /* If length < 8 we read to much, usally ok */
+ xor0 ^= in[0];
+ xor1 ^= in[1];
+ fc_ecb_enc(xor0, xor1, b8, sched);
+ xor0 = in[0] ^ b8[0];
+ xor1 = in[1] ^ b8[1];
+
+ /* Out is always a multiple of 8 */
+ memcpy(out, b8, 8);
+ out += 2;
+ in += 2;
+ }
+ iv[0] = xor0;
+ iv[1] = xor1;
+}
+
+static inline
+void
+fc_cbc_dec(const u_int32 *in,
+ u_int32 *out,
+ int32 length,
+ const int32 sched[ROUNDS],
+ u_int32 iv[2])
+{
+ int32 xor0 = iv[0], xor1 = iv[1];
+
+ for (; length > 0; length -= 8)
+ {
+ u_int32 b8[2];
+ /* In is always a multiple of 8 */
+ fc_ecb_dec(in[0], in[1], b8, sched);
+ b8[0] ^= xor0;
+ b8[1] ^= xor1;
+ xor0 = in[0] ^ b8[0];
+ xor1 = in[1] ^ b8[1];
+
+#if 0
+ if (length >= 8)
+ memcpy(out, b8, 8);
+ else
+ memcpy(out, b8, length); /* Don't write to much when length < 8 */
+#else
+ /* If length < 8 we write to much, this is not always ok */
+ memcpy(out, b8, 8);
+#endif
+ out += 2;
+ in += 2;
+ }
+ iv[0] = xor0;
+ iv[1] = xor1;
+}
+
+int
+fc_ecb_encrypt(const void *in_,
+ void *out_,
+ const int32 sched[ROUNDS],
+ int encrypt)
+{
+ const u_int32 *in = in_; /* In must be u_int32 aligned */
+ u_int32 *out = out_; /* Out must be u_int32 aligned */
+ if (encrypt)
+ fc_ecb_enc(in[0], in[1], out, sched);
+ else
+ fc_ecb_dec(in[0], in[1], out, sched);
+ return 0;
+}
+
+int
+fc_cbc_encrypt(const void *in_,
+ void *out_,
+ int32 length,
+ const int32 sched[ROUNDS],
+ u_int32 iv[2],
+ int encrypt)
+{
+ const u_int32 *in = in_; /* In must be u_int32 aligned */
+ u_int32 *out = out_; /* Out must be u_int32 aligned */
+ if (encrypt)
+ fc_cbc_enc(in, out, length, sched, iv);
+ else
+ fc_cbc_dec(in, out, length, sched, iv);
+ return 0;
+}
+
+/* Rotate two 32 bit numbers as a 56 bit number */
+#define ROT56R(hi, lo, n) { \
+ u_int32 t = lo & ((1<<n)-1); \
+ lo = (lo >> n) | ((hi & ((1<<n)-1)) << (32-n)); \
+ hi = (hi >> n) | (t << (24-n)); }
+
+/* Rotate one 64 bit number as a 56 bit number */
+#define ROT56R64(k, n) { \
+ k = (k >> n) | ((k & ((1<<n) - 1)) << (56-n)); }
+
+/*
+ * Generate a key schedule from key, the least significant bit in each
+ * key byte is parity and shall be ignored. This leaves 56 significant
+ * bits in the key to scatter over the 16 key schedules. For each
+ * schedule extract the low order 32 bits and use as schedule, then
+ * rotate right by 11 bits.
+ *
+ * Note that this fc_keysched() generates a schedule in natural byte
+ * order, the Transarc function does not. Therefore it's *not*
+ * possible to mix fc_keysched, fc_ecb_encrypt and fc_cbc_encrypt
+ * from different implementations. Keep them in the same module!
+ */
+int
+fc_keysched(const void *key_,
+ int32 sched[ROUNDS])
+{
+ const unsigned char *key = key_;
+
+ /* Do we have 56 bit longs or even longer longs? */
+#if ((1ul << 31) << 1) && defined(ULONG_MAX) && ((ULONG_MAX >> 55) != 0) && ((1ul << 55) != 0)
+ unsigned long k; /* k holds all 56 non parity bits */
+
+ /* Compress out parity bits */
+ k = (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key++) >> 1;
+ k <<= 7;
+ k |= (*key) >> 1;
+
+ /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ ROT56R64(k, 11);
+ *sched++ = EFF_NTOHL((u_int32)k);
+ return 0;
+#else
+ u_int32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */
+
+ /* Compress out parity bits */
+ lo = (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ hi = lo >> 4;
+ lo &= 0xf;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key++) >> 1;
+ lo <<= 7;
+ lo |= (*key) >> 1;
+
+ /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ ROT56R(hi, lo, 11);
+ *sched++ = EFF_NTOHL(lo);
+ return 0;
+#endif
+}
+
+/*
+ * Encryption/decryption of Rx packets is pretty straight forward. Run
+ * fc_cbc_encrypt over the packet fragments until len bytes have been
+ * processed. Skip the Rx packet header but not the security header.
+ */
+int
+rxkad_EncryptPacket(const void *rx_connection_not_used,
+ const int32 sched[ROUNDS],
+ const u_int32 iv[2],
+ int len,
+ struct rx_packet *packet)
+{
+ u_int32 ivec[2];
+ struct iovec *frag;
+
+ {
+ /* What is this good for?
+ * It turns out that the security header for auth_enc is of
+ * size 8 bytes and the last 4 bytes are defined to be 0!
+ */
+ u_int32 *t = (u_int32 *)packet->wirevec[1].iov_base;
+ t[1] = 0;
+ }
+
+ memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */
+ for (frag = &packet->wirevec[1]; len; frag++)
+ {
+ int iov_len = frag->iov_len;
+ u_int32 *iov_bas = (u_int32 *) frag->iov_base;
+ if (iov_len == 0)
+ return RXKADDATALEN; /* Length mismatch */
+ if (len < iov_len)
+ iov_len = len; /* Don't process to much data */
+ fc_cbc_enc(iov_bas, iov_bas, iov_len, sched, ivec);
+ len -= iov_len;
+ }
+ return 0;
+}
+
+int
+rxkad_DecryptPacket(const void *rx_connection_not_used,
+ const int32 sched[ROUNDS],
+ const u_int32 iv[2],
+ int len,
+ struct rx_packet *packet)
+{
+ u_int32 ivec[2];
+ struct iovec *frag;
+
+ memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */
+ for (frag = &packet->wirevec[1]; len > 0; frag++)
+ {
+ int iov_len = frag->iov_len;
+ u_int32 *iov_bas = (u_int32 *) frag->iov_base;
+ if (iov_len == 0)
+ return RXKADDATALEN; /* Length mismatch */
+ if (len < iov_len)
+ iov_len = len; /* Don't process to much data */
+ fc_cbc_dec(iov_bas, iov_bas, iov_len, sched, ivec);
+ len -= iov_len;
+ }
+ return 0;
+}
+
+#if defined(TEST) || defined(TEST_KERNEL)
+/*
+ * It is possible to link with the client kernel libafs.a to verify
+ * the test case. Use TEST_KERNEL to get the mangled names.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <time.h>
+
+const char the_quick[] = "The quick brown fox jumps over the lazy dogs.\0\0";
+
+const unsigned char key1[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87};
+const char ciph1[] = {
+ 0x00, 0xf0, 0xe, 0x11, 0x75, 0xe6, 0x23, 0x82, 0xee, 0xac, 0x98, 0x62,
+ 0x44, 0x51, 0xe4, 0x84, 0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+ 0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03, 0x23, 0xb5, 0x62, 0xd7,
+ 0xc, 0xf5, 0x27, 0xd1, 0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef };
+
+const unsigned char key2[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
+const char ciph2[] = {
+ 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c, 0x01, 0x88, 0x7f, 0x3e,
+ 0x31, 0x6e, 0x62, 0x9d, 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+ 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0, 0x19, 0x89, 0x09, 0x1c,
+ 0x2a, 0x8e, 0x8c, 0x94, 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f };
+
+#ifdef TEST_KERNEL
+#define fc_keysched _afs_QTKrFdpoFL
+#define fc_ecb_encrypt _afs_sDLThwNLok
+#define fc_cbc_encrypt _afs_fkyCWTvfRS
+#define rxkad_DecryptPacket _afs_SRWEeqTXrS
+#define rxkad_EncryptPacket _afs_bpwQbdoghO
+#endif
+
+int rx_SlowPutInt32() { abort(); }
+
+int
+main()
+{
+ int32 sched[ROUNDS];
+ char ciph[100], clear[100], tmp[100];
+ u_int32 data[2];
+ u_int32 iv[2];
+ struct rx_packet packet;
+
+ if (sizeof(int32) != 4)
+ fprintf(stderr, "error: sizeof(int32) != 4\n");
+ if (sizeof(u_int32) != 4)
+ fprintf(stderr, "error: sizeof(u_int32) != 4\n");
+
+ /*
+ * Use key1 and key2 as iv */
+ fc_keysched(key1, sched);
+ memcpy(iv, key2, sizeof(iv));
+ fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
+ if (memcmp(ciph1, ciph, sizeof(ciph1)) != 0)
+ fprintf(stderr, "encrypt FAILED\n");
+ memcpy(iv, key2, sizeof(iv));
+ fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
+ if (strcmp(the_quick, clear) != 0)
+ fprintf(stderr, "crypt decrypt FAILED\n");
+
+ /*
+ * Use key2 and key1 as iv
+ */
+ fc_keysched(key2, sched);
+ memcpy(iv, key1, sizeof(iv));
+ fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
+ if (memcmp(ciph2, ciph, sizeof(ciph2)) != 0)
+ fprintf(stderr, "encrypt FAILED\n");
+ memcpy(iv, key1, sizeof(iv));
+ fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
+ if (strcmp(the_quick, clear) != 0)
+ fprintf(stderr, "crypt decrypt FAILED\n");
+
+ /*
+ * Test Encrypt- and Decrypt-Packet, use key1 and key2 as iv
+ */
+ fc_keysched(key1, sched);
+ memcpy(iv, key2, sizeof(iv));
+ strcpy(clear, the_quick);
+ packet.wirevec[1].iov_base = clear;
+ packet.wirevec[1].iov_len = sizeof(the_quick);
+ packet.wirevec[2].iov_len = 0;
+
+ /* For unknown reasons bytes 4-7 are zeroed in rxkad_EncryptPacket */
+ rxkad_EncryptPacket(tmp, sched, iv, sizeof(the_quick), &packet);
+ rxkad_DecryptPacket(tmp, sched, iv, sizeof(the_quick), &packet);
+ clear[4] ^= 'q';
+ clear[5] ^= 'u';
+ clear[6] ^= 'i';
+ clear[7] ^= 'c';
+ if (strcmp(the_quick, clear) != 0)
+ fprintf(stderr, "rxkad_EncryptPacket/rxkad_DecryptPacket FAILED\n");
+
+ {
+ struct timeval start, stop;
+ int i;
+
+ fc_keysched(key1, sched);
+ gettimeofday(&start, 0);
+ for (i = 0; i < 1000000; i++)
+ fc_keysched(key1, sched);
+ gettimeofday(&stop, 0);
+ printf("fc_keysched = %2.2f us\n",
+ (stop.tv_sec - start.tv_sec
+ + (stop.tv_usec - start.tv_usec)/1e6)*1);
+
+ fc_ecb_encrypt(data, data, sched, ENCRYPT);
+ gettimeofday(&start, 0);
+ for (i = 0; i < 1000000; i++)
+ fc_ecb_encrypt(data, data, sched, ENCRYPT);
+ gettimeofday(&stop, 0);
+ printf("fc_ecb_encrypt = %2.2f us\n",
+ (stop.tv_sec - start.tv_sec
+ + (stop.tv_usec - start.tv_usec)/1e6)*1);
+
+ fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
+ gettimeofday(&start, 0);
+ for (i = 0; i < 100000; i++)
+ fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
+ gettimeofday(&stop, 0);
+ printf("fc_cbc_encrypt = %2.2f us\n",
+ (stop.tv_sec - start.tv_sec
+ + (stop.tv_usec - start.tv_usec)/1e6)*10);
+
+ }
+
+ exit(0);
+}
+#endif /* TEST */
diff --git a/usr.sbin/afs/src/rxkad/rxk_info.c b/usr.sbin/afs/src/rxkad/rxk_info.c
new file mode 100644
index 00000000000..cc38107fc86
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxk_info.c
@@ -0,0 +1,75 @@
+/* $OpenBSD: rxk_info.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: rxk_info.c,v 1.3 1998/02/22 11:49:55 assar Exp $");
+
+int32
+rxkad_GetServerInfo(struct rx_connection *con,
+ rxkad_level *level,
+ u_int32 *expiration,
+ char *name,
+ char *instance,
+ char *cell,
+ int32 *kvno)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ if (cdat && cdat->authenticated
+ && (time(0) < cdat->expires)
+ && cdat->user)
+ {
+ if (level)
+ *level = cdat->cur_level;
+ if (expiration)
+ *expiration = cdat->expires;
+ if (name)
+ strcpy(name, cdat->user->name);
+ if (instance)
+ strcpy(instance, cdat->user->instance);
+ if (cell)
+ strcpy(cell, cdat->user->realm);
+ if (kvno)
+ *kvno = -1; /* Where do we find this and who needs it? */
+ return 0;
+ }
+ else
+ return RXKADNOAUTH;
+}
diff --git a/usr.sbin/afs/src/rxkad/rxk_locl.c b/usr.sbin/afs/src/rxkad/rxk_locl.c
new file mode 100644
index 00000000000..7d0c700d62b
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxk_locl.c
@@ -0,0 +1,276 @@
+/* $OpenBSD: rxk_locl.c,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+RCSID("$KTH: rxk_locl.c,v 1.7 1998/04/05 10:58:16 assar Exp $");
+
+/* The header checksum is the last 16 bits of this struct after
+ * encryption. Note that only the last 8 bytes change per packet. */
+#if 0
+struct header_data {
+ struct const_header_data c; /* 16 bytes */
+ struct variable_header_data v; /* 8 bytes */
+};
+#endif
+
+struct const_header_data {
+ /* Data that is constant per connection */
+ u_int32 epoch;
+ u_int32 cid;
+ u_int32 zero;
+ u_int32 security_index;
+};
+
+struct variable_header_data {
+ /* Data that changes per packet */
+ u_int32 call_number;
+ u_int32 channel_and_seq;
+};
+
+/* To create a 16 bit packet header checksum we first create an iv
+ * dependent on the epoch, the connection ID and the security index.
+ */
+void
+rxkad_calc_header_iv(const struct rx_connection *conn,
+ const int32 *sched,
+ const des_cblock *in_iv,
+ u_int32 *out_iv)
+{
+ struct const_header_data h;
+ u_int32 *t;
+
+ h.epoch = htonl(conn->epoch);
+ h.cid = htonl(conn->cid & RX_CIDMASK);
+ h.zero = 0;
+ h.security_index = htonl(conn->securityIndex);
+
+ t = (u_int32 *)in_iv; /* memcpy(out_iv, in_iv, 8); */
+ out_iv[0] = t[0];
+ out_iv[1] = t[1];
+ fc_cbc_encrypt(&h, &h, sizeof(h), sched, out_iv, ENCRYPT);
+ /* Extract last 8 bytes as iv */
+ assert(out_iv[0] == h.zero);
+ /* out_iv[0] = h.zero; */
+ out_iv[1] = h.security_index;
+}
+
+/* Make a 16 bit header checksum dependent on call number, channel
+ * number and packet sequence number. In addition, the checksum is
+ * indirectly dependent (via the iv) on epoch, connection ID and
+ * security index.
+ */
+static
+int
+rxkad_cksum_header(const struct rx_packet *packet,
+ const int32 *sched,
+ const unsigned int *iv)
+{
+ struct variable_header_data h;
+ u_int32 t;
+
+ /* Collect selected packet fields */
+ h.call_number = htonl(packet->header.callNumber);
+ t = ((packet->header.cid & RX_CHANNELMASK) << (32 - RX_CIDSHIFT))
+ | ((packet->header.seq & 0x3fffffff));
+ h.channel_and_seq = htonl(t);
+
+ /* Encrypt selected fields (this is hand rolled CBC mode) */
+ h.call_number ^= iv[0];
+ h.channel_and_seq ^= iv[1];
+ fc_ecb_encrypt(&h, &h, sched, ENCRYPT);
+
+ /* Select 16 bits that are now dependent on all selected packet fields */
+ t = (ntohl(h.channel_and_seq) >> 16) & 0xffff;
+ if (t != 0)
+ return t;
+ else
+ return 1; /* No checksum is 0 */
+}
+
+/* Checksum a rxkad_response, this checksum is buried within the
+ * encrypted part of the response but covers the entire response. */
+u_int32
+rxkad_cksum_response(rxkad_response *r)
+{
+ u_char *t;
+ u_int32 cksum = 1000003;
+
+ for (t = (u_char *)r; t < (u_char*)(r + 1); t++)
+ cksum = *t + cksum * 0x10204081;
+
+ return htonl(cksum);
+}
+
+int
+rxkad_prepare_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int level,
+ key_stuff *k,
+ end_stuff *e)
+{
+ u_int len = rx_GetDataSize(pkt);
+
+ /* Checksum header */
+ rx_SetPacketCksum(pkt, rxkad_cksum_header(pkt, k->keysched, e->header_iv));
+
+ e->packetsSent++;
+ e->bytesSent += len;
+
+ if (level != rxkad_clear)
+ {
+ u_int32 *data = (u_int32 *) rx_DataOf(pkt);
+ u_int32 t;
+ int32 code = 0;
+
+ assert(pkt->wirevec[1].iov_len >= 4);
+
+ /* First 4 bytes of security header, includes encrypted length */
+ t = pkt->header.seq ^ pkt->header.callNumber;
+ t <<= 16;
+ t |= len; /* Extracted on receiving side */
+ data[0] = htonl(t);
+
+ switch (level) {
+ case rxkad_auth:
+ len += rx_GetSecurityHeaderSize(con); /* Extended pkt len */
+ /* Extend packet length so that we can encrypt the first 8 bytes */
+ if (pkt->wirevec[1].iov_len < 8)
+ {
+ int diff = 8 - pkt->wirevec[1].iov_len;
+ pkt->wirevec[1].iov_len += diff;
+ len += diff;
+ }
+ rx_SetDataSize(pkt, len); /* Set extended packet length */
+
+ /* Encrypt security header (4 bytes) and the next 4 bytes */
+ assert(pkt->wirevec[1].iov_len >= 8);
+ fc_ecb_encrypt(data, data, k->keysched, ENCRYPT);
+ break;
+
+ case rxkad_crypt:
+ len += rx_GetSecurityHeaderSize(con); /* Extended pkt len */
+ /* Round up to 8 byte boundary for encryption to work */
+ if (len % 8)
+ {
+ int diff = 8 - (len % 8);
+ rxi_RoundUpPacket(pkt, diff);
+ len += diff;
+ }
+ rx_SetDataSize(pkt, len); /* Set extended packet length */
+
+ assert((len % 8) == 0);
+ code = rxkad_EncryptPacket(con, k->keysched,(u_int32*)k->key, len,pkt);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return code;
+ }
+ return 0;
+}
+
+int
+rxkad_check_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int level,
+ key_stuff *k,
+ end_stuff *e)
+{
+ u_int xlen = rx_GetDataSize(pkt); /* Extended packet length */
+
+ if (rx_GetPacketCksum(pkt)
+ != rxkad_cksum_header(pkt, k->keysched, e->header_iv))
+ return RXKADSEALEDINCON;
+
+ e->packetsReceived++;
+
+ if (level == rxkad_clear)
+ {
+ e->bytesReceived += xlen; /* Same as real length */
+ }
+ else
+ {
+ u_int len; /* Real packet length */
+ u_int32 *data = (u_int32 *) rx_DataOf(pkt);
+ u_int32 t;
+ int32 code;
+
+ switch (level) {
+ case rxkad_auth:
+ assert(rx_Contiguous(pkt) >= 8);
+ fc_ecb_encrypt(data, data, k->keysched, DECRYPT);
+ break;
+
+ case rxkad_crypt:
+ code = rxkad_DecryptPacket(con, k->keysched,(u_int32*)k->key, xlen, pkt);
+ if (code)
+ return code;
+ break;
+
+ default:
+ assert(0);
+ }
+
+ assert(rx_Contiguous(pkt) >= 4);
+
+ t = ntohl(data[0]);
+ len = t & 0xffff; /* Extract real length */
+ t >>= 16;
+ if (t != ((pkt->header.seq ^ pkt->header.callNumber) & 0xffff))
+ return RXKADSEALEDINCON;
+
+#define TBYTES 15
+ /* The packet is extended with 0 - 7 bytes to a chipher block
+ * boundary. This is however not true with the Transarc
+ * implementation, for unknown reasons it sometimes extendeds
+ * the packet with anything up to TBYTES. */
+ if (len > xlen)
+ return RXKADSEALEDINCON;
+ if (xlen > len + TBYTES)
+ return RXKADSEALEDINCON;
+
+ e->bytesReceived += len;
+ rx_SetDataSize(pkt, len); /* Set real packet length */
+ return 0;
+ }
+ return 0;
+}
diff --git a/usr.sbin/afs/src/rxkad/rxk_serv.c b/usr.sbin/afs/src/rxkad/rxk_serv.c
new file mode 100644
index 00000000000..443c168ec43
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxk_serv.c
@@ -0,0 +1,558 @@
+/* $OpenBSD: rxk_serv.c,v 1.1.1.1 1998/09/14 21:53:20 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 "rxkad_locl.h"
+
+#if defined(KRB5)
+#include <krb5.h>
+#endif
+
+RCSID("$KTH: rxk_serv.c,v 1.4 1998/02/22 21:12:27 lha Exp $");
+
+/* Security object specific server data */
+typedef struct rxkad_serv_class {
+ struct rx_securityClass klass;
+ rxkad_level min_level;
+ void *appl_data;
+ int (*get_key)(void *appl_data, int kvno, des_cblock *key);
+ int (*user_ok)(char *name, char *inst, char *realm, int kvno);
+} rxkad_serv_class;
+
+static
+int
+server_NewConnection(struct rx_securityClass *obj, struct rx_connection *con)
+{
+ assert(con->securityData == 0);
+ obj->refCount++;
+ con->securityData = (char *) osi_Alloc(sizeof(serv_con_data));
+ memset(con->securityData, 0x0, sizeof(serv_con_data));
+ return 0;
+}
+
+static
+int
+server_Close(struct rx_securityClass *obj)
+{
+ obj->refCount--;
+ if (obj->refCount <= 0)
+ osi_Free(obj, sizeof(rxkad_serv_class));
+ return 0;
+}
+
+static
+int
+server_DestroyConnection(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ serv_con_data *cdat = (serv_con_data *)con->securityData;
+
+ if (cdat)
+ {
+ if (cdat->user)
+ osi_Free(cdat->user, sizeof(krb_principal));
+ osi_Free(cdat, sizeof(serv_con_data));
+ }
+ return server_Close(obj);
+}
+
+/*
+ * Check whether a connection authenticated properly.
+ * Zero is good (authentication succeeded).
+ */
+static
+int
+server_CheckAuthentication(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ if (cdat)
+ return !cdat->authenticated;
+ else
+ return RXKADNOAUTH;
+}
+
+/*
+ * Select a nonce for later use.
+ */
+static
+int
+server_CreateChallenge(struct rx_securityClass *obj_,
+ struct rx_connection *con)
+{
+ rxkad_serv_class *obj = (rxkad_serv_class *) obj_;
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ union {
+ u_int32 rnd[2];
+ des_cblock k;
+ } u;
+
+ /* Any good random numbers will do, no real need to use
+ * cryptographic techniques here */
+ des_random_key(u.k);
+ cdat->nonce = u.rnd[0] ^ u.rnd[1];
+ cdat->authenticated = 0;
+ cdat->cur_level = obj->min_level;
+ return 0;
+}
+
+/*
+ * Wrap the nonce in a challenge packet.
+ */
+static
+int
+server_GetChallenge(const struct rx_securityClass *obj,
+ const struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ rxkad_challenge c;
+
+ /* Make challenge */
+ c.version = htonl(RXKAD_VERSION);
+ c.nonce = htonl(cdat->nonce);
+ c.min_level = htonl((int32)cdat->cur_level);
+ c.unused = 0; /* Use this to hint client we understand krb5 tickets??? */
+
+ /* Stuff into packet */
+ if (rx_SlowWritePacket(pkt, 0, sizeof(c), &c) != sizeof(c))
+ return RXKADPACKETSHORT;
+ rx_SetDataSize(pkt, sizeof(c));
+ return 0;
+}
+
+static
+int
+decode_krb5_ticket(rxkad_serv_class *obj,
+ int serv_kvno,
+ char *ticket,
+ int32 ticket_len,
+ /* OUT parms */
+ des_cblock session_key,
+ u_int32 *expires,
+ krb_principal *p)
+{
+#if !defined(KRB5)
+ return RXKADBADTICKET;
+#else
+ des_cblock serv_key; /* Service's secret key */
+ krb5_keyblock key; /* Uses serv_key above */
+ int code;
+ size_t siz;
+
+ Ticket t5; /* Must free */
+ EncTicketPart decr_part; /* Must free */
+ krb5_context context; /* Must free */
+ krb5_data plain; /* Must free */
+
+ memset(&t5, 0x0, sizeof(t5));
+ memset(&decr_part, 0x0, sizeof(decr_part));
+ krb5_init_context(&context);
+ krb5_data_zero(&plain);
+
+ assert(serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5);
+
+ code = decode_Ticket(ticket, ticket_len, &t5, &siz);
+ if (code != 0)
+ goto bad_ticket;
+
+ /* Find the real service key version number */
+ serv_kvno = t5.tkt_vno;
+
+ /* Check that the key type really fit into 8 bytes */
+ switch (t5.enc_part.etype) {
+ case ETYPE_DES_CBC_CRC:
+ case ETYPE_DES_CBC_MD4:
+ case ETYPE_DES_CBC_MD5:
+ key.keytype = KEYTYPE_DES;
+ key.keyvalue.length = 8;
+ key.keyvalue.data = serv_key;
+ break;
+ default:
+ goto unknown_key;
+ }
+
+ /* Get the service key. We have to assume that the key type is of
+ * size 8 bytes or else we can't store service keys for both krb4
+ * and krb5 in the same way in /usr/afs/etc/KeyFile.
+ */
+ code = (*obj->get_key)(obj->appl_data, serv_kvno, &serv_key);
+ if (code)
+ goto unknown_key;
+
+ /* Decrypt ticket */
+ code = krb5_decrypt(context,
+ t5.enc_part.cipher.data,
+ t5.enc_part.cipher.length,
+ t5.enc_part.etype,
+ &key,
+ &plain);
+ if (code != 0)
+ goto bad_ticket;
+
+ /* Decode ticket */
+ code = decode_EncTicketPart(plain.data, plain.length, &decr_part, &siz);
+ if (code != 0)
+ goto bad_ticket;
+
+ /* Extract realm and principal */
+ memset(p, 0x0, sizeof(p));
+ strncpy(p->realm, decr_part.crealm, REALM_SZ - 1);
+ switch (decr_part.cname.name_string.len) {
+ case 2:
+ strncpy(p->instance, decr_part.cname.name_string.val[1], ANAME_SZ - 1);
+ case 1:
+ strncpy(p->name, decr_part.cname.name_string.val[0], ANAME_SZ - 1);
+ break;
+ default:
+ goto bad_ticket;
+ }
+
+ /* Extract session key */
+ memcpy(session_key, decr_part.key.keyvalue.data, 8);
+
+ /* Check lifetimes and host addresses, flags etc */
+ {
+ time_t now = time(0); /* Use fast time package instead??? */
+ time_t start = decr_part.authtime;
+ if (decr_part.starttime)
+ start = *decr_part.starttime;
+ if (start - now > context->max_skew || decr_part.flags.invalid)
+ goto no_auth;
+ if (now > decr_part.endtime)
+ goto tkt_expired;
+ *expires = decr_part.endtime;
+ }
+
+#if 0
+ /* Check host addresses */
+#endif
+
+cleanup:
+ free_Ticket(&t5);
+ free_EncTicketPart(&decr_part);
+ krb5_free_context(context);
+ krb5_data_free(&plain);
+ return code;
+
+unknown_key:
+ code = RXKADUNKNOWNKEY;
+ goto cleanup;
+no_auth:
+ code = RXKADNOAUTH;
+ goto cleanup;
+tkt_expired:
+ code = RXKADEXPIRED;
+ goto cleanup;
+bad_ticket:
+ code = RXKADBADTICKET;
+ goto cleanup;
+#endif /* KRB5 */
+}
+
+static
+int
+decode_krb4_ticket(rxkad_serv_class *obj,
+ int serv_kvno,
+ char *ticket,
+ int32 ticket_len,
+ /* OUT parms */
+ des_cblock session_key,
+ u_int32 *expires,
+ krb_principal *p)
+{
+ u_char kflags;
+ int klife;
+ u_int32 start;
+ u_int32 paddress;
+ char sname[SNAME_SZ], sinstance[INST_SZ];
+ KTEXT_ST tkt;
+ des_cblock serv_key; /* Service's secret key */
+ des_key_schedule serv_sched; /* Service's schedule */
+
+ /* First get service key */
+ int code = (*obj->get_key)(obj->appl_data, serv_kvno, &serv_key);
+ if (code)
+ return RXKADUNKNOWNKEY;
+
+ des_key_sched(&serv_key, serv_sched);
+ tkt.length = ticket_len;
+ memcpy(tkt.dat, ticket, ticket_len);
+ code = decomp_ticket(&tkt, &kflags,
+ p->name, p->instance, p->realm, &paddress,
+ session_key, &klife, &start,
+ sname, sinstance,
+ &serv_key, serv_sched);
+ if (code != KSUCCESS)
+ return RXKADBADTICKET;
+
+#if 0
+ if (paddress != ntohl(con->peer->host))
+ return RXKADBADTICKET;
+#endif
+
+ {
+ time_t end = krb_life_to_time(start, klife);
+ time_t now = time(0);
+ start -= CLOCK_SKEW;
+ if (now < start)
+ return RXKADNOAUTH;
+ else if (now > end)
+ return RXKADEXPIRED;
+ *expires = end;
+ }
+ return 0; /* Success */
+}
+
+/*
+ * Process a response to a challange.
+ */
+static
+int
+server_CheckResponse(struct rx_securityClass *obj_,
+ struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ rxkad_serv_class *obj = (rxkad_serv_class *) obj_;
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ int serv_kvno; /* Service's kvno we used */
+ int32 ticket_len;
+ char ticket[MAXKRB5TICKETLEN];
+ int code;
+ rxkad_response r;
+ krb_principal p;
+ u_int32 cksum;
+
+ if (rx_SlowReadPacket(pkt, 0, sizeof(r), &r) != sizeof(r))
+ return RXKADPACKETSHORT;
+
+ serv_kvno = ntohl(r.kvno);
+ ticket_len = ntohl(r.ticket_len);
+
+ if (ticket_len > MAXKRB5TICKETLEN)
+ return RXKADTICKETLEN;
+
+ if (rx_SlowReadPacket(pkt, sizeof(r), ticket_len, ticket) != ticket_len)
+ return RXKADPACKETSHORT;
+
+ /* Disassemble kerberos ticket */
+ if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
+ code = decode_krb5_ticket(obj, serv_kvno, ticket, ticket_len,
+ cdat->k.key, &cdat->expires, &p);
+ else
+ code = decode_krb4_ticket(obj, serv_kvno, ticket, ticket_len,
+ cdat->k.key, &cdat->expires, &p);
+ if (code != 0)
+ return code;
+
+ fc_keysched(cdat->k.key, cdat->k.keysched);
+
+ /* Unseal r.encrypted */
+ fc_cbc_enc2(&r.encrypted, &r.encrypted, sizeof(r.encrypted),
+ cdat->k.keysched, (u_int32*)cdat->k.key, DECRYPT);
+
+ /* Verify response integrity */
+ cksum = r.encrypted.cksum;
+ r.encrypted.cksum = 0;
+ if (r.encrypted.epoch != ntohl(con->epoch)
+ || r.encrypted.cid != ntohl(con->cid & RX_CIDMASK)
+ || r.encrypted.security_index != ntohl(con->securityIndex)
+ || cksum != rxkad_cksum_response(&r))
+ return RXKADSEALEDINCON;
+ {
+ int i;
+ for (i = 0; i < RX_MAXCALLS; i++)
+ {
+ r.encrypted.call_numbers[i] = ntohl(r.encrypted.call_numbers[i]);
+ if (r.encrypted.call_numbers[i] < 0)
+ return RXKADSEALEDINCON;
+ }
+ }
+
+ if (ntohl(r.encrypted.inc_nonce) != cdat->nonce+1)
+ return RXKADOUTOFSEQUENCE;
+
+ {
+ int level = ntohl(r.encrypted.level);
+ if ((level < cdat->cur_level) || (level > rxkad_crypt))
+ return RXKADLEVELFAIL;
+ cdat->cur_level = level;
+ /* We don't use trailers but the transarc implementation breaks if
+ * we don't set the trailer size, packets get to large */
+ if (level == rxkad_auth)
+ {
+ rx_SetSecurityHeaderSize(con, 4);
+ rx_SetSecurityMaxTrailerSize(con, 4);
+ }
+ else if (level == rxkad_crypt)
+ {
+ rx_SetSecurityHeaderSize(con, 8);
+ rx_SetSecurityMaxTrailerSize(con, 8);
+ }
+ }
+
+ rxi_SetCallNumberVector(con, r.encrypted.call_numbers);
+
+ rxkad_calc_header_iv(con, cdat->k.keysched,
+ (const des_cblock *)&cdat->k.key, cdat->e.header_iv);
+ cdat->authenticated = 1;
+
+ if (obj->user_ok)
+ {
+ code = obj->user_ok(p.name, p.instance, p.realm, serv_kvno);
+ if (code)
+ return RXKADNOAUTH;
+ }
+ else
+ {
+ krb_principal *user = (krb_principal *) osi_Alloc(sizeof(krb_principal));
+ *user = p;
+ cdat->user = user;
+ }
+ return 0;
+}
+
+/*
+ * Checksum and/or encrypt packet
+ */
+static
+int
+server_PreparePacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ struct rx_connection *con = rx_ConnectionOf(call);
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ key_stuff *k = &cdat->k;
+ end_stuff *e = &cdat->e;
+
+ return rxkad_prepare_packet(pkt, con, cdat->cur_level, k, e);
+}
+
+/*
+ * Verify checksum and/or decrypt packet.
+ */
+static
+int
+server_CheckPacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ struct rx_connection *con = rx_ConnectionOf(call);
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ key_stuff *k = &cdat->k;
+ end_stuff *e = &cdat->e;
+
+ if (time(0) > cdat->expires) /* Use fast time package instead??? */
+ return RXKADEXPIRED;
+
+ return rxkad_check_packet(pkt, con, cdat->cur_level, k, e);
+}
+
+static
+int
+server_GetStats(const struct rx_securityClass *obj_,
+ const struct rx_connection *con,
+ struct rx_securityObjectStats *st)
+{
+ rxkad_serv_class *obj = (rxkad_serv_class *) obj_;
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ st->type = rxkad_disipline;
+ st->level = obj->min_level;
+ st->flags = rxkad_checksummed;
+ if (cdat == 0)
+ st->flags |= rxkad_unallocated;
+ {
+ st->bytesReceived = cdat->e.bytesReceived;
+ st->packetsReceived = cdat->e.packetsReceived;
+ st->bytesSent = cdat->e.bytesSent;
+ st->packetsSent = cdat->e.packetsSent;
+ st->expires = cdat->expires;
+ st->level = cdat->cur_level;
+ if (cdat->authenticated)
+ st->flags |= rxkad_authenticated;
+ }
+ return 0;
+}
+
+static struct rx_securityOps server_ops = {
+ server_Close,
+ server_NewConnection,
+ server_PreparePacket,
+ 0,
+ server_CheckAuthentication,
+ server_CreateChallenge,
+ server_GetChallenge,
+ 0,
+ server_CheckResponse,
+ server_CheckPacket,
+ server_DestroyConnection,
+ server_GetStats,
+};
+
+struct rx_securityClass *
+rxkad_NewServerSecurityObject(/*rxkad_level*/ int min_level,
+ void *appl_data,
+ int (*get_key)(void *appl_data,
+ int kvno,
+ des_cblock *key),
+ int (*user_ok)(char *name,
+ char *inst,
+ char *realm,
+ int kvno))
+{
+ rxkad_serv_class *obj;
+
+ if (!get_key)
+ return 0;
+
+ obj = (rxkad_serv_class *) osi_Alloc(sizeof(rxkad_serv_class));
+ obj->klass.refCount = 1;
+ obj->klass.ops = &server_ops;
+ obj->klass.privateData = (char *) obj;
+
+ obj->min_level = min_level;
+ obj->appl_data = appl_data;
+ obj->get_key = get_key;
+ obj->user_ok = user_ok;
+
+ return &obj->klass;
+}
diff --git a/usr.sbin/afs/src/rxkad/rxkad.h b/usr.sbin/afs/src/rxkad/rxkad.h
new file mode 100644
index 00000000000..ec03481deef
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxkad.h
@@ -0,0 +1,169 @@
+/* $OpenBSD: rxkad.h,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/* -*- C -*- */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* @(#)$KTH: rxkad.h,v 1.7 1998/02/23 03:23:24 assar Exp $ */
+
+#ifndef __RXKAD_H
+#define __RXKAD_H
+
+#ifdef HAVE_STDS_H
+#include <stds.h>
+#endif
+
+/* Krb4 tickets can't have a key version number of 256. This is used
+ * as a magic kvno to indicate that this is really a krb5 ticket. The
+ * real kvno can be retrieved from the cleartext portion of the
+ * ticket. For more info see the Transarc header file rxkad.h.
+ */
+#define RXKAD_TKT_TYPE_KERBEROS_V5 256
+
+/* Is this really large enough for a krb5 ticket? */
+#define MAXKRB5TICKETLEN 1024
+
+typedef char rxkad_level;
+#define rxkad_clear 0 /* checksum some selected header fields */
+#define rxkad_auth 1 /* rxkad_clear + protected packet length */
+#define rxkad_crypt 2 /* rxkad_crypt + encrypt packet payload */
+extern int rxkad_min_level; /* enforce min level at client end */
+
+extern int rxkad_EpochWasSet;
+
+#ifndef __P
+#define __P(x) x
+#endif
+
+int32 rxkad_GetServerInfo __P((struct rx_connection *con,
+ rxkad_level *level,
+ u_int32 *expiration,
+ char *name,
+ char *instance,
+ char *cell,
+ int32 *kvno));
+
+struct rx_securityClass *
+rxkad_NewServerSecurityObject __P((/*rxkad_level*/ int min_level,
+ void *appl_data,
+ int (*get_key)(void *appl_data,
+ int kvno,
+ des_cblock *key),
+ int (*user_ok)(char *name,
+ char *inst,
+ char *realm,
+ int kvno)));
+
+struct rx_securityClass *
+rxkad_NewClientSecurityObject __P((/*rxkad_level*/ int level,
+ void *sessionkey,
+ int32 kvno,
+ int ticketLen,
+ char *ticket));
+
+#define RXKADINCONSISTENCY (19270400L)
+#define RXKADPACKETSHORT (19270401L)
+#define RXKADLEVELFAIL (19270402L)
+#define RXKADTICKETLEN (19270403L)
+#define RXKADOUTOFSEQUENCE (19270404L)
+#define RXKADNOAUTH (19270405L)
+#define RXKADBADKEY (19270406L)
+#define RXKADBADTICKET (19270407L)
+#define RXKADUNKNOWNKEY (19270408L)
+#define RXKADEXPIRED (19270409L)
+#define RXKADSEALEDINCON (19270410L)
+#define RXKADDATALEN (19270411L)
+#define RXKADILLEGALLEVEL (19270412L)
+
+/* The rest is backwards compatibility stuff that we don't use! */
+#define MAXKTCTICKETLIFETIME (30*24*60*60)
+#define MINKTCTICKETLEN (32)
+#define MAXKTCTICKETLEN (344)
+#define MAXKTCNAMELEN (64)
+#define MAXKTCREALMLEN (64)
+
+/*
+#define MAXKTCNAMELEN ANAME_SZ
+#define MAXKTCREALMLEN REALM_SZ
+*/
+
+#define KTC_TIME_UNCERTAINTY (CLOCK_SKEW)
+
+/*
+#define KTC_TIME_UNCERTAINTY (60*15)
+*/
+
+struct ktc_encryptionKey {
+ char data[8];
+};
+
+struct ktc_principal {
+ char name[MAXKTCNAMELEN];
+ char instance[MAXKTCNAMELEN];
+ char cell[MAXKTCREALMLEN];
+};
+
+u_int32 life_to_time __P((u_int32 start, int life_));
+
+int time_to_life __P((u_int32 start, u_int32 end));
+
+int tkt_CheckTimes __P((int32 begin, int32 end, int32 now));
+
+int
+tkt_MakeTicket __P((char *ticket,
+ int *ticketLen,
+ struct ktc_encryptionKey *key,
+ char *name, char *inst, char *cell,
+ u_int32 start, u_int32 end,
+ struct ktc_encryptionKey *sessionKey,
+ u_int32 host,
+ char *sname, char *sinst));
+
+int
+tkt_DecodeTicket __P((char *asecret,
+ int32 ticketLen,
+ struct ktc_encryptionKey *key,
+ char *name,
+ char *inst,
+ char *cell,
+ char *sessionKey,
+ int32 *host,
+ int32 *start,
+ int32 *end));
+
+#endif /* __RXKAD_H */
diff --git a/usr.sbin/afs/src/rxkad/rxkad_locl.h b/usr.sbin/afs/src/rxkad/rxkad_locl.h
new file mode 100644
index 00000000000..e4f3e060544
--- /dev/null
+++ b/usr.sbin/afs/src/rxkad/rxkad_locl.h
@@ -0,0 +1,195 @@
+/* $OpenBSD: rxkad_locl.h,v 1.1.1.1 1998/09/14 21:53:19 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* @(#)$KTH: rxkad_locl.h,v 1.8 1998/03/28 16:35:49 lha Exp $ */
+
+#ifndef __RXKAD_LOCL_H
+#define __RXKAD_LOCL_H
+
+/* $KTH: rxkad_locl.h,v 1.8 1998/03/28 16:35:49 lha Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#ifdef USE_MMAPTIME
+#include <mmaptime.h>
+#define gettimeofday mmaptime_gettimeofday
+#endif
+
+#ifdef NDEBUG
+#define assert(e) ((void)0)
+#else
+#define assert(e) ((e) ? (void)0 : (void)osi_Panic("assert(%s) failed: file %s, line %d\n", #e, __FILE__, __LINE__, #e))
+#endif
+
+#include <des.h>
+#include <kerberosIV/krb.h>
+
+#undef RCSID
+#include <rx/rx.h>
+#undef RCSID
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+extern int rx_epoch, rx_nextCid;
+
+#include "rxkad.h"
+
+#define rxkad_disipline 3
+
+#define rxkad_unallocated 1
+#define rxkad_authenticated 2
+#define rxkad_expired 4
+#define rxkad_checksummed 8
+
+#define ROUNDS 16
+
+int fc_keysched(const void *key_, int32 sched[ROUNDS]);
+
+/* In_ and out_ MUST be u_int32 aligned */
+int fc_ecb_encrypt(const void *in_, void *out_,
+ const int32 sched[ROUNDS], int encrypt);
+
+/* In_ and out_ MUST be u_int32 aligned */
+int fc_cbc_encrypt(const void *in_, void *out_, int32 length,
+ const int32 sched[ROUNDS], u_int32 iv[2],
+ int encrypt);
+
+int rxkad_EncryptPacket(const void *rx_connection_not_used,
+ const int32 sched[ROUNDS], const u_int32 iv[2],
+ int len, struct rx_packet *packet);
+
+int rxkad_DecryptPacket(const void *rx_connection_not_used,
+ const int32 sched[ROUNDS], const u_int32 iv[2],
+ int len, struct rx_packet *packet);
+
+#ifdef __GNUC__
+static inline
+void
+fc_cbc_enc2(const void *in, void *out, int32 length, const int32 sched[ROUNDS],
+ const u_int32 iv_[2], int encrypt)
+{
+ u_int32 iv[2];
+ iv[0] = iv_[0];
+ iv[1] = iv_[1];
+ fc_cbc_encrypt(in, out, length, sched, iv, encrypt);
+}
+#else
+#define fc_cbc_enc2(in, out, length, sched, iv_, encrypt) \
+{ u_int32 _iv_[2]; u_int32 *_tmp_ = (iv_); \
+ memcpy(_iv_, _tmp_, 8); \
+ fc_cbc_encrypt((in), (out), (length), (sched), (_iv_), (encrypt)); }
+#endif
+
+#define RXKAD_VERSION 2
+
+/* Version 2 challenge format */
+typedef struct rxkad_challenge {
+ int32 version;
+ int32 nonce;
+ int32 min_level;
+ int32 unused;
+} rxkad_challenge;
+
+/* To protect the client from being used as an oracle the response
+ * contains connection specific information. */
+typedef struct rxkad_response {
+ int32 version;
+ int32 unused;
+ struct {
+ int32 epoch;
+ int32 cid;
+ u_int32 cksum; /* Cksum of this response */
+ int32 security_index;
+ int32 call_numbers[RX_MAXCALLS];
+ int32 inc_nonce;
+ int32 level;
+ } encrypted;
+ int32 kvno;
+ int32 ticket_len;
+ /* u_char the_ticket[ticket_len]; */
+} rxkad_response;
+
+typedef struct key_stuff {
+ int32 keysched[ROUNDS];
+ des_cblock key;
+} key_stuff;
+
+typedef struct end_stuff {
+ u_int32 header_iv[2];
+ u_int32 bytesReceived, packetsReceived, bytesSent, packetsSent;
+} end_stuff;
+
+u_int32
+rxkad_cksum_response(rxkad_response *r);
+
+void
+rxkad_calc_header_iv(const struct rx_connection *conn,
+ const int32 sched[ROUNDS],
+ const des_cblock *in_iv,
+ u_int32 out_iv[2]);
+
+int
+rxkad_prepare_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e);
+
+int
+rxkad_check_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e);
+
+/* Per connection specific server data */
+typedef struct serv_con_data {
+ end_stuff e;
+ key_stuff k;
+ u_int32 expires;
+ int32 nonce;
+ krb_principal *user;
+ rxkad_level cur_level; /* Starts at min_level and can only increase */
+ char authenticated;
+} serv_con_data;
+
+#endif /* __RXKAD_LOCL_H */
diff --git a/usr.sbin/afs/src/util/atom.c b/usr.sbin/afs/src/util/atom.c
new file mode 100644
index 00000000000..361522c59da
--- /dev/null
+++ b/usr.sbin/afs/src/util/atom.c
@@ -0,0 +1,72 @@
+/* $OpenBSD: atom.c,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: atom.c,v 1.5 1998/02/22 11:22:13 assar Exp $");
+#endif
+
+#include <string.h>
+#include <hash.h>
+#include <atom.h>
+
+#define ATOMSIZE 1009
+
+static Hashtab *atomtab;
+
+/*
+ *
+ */
+
+void
+atominit(void)
+{
+ atomtab = hashtabnew(ATOMSIZE, (hashtabnew_arg2_t) strcmp,
+ (hashtabnew_arg3_t) hashjpw);
+}
+
+/*
+ *
+ */
+
+void *
+atomenter(char *s)
+{
+ return hashtabadd(atomtab, s);
+}
diff --git a/usr.sbin/afs/src/util/atom.h b/usr.sbin/afs/src/util/atom.h
new file mode 100644
index 00000000000..1b42af60ce8
--- /dev/null
+++ b/usr.sbin/afs/src/util/atom.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: atom.h,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: atom.h,v 1.3 1998/01/11 00:33:57 assar Exp $ */
+
+#ifndef _ATOM_
+#define _ATOM_
+
+void atominit(void);
+void * atomenter(char *);
+
+#endif /* _ATOM_ */
diff --git a/usr.sbin/afs/src/util/bool.h b/usr.sbin/afs/src/util/bool.h
new file mode 100644
index 00000000000..021eb7b20dd
--- /dev/null
+++ b/usr.sbin/afs/src/util/bool.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: bool.h,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Boolean
+ */
+
+/* $KTH: bool.h,v 1.2 1997/11/09 23:48:45 assar Exp $ */
+
+#ifndef _BOOL_
+#define _BOOL_
+
+#ifndef FALSE
+
+typedef enum {
+ FALSE = 0, TRUE = 1
+} Bool;
+
+#else /* FALSE */
+
+typedef int Bool;
+
+#endif
+
+#endif /* _BOOL_ */
diff --git a/usr.sbin/afs/src/util/date_rfc822.c b/usr.sbin/afs/src/util/date_rfc822.c
new file mode 100644
index 00000000000..5b1133a7ed3
--- /dev/null
+++ b/usr.sbin/afs/src/util/date_rfc822.c
@@ -0,0 +1,80 @@
+/* $OpenBSD: date_rfc822.c,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * $KTH: date_rfc822.c,v 1.5 1998/02/11 03:43:32 art Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: date_rfc822.c,v 1.5 1998/02/11 03:43:32 art Exp $");
+#endif
+
+#include <roken.h>
+#include <time.h>
+#include "date_rfc822.h"
+
+/*
+ * Return current date in RFC822-format with timezone GMT.
+ * Memory is allocated with strdup.
+ */
+
+char *
+date_time2rfc822 (time_t t)
+{
+ char tmp [80];
+
+ strftime (tmp, sizeof (tmp), "%A, %d-%h-%y %H:%M:%S %Z", gmtime (&t));
+ return strdup (tmp);
+}
+
+#if 0 /* XXX */
+/*
+ * Convert from RFC 822 representation of date into a time_t.
+ */
+
+time_t
+date_rfc8222time (char *s)
+{
+ struct tm tm;
+
+ strptime (s, "%d-%h-%y %H:%M:%S ", &tm);
+ return timegm (&tm);
+}
+#endif
diff --git a/usr.sbin/afs/src/util/date_rfc822.h b/usr.sbin/afs/src/util/date_rfc822.h
new file mode 100644
index 00000000000..59d5fe7dc85
--- /dev/null
+++ b/usr.sbin/afs/src/util/date_rfc822.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: date_rfc822.h,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: date_rfc822.h,v 1.1 1998/01/11 00:33:58 assar Exp $ */
+
+#ifndef _DATE_RFC822_
+#define _DATE_RFC822_
+
+char *
+date_time2rfc822 (time_t t);
+
+#endif /* _DATE_RFC822_ */
diff --git a/usr.sbin/afs/src/util/efile.c b/usr.sbin/afs/src/util/efile.c
new file mode 100644
index 00000000000..21546752acc
--- /dev/null
+++ b/usr.sbin/afs/src/util/efile.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: efile.c,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: efile.c,v 1.4 1998/02/22 11:22:14 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include "efile.h"
+
+FILE *
+efopen (char *name, char *mode)
+{
+ FILE *tmp;
+
+ tmp = fopen (name, mode);
+ if (tmp == NULL) {
+ fprintf (stderr, "Could not open file %s in mode %s\n",
+ name, mode);
+ perror ("open");
+ exit (1);
+ }
+ return tmp;
+}
+
+void
+efclose (FILE *f)
+{
+ if (fclose (f)) {
+ fprintf (stderr, "Problems closing a file\n");
+ perror ("close");
+ }
+}
+
+size_t
+efread (void *ptr, size_t size, size_t nitems, FILE *stream)
+{
+ size_t res;
+
+ res = fread (ptr, size, nitems, stream);
+ if (res == 0) {
+ fprintf (stderr, "Error reading\n");
+ perror ("read");
+ exit (1);
+ }
+ return res;
+}
+
+size_t
+efwrite (const void *ptr, size_t size, size_t nitems, FILE *stream)
+{
+ size_t res;
+
+ res = fwrite (ptr, size, nitems, stream);
+ if (res == 0) {
+ fprintf (stderr, "Error writing\n");
+ perror ("read");
+ exit (1);
+ }
+ return res;
+}
diff --git a/usr.sbin/afs/src/util/efile.h b/usr.sbin/afs/src/util/efile.h
new file mode 100644
index 00000000000..0bb72a5d0d5
--- /dev/null
+++ b/usr.sbin/afs/src/util/efile.h
@@ -0,0 +1,53 @@
+/* $OpenBSD: efile.h,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: efile.h,v 1.2 1997/11/09 23:48:47 assar Exp $ */
+
+#ifndef _EFILE_
+#define _EFILE_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+FILE *efopen(char *name, char *mode);
+void efclose(FILE *);
+size_t efread (void *ptr, size_t size, size_t nitems, FILE *stream);
+size_t efwrite (const void *ptr, size_t size, size_t nitems, FILE *stream);
+
+#endif /* _EFILE_ */
diff --git a/usr.sbin/afs/src/util/fnameutil.c b/usr.sbin/afs/src/util/fnameutil.c
new file mode 100644
index 00000000000..80dd238fff0
--- /dev/null
+++ b/usr.sbin/afs/src/util/fnameutil.c
@@ -0,0 +1,92 @@
+/* $OpenBSD: fnameutil.c,v 1.1.1.1 1998/09/14 21:53:21 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: fnameutil.c,v 1.6 1998/03/13 04:36:32 assar Exp $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <mem.h>
+#include "fnameutil.h"
+
+/*
+ * Return the basename of `s'.
+ * The result is malloc'ed
+ */
+
+char *
+copy_basename (const char *s)
+{
+ const char *p, *q;
+ char *res;
+
+ p = strrchr (s, '/');
+ if (p == NULL)
+ p = s;
+ else
+ ++p;
+ q = strchr (p, '.');
+ if (q == NULL)
+ q = s + strlen (s);
+ res = (char *)emalloc (q - p + 1);
+ strncpy (res, p, q - p);
+ res[q - p] = '\0';
+ return res;
+}
+
+char *
+copy_dirname (const char *s)
+{
+ const char *p;
+ char *res;
+
+ p = strrchr (s, '/');
+ if (p == NULL)
+ return strdup(".");
+ res = (char *)emalloc (p - s + 1);
+ strncpy (res, s, p - s);
+ res[p - s] = '\0';
+ return res;
+}
diff --git a/usr.sbin/afs/src/util/fnameutil.h b/usr.sbin/afs/src/util/fnameutil.h
new file mode 100644
index 00000000000..737692f86b4
--- /dev/null
+++ b/usr.sbin/afs/src/util/fnameutil.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: fnameutil.h,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: fnameutil.h,v 1.4 1998/03/13 04:36:33 assar Exp $ */
+
+#ifndef _FNAMEUTIL_
+#define _FNAMEUTIL_
+
+char *copy_basename (const char *);
+char *copy_dirname (const char *);
+
+#endif /* _FNAMEUTIL_ */
diff --git a/usr.sbin/afs/src/util/freelist.c b/usr.sbin/afs/src/util/freelist.c
new file mode 100644
index 00000000000..0551b94878d
--- /dev/null
+++ b/usr.sbin/afs/src/util/freelist.c
@@ -0,0 +1,107 @@
+/* $OpenBSD: freelist.c,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Function for handling freelist of different stuff.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: freelist.c,v 1.3 1998/02/22 11:22:15 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "freelist.h"
+
+/*
+ * Create a freelist, that is a block of data stuff and a list of the
+ * free ones.
+ */
+
+Freelist *
+freelistnew (size_t n, size_t sz)
+{
+ Freelist *f;
+ int i;
+
+ f = (Freelist *)malloc (sizeof (Freelist));
+ if (f == NULL)
+ return NULL;
+ f->list = listnew ();
+ f->data = malloc (n * sz);
+ for (i = 0; i < n; ++i)
+ listaddhead (f->list, (char *)f->data + i * sz);
+ return f;
+}
+
+/*
+ * Allocate an element from a freelist.
+ * Right now just fail if there is no place, otherwise we might want
+ * to allocate some more data.
+ */
+
+void *
+freelistalloc (Freelist *f)
+{
+ return listdelhead (f->list);
+}
+
+/*
+ * Free an element and return it to the freelist.
+ */
+
+void
+freelistfree (Freelist *f, void *q)
+{
+ listaddhead (f->list, q);
+}
+
+/*
+ * Delete an freelist. All elements are deleted and there should be no
+ * references left to it.
+ */
+
+void
+freelistdel (Freelist *f)
+{
+ free (f->data);
+ free (f->list);
+}
diff --git a/usr.sbin/afs/src/util/freelist.h b/usr.sbin/afs/src/util/freelist.h
new file mode 100644
index 00000000000..12707e9a004
--- /dev/null
+++ b/usr.sbin/afs/src/util/freelist.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: freelist.h,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: freelist.h,v 1.2 1997/11/09 23:48:49 assar Exp $ */
+
+#ifndef _FREELIST_
+#define _FREELIST_
+
+#include <list.h>
+
+typedef struct {
+ void *data;
+ List *list;
+} Freelist;
+
+Freelist *freelistnew (size_t n, size_t sz);
+void *freelistalloc (Freelist *f);
+void freelistfree (Freelist *f, void *q);
+void freelistdel (Freelist *f);
+
+#endif /* _FREELIST_ */
diff --git a/usr.sbin/afs/src/util/hash.c b/usr.sbin/afs/src/util/hash.c
new file mode 100644
index 00000000000..59290bbab0b
--- /dev/null
+++ b/usr.sbin/afs/src/util/hash.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: hash.c,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Hash table functions
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: hash.c,v 1.10 1998/03/18 19:30:03 art Exp $");
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <bool.h>
+#include <hash.h>
+
+static Hashentry *_search(Hashtab * htab, /* The hash table */
+ void *ptr); /* And key */
+
+Hashtab *
+hashtabnew(int sz,
+ int (*cmp) (void *, void *),
+ unsigned (*hash) (void *))
+{
+ Hashtab *htab;
+ int i;
+
+ assert(sz > 0);
+
+ htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));
+
+ if (htab == NULL)
+ return NULL;
+
+ for (i = 0; i < sz; ++i)
+ htab->tab[i] = NULL;
+
+ htab->cmp = cmp;
+ htab->hash = hash;
+ htab->sz = sz;
+ return htab;
+}
+
+/* Intern search function */
+
+static Hashentry *
+_search(Hashtab * htab, void *ptr)
+{
+ Hashentry *hptr;
+
+ assert(htab && ptr);
+
+ for (hptr = htab->tab[(*htab->hash) (ptr) % htab->sz];
+ hptr;
+ hptr = hptr->next)
+ if ((*htab->cmp) (ptr, hptr->ptr) == 0)
+ break;
+ return hptr;
+}
+
+/* Search for element in hash table */
+
+void *
+hashtabsearch(Hashtab * htab, void *ptr)
+{
+ Hashentry *tmp;
+
+ tmp = _search(htab, ptr);
+ return tmp ? tmp->ptr : tmp;
+}
+
+/* add element to hash table */
+/* if already there, set new value */
+/* !NULL if succesful */
+
+void *
+hashtabadd(Hashtab * htab, void *ptr)
+{
+ Hashentry *h = _search(htab, ptr);
+ Hashentry **tabptr;
+
+ assert(htab && ptr);
+
+ if (h)
+ free((void *) h->ptr);
+ else {
+ h = (Hashentry *) malloc(sizeof(Hashentry));
+ if (h == NULL) {
+ return NULL;
+ }
+ tabptr = &htab->tab[(*htab->hash) (ptr) % htab->sz];
+ h->next = *tabptr;
+ *tabptr = h;
+ h->prev = tabptr;
+ if (h->next)
+ h->next->prev = &h->next;
+ }
+ h->ptr = ptr;
+ return h;
+}
+
+/* delete element with key key. Iff freep, free Hashentry->ptr */
+
+int
+_hashtabdel(Hashtab * htab, void *ptr, int freep)
+{
+ Hashentry *h;
+
+ assert(htab && ptr);
+
+ h = _search(htab, ptr);
+ if (h) {
+ if (freep)
+ free(h->ptr);
+ if ((*(h->prev) = h->next))
+ h->next->prev = h->prev;
+ free(h);
+ return 0;
+ } else
+ return -1;
+}
+
+/* Do something for each element */
+
+void
+hashtabforeach(Hashtab * htab, Bool(*func) (void *ptr, void *arg),
+ void *arg)
+{
+ Hashentry **h, *g, *next;
+
+ assert(htab);
+
+ for (h = htab->tab; h < &htab->tab[htab->sz]; ++h)
+ for (g = *h; g; g = next) {
+ next = g->next;
+ if ((*func) (g->ptr, arg))
+ return;
+ }
+}
+
+
+/* Clean out all elements that meet condition */
+
+void
+hashtabcleantab(Hashtab * htab, Bool(*cond) (void *ptr, void *arg),
+ void *arg)
+{
+ Hashentry **h, *g, *f;
+
+ assert(htab);
+
+ for (h = htab->tab; h < &htab->tab[htab->sz]; ++h) {
+ for (g = *h; g;) {
+ if ((*cond) (g->ptr, arg)) {
+ f = g ;
+ g = g->next ;
+ if ((*(f->prev) = f->next))
+ f->next->prev = f->prev;
+ free(g);
+ } else {
+ g = g->next;
+ }
+ }
+ }
+}
+
+
+/* standard hash-functions for strings */
+
+unsigned
+hashadd(const char *s)
+{ /* Standard hash function */
+ unsigned i;
+
+ assert(s);
+
+ for (i = 0; *s; ++s)
+ i += *s;
+ return i;
+}
+
+unsigned
+hashcaseadd(const char *s)
+{ /* Standard hash function */
+ unsigned i;
+
+ assert(s);
+
+ for (i = 0; *s; ++s)
+ i += toupper(*s);
+ return i;
+}
+
+#define TWELVE (sizeof(unsigned))
+#define SEVENTYFIVE (6*sizeof(unsigned))
+#define HIGH_BITS (~((unsigned)(~0) >> TWELVE))
+
+unsigned
+hashjpw(const char *ss)
+{ /* another hash function */
+ unsigned h = 0;
+ unsigned g;
+ unsigned const char *s = (unsigned const char *) ss;
+
+ for (; *s; ++s) {
+ h = (h << TWELVE) + *s;
+ if ((g = h & HIGH_BITS))
+ h = (h ^ (g >> SEVENTYFIVE)) & ~HIGH_BITS;
+ }
+ return h;
+}
diff --git a/usr.sbin/afs/src/util/hash.h b/usr.sbin/afs/src/util/hash.h
new file mode 100644
index 00000000000..9bad44737d9
--- /dev/null
+++ b/usr.sbin/afs/src/util/hash.h
@@ -0,0 +1,101 @@
+/* $OpenBSD: hash.h,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * hash.h. Header file for hash table functions
+ */
+
+/* $KTH: hash.h,v 1.4 1997/11/27 18:45:59 mho Exp $ */
+
+#include <bool.h>
+
+struct hashentry { /* Entry in bucket */
+ struct hashentry **prev;
+ struct hashentry *next;
+ void *ptr;
+};
+
+typedef struct hashentry Hashentry;
+
+struct hashtab { /* Hash table */
+ int (*cmp)(void *, void *); /* Compare function */
+ unsigned (*hash)(void *); /* hash function */
+ int sz; /* Size */
+ Hashentry *tab[1]; /* The table */
+};
+
+typedef struct hashtab Hashtab;
+typedef int (*hashtabnew_arg2_t)(void *, void *);
+typedef unsigned (*hashtabnew_arg3_t)(void *);
+
+/* prototypes */
+
+Hashtab *hashtabnew(int sz,
+ int (*cmp)(void *, void *),
+ unsigned (*hash)(void *)); /* Make new hash table */
+
+void *hashtabsearch(Hashtab *htab, /* The hash table */
+ void *ptr); /* The key */
+
+
+void *hashtabadd(Hashtab *htab, /* The hash table */
+ void *ptr); /* The element */
+
+int _hashtabdel(Hashtab *htab, /* The table */
+ void *ptr, /* Key */
+ int freep); /* Free data part? */
+
+void hashtabforeach(Hashtab *htab,
+ Bool (*func)(void *ptr, void *arg),
+ void *arg);
+
+void hashtabcleantab(Hashtab * htab,
+ Bool(*cond) (void *ptr, void *arg),
+ void *arg);
+
+unsigned hashadd(const char *s); /* Standard hash function */
+unsigned hashcaseadd(const char *s); /* Standard hash function */
+unsigned hashjpw(const char *s); /* another hash function */
+
+/* macros */
+
+ /* Don't free space */
+#define hashtabdel(htab,key) _hashtabdel(htab,key,FALSE)
+
+#define hashtabfree(htab,key) _hashtabdel(htab,key,TRUE) /* Do! */
diff --git a/usr.sbin/afs/src/util/ip.c b/usr.sbin/afs/src/util/ip.c
new file mode 100644
index 00000000000..6955038ef28
--- /dev/null
+++ b/usr.sbin/afs/src/util/ip.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: ip.c,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: ip.c,v 1.5 1998/03/13 04:38:09 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ip.h"
+#include <netdb.h>
+#include <sys/socket.h>
+
+/*
+ * Get the address given the string representation addr.
+ * Can be a name or a x.y.z.d given address.
+ */
+
+struct in_addr *
+ipgetaddr (const char *addr, struct in_addr *ret)
+{
+ struct hostent *hostent;
+
+ hostent = gethostbyname (addr);
+
+ if (hostent == NULL) {
+ if ((ret->s_addr = inet_addr(addr)) == -1 )
+ return NULL;
+ } else
+ memcpy(ret,
+ hostent->h_addr_list[0],
+ hostent->h_length);
+ return ret;
+}
+
+/*
+ * Get the canonical name for this address.
+ * If no luck with dns, return dot-separated instead.
+ */
+
+char *ipgetname (struct in_addr *addr)
+{
+ struct hostent *hostent;
+
+ hostent = gethostbyaddr ((const char *) addr, sizeof(*addr), AF_INET);
+
+ if (hostent == NULL)
+ return inet_ntoa (*addr);
+ else
+ return hostent->h_name;
+}
diff --git a/usr.sbin/afs/src/util/ip.h b/usr.sbin/afs/src/util/ip.h
new file mode 100644
index 00000000000..8429f3cf2e2
--- /dev/null
+++ b/usr.sbin/afs/src/util/ip.h
@@ -0,0 +1,52 @@
+/* $OpenBSD: ip.h,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: ip.h,v 1.3 1998/03/13 04:38:25 assar Exp $ */
+
+#ifndef _IP_
+#define _IP_
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+struct in_addr *ipgetaddr (const char *addr, struct in_addr *ret);
+char *ipgetname (struct in_addr *addr);
+
+#endif /* _IP_ */
diff --git a/usr.sbin/afs/src/util/list.c b/usr.sbin/afs/src/util/list.c
new file mode 100644
index 00000000000..740adce011d
--- /dev/null
+++ b/usr.sbin/afs/src/util/list.c
@@ -0,0 +1,283 @@
+/* $OpenBSD: list.c,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * List handling functions
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: list.c,v 1.7 1998/07/05 18:25:55 assar Exp $");
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "list.h"
+
+/*
+ * The representation is with a double-linked list, a pointer to
+ * the tail, and another one to the head.
+ */
+
+/*
+ * Create a new list.
+ */
+
+List*
+listnew (void)
+{
+ List *tmp = (List *)malloc (sizeof (List));
+
+ if (tmp)
+ tmp->head = tmp->tail = NULL;
+ return tmp;
+}
+
+/*
+ * Add an element before `item'
+ */
+
+Listitem *
+listaddbefore (List *list, Listitem *old_item, void *data)
+{
+ Listitem *item = (Listitem *)malloc (sizeof (Listitem));
+
+ if (item == NULL)
+ return item;
+
+ item->data = data;
+ item->prev = old_item->prev;
+ item->next = old_item;
+ if (item->prev)
+ item->prev->next = item;
+ else
+ list->head = item;
+ old_item->prev = item;
+ return item;
+}
+
+/*
+ * Add an element after `item'
+ */
+
+Listitem *
+listaddafter (List *list, Listitem *old_item, void *data)
+{
+ Listitem *item = (Listitem *)malloc (sizeof (Listitem));
+
+ if (item == NULL)
+ return item;
+
+ item->data = data;
+ item->next = old_item->next;
+ item->prev = old_item;
+ if (item->next)
+ item->next->prev = item;
+ else
+ list->tail = item;
+ old_item->next = item;
+ return item;
+}
+
+/*
+ * Add an element to the head of the list
+ */
+
+Listitem *
+listaddhead (List *list, void *data)
+{
+ Listitem *item = (Listitem *)malloc (sizeof (Listitem));
+
+ if (item == NULL)
+ return item;
+
+ item->data = data;
+ item->prev = NULL;
+ item->next = list->head;
+ if (list->head)
+ list->head->prev = item;
+ list->head = item;
+ if (list->tail == NULL)
+ list->tail = item;
+ return item;
+}
+
+/*
+ * Add an element to the tail of the list
+ */
+
+Listitem *
+listaddtail (List *list, void *data)
+{
+ Listitem *item = (Listitem *)malloc (sizeof (Listitem));
+
+ if (item == NULL)
+ return item;
+
+ item->data = data;
+ item->next = NULL;
+ item->prev = list->tail;
+ if (list->tail)
+ list->tail->next = item;
+ list->tail = item;
+ if (list->head == NULL)
+ list->head = item;
+ return item;
+}
+
+/*
+ * TRUE iff the list is empty.
+ */
+
+Bool
+listemptyp (List *list)
+{
+ return list->head == NULL;
+}
+
+/*
+ * Remove an element from the head of the list.
+ * Return this element.
+ */
+
+void *
+listdelhead (List *list)
+{
+ Listitem *item = list->head;
+ void *ret;
+
+ if (item == NULL)
+ return NULL;
+ ret = item->data;
+
+ list->head = list->head->next;
+ if (list->head)
+ list->head->prev = NULL;
+ free(item);
+ if (list->tail == item)
+ list->tail = NULL;
+ return ret;
+}
+
+/*
+ * Remove an element from the tail of the list.
+ * Return this element.
+ */
+
+void *
+listdeltail (List *list)
+{
+ Listitem *item = list->tail;
+ void *ret;
+
+ if (item == NULL)
+ return NULL;
+ ret = item->data;
+
+ list->tail = list->tail->prev;
+ if (list->tail)
+ list->tail->next = NULL;
+ free (item);
+ if (list->head == item)
+ list->head = NULL;
+ return ret;
+}
+
+/*
+ * listdel
+ */
+
+void
+listdel (List *list, Listitem *item)
+{
+ if (item->prev)
+ item->prev->next = item->next;
+ if (item->next)
+ item->next->prev = item->prev;
+ if (item == list->head)
+ list->head = item->next;
+ if (item == list->tail)
+ list->tail = item->prev;
+ free (item);
+}
+
+Listitem *
+listhead (List *list)
+{
+ return list->head;
+}
+
+Listitem *
+listtail (List *list)
+{
+ return list->tail;
+}
+
+Listitem *
+listprev (List *list, Listitem *item)
+{
+ return item->prev;
+}
+
+Listitem *
+listnext (List *list, Listitem *item)
+{
+ return item->next;
+}
+
+void *
+listdata (Listitem *item)
+{
+ return item->data;
+}
+
+/*
+ * Iterate through all the items in a list.
+ */
+
+void listiter (List *list, Bool (*fn)(List *, Listitem *, void *arg),
+ void *arg)
+{
+ Listitem *item;
+
+ for (item = list->head; item; item = item->next)
+ if ((*fn) (list, item, arg))
+ break;
+}
diff --git a/usr.sbin/afs/src/util/list.h b/usr.sbin/afs/src/util/list.h
new file mode 100644
index 00000000000..f8aaa572311
--- /dev/null
+++ b/usr.sbin/afs/src/util/list.h
@@ -0,0 +1,99 @@
+/* $OpenBSD: list.h,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * list handling functions
+ */
+
+/* $KTH: list.h,v 1.4 1998/07/05 18:25:00 assar Exp $ */
+
+#ifndef _LIST_
+#define _LIST_
+
+#include "bool.h"
+
+struct listitem {
+ void *data;
+ struct listitem *prev, *next;
+};
+
+typedef struct listitem Listitem;
+
+struct list {
+ Listitem *head, *tail;
+};
+
+typedef struct list List;
+
+/*
+ * functions
+ */
+
+List *listnew (void);
+
+Listitem *listaddhead (List *list, void *data);
+
+Listitem *listaddtail (List *list, void *data);
+
+void listdel (List *list, Listitem *item);
+
+Listitem *listaddbefore (List *list, Listitem *old_item, void *data);
+
+Listitem *listaddafter (List *list, Listitem *old_item, void *data);
+
+void *listdelhead (List *list);
+
+void *listdeltail (List *list);
+
+Bool listemptyp (List *list);
+
+Listitem *listhead (List *list);
+
+Listitem *listtail (List *list);
+
+Listitem *listprev (List *list, Listitem *item);
+
+Listitem *listnext (List *list, Listitem *item);
+
+void *listdata (Listitem *item);
+
+void listiter (List *list, Bool (*fn)(List *, Listitem *, void *arg),
+ void *arg);
+
+#endif /* _LIST_ */
diff --git a/usr.sbin/afs/src/util/log.c b/usr.sbin/afs/src/util/log.c
new file mode 100644
index 00000000000..0ad4414c401
--- /dev/null
+++ b/usr.sbin/afs/src/util/log.c
@@ -0,0 +1,261 @@
+/* $OpenBSD: log.c,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Logging functions
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: log.c,v 1.12 1998/07/09 19:57:26 art Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <roken.h>
+#include "log.h"
+
+/*
+ * The structure for each logging method.
+ */
+
+struct log_method {
+ char *name;
+ void (*open)(Log_method *, char *progname, char *fname);
+ void (*vprint)(Log_method *, char *, va_list);
+ void (*print)(Log_method *, char *);
+ void (*close)(Log_method *);
+ union {
+ void *v;
+ int i;
+ } data;
+ unsigned mask;
+};
+
+#if HAVE_SYSLOG
+static void log_open_syslog (Log_method *lm, char *progname, char *fname);
+
+static void log_close_syslog (Log_method *lm);
+#if HAVE_VSYSLOG
+static void log_vprint_syslog (Log_method *lm, char *, va_list);
+#else
+static void log_print_syslog (Log_method *lm, char *);
+#endif /* HAVE_VSYSLOG */
+#endif /* HAVE_SYSLOG */
+
+static void
+log_open_stderr (Log_method *lm, char *progname, char *fname);
+
+static void
+log_open_file (Log_method *lm, char *progname, char *fname);
+
+static void
+log_close_file (Log_method *lm);
+
+static void
+log_vprint_file (Log_method *lm, char *, va_list);
+
+/*
+ * The names for which we do special handling in the logging routines.
+ */
+
+static
+Log_method special_names[] = {
+#if HAVE_SYSLOG
+{"syslog", log_open_syslog,
+#if HAVE_VSYSLOG
+ log_vprint_syslog, NULL
+#else
+ NULL, log_print_syslog
+#endif /* HAVE_VSYSLOG */
+ , log_close_syslog},
+#endif /* HAVE_SYSLOG */
+{"/dev/stderr", log_open_stderr, log_vprint_file, NULL, NULL},
+{NULL, log_open_file, log_vprint_file, NULL, log_close_file}
+/* Should be last */
+};
+
+#if HAVE_SYSLOG
+static void
+log_open_syslog (Log_method *lm, char *progname, char *fname)
+{
+ openlog (progname, LOG_PID, LOG_DAEMON);
+}
+
+#if HAVE_VSYSLOG
+
+static void
+log_vprint_syslog (Log_method *lm, char *fmt, va_list args)
+{
+ vsyslog (LOG_INFO, fmt, args);
+}
+#else
+
+static void
+log_print_syslog (Log_method *lm, char *str)
+{
+ syslog (LOG_INFO, str);
+}
+#endif /* HAVE_VSYSLOG */
+
+static void
+log_close_syslog (Log_method *lm)
+{
+ closelog ();
+}
+
+#endif /* HAVE_SYSLOG */
+
+static void
+log_open_stderr (Log_method *lm, char *progname, char *fname)
+{
+#if 0
+ lm = &special_names[sizeof(special_names) /
+ sizeof(*special_names) - 1];
+#endif
+ lm->data.v = stderr;
+}
+
+static void
+log_open_file (Log_method *lm, char *progname, char *fname)
+{
+ lm->data.v = (void *)fopen (fname, "a");
+ if (lm->data.v == NULL)
+ lm->data.v = stderr;
+}
+
+static void
+log_vprint_file (Log_method *lm, char *fmt, va_list args)
+{
+ struct timeval tv = { 0, 0 };
+ char *time;
+ time_t t;
+
+ gettimeofday(&tv, NULL);
+ t = tv.tv_sec;
+ time = strdup(ctime(&t));
+ if (time) {
+ time[strlen(time)-1] = '\0';
+ fprintf ((FILE *)lm->data.v, "%s: ", time);
+ free(time);
+ } else
+ fprintf ((FILE *)lm->data.v, "unknown time:");
+
+ fprintf ((FILE *)lm->data.v, "%s: ", __progname);
+ vfprintf ((FILE *)lm->data.v, fmt, args);
+ putc ('\n', (FILE *)lm->data.v);
+}
+
+static void
+log_close_file (Log_method *lm)
+{
+ fclose ((FILE *)lm->data.v);
+}
+
+Log_method *
+log_open (char *progname, char *fname)
+{
+ int i;
+ Log_method *log;
+
+ log = (Log_method *)malloc (sizeof(Log_method));
+ if (log == NULL)
+ return log;
+ for (i = 0; i < sizeof(special_names) / sizeof(*special_names);
+ ++i)
+ if (special_names[i].name == NULL
+ || strcmp (special_names[i].name, fname) == 0) {
+ *log = special_names[i];
+ break;
+ }
+ (*log->open)(log, progname, fname);
+ return log;
+}
+
+void
+log_set_mask (Log_method *log, unsigned m)
+{
+ log->mask = m;
+}
+
+unsigned
+log_get_mask (Log_method *log)
+{
+ return log->mask;
+}
+
+void
+log_vlog(Log_method *log, unsigned level, const char *fmt, va_list args)
+{
+ if (level & log->mask) {
+ if (log->vprint)
+ (*log->vprint)(log, (char *) fmt, args);
+ else {
+ char *buf;
+
+ vasprintf (&buf, fmt, args);
+ (*log->print)(log, buf);
+
+ free(buf);
+ }
+ }
+}
+
+
+void
+log_log (Log_method *log, unsigned level, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ log_vlog(log, level, fmt, args);
+ va_end (args);
+}
+
+void
+log_close (Log_method *log)
+{
+ (*log->close)(log);
+ free (log);
+}
diff --git a/usr.sbin/afs/src/util/log.h b/usr.sbin/afs/src/util/log.h
new file mode 100644
index 00000000000..159f430a4cd
--- /dev/null
+++ b/usr.sbin/afs/src/util/log.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: log.h,v 1.1.1.1 1998/09/14 21:53:23 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: log.h,v 1.5 1998/04/03 03:34:26 assar Exp $ */
+
+#ifndef _LOG_
+#define _LOG_
+
+#include <stdarg.h>
+
+#if HAVE_SYSLOG
+#include <syslog.h>
+#endif /* HAVE_SYSLOG */
+
+typedef struct log_method Log_method;
+
+/*
+ * Functions for handling logging
+ */
+
+Log_method *log_open (char *progname, char *fname);
+/* Starting logging to `fname'. Label all messages as coming from
+ * `progname'. */
+
+void log_close (Log_method *log);
+
+void log_log (Log_method *log, unsigned level, const char *fmt, ...)
+__attribute__((format (printf, 3, 4)))
+;
+
+void log_vlog(Log_method *log, unsigned level, const char *fmt, va_list args)
+__attribute__((format (printf, 3, 0)))
+;
+
+unsigned log_get_mask (Log_method *log);
+
+void log_set_mask (Log_method *log, unsigned mask);
+
+#endif /* _LOG_ */
diff --git a/usr.sbin/afs/src/util/mem.c b/usr.sbin/afs/src/util/mem.c
new file mode 100644
index 00000000000..c5a6630edca
--- /dev/null
+++ b/usr.sbin/afs/src/util/mem.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: mem.c,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: mem.c,v 1.3 1998/02/22 11:22:17 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include "mem.h"
+
+/*
+ * Like malloc, but write an error message if not succesful.
+ */
+
+void *
+emalloc(size_t sz)
+{
+ void *tmp = malloc(sz);
+
+ if( tmp )
+ return tmp;
+ else {
+ fprintf(stderr, "malloc for %u bytes failed\n", sz);
+ exit(1);
+ }
+}
+
+/*
+ * Like realloc, but write an error message if not succesful.
+ */
+
+void *
+erealloc (void *ptr, size_t sz)
+{
+ void *tmp;
+
+ if (ptr)
+ tmp = realloc (ptr, sz);
+ else
+ tmp = malloc (sz);
+
+ if (tmp)
+ return tmp;
+ else {
+ fprintf (stderr, "realloc for %u bytes failed\n", sz);
+ exit (1);
+ }
+}
diff --git a/usr.sbin/afs/src/util/mem.h b/usr.sbin/afs/src/util/mem.h
new file mode 100644
index 00000000000..b9b2e5e7589
--- /dev/null
+++ b/usr.sbin/afs/src/util/mem.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: mem.h,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: mem.h,v 1.2 1997/11/09 23:48:55 assar Exp $ */
+
+#ifndef _MEM_
+#define _MEM_
+
+#include <stdlib.h>
+
+void *emalloc(size_t sz);
+void *erealloc(void *ptr, size_t sz);
+
+#endif /* _MEM_ */
diff --git a/usr.sbin/afs/src/util/minmax.h b/usr.sbin/afs/src/util/minmax.h
new file mode 100644
index 00000000000..397118b68b2
--- /dev/null
+++ b/usr.sbin/afs/src/util/minmax.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: minmax.h,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: minmax.h,v 1.2 1997/11/09 23:48:55 assar Exp $ */
+
+#ifndef _MINMAX_
+#define _MINMAX_
+
+#ifndef min
+#define min(a,b) (((a)>(b))?(b):(a))
+#define max(a,b) (((a)<(b))?(b):(a))
+#endif /* min */
+
+#endif /* _MINMAX_ */
diff --git a/usr.sbin/afs/src/util/mmaptime.c b/usr.sbin/afs/src/util/mmaptime.c
new file mode 100644
index 00000000000..eb04517d66e
--- /dev/null
+++ b/usr.sbin/afs/src/util/mmaptime.c
@@ -0,0 +1,203 @@
+/* $OpenBSD: mmaptime.c,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: mmaptime.c,v 1.5 1998/05/24 16:07:18 lha Exp $");
+
+#include <stdio.h>
+
+/*
+ * Speed hack
+ *
+ * Here we try to mmap time from the kernelspace.
+ * There are people claiming that this is about 100 times faster
+ * then gettimeofday()
+ *
+ * You need to have USE_MMAPTIME defined to get it.
+ *
+ * Other thing that you need is mmap(), getpagesize(), kvm_open() & co
+ *
+ * If not initalized with mmaptime_probe gettimeofday will be called
+ *
+ */
+
+#include "mmaptime.h"
+
+#if defined(USE_MMAPTIME) && defined(HAVE_MMAP) && defined(HAVE_KVM_OPEN) && defined(HAVE_KVM_NLIST) && defined(HAVE_GETPAGESIZE)
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_NLIST_H
+#include <nlist.h>
+#endif
+#ifdef HAVE_ELFLIB_NLIST_H
+#include <elflib/nlist.h>
+#endif
+#ifdef HAVE_KVM_H
+#include <kvm.h>
+#endif
+#include <errno.h>
+
+
+static unsigned long ps;
+static unsigned long begpage;
+static void *mem;
+static int kmemfd = -1;
+static struct timeval *tp = NULL;
+
+
+int mmaptime_probe(void)
+{
+ kvm_t *kvm;
+ unsigned long value;
+ struct nlist nl[2];
+ int i, saved_errno;
+
+ if (tp)
+ return 0;
+
+ if (geteuid()) {
+ fprintf(stderr, "mmaptime needs to be run as root, falling back on gettimeofday\n");
+ return EPERM;
+ }
+
+ kvm = kvm_open(NULL, NULL, NULL, O_RDONLY, "util/mmaptime");
+ nl[0].n_name = "_time";
+ nl[1].n_name = NULL;
+ i = kvm_nlist(kvm, nl);
+
+ /*
+ * SunOS 5.6 is broken and returns a zero even when it fails.
+ */
+
+ if (nl[0].n_value == 0) {
+ nl[0].n_name = "time";
+ nl[1].n_name = NULL;
+ i = kvm_nlist(kvm, nl);
+ }
+
+ kvm_close(kvm);
+
+ if (i != 0)
+ return ENOENT;
+
+ kmemfd = open("/dev/kmem", O_RDONLY);
+ if (kmemfd < 0)
+ return errno;
+
+ value = nl[0].n_value;
+
+ ps = getpagesize();
+
+ begpage = value - value % ps ;
+ mem = mmap(NULL, ps, PROT_READ, MAP_SHARED, kmemfd, begpage);
+
+ if (mem == (void *) -1) {
+ saved_errno = errno;
+ close(kmemfd);
+ return saved_errno;
+ }
+
+ tp = (struct timeval *) (mem + value % ps);
+ return 0;
+}
+
+
+int
+mmaptime_close(void)
+{
+ if (tp)
+ munmap(mem, ps);
+
+ tp = NULL;
+
+ if (kmemfd >= 0)
+ close(kmemfd);
+
+
+ return 0;
+}
+
+int
+mmaptime_gettimeofday(struct timeval *t, void *tzp)
+{
+ if (t && tp && !tzp) {
+ *t = *tp;
+ return 0;
+ } else
+ return gettimeofday(tp, tzp);
+
+ /* NOT REACHED */
+ return -1;
+}
+
+
+#else /* USE_MMAPTIME */
+
+#include <errno.h>
+
+int
+mmaptime_probe(void)
+{
+ return EOPNOTSUPP;
+}
+
+int
+mmaptime_gettimeofday(struct timeval *tp, void *tzp)
+{
+ return gettimeofday(tp, tzp);
+}
+
+int
+mmaptime_close(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/usr.sbin/afs/src/util/mmaptime.h b/usr.sbin/afs/src/util/mmaptime.h
new file mode 100644
index 00000000000..c8cff613a99
--- /dev/null
+++ b/usr.sbin/afs/src/util/mmaptime.h
@@ -0,0 +1,53 @@
+/* $OpenBSD: mmaptime.h,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: mmaptime.h,v 1.1 1998/03/28 10:45:23 lha Exp $ */
+
+#ifndef _UTIL_MMAPTIME_H
+#define _UTIL_MMAPTIME_H 1
+
+#include <sys/time.h>
+
+int mmaptime_probe(void);
+int mmaptime_gettimeofday(struct timeval *tp, void *tzp);
+int mmaptime_close(void);
+
+#endif
+
+
diff --git a/usr.sbin/afs/src/util/mmaptime_test.c b/usr.sbin/afs/src/util/mmaptime_test.c
new file mode 100644
index 00000000000..90439ee6e7e
--- /dev/null
+++ b/usr.sbin/afs/src/util/mmaptime_test.c
@@ -0,0 +1,131 @@
+/* $OpenBSD: mmaptime_test.c,v 1.1.1.1 1998/09/14 21:53:22 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: mmaptime_test.c,v 1.2 1998/07/09 19:57:58 art Exp $");
+
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <err.h>
+#include "mmaptime.h"
+
+void
+print_time_diff(char *str, struct timeval *tv, struct timeval *tv2)
+{
+ struct timeval t;
+
+ t.tv_sec = tv2->tv_sec - tv->tv_sec;
+ t.tv_usec = tv2->tv_usec - tv->tv_usec;
+ if (t.tv_usec < 0) {
+ t.tv_usec += 100000;
+ --t.tv_sec;
+ }
+
+ printf("%s: %f\n",
+ str,
+ (double)t.tv_sec +
+ (double)t.tv_usec / 100000 );
+}
+
+
+int main(int argc, char **argv)
+{
+ struct timeval t, t2, start, stop;
+ int i, times;
+ time_t tim;
+
+ i = mmaptime_probe();
+ if (i == EOPNOTSUPP) {
+ errx(1, "You don't have support for mmaptime\n"
+ "Try run configure with --enable-mmaptime");
+ } else if (i) {
+ err(1, "probe");
+ }
+
+ if (!(argc == 2 && sscanf(argv[1], "%d", &times) == 1))
+ times = 100000;
+
+ /* Get date two diffrent ways */
+
+ if (mmaptime_gettimeofday(&t, NULL))
+ err(1, "mmaptime_gettimeofday: here am I");
+ if (gettimeofday(&t2, NULL))
+ err(1, "gettimeofday: this should not happen");
+ tim = t.tv_sec;
+ printf("mmaptime: %s", ctime(&tim));
+ tim = t2.tv_sec;
+ printf("gettimeofday: %s", ctime(&tim));
+
+ print_time_diff("Diff", &t, &t2);
+
+ /* Test run */
+
+ printf("Doing %d tests of mmaptime_gettimeofday()\n", times);
+ if (mmaptime_gettimeofday(&start, NULL))
+ err(1, "mmaptime_gettimeofday: start");
+ for (i = 0 ; i < times ; i++) {
+ if (mmaptime_gettimeofday(&t, NULL))
+ err(1, "mmaptime_gettimeofday: running");
+ }
+ if (mmaptime_gettimeofday(&stop, NULL))
+ err(1, "mmaptime_gettimeofday: stop");
+ print_time_diff("End time", &start, &stop);
+
+ mmaptime_close();
+
+ /* Do the same with gettimeofday */
+
+ printf("Doing %d tests of gettimeofday()\n", times);
+ if (gettimeofday(&start, NULL))
+ err(1, "gettimeofday: start");
+ for (i = 0 ; i < times ; i++) {
+ if (gettimeofday(&t, NULL))
+ err(1, "gettimeofday: running");
+ }
+ if (gettimeofday(&stop, NULL))
+ err(1, "gettimeofday: stop");
+ print_time_diff("End time", &start, &stop);
+
+ return 0;
+}
+
diff --git a/usr.sbin/afs/src/util/prio.c b/usr.sbin/afs/src/util/prio.c
new file mode 100644
index 00000000000..ecd314eafda
--- /dev/null
+++ b/usr.sbin/afs/src/util/prio.c
@@ -0,0 +1,173 @@
+/* $OpenBSD: prio.c,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: prio.c,v 1.1 1998/07/07 15:57:10 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include "bool.h"
+#include "prio.h"
+
+#define PRIO_PARENT(x) (((x) + 1)/ 2 -1 )
+#define PRIO_LEFT(x) (2 * (i) + 1)
+#define PRIO_RIGHT(x) (2 * (i) + 2)
+
+
+Prio *
+prionew(unsigned size, prio_cmp cmp)
+{
+ Prio *prio;
+
+ if (!size || !cmp)
+ return NULL;
+
+ prio = calloc(sizeof(Prio), 1);
+ if (!prio)
+ return prio;
+
+ prio->heap = calloc(sizeof(Prio), size);
+ if (!prio->heap)
+ free(prio);
+
+ prio->cmp = cmp;
+ prio->sz = size;
+
+ return prio;
+}
+
+void
+priofree(Prio *prio)
+{
+ if (!prio)
+ return;
+
+ free(prio);
+}
+
+static void
+heapify(Prio *prio, unsigned i)
+{
+ unsigned j;
+ void *el;
+
+ if (!prio || i > prio->sz)
+ return;
+
+ el = &prio->heap[0];
+ while (prio->size && i <= PRIO_PARENT(prio->size)) {
+ j = PRIO_LEFT(i);
+ if (j < prio->size) {
+ if (prio->cmp(prio->heap[i], prio->heap[j]) < 0)
+ j++;
+
+ if (prio->cmp(prio->heap[0], prio->heap[j]) < 0)
+ break;
+
+ prio->heap[i] = prio->heap[j];
+ }
+ i = j;
+ }
+ prio->heap[i] = el;
+}
+
+
+
+int
+prioinsert(Prio *prio, void *data)
+{
+ void **ptr;
+ unsigned i;
+
+ if (!prio || !data)
+ return -1;
+
+
+ if (prio->sz == prio->size) {
+ ptr = realloc(prio->heap, prio->sz *2);
+ if (!ptr)
+ return -1;
+
+ prio->heap = ptr;
+ }
+
+ i = prio->size++;
+
+ while (i > 0 &&
+ prio->cmp(data,prio->heap[PRIO_PARENT(i)]) < 0)
+ {
+ prio->heap[i] = prio->heap[PRIO_PARENT(i)];
+ i = PRIO_PARENT(i);
+ }
+ prio->heap[i] = data;
+ return 0;
+}
+
+void *
+priohead(Prio *prio)
+{
+ if (!prio)
+ return NULL;
+
+ return prio->heap[0];
+}
+
+void
+prioremove(Prio *prio)
+{
+ if (!prio)
+ return;
+
+ if (prioemptyp (prio)) /* underflow */
+ return;
+
+ prio->heap[0] = prio->heap[--prio->size];
+ heapify (prio, prio->size);
+}
+
+Bool
+prioemptyp(Prio *prio)
+{
+ if (!prio || prio->size == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
diff --git a/usr.sbin/afs/src/util/prio.h b/usr.sbin/afs/src/util/prio.h
new file mode 100644
index 00000000000..90709b88c56
--- /dev/null
+++ b/usr.sbin/afs/src/util/prio.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: prio.h,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 _PRIO_H
+#define _PRIO_H 1
+
+#include <time.h>
+#include <bool.h>
+
+typedef int (*prio_cmp)(void *, void *);
+
+typedef struct prio {
+ unsigned sz; /* current size */
+ unsigned size; /* max size */
+ prio_cmp cmp;
+ void **heap;
+} Prio;
+
+Prio *prionew(unsigned size, prio_cmp cmp);
+
+void priofree(Prio *prio);
+
+int prioinsert(Prio *prio, void *data);
+
+void *priohead(Prio *prio);
+
+void prioremove(Prio *prio);
+
+Bool prioemptyp(Prio *prio);
+
+#endif
+
+
diff --git a/usr.sbin/afs/src/util/strmatch.c b/usr.sbin/afs/src/util/strmatch.c
new file mode 100644
index 00000000000..c67344bbd8a
--- /dev/null
+++ b/usr.sbin/afs/src/util/strmatch.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: strmatch.c,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strmatch.c,v 1.5 1998/07/22 03:23:45 assar Exp $");
+#endif
+
+#include "strmatch.h"
+
+/*
+ * Return 1 iff `str' matches the pattern in `pat'.
+ * The pattern consists of ordinary characters that must match exactly,
+ * ? that match one character and * that match zero of more characters.
+ * \ may be used to quite characters.
+ */
+
+int
+strmatch (const char *pat, const char *str)
+{
+ int c1, c2;
+
+ while ((c1 = *pat++) != '\0') {
+ c2 = *str;
+ if (c1 == '\\')
+ if ((c1 = *pat++) != c2)
+ return 1;
+ if (c1 == c2 || c1 == '?')
+ ;
+ else if (c1 == '*') {
+ if (*pat == '\0')
+ return 0;
+ while (*str) {
+ if (strmatch (pat, str) == 0)
+ return 0;
+ ++str;
+ }
+ return 1;
+ } else
+ return 1;
+ ++str;
+ }
+ return *str != c1;
+}
diff --git a/usr.sbin/afs/src/util/strmatch.h b/usr.sbin/afs/src/util/strmatch.h
new file mode 100644
index 00000000000..61c9dad77f2
--- /dev/null
+++ b/usr.sbin/afs/src/util/strmatch.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: strmatch.h,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: strmatch.h,v 1.2 1998/07/22 03:24:12 assar Exp $ */
+
+#ifndef _STRMATCH_
+#define _STRMATCH_
+
+int
+strmatch (const char *pat, const char *str);
+
+#endif /* _STRMATCH_ */
diff --git a/usr.sbin/afs/src/util/strsplit.c b/usr.sbin/afs/src/util/strsplit.c
new file mode 100644
index 00000000000..fe9c6b5150e
--- /dev/null
+++ b/usr.sbin/afs/src/util/strsplit.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: strsplit.c,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Split a string
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strsplit.c,v 1.4 1998/02/22 11:22:18 assar Exp $");
+#endif
+
+#include <string.h>
+#include "strsplit.h"
+
+/* XXX - fix this */
+int
+strsplit (char *str, char *pat, ...)
+{
+ va_list args;
+ char *p;
+ char **sub;
+ unsigned hits = 0;
+
+ va_start(args, pat);
+ if (pat == NULL)
+ pat = " \t";
+
+ for (p = str; *p; ++hits) {
+ p += strspn (p, pat);
+ sub = va_arg(args, char **);
+ if (*p == '\0' || sub == NULL)
+ break;
+ *sub = p;
+ p += strcspn (p, pat);
+ if (*p != '\0') {
+ *p = '\0';
+ p++;
+ }
+ }
+ va_end(args);
+ return hits;
+}
+
+int
+vstrsplit (char *str, char *pat, unsigned nsub, char **sub)
+{
+ unsigned hits = 0;
+ char *p;
+
+ if (pat == NULL)
+ pat = " \t";
+
+ for (p = str; *p; ++hits) {
+ p += strspn (p, pat);
+ if (*p == '\0' || sub == NULL || nsub-- == 0)
+ break;
+ *sub++ = p;
+ p += strcspn (p, pat);
+ if (*p != '\0') {
+ *p = '\0';
+ p++;
+ }
+ }
+ return hits;
+}
diff --git a/usr.sbin/afs/src/util/strsplit.h b/usr.sbin/afs/src/util/strsplit.h
new file mode 100644
index 00000000000..6747dccaef1
--- /dev/null
+++ b/usr.sbin/afs/src/util/strsplit.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: strsplit.h,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: strsplit.h,v 1.1 1998/01/11 00:34:02 assar Exp $ */
+
+#ifndef _STRSPLIT_
+#define _STRSPLIT_
+
+#include <stdarg.h>
+
+int strsplit (char *str, char *pat, ...);
+int vstrsplit (char *str, char *pat, unsigned nsub, char **sub);
+
+#endif /* _STRSPLIT_ */
diff --git a/usr.sbin/afs/src/util/strutil.c b/usr.sbin/afs/src/util/strutil.c
new file mode 100644
index 00000000000..63dbcb0377c
--- /dev/null
+++ b/usr.sbin/afs/src/util/strutil.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: strutil.c,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strutil.c,v 1.5 1998/03/18 19:30:42 art Exp $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include "strutil.h"
+
+/*
+ * Remove all leading and trailing whitespace from s.
+ */
+
+char *
+strtrim (char *str)
+{
+ char *s;
+ unsigned len = strlen (str);
+
+ for (s = str + len - 1; s >= str && *s && isspace(*s); --s)
+ ;
+ *(s + 1) = '\0';
+ len = s - str;
+ for (s = str; *s && isspace(*s); ++s)
+ ;
+ if (s != str)
+#ifdef HAVE_MEMMOVE
+ memmove (str, s, len - (str - s));
+#else
+ bcopy (s, str, len - (str - s));
+#endif
+ return str;
+}
+
+/*
+ * Uppercase all characters in string and return it.
+ */
+
+char *
+strupr (char *s)
+{
+ char *t = s;
+
+ for (; *t; t++)
+ *t = toupper (*t);
+ return s;
+}
+
+/*
+ * Lowercase all characters in string and return it.
+ */
+
+char *
+strlwr (char *s)
+{
+ char *t = s;
+
+ for (; *t; t++)
+ *t = tolower (*t);
+ return s;
+}
+
diff --git a/usr.sbin/afs/src/util/strutil.h b/usr.sbin/afs/src/util/strutil.h
new file mode 100644
index 00000000000..f74cd8c8826
--- /dev/null
+++ b/usr.sbin/afs/src/util/strutil.h
@@ -0,0 +1,49 @@
+/* $OpenBSD: strutil.h,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: strutil.h,v 1.2 1997/11/09 23:48:58 assar Exp $ */
+
+#ifndef _STRUTIL_
+#define _STRUTIL_
+
+char *strupr (char *);
+char *strlwr (char *);
+char *strtrim (char *);
+
+#endif /* _STRUTIL_ */
diff --git a/usr.sbin/afs/src/util/timeprio.c b/usr.sbin/afs/src/util/timeprio.c
new file mode 100644
index 00000000000..4e4441bad11
--- /dev/null
+++ b/usr.sbin/afs/src/util/timeprio.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: timeprio.c,v 1.1.1.1 1998/09/14 21:53:24 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: timeprio.c,v 1.1 1998/07/07 15:57:11 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include "bool.h"
+#include "timeprio.h"
+
+
+static int
+timeprio_cmp(void *a1, void *b1)
+{
+ Tpel *a = a1, *b = b1;
+
+ return a->time > b->time;
+}
+
+
+Timeprio *
+timeprionew(unsigned size)
+{
+ return (Timeprio *) prionew(size, timeprio_cmp);
+}
+
+void
+timepriofree(Timeprio *prio)
+{
+ priofree(prio);
+}
+
+int
+timeprioinsert(Timeprio *prio, time_t time, void *data)
+{
+ Tpel *el = malloc(sizeof(Tpel));
+ if (!el)
+ return -1;
+
+ el->time = time;
+ el->data = data;
+ if (prioinsert(prio, el)) {
+ free(el);
+ el = NULL;
+ }
+ return el ? 0 : -1;
+}
+
+void *
+timepriohead(Timeprio *prio)
+{
+ Tpel *el = priohead(prio);
+
+ return el->data;
+}
+
+void
+timeprioremove(Timeprio *prio)
+{
+ void *el;
+
+ if (timeprioemptyp((Prio *)prio))
+ return;
+
+ el = priohead(prio);
+ if (el) free (el);
+
+ prioremove((Prio *)prio);
+}
+
+Bool
+timeprioemptyp(Timeprio *prio)
+{
+ return prioemptyp(prio);
+}
+
diff --git a/usr.sbin/afs/src/util/timeprio.h b/usr.sbin/afs/src/util/timeprio.h
new file mode 100644
index 00000000000..86a8dd7ab16
--- /dev/null
+++ b/usr.sbin/afs/src/util/timeprio.h
@@ -0,0 +1,70 @@
+/* $OpenBSD: timeprio.h,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 _TIMEPRIO_H
+#define _TIMEPRIO_H 1
+
+#include <time.h>
+#include "prio.h"
+#include "bool.h"
+
+typedef struct tpel {
+ time_t time;
+ void *data;
+} Tpel;
+
+typedef Prio Timeprio;
+
+Timeprio *timeprionew(unsigned size);
+
+void timepriofree(Timeprio *prio);
+
+int timeprioinsert(Timeprio *prio, time_t time, void *data);
+
+void *timepriohead(Timeprio *prio);
+
+void timeprioremove(Timeprio *prio);
+
+Bool timeprioemptyp(Timeprio *prio);
+
+time_t timepriotimehead(Timeprio *prio);
+
+#endif
+
+
diff --git a/usr.sbin/afs/src/util/timeval.c b/usr.sbin/afs/src/util/timeval.c
new file mode 100644
index 00000000000..ee7916446e5
--- /dev/null
+++ b/usr.sbin/afs/src/util/timeval.c
@@ -0,0 +1,81 @@
+/* $OpenBSD: timeval.c,v 1.1.1.1 1998/09/14 21:53:25 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Timeval stuff
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: timeval.c,v 1.3 1998/02/22 11:22:19 assar Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include "timeval.h"
+
+void
+timevalfix(struct timeval *t1)
+{
+ if (t1->tv_usec < 0) {
+ t1->tv_sec--;
+ t1->tv_usec += 1000000;
+ }
+ if (t1->tv_usec >= 1000000) {
+ t1->tv_sec++;
+ t1->tv_usec -= 1000000;
+ }
+}
+
+void
+timevaladd(struct timeval *t1, struct timeval *t2)
+{
+ t1->tv_sec += t2->tv_sec;
+ t1->tv_usec += t2->tv_usec;
+ timevalfix(t1);
+}
+
+void
+timevalsub(struct timeval *t1, struct timeval *t2)
+{
+
+ t1->tv_sec -= t2->tv_sec;
+ t1->tv_usec -= t2->tv_usec;
+ timevalfix(t1);
+}
diff --git a/usr.sbin/afs/src/util/timeval.h b/usr.sbin/afs/src/util/timeval.h
new file mode 100644
index 00000000000..4ab99120d6f
--- /dev/null
+++ b/usr.sbin/afs/src/util/timeval.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: timeval.h,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * timeval handling functions
+ * Stolen from olof@sics.se
+ */
+
+/* $KTH: timeval.h,v 1.2 1997/11/09 23:48:59 assar Exp $ */
+
+#ifndef _TIMEVAL_
+#define _TIMEVAL_
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+void timevalfix(struct timeval *t1);
+void timevaladd(struct timeval *t1, struct timeval *t2);
+void timevalsub(struct timeval *t1, struct timeval *t2);
+
+#endif /* _TIMEVAL_ */
diff --git a/usr.sbin/afs/src/util/util-tester.c b/usr.sbin/afs/src/util/util-tester.c
new file mode 100644
index 00000000000..a1be8a97a79
--- /dev/null
+++ b/usr.sbin/afs/src/util/util-tester.c
@@ -0,0 +1,161 @@
+/* $OpenBSD: util-tester.c,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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 <stdlib.h>
+#include <sys/time.h>
+
+#include "bool.h"
+#include "timeprio.h"
+#include "hash.h"
+
+struct timeval time1, time2;
+
+static void
+starttesting(char *msg)
+{
+ printf("--------------------------------------------\n");
+ printf("testing %s...\n", msg);
+ gettimeofday(&time1, NULL);
+}
+
+static int
+endtesting(int bool)
+{
+ gettimeofday(&time2, NULL);
+ printf("-%s--------------------------------------\n",
+ !bool ? "ok --" : "fail ");
+ time2.tv_usec -= time1.tv_usec;
+ if (time2.tv_usec < 0) {
+ time2.tv_usec += 10000;
+ --time2.tv_sec;
+ }
+ time2.tv_sec -= time1.tv_sec;
+ printf("timing: %ld.%ld\n",time2.tv_sec, time2.tv_usec);
+
+ return bool;
+}
+
+
+int
+test_timeprio(void)
+{
+ Timeprio *tp = timeprionew(100);
+
+ starttesting("timeprio");
+
+ timeprioinsert(tp, 10, "ten");
+ timeprioinsert(tp, 40, "fourty");
+ timeprioinsert(tp, 30, "thirty");
+
+
+ while(!timeprioemptyp(tp)) {
+ printf("timepriohead(tp) = %s\n", (char *) timepriohead(tp));
+ timeprioremove(tp);
+ }
+
+ timepriofree(tp);
+
+ endtesting(0);
+
+ return 0;
+}
+
+int
+hash_cmp(void *foo, void *bar)
+{
+ return strcmp((char *) foo, (char *)bar);
+}
+
+unsigned
+hash_hash(void *foo)
+{
+ return hashcaseadd((char *) foo);
+}
+
+Bool
+hash_print(void *foo, void *bar)
+{
+ printf("%s\n", (char *) foo);
+ return FALSE;
+}
+
+int
+test_hash(void)
+{
+ Hashtab *h;
+
+ starttesting("hashtab");
+
+ h = hashtabnew(100, hash_cmp, hash_hash);
+ if (!h)
+ return endtesting(1);
+
+ if (!hashtabadd(h, "one")||
+ !hashtabadd(h, "two")||
+ !hashtabadd(h, "three")||
+ !hashtabadd(h, "four"))
+ return endtesting(1);
+
+ printf("foreach ----\n");
+ hashtabforeach(h, hash_print, NULL);
+
+ printf("search ----\none == %s\ntwo == %s\nthree == %s\nfour == %s\n",
+ (char *)hashtabsearch(h, "one"),
+ (char *)hashtabsearch(h, "two"),
+ (char *)hashtabsearch(h, "three"),
+ (char *)hashtabsearch(h, "four"));
+
+
+ printf("XXX there is no simple way to free a hashtab\n");
+ return endtesting(0);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ test_timeprio();
+ test_hash();
+ return 0;
+}
+
+
+
+
diff --git a/usr.sbin/afs/src/ydr/lex.h b/usr.sbin/afs/src/ydr/lex.h
new file mode 100644
index 00000000000..511101d1124
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/lex.h
@@ -0,0 +1,47 @@
+/* $OpenBSD: lex.h,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: lex.h,v 1.3 1998/02/19 05:11:49 assar Exp $ */
+
+#ifndef _LEX_
+#define _LEX_
+
+void error_message (char *, ...);
+
+#endif /* _LEX_ */
diff --git a/usr.sbin/afs/src/ydr/lex.l b/usr.sbin/afs/src/ydr/lex.l
new file mode 100644
index 00000000000..9cc0f69f91e
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/lex.l
@@ -0,0 +1,167 @@
+%{
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: lex.l,v 1.1.1.1 1998/09/14 21:53:27 art Exp $");
+#endif
+
+#undef ECHO
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <roken.h>
+#include "sym.h"
+#include "types.h"
+#include "parse.h"
+#include "lex.h"
+#include "output.h"
+
+static unsigned lineno;
+
+static char filename[256];
+
+static void parse_filename (char *s);
+static void parse_lineno (char *s);
+%}
+
+%%
+^\#[ ][0-9]+[ ]\"[^\n\"]*\".*$ { parse_filename (yytext); }
+^\#line[ ][0-9]+[ ]\"[^\n\"]*\".*$ { parse_filename (yytext); }
+^\#[ ][0-9]+ { parse_lineno (yytext); }
+^\#line[ ][0-9]+ { parse_lineno (yytext); }
+^\#ident.*$ { }
+const { return T_CONST; }
+enum { return T_ENUM; }
+struct { return T_STRUCT; }
+typedef { return T_TYPEDEF; }
+unsigned { return T_UNSIGNED; }
+long { return T_LONG; }
+int32_t { return T_LONG; }
+u_long { return T_ULONG; }
+u_int32_t { return T_ULONG; }
+short { return T_SHORT; }
+int16_t { return T_SHORT; }
+u_short { return T_USHORT; }
+u_int16_t { return T_USHORT; }
+int { return T_INT; }
+u_char { return T_UCHAR; }
+char { return T_CHAR; }
+string { return T_STRING; }
+opaque { return T_OPAQUE; }
+package { return T_PACKAGE; }
+split { return T_SPLIT; }
+multi { return T_MULTI; }
+IN { return T_IN; }
+OUT { return T_OUT; }
+INOUT { return T_INOUT; }
+ASIS { return T_ASIS; }
+"["|"]"|[,;=()<>]|"{"|"}"|"*" { return *yytext; }
+^\%[^\n]*$ { yylval.name = strdup (yytext+1); return T_VERBATIM; }
+-?[0-9]+ { yylval.constant = atoi(yytext); return T_CONSTANT; }
+0[Xx][0-9a-fA-F]+ { yylval.constant = (int)strtol(yytext+2, NULL, 0x10); return T_CONSTANT; }
+[A-Za-z][A-Za-z0-9_]* {
+Symbol *sym;
+
+sym = findsym(yytext);
+yylval.sym = sym;
+if (sym == NULL) {
+ yylval.name = strdup(yytext);
+ return T_IDENTIFIER;
+} else if (sym->type == TCONST)
+ return T_IDCONST;
+else if (sym->type == TTYPEDEF || sym->type == TENUM || sym->type == TSTRUCT)
+ return T_IDTYPE;
+else
+ error_message ("Ignoring \"%s\"\n", yytext);
+}
+[ \t] ;
+\n { lineno++; }
+. { error_message("Ignoring char(%c)\n", *yytext); }
+%%
+
+#ifndef yywrap
+int
+yywrap (void)
+{
+ return 1;
+}
+#endif /* !yywrap */
+
+void
+error_message (char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ fprintf (stderr, "%s:%d: ", filename, lineno);
+ vfprintf (stderr, format, args);
+ va_end (args);
+}
+
+static void
+parse_filename (char *s)
+{
+ char *d1, *d2;
+
+ while (!isspace(*s))
+ ++s;
+ while (isspace(*s))
+ ++s;
+
+ lineno = atoi (s);
+ d1 = strchr (s, '"') + 1;
+ d2 = strchr (d1, '"');
+ *d2 = '\0';
+ if (strcmp (d1, "") != 0)
+ strcpy (filename, d1);
+}
+
+static void
+parse_lineno (char *s)
+{
+ while (!isspace(*s))
+ ++s;
+ while (isspace(*s))
+ ++s;
+
+ lineno = atoi (s);
+}
diff --git a/usr.sbin/afs/src/ydr/main.c b/usr.sbin/afs/src/ydr/main.c
new file mode 100644
index 00000000000..395e4dc78c7
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/main.c
@@ -0,0 +1,118 @@
+/* $OpenBSD: main.c,v 1.1.1.1 1998/09/14 21:53:27 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: main.c,v 1.9 1998/03/13 04:46:33 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <mem.h>
+#include <fnameutil.h>
+#include "sym.h"
+#include "output.h"
+#include <err.h>
+#include <roken.h>
+
+extern FILE *yyin;
+
+/*
+ * ydr - generate stub routines for encode/decoding and RX
+ */
+
+int yyparse(void);
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+ FILE *foo;
+ char tmp_filename[64];
+ char *cpp = CPP;
+ int arglen;
+ int i;
+ char *arg;
+ char *filename;
+
+ if (argc < 2)
+ errx (1, "Usage: %s [cpp-arguments] filename", argv[0]);
+
+ snprintf (tmp_filename, sizeof(tmp_filename),
+ "ydr_tmp_%u.c", (unsigned)getpid());
+ foo = fopen (tmp_filename, "w");
+ if (foo == NULL)
+ errx (1, "Cannot fopen %s for writing", tmp_filename);
+ filename = copy_basename (argv[argc - 1]);
+ fprintf (foo, "#include \"%s\"\n", argv[argc - 1]);
+ fclose (foo);
+
+ initsym ();
+ init_generate (filename);
+
+ arglen = strlen(cpp) + 1;
+ for (i = 1; i < argc - 1; ++i) {
+ arglen += strlen (argv[i]) + 1;
+ }
+ arglen += strlen(tmp_filename) + 1;
+
+ arg = malloc (arglen);
+ if (arg == NULL) {
+ unlink (tmp_filename);
+ errx (1, "malloc: out of memory");
+ }
+ strcpy (arg, cpp);
+ strcat (arg, " ");
+ for (i = 1; i < argc - 1; ++i) {
+ strcat (arg, argv[i]);
+ strcat (arg, " ");
+ }
+ strcat (arg, tmp_filename);
+
+ yyin = popen (arg, "r");
+ free (arg);
+ ret = yyparse ();
+ generate_server_switch (serverfile, serverhdrfile);
+ pclose (yyin);
+ close_generator (filename);
+ unlink (tmp_filename);
+ return ret;
+}
diff --git a/usr.sbin/afs/src/ydr/output.c b/usr.sbin/afs/src/ydr/output.c
new file mode 100644
index 00000000000..d8236675e06
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/output.c
@@ -0,0 +1,1428 @@
+/* $OpenBSD: output.c,v 1.1.1.1 1998/09/14 21:53:26 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: output.c,v 1.31 1998/09/06 23:33:39 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <list.h>
+#include <efile.h>
+#include <string.h>
+#include <strutil.h>
+#include <mem.h>
+#include <roken.h>
+#include "sym.h"
+#include "output.h"
+#include "types.h"
+#include "lex.h"
+
+/*
+ * The name of the current package that we're generating stubs for
+ */
+
+char *package = "";
+
+/*
+ * File handles for the generated files themselves.
+ */
+
+FILE *headerfile,
+ *clientfile,
+ *serverfile,
+ *clienthdrfile,
+ *serverhdrfile,
+ *ydrfile;
+
+long tmpcnt = 0 ;
+
+typedef enum { ENCODE_RX, DECODE_RX, ENCODE_MEM, DECODE_MEM } EncodeType;
+
+
+static void print_type (char *name, Type *type, FILE *f);
+static Bool print_entry (List *list, Listitem *item, void *i);
+static void generate_hdr_struct (Symbol *s, FILE *f);
+static void generate_hdr_enum (Symbol *s, FILE *f);
+static void generate_hdr_const (Symbol *s, FILE *f);
+static void generate_hdr_typedef (Symbol *s, FILE *f);
+static int sizeof_type (Type *type);
+static int sizeof_symbol (Symbol *);
+static void encode_type (char *name, Type *type, FILE *f,
+ EncodeType encodetype);
+static Bool encode_entry (List *list, Listitem *item, void *arg);
+static void encode_struct (Symbol *s, char *name, FILE *f,
+ EncodeType encodetype);
+static void encode_enum (Symbol *s, char *name, FILE *f, EncodeType encodetype);
+static void encode_typedef (Symbol *s, char *name, FILE *f,
+ EncodeType encodetype);
+static void encode_symbol (Symbol *s, char *name, FILE *f,
+ EncodeType encodetype);
+
+static void
+print_type (char *name, Type *type, FILE *f)
+{
+ switch (type->type) {
+ case TCHAR :
+ fprintf (f, "char %s", name);
+ break;
+ case TUCHAR :
+ fprintf (f, "unsigned char %s", name);
+ break;
+ case TSHORT :
+ fprintf (f, "int16_t %s", name);
+ break;
+ case TUSHORT :
+ fprintf (f, "u_int16_t %s", name);
+ break;
+ case TLONG :
+ fprintf (f, "int32_t %s", name);
+ break;
+ case TULONG :
+ fprintf (f, "u_int32_t %s", name);
+ break;
+ case TSTRING :
+ fprintf (f, "char %s[%d]", name, type->size);
+ break;
+ case TPOINTER :
+ {
+ char *tmp;
+
+ tmp = (char *)emalloc (strlen(name) + 2);
+ *tmp = '*';
+ strcpy (tmp+1, name);
+ print_type (tmp, type->subtype, f);
+ free (tmp);
+ break;
+ }
+ case TUSERDEF :
+ if(type->symbol->type == TSTRUCT)
+ fprintf (f, "struct %s %s", type->symbol->name, name);
+ else
+ fprintf (f, "%s %s", type->symbol->name, name);
+ break;
+ case TVARRAY :
+ {
+ char *s;
+
+ s = (char *)emalloc (strlen (name) + 6);
+ *s = '*';
+ strcpy (s + 1, name);
+ strcat (s, "_len");
+
+ fprintf (f, "struct {\n");
+ if (type->indextype)
+ print_type ("len", type->indextype, f);
+ else
+ fprintf (f, "unsigned %s", "len");
+ fprintf (f, ";\n");
+ strcpy(s + strlen(s) - 3, "val");
+ print_type ("*val", type->subtype, f);
+ fprintf (f, ";\n} %s", name);
+ free(s);
+ break;
+ }
+ case TARRAY :
+ print_type (name, type->subtype, f);
+ fprintf (f, "[ %d ]", type->size);
+ break;
+ case TOPAQUE :
+ fprintf (f, "char %s", name);
+ break;
+ default :
+ abort();
+ }
+}
+
+static Bool
+print_entry (List *list, Listitem *item, void *i)
+{
+ StructEntry *s = (StructEntry *)listdata (item);
+ FILE *f = (FILE *)i;
+
+ fprintf (f, " ");
+ print_type (s->name, s->type, f);
+ fprintf (f, ";\n");
+ return FALSE;
+}
+
+/*
+ * Return the size of this type in bytes.
+ * In the case of a variable-sized type, return -1.
+ */
+
+static Bool
+sizeof_struct_iter (List *list, Listitem *item, void *arg)
+{
+ int *tot = (int *)arg;
+ StructEntry *s = (StructEntry *)listdata (item);
+ int sz;
+
+ sz = sizeof_type (s->type);
+ if (sz == -1) {
+ *tot = -1;
+ return TRUE;
+ } else {
+ *tot += sz;
+ return FALSE;
+ }
+}
+
+static int
+sizeof_struct (Symbol *s)
+{
+ int tot = 0;
+
+ listiter (s->u.list, sizeof_struct_iter, &tot);
+ return tot;
+}
+
+static int
+sizeof_type (Type *t)
+{
+ switch (t->type) {
+ case TCHAR :
+ case TUCHAR :
+/* return 1;*/
+ case TSHORT :
+ case TUSHORT :
+/* return 2;*/
+ case TLONG :
+ case TULONG :
+ return 4;
+ case TSTRING :
+ if (t->size == 0)
+ return -1;
+ else
+ return t->size;
+ case TOPAQUE :
+ return -1;
+ case TUSERDEF :
+ return sizeof_symbol (t->symbol);
+ case TARRAY :
+ {
+ int sz = sizeof_type (t->subtype);
+
+ if (sz == -1)
+ return -1;
+ else
+ return t->size * sz;
+ }
+ case TVARRAY :
+ return -1;
+ case TPOINTER :
+ return -1;
+ default :
+ abort ();
+ }
+}
+
+static int
+sizeof_symbol (Symbol *s)
+{
+ switch (s->type) {
+ case TUNDEFINED :
+ fprintf (stderr, "What is %s doing in sizeof_type?", s->name);
+ return 0;
+ case TSTRUCT :
+ return sizeof_struct (s);
+ case TENUM :
+ return 4;
+ case TCONST :
+ return 0;
+ case TENUMVAL :
+ return 0;
+ case TTYPEDEF :
+ return sizeof_type (s->u.type);
+ default :
+ abort ();
+ }
+}
+
+/*
+ * Generate header contents
+ */
+
+static void
+generate_hdr_struct (Symbol *s, FILE *f)
+{
+ fprintf (f, "struct %s {\n", s->name);
+ listiter (s->u.list, print_entry, f);
+ fprintf (f, "};\ntypedef struct %s %s;\n", s->name, s->name);
+}
+
+static void
+generate_hdr_enum (Symbol *s, FILE *f)
+{
+ Listitem *item;
+ Symbol *e;
+
+ fprintf (f, "enum %s {\n", s->name);
+ for (item = listhead (s->u.list);
+ item && listnext (s->u.list, item);
+ item = listnext (s->u.list, item)) {
+ e = (Symbol *)listdata (item);
+
+ fprintf (f, " %s = %d,\n", e->name, e->u.val);
+ }
+ e = (Symbol *)listdata (item);
+ fprintf (f, " %s = %d\n};\ntypedef enum %s %s;\n",
+ e->name, e->u.val, s->name, s->name);
+}
+
+static void
+generate_hdr_const (Symbol *s, FILE *f)
+{
+ fprintf (f, "#define %s %d\n", s->name, s->u.val);
+}
+
+static void
+generate_hdr_typedef (Symbol *s, FILE *f)
+{
+ fprintf (f, "typedef ");
+ print_type (s->name, s->u.type, f);
+ fprintf (f, ";\n");
+}
+
+void
+generate_sizeof (Symbol *s, FILE *f)
+{
+ int sz;
+
+ if (s->type == TCONST)
+ return;
+
+ sz = sizeof_symbol (s);
+ if (sz != -1) {
+ char *name;
+
+ name = strdup (s->name);
+ fprintf (f, "#define %s_SIZE %d\n", strupr (name), sz);
+ free (name);
+ }
+}
+
+void
+generate_header (Symbol *s, FILE *f)
+{
+ switch (s->type) {
+ case TUNDEFINED :
+ fprintf (f, "What is %s doing in generate_heaer?", s->name);
+ break;
+ case TSTRUCT :
+ generate_hdr_struct (s, f);
+ break;
+ case TENUM :
+ generate_hdr_enum (s, f);
+ break;
+ case TCONST :
+ generate_hdr_const (s, f);
+ break;
+ case TENUMVAL :
+ break;
+ case TTYPEDEF :
+ generate_hdr_typedef (s, f);
+ default :
+ break;
+ }
+ putc ('\n', f);
+}
+
+/*
+ * Generate functions for encoding and decoding.
+ */
+
+/* XXX - still assumes that a word is 32 bits */
+
+static char *
+encode_function (Type *type, EncodeType encodetype)
+{
+ if (type->flags & TASIS)
+ return "";
+ else if (encodetype == ENCODE_RX || encodetype == ENCODE_MEM)
+ return "htonl";
+#if 0
+ if (type->type == TSHORT || type->type == TUSHORT)
+ return "htons";
+ else if (type->type == TLONG || type->type == TULONG)
+ return "htonl";
+ else
+ abort();
+#endif
+ else if (encodetype == DECODE_RX || encodetype == DECODE_MEM)
+ return "ntohl";
+#if 0
+ if (type->type == TSHORT || type->type == TUSHORT)
+ return "ntohs";
+ else if (type->type == TLONG || type->type == TULONG)
+ return "ntohl";
+ else
+ abort();
+#endif
+ else
+ abort();
+}
+
+static void
+encode_long (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f, "{ u_int32_t u;\n"
+ "u = %s (%s);\n"
+ "if(rx_Write(call, &u, sizeof(u)) != sizeof(u))\n"
+ "goto fail;\n"
+ "}\n",
+ encode_function (type, encodetype),
+ name);
+ break;
+ case DECODE_RX :
+ fprintf (f, "{ u_int32_t u;\n"
+ "if(rx_Read(call, &u, sizeof(u)) != sizeof(u))\n"
+ "goto fail;\n"
+ "%s = %s (u);\n"
+ "}\n", name,
+ encode_function (type, encodetype));
+ break;
+ case ENCODE_MEM :
+ fprintf (f, "{ int32_t tmp = %s(%s); "
+ "if (*total_len < sizeof(int32_t)) { errno = EFAULT; return NULL ; } "
+ "bcopy ((char*)&tmp, ptr, sizeof(int32_t)); "
+ "ptr += sizeof(int32_t); "
+ "*total_len -= sizeof(int32_t);}\n",
+ encode_function (type, encodetype),
+ name);
+ break;
+ case DECODE_MEM :
+ fprintf (f, "{ int32_t tmp; "
+ "if (*total_len < sizeof(int32_t)) { errno = EFAULT; return NULL ; } "
+ "bcopy (ptr, (char *)&tmp, sizeof(int32_t)); "
+ "%s = %s(tmp); "
+ "ptr += sizeof(int32_t); "
+ "*total_len -= sizeof(int32_t);}\n",
+ name,
+ encode_function (type, encodetype));
+ break;
+ default :
+ abort ();
+ }
+}
+
+#ifdef not_yet
+static void
+encode_char (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f,
+ "if(rx_Write(call, &%s, sizeof(%s)) != sizeof(%s))\n"
+ "goto fail;\n",
+ name, name, name);
+ break;
+ case DECODE_RX :
+ fprintf (f,
+ "if(rx_Read(call, &%s, sizeof(%s)) != sizeof(%s))\n"
+ "goto fail;\n",
+ name, name, name);
+ break;
+ case ENCODE_MEM :
+ fprintf (f, "{ if (*total_len < sizeof(char)) { errno = EFAULT; return NULL ; } "
+ "*((char *)ptr) = %s; "
+ "ptr += sizeof(char); *total_len -= sizeof(char);}\n",
+ name);
+ break;
+ case DECODE_MEM :
+ fprintf (f, "{ if (*total_len < sizeof(char)) { errno = EFAULT; return NULL ; } "
+ "%s = *((char *)ptr); "
+ "ptr += sizeof(char); *total_len -= sizeof(char);}\n",
+ name);
+ break;
+ default :
+ abort ();
+ }
+}
+
+static void
+encode_short (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f, "{ int16_t u;\n"
+ "u = %s (%s);\n"
+ "if(rx_Write(call, &u, sizeof(u)) != sizeof(u))\n"
+ "goto fail;\n"
+ "}\n",
+ encode_function (type, encodetype),
+ name);
+ break;
+ case DECODE_RX :
+ fprintf (f, "{ int16_t u;\n"
+ "if(rx_Read(call, &u, sizeof(u)) != sizeof(u))\n"
+ "goto fail;\n"
+ "%s = %s (u);\n"
+ "}\n", name,
+ encode_function (type, encodetype));
+ break;
+ case ENCODE_MEM :
+ fprintf (f, "{ in16_t tmp = %s(%s); "
+ "if (*total_len < sizeof(int16_t)) { errno = EFAULT; return NULL ; } "
+ "bcopy ((char*)&tmp, ptr, sizeof(int16_t)); "
+ "ptr += sizeof(int16_t); "
+ "*total_len -= sizeof(int16_t);}\n",
+ encode_function (type, encodetype),
+ name);
+ break;
+ case DECODE_MEM :
+ fprintf (f, "{ int16_t tmp; "
+ "if (*total_len < sizeof(int16_t)) { errno = EFAULT; return NULL ; } "
+ "bcopy (ptr, (char *)&tmp, sizeof(int16_t)); "
+ "%s = %s(tmp); "
+ "ptr += sizeof(int16_t); "
+ "*total_len -= sizeof(int16_t); }\n",
+ name,
+ encode_function (type, encodetype));
+ break;
+ default :
+ abort ();
+ }
+}
+#endif
+
+static void
+encode_string (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ Type lentype = {TULONG};
+
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f, "{ unsigned len;\n"
+ "char zero[4] = {0, 0, 0, 0};\n"
+ "unsigned padlen;\n"
+ "len = strlen(%s);\n"
+ "padlen = (4 - (len %% 4)) %% 4;\n",
+ name);
+ encode_type ("len", &lentype, f, encodetype);
+ fprintf (f,
+ "if(rx_Write(call, %s, len) != len)\n"
+ "goto fail;\n"
+ "if(rx_Write(call, zero, padlen) != padlen)\n"
+ "goto fail;\n"
+ "}\n", name);
+ break;
+ case DECODE_RX :
+ fprintf (f, "{ unsigned len;\n"
+ "unsigned padlen;\n"
+ "char zero[4] = {0, 0, 0, 0};\n");
+ encode_type ("len", &lentype, f, encodetype);
+ if (type->size != 0)
+ fprintf (f,
+ "if (len >= %u)\n"
+ "abort();\n",
+ type->size);
+ fprintf (f,
+ "if(rx_Read(call, %s, len) != len)\n"
+ "goto fail;\n"
+ "%s[len] = '\\0';\n"
+ "padlen = (4 - (len %% 4)) %% 4;\n"
+ "if(rx_Read(call, zero, padlen) != padlen)\n"
+ "goto fail;\n"
+ "}\n", name, name);
+ break;
+ case ENCODE_MEM :
+ fprintf (f,
+ "{\nunsigned len = strlen(%s);\n"
+ "if (*total_len < len) { errno = EFAULT; return NULL ; } "
+ "*total_len -= len;\n",
+ name);
+ encode_type ("len", &lentype, f, encodetype);
+ fprintf (f, "strncpy (ptr, %s, len);\n", name);
+ fprintf (f, "ptr += len + (4 - (len %% 4) %% 4);\n}\n");
+ break;
+ case DECODE_MEM :
+ fprintf (f,
+ "{\nunsigned len;\n");
+ encode_type ("len", &lentype, f, encodetype);
+ fprintf (f,
+ "if (*total_len < len) { errno = EFAULT; return NULL ; }\n"
+ "*total_len -= len;\n"
+ "memcpy (%s, ptr, len);\n"
+ "%s[len] = '\\0';\n"
+ "ptr += len + (4 - (len %% 4)) %% 4;\n}\n",
+ name, name);
+ break;
+ default :
+ abort ();
+ }
+}
+
+static void
+encode_array (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ if (type->subtype->type == TOPAQUE) {
+ if (type->size % 4 != 0)
+ error_message ("Opaque array should be"
+ "multiple of 4");
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f,
+ "if(rx_Write (call, %s, %d) != %d)\n"
+ "goto fail;",
+ name, type->size, type->size);
+ break;
+ case DECODE_RX :
+ fprintf (f,
+ "if(rx_Read (call, %s, %d) != %d)\n"
+ "goto fail;",
+ name, type->size, type->size);
+ break;
+ case ENCODE_MEM :
+ fprintf (f, "if (*total_len < %u) { errno = EFAULT; return NULL ; }\n"
+ "memcpy (ptr, %s, %u);\n", type->size, name,
+ type->size);
+ fprintf (f, "ptr += %u; *total_len -= %u;\n",
+ type->size, type->size);
+ break;
+ case DECODE_MEM :
+ fprintf (f, "if (*total_len < %u) { errno = EFAULT; return NULL ; }\n"
+ "memcpy (%s, ptr, %u);\n", type->size, name,
+ type->size);
+ fprintf (f, "ptr += %u; *total_len -= %u;\n",
+ type->size, type->size);
+ break;
+ default :
+ abort ();
+ }
+ } else {
+ char tmp[256];
+
+ fprintf (f, "{\nint i%lu;\nfor(i%lu = 0; i%lu < %u;"
+ "++i%lu){\n", tmpcnt, tmpcnt, tmpcnt, type->size,tmpcnt);
+ snprintf(tmp, sizeof(tmp)-1, "%s[i%lu]", name, tmpcnt);
+ tmpcnt++;
+ encode_type (tmp , type->subtype, f, encodetype);
+ tmpcnt--;
+ fprintf (f, "}\n}\n");
+ }
+}
+
+static void
+encode_varray (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ char tmp[256];
+ Type lentype = {TULONG};
+
+ strcpy (tmp, name);
+ strcat (tmp, ".len");
+
+ encode_type (tmp, type->indextype ? type->indextype : &lentype,
+ f, encodetype);
+ if (encodetype == DECODE_MEM || encodetype == DECODE_RX) {
+ fprintf (f, "%s.val = (", name);
+ print_type ("*", type->subtype, f);
+ fprintf (f, ")malloc(sizeof(");
+ print_type ("", type->subtype, f);
+ fprintf (f, ") * %s);\n", tmp);
+ }
+ if (type->subtype->type == TOPAQUE) {
+ switch (encodetype) {
+ case ENCODE_RX :
+ fprintf (f, "{\n"
+ "char zero[4] = {0, 0, 0, 0};\n"
+ "unsigned padlen = (4 - (%s %% 4)) %% 4;\n"
+ "if(rx_Write (call, %s.val, %s) != %s)\n"
+ "goto fail;\n"
+ "if(rx_Write (call, zero, padlen) != padlen)\n"
+ "goto fail;\n"
+ "}\n",
+ tmp, name, tmp, tmp);
+ break;
+ case DECODE_RX :
+ fprintf (f, "{\n"
+ "char zero[4] = {0, 0, 0, 0};\n"
+ "unsigned padlen = (4 - (%s %% 4)) %% 4;\n"
+ "if(rx_Read (call, %s.val, %s) != %s)\n"
+ "goto fail;\n"
+ "if(rx_Read (call, zero, padlen) != padlen)\n"
+ "goto fail;\n"
+ "}\n",
+ tmp, name, tmp, tmp);
+ break;
+ case ENCODE_MEM :
+ /* XXX bounce checking */
+ fprintf (f, "{\n"
+ "char zero[4] = {0, 0, 0, 0};\n"
+ "memcpy (ptr, %s.val, %s);\n"
+ "memcpy (ptr + %s, zero, (4 - (%s %% 4)) %% 4);\n"
+ "ptr += %s + (4 - (%s %% 4)) %% 4;\n"
+ "}\n",
+ name, tmp, tmp, tmp, tmp, tmp);
+ break;
+ case DECODE_MEM :
+ /* XXX bounce checking */
+ fprintf (f, "{\n"
+ "memcpy (%s.val, ptr, %s);\n"
+ "ptr += %s + (4 - (%s %% 4)) %% 4;\n"
+ "}\n",
+ name, tmp, tmp, tmp);
+ break;
+ default :
+ abort ();
+ }
+ } else {
+ fprintf (f, "{\nint i%lu;\nfor(i%lu = 0; i%lu < %s;"
+ "++i%lu){\n", tmpcnt, tmpcnt, tmpcnt, tmp, tmpcnt);
+ snprintf(tmp, sizeof(tmp)-1, "%s.val[i%lu]", name, tmpcnt);
+ tmpcnt++;
+ encode_type (tmp , type->subtype, f, encodetype);
+ tmpcnt--;
+ fprintf (f, "}\n}\n");
+ }
+}
+
+static void
+encode_pointer (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ Type booltype = {TULONG};
+ char tmp[256];
+
+ sprintf (tmp, "*(%s)", name);
+
+ switch(encodetype) {
+ case ENCODE_RX:
+ abort ();
+ case ENCODE_MEM:
+ fprintf(f, "{ unsigned bool;\n"
+ "bool = %s != NULL;\n", name);
+ encode_type ("bool", &booltype, f, encodetype);
+ fprintf (f, "if(%s) {\n", name);
+ encode_type (tmp, type->subtype, f, encodetype);
+ fprintf (f, "}\n"
+ "}\n");
+ break;
+ case DECODE_RX:
+ abort();
+ case DECODE_MEM:
+ fprintf(f, "{ unsigned bool;\n");
+ encode_type ("bool", &booltype, f, encodetype);
+ fprintf (f, "if(bool) {\n");
+ fprintf (f, "%s = malloc(sizeof(%s));\n"
+ "if (%s == NULL) return ENOMEM;\n",
+ name, tmp, name);
+ encode_type (tmp, type->subtype, f, encodetype);
+ fprintf (f, "} else {\n"
+ "%s = NULL;\n"
+ "}\n"
+ "}\n", name);
+ break;
+ default:
+ abort ();
+ }
+}
+
+static void
+encode_type (char *name, Type *type, FILE *f, EncodeType encodetype)
+{
+ switch (type->type) {
+ case TCHAR :
+ case TUCHAR :
+#if 0
+ encode_char (name, type, f, encodetype);
+ break;
+#endif
+ case TSHORT :
+ case TUSHORT :
+#if 0
+ encode_short (name, type, f, encodetype);
+ break;
+#endif
+ case TLONG :
+ case TULONG :
+ encode_long (name, type, f, encodetype);
+ break;
+ case TSTRING :
+ encode_string (name, type, f, encodetype);
+ break;
+ case TOPAQUE :
+ error_message ("Type opaque only allowed as part of an array");
+ break;
+ case TUSERDEF :
+ encode_symbol (type->symbol, name, f, encodetype);
+ break;
+ case TARRAY :
+ encode_array (name, type, f, encodetype);
+ break;
+ case TVARRAY :
+ encode_varray (name, type, f, encodetype);
+ break;
+ case TPOINTER :
+ encode_pointer (name, type, f, encodetype);
+ break;
+ default :
+ abort();
+ }
+}
+
+struct context {
+ char *name;
+ FILE *f;
+ Symbol *symbol;
+ EncodeType encodetype;
+};
+
+static Bool
+encode_entry (List *list, Listitem *item, void *arg)
+{
+ StructEntry *s = (StructEntry *)listdata (item);
+ char tmp[256];
+ struct context *context = (struct context *)arg;
+
+ strcpy (tmp, context->name);
+ strcat (tmp, ".");
+ strcat (tmp, s->name);
+
+ if (s->type->type == TPOINTER
+ && s->type->subtype->type == TUSERDEF
+ && s->type->subtype->symbol->type == TSTRUCT
+ && strcmp(s->type->subtype->symbol->name,
+ context->symbol->name) == 0) {
+ fprintf (context->f,
+ "ptr = ydr_encode_%s(%s, ptr);\n",
+ context->symbol->name,
+ tmp);
+ } else {
+ encode_type (tmp, s->type, context->f, context->encodetype);
+ }
+
+ return FALSE;
+}
+
+static void
+encode_struct (Symbol *s, char *name, FILE *f, EncodeType encodetype)
+{
+ struct context context;
+
+ context.name = name;
+ context.symbol = s;
+ context.f = f;
+ context.encodetype = encodetype;
+
+ listiter (s->u.list, encode_entry, (void *)&context);
+}
+
+static void
+encode_enum (Symbol *s, char *name, FILE *f, EncodeType encodetype)
+{
+ Type type = {TLONG};
+ char tmp[256];
+
+ strcpy (tmp, "(int)");
+ strcat (tmp, name);
+
+ encode_type (tmp, &type, f, encodetype);
+}
+
+static void
+encode_typedef (Symbol *s, char *name, FILE *f, EncodeType encodetype)
+{
+ encode_type (name, s->u.type, f, encodetype);
+}
+
+static void
+encode_symbol (Symbol *s, char *name, FILE *f, EncodeType encodetype)
+{
+ switch (s->type) {
+ case TSTRUCT :
+ encode_struct (s, name, f, encodetype);
+ break;
+ case TENUM :
+ encode_enum (s, name, f, encodetype);
+ break;
+ case TTYPEDEF :
+ encode_typedef (s, name, f, encodetype);
+ break;
+ default :
+ abort();
+ }
+}
+
+/*
+ * Generate the definition of an encode/decode function.
+ */
+
+static void
+generate_function_definition (Symbol *s, FILE *f, Bool encodep)
+{
+ if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) {
+ fprintf (f,
+ "char *ydr_%scode_%s(%s *o, char *ptr, size_t *total_len)",
+ encodep ? "en" : "de",
+ s->name, s->name);
+ } else if (s->type == TCONST || s->type == TENUMVAL
+ || s->type == TTYPEDEF)
+ ;
+ else
+ error_message ("What is %s (type %d) doing here?\n",
+ s->name, s->type);
+}
+
+/*
+ * Generate an encode/decode function
+ */
+
+void
+generate_function (Symbol *s, FILE *f, Bool encodep)
+{
+ if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) {
+ generate_function_definition (s, f, encodep);
+ fprintf (f, "\n{\n");
+ encode_symbol (s, "(*o)", f, encodep ? ENCODE_MEM : DECODE_MEM);
+ fprintf (f, "return ptr;\n}\n");
+ } else if (s->type == TCONST || s->type == TENUMVAL
+ || s->type == TTYPEDEF)
+ ;
+ else
+ error_message ("What is %s (type %d) doing here?\n",
+ s->name, s->type);
+}
+
+/*
+ * Generate an prototype for an encode/decode function
+ */
+
+void
+generate_function_prototype (Symbol *s, FILE *f, Bool encodep)
+{
+ if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) {
+ generate_function_definition (s, f, encodep);
+ fprintf (f, ";\n");
+ } else if (s->type == TCONST || s->type == TENUMVAL
+ || s->type == TTYPEDEF)
+ ;
+ else
+ error_message ("What is %s (type %d) doing here?\n",
+ s->name, s->type);
+}
+
+static Bool
+gen1 (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if ((a->argtype == TOUT || a->argtype == TINOUT)
+ && a->type->type != TPOINTER
+ && a->type->type != TSTRING)
+ error_message ("Argument %s is OUT and not pointer or string.\n",
+ a->name);
+ fprintf (f, ", ");
+ if (a->argtype == TIN)
+ fprintf (f, "const ");
+ print_type (a->name, a->type, f);
+ fprintf (f, "\n");
+ return FALSE;
+}
+
+static Bool
+genin (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->argtype == TIN || a->argtype == TINOUT) {
+ fprintf (f, ", ");
+ print_type (a->name, a->type, f);
+ fprintf (f, "\n");
+ }
+ return FALSE;
+}
+
+static Bool
+genout (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+
+ if (a->argtype == TOUT || a->argtype == TINOUT)
+ return gen1 (list, item, arg);
+ else
+ return FALSE;
+}
+
+static Bool
+gendeclare (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->type->type == TPOINTER)
+ print_type (a->name, a->type->subtype, f);
+ else
+ print_type (a->name, a->type, f);
+ fprintf (f, ";\n");
+ return FALSE;
+}
+
+static Bool
+genfree_isarrayp(Type *type)
+{
+ if (type->type == TVARRAY)
+ return TRUE;
+ if (type->type == TPOINTER)
+ return genfree_isarrayp(type->subtype);
+ if (type->type == TUSERDEF &&
+ type->symbol &&
+ type->symbol->type == TTYPEDEF)
+ return genfree_isarrayp(type->symbol->u.type);
+
+ return FALSE;
+}
+
+
+static Bool
+genfree (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (genfree_isarrayp(a->type))
+ fprintf(f, "free(%s.val);\n", a->name);
+
+ return FALSE;
+}
+
+static Bool
+genencodein (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->argtype != TIN && a->argtype != TINOUT)
+ return TRUE;
+ else {
+ if (a->type->type == TPOINTER) {
+ char *tmp = (char *)emalloc (strlen (a->name) + 4);
+
+ sprintf (tmp, "(*%s)", a->name);
+
+ encode_type (tmp, a->type->subtype, f, ENCODE_RX);
+ free (tmp);
+ } else
+ encode_type (a->name, a->type, f, ENCODE_RX);
+ return FALSE;
+ }
+}
+
+static Bool
+gendecodeout (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->argtype == TOUT || a->argtype == TINOUT) {
+ if (a->type->type == TPOINTER) {
+ char *tmp = (char *)emalloc (strlen (a->name) + 4);
+
+ sprintf (tmp, "(*%s)", a->name);
+
+ encode_type (tmp, a->type->subtype, f, DECODE_RX);
+ free (tmp);
+ } else if(a->type->type == TSTRING) {
+ encode_type (a->name, a->type, f, DECODE_RX);
+ }
+ }
+ return FALSE;
+}
+
+static Bool
+gendecodein (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->argtype != TIN && a->argtype != TINOUT)
+ return TRUE;
+ else {
+ if (a->type->type == TPOINTER) {
+#if 0
+ char *tmp = (char *)emalloc (strlen (a->name) + 4);
+
+ sprintf (tmp, "(*%s)", a->name);
+
+ encode_type (tmp, a->type->subtype, f, DECODE_RX);
+ free (tmp);
+#endif
+ encode_type (a->name, a->type->subtype, f, DECODE_RX);
+ } else
+ encode_type (a->name, a->type, f, DECODE_RX);
+ return FALSE;
+ }
+}
+
+static Bool
+genencodeout (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->argtype == TOUT || a->argtype == TINOUT) {
+ if (a->type->type == TPOINTER)
+ encode_type (a->name, a->type->subtype, f, ENCODE_RX);
+ else
+ encode_type (a->name, a->type, f, ENCODE_RX);
+ }
+ return FALSE;
+}
+
+static Bool
+findargtypeiter (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ int *type = (int *)arg;
+
+ if (a->argtype == *type) {
+ (*type)++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static Bool
+findargtype(List *list, int type)
+{
+ int savedtype = type;
+ listiter(list, findargtypeiter, &type);
+ if (type != savedtype)
+ return TRUE;
+ return FALSE;
+}
+
+static Bool
+genargs (List *list, Listitem *item, void *arg)
+{
+ Argument *a = (Argument *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ if (a->type->type == TPOINTER)
+ putc ('&', f);
+ fputs (a->name, f);
+ if (listnext (list, item))
+ fprintf (f, ", ");
+ return FALSE;
+}
+
+/*
+ * Generate the stub functions for this RPC call
+ */
+
+static void
+generate_simple_stub (Symbol *s, FILE *f, FILE *headerf)
+{
+ Type type = {TLONG};
+ char *op;
+
+ fprintf (headerf, "int %s%s(\nstruct rx_connection *connection\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, gen1, headerf);
+ fprintf (headerf, ");\n\n");
+
+ fprintf (f, "int %s%s(\nstruct rx_connection *connection\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, gen1, f);
+ fprintf (f, ")\n{\n"
+ "struct rx_call *call;\n"
+ "int ret = 0;\n"
+ "call = rx_NewCall (connection);\n");
+
+ asprintf (&op, "%u", s->u.proc.id);
+
+ encode_type (op, &type, f, ENCODE_RX);
+ free (op);
+ listiter (s->u.proc.arguments, genencodein, f);
+ listiter (s->u.proc.arguments, gendecodeout, f);
+ fprintf (f,
+ "return rx_EndCall (call,0);\n"
+ "fail:\n"
+ "ret = rx_Error(call);\n"
+ "rx_EndCall (call, 0);\n"
+ "return ret;\n"
+ "}\n");
+}
+
+static void
+generate_split_stub (Symbol *s, FILE *f, FILE *headerf)
+{
+ Type type = {TLONG};
+ char *op;
+
+ fprintf (headerf, "int Start%s%s(\nstruct rx_call *call\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, genin, headerf);
+ fprintf (headerf, ");\n\n");
+
+ fprintf (f, "int Start%s%s(\nstruct rx_call *call\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, genin, f);
+ fprintf (f, ")\n{\n");
+
+
+ asprintf (&op, "%u", s->u.proc.id);
+ encode_type (op, &type, f, ENCODE_RX);
+ free (op);
+ listiter (s->u.proc.arguments, genencodein, f);
+ fprintf (f, "return 0;\n");
+ /* XXX only in arg */
+ if (findargtype(s->u.proc.arguments, TIN) ||
+ findargtype(s->u.proc.arguments, TINOUT))
+ fprintf (f, "fail:\n"
+ "return rx_Error(call);\n");
+ fprintf (f, "}\n\n");
+
+ fprintf (headerf, "int End%s%s(\nstruct rx_call *call\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, genout, headerf);
+ fprintf (headerf, ");\n\n");
+
+ fprintf (f, "int End%s%s(\nstruct rx_call *call\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, genout, f);
+ fprintf (f, ")\n{\n");
+
+ listiter (s->u.proc.arguments, gendecodeout, f);
+ fprintf (f, "return 0;\n");
+ /* XXX only out arg */
+ if (findargtype(s->u.proc.arguments, TOUT) ||
+ findargtype(s->u.proc.arguments, TINOUT))
+ fprintf (f, "fail:\n"
+ "return rx_Error(call);\n");
+ fprintf (f, "}\n\n");
+}
+
+void
+generate_client_stub (Symbol *s, FILE *f, FILE *headerf)
+{
+ if (s->u.proc.flags & TSPLIT)
+ generate_split_stub (s, f, headerf);
+ if (s->u.proc.flags & TSIMPLE)
+ generate_simple_stub (s, f, headerf);
+}
+
+/*
+ * A list of all the functions that are to be recognized by the
+ * server, later used in generate_server_switch.
+ */
+
+static List *func_list;
+
+/*
+ * open all files
+ */
+
+void
+init_generate (char *filename)
+{
+ char *tmp;
+ char *fileuppr;
+
+ func_list = listnew ();
+
+ tmp = (char *)emalloc (strlen (filename) + 17);
+ sprintf (tmp, "%s.h", filename);
+ headerfile = efopen (tmp, "w");
+ fileuppr = strdup (filename);
+ strupr (fileuppr);
+ fprintf (headerfile, "/* Generated from %s.xg */\n", filename);
+ fprintf (headerfile, "#ifndef _%s_\n"
+ "#define _%s_\n\n", fileuppr, fileuppr);
+ free (fileuppr);
+
+ sprintf (tmp, "%s.ydr.c", filename);
+ ydrfile = efopen (tmp, "w");
+ fprintf (ydrfile, "/* Generated from %s.xg */\n", filename);
+ fprintf (ydrfile, "#include <%s.h>\n\n", filename);
+ fprintf (ydrfile, "#include <stdio.h>\n");
+ fprintf (ydrfile, "#include <stdlib.h>\n");
+ fprintf (ydrfile, "#include <sys/types.h>\n");
+ fprintf (ydrfile, "#include <netinet/in.h>\n");
+ fprintf (ydrfile, "#include <roken.h>\n");
+ fprintf (ydrfile, "#ifndef HAVE_BCOPY\n"
+ "#define bcopy(a,b,c) memcpy((b),(a),(c))\n"
+ "#endif /* !HAVE_BCOPY */\n\n");
+
+ sprintf (tmp, "%s.cs.c", filename);
+ clientfile = efopen (tmp, "w");
+ fprintf (clientfile, "/* Generated from %s.xg */\n", filename);
+ fprintf (clientfile, "#include \"%s.h\"\n\n", filename);
+ fprintf (clientfile, "#include \"%s.cs.h\"\n\n", filename);
+ fprintf (clientfile, "#include <stdio.h>\n");
+ fprintf (clientfile, "#include <stdlib.h>\n");
+ fprintf (clientfile, "#include <sys/types.h>\n");
+ fprintf (clientfile, "#include <netinet/in.h>\n");
+ fprintf (clientfile, "#include <roken.h>\n");
+ fprintf (clientfile, "#ifndef HAVE_BCOPY\n"
+ "#define bcopy(a,b,c) memcpy((b),(a),(c))\n"
+ "#endif /* !HAVE_BCOPY */\n\n");
+
+ sprintf (tmp, "%s.ss.c", filename);
+ serverfile = efopen (tmp, "w");
+ fprintf (serverfile, "/* Generated from %s.xg */\n", filename);
+ fprintf (serverfile, "#include \"%s.h\"\n\n", filename);
+ fprintf (serverfile, "#include \"%s.ss.h\"\n\n", filename);
+ fprintf (serverfile, "#include <stdio.h>\n");
+ fprintf (serverfile, "#include <stdlib.h>\n");
+ fprintf (serverfile, "#include <sys/types.h>\n");
+ fprintf (serverfile, "#include <netinet/in.h>\n");
+ fprintf (serverfile, "#include <roken.h>\n");
+ fprintf (serverfile, "#ifndef HAVE_BCOPY\n"
+ "#define bcopy(a,b,c) memcpy((b),(a),(c))\n"
+ "#endif /* !HAVE_BCOPY */\n\n");
+
+ sprintf (tmp, "%s.cs.h", filename);
+ clienthdrfile = efopen (tmp, "w");
+ fprintf (clienthdrfile, "/* Generated from %s.xg */\n", filename);
+
+ sprintf (tmp, "%s.ss.h", filename);
+ serverhdrfile = efopen (tmp, "w");
+ fprintf (serverhdrfile, "/* Generated from %s.xg */\n", filename);
+ fprintf (serverhdrfile, "#include <rx/rx.h>\n");
+
+ free (tmp);
+}
+
+void
+close_generator (char *filename)
+{
+ char *fileupr = strdup (filename);
+
+ strupr (fileupr);
+ fprintf (headerfile, "\n#endif /* %s */\n", fileupr);
+ efclose (headerfile);
+ efclose (clientfile);
+ efclose (serverfile);
+ efclose (clienthdrfile);
+ efclose (serverhdrfile);
+ efclose (ydrfile);
+}
+
+/*
+ * Generate the server-side stub function for the function in s and
+ * write it to the file f.
+ */
+
+void
+generate_server_stub (Symbol *s, FILE *f, FILE *headerf)
+{
+ fprintf (headerf, "int _%s%s(\nstruct rx_call *call);\n",
+ package, s->name);
+ fprintf (headerf, "int %s%s(\nstruct rx_call *call\n",
+ package, s->name);
+ listiter (s->u.proc.arguments, gen1, headerf);
+ fprintf (headerf, ");\n\n");
+
+ fprintf (f, "int _%s%s(\nstruct rx_call *call)\n",
+ package, s->name);
+ fprintf (f, "{\n"
+ "int _result;\n");
+ listiter (s->u.proc.arguments, gendeclare, f);
+ fprintf (f, "\n");
+ listiter (s->u.proc.arguments, gendecodein, f);
+ fprintf (f, "_result = %s%s(", package, s->name);
+ if (/* s->u.proc.splitp */ 1) {
+ fprintf (f, "call");
+ if (!listemptyp (s->u.proc.arguments))
+ fprintf (f, ", ");
+ }
+ listiter (s->u.proc.arguments, genargs, f);
+ fprintf (f, ");\n");
+ listiter (s->u.proc.arguments, genencodeout, f);
+ listiter (s->u.proc.arguments, genfree, f);
+ fprintf (f, "return _result;\n");
+ if (!listemptyp(s->u.proc.arguments))
+ fprintf(f, "fail:\n"
+ "return rx_Error(call);\n");
+ fprintf(f, "}\n\n");
+
+ listaddtail (func_list, s);
+}
+
+static Bool
+gencase (List *list, Listitem *item, void *arg)
+{
+ Symbol *s = (Symbol *)listdata (item);
+ FILE *f = (FILE *)arg;
+
+ fprintf (f, "case %u: {\n"
+ "_result = _%s%s(call);\n"
+ "break;\n"
+ "}\n",
+ s->u.proc.id, package, s->name);
+ return FALSE;
+}
+
+/*
+ *
+ */
+
+void
+generate_server_switch (FILE *c_file,
+ FILE *h_file)
+{
+ Type optype = {TULONG};
+
+ fprintf (h_file,
+ "int %sExecuteRequest(struct rx_call *call);\n",
+ package);
+
+ fprintf (c_file, "int %sExecuteRequest(struct rx_call *call)\n"
+ "{\n"
+ "unsigned opcode;\n"
+ "int _result;\n",
+ package);
+
+ encode_type ("opcode", &optype, c_file, DECODE_RX);
+ fprintf (c_file, "switch(opcode) {\n");
+
+ listiter (func_list, gencase, c_file);
+
+ fprintf (c_file, "default:\n"
+ "fprintf (stderr, \"Ignoring %%d\\n\", opcode);\n"
+ "}\n"
+ "return _result;\n"
+ "fail:\n"
+ "return rx_Error(call);\n"
+ "}\n\n");
+}
diff --git a/usr.sbin/afs/src/ydr/output.h b/usr.sbin/afs/src/ydr/output.h
new file mode 100644
index 00000000000..054da7bdf29
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/output.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: output.h,v 1.1.1.1 1998/09/14 21:53:27 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: output.h,v 1.7 1998/04/27 20:17:17 assar Exp $ */
+
+#ifndef _OUTPUT_
+#define _OUTPUT_
+
+#include <stdio.h>
+#include <bool.h>
+
+void generate_header (Symbol *s, FILE *f);
+void generate_sizeof (Symbol *s, FILE *f);
+void generate_function (Symbol *s, FILE *f, Bool encodep);
+void generate_function_prototype (Symbol *s, FILE *f, Bool encodep);
+void generate_client_stub (Symbol *s, FILE *f, FILE *headerf);
+void generate_server_stub (Symbol *s, FILE *f, FILE *headerf);
+void generate_server_switch (FILE *c_f, FILE *h_file);
+void init_generate (char *filename);
+void close_generator (char *filename);
+
+extern char *package;
+
+extern FILE *headerfile, *clientfile, *serverfile, *clienthdrfile,
+ *serverhdrfile, *ydrfile;
+
+#endif /* _OUTPUT_ */
diff --git a/usr.sbin/afs/src/ydr/parse.y b/usr.sbin/afs/src/ydr/parse.y
new file mode 100644
index 00000000000..9ed3b67ee35
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/parse.y
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse.y,v 1.1.1.1 1998/09/14 21:53:27 art Exp $");
+#endif
+
+#include <stdio.h>
+#include <list.h>
+#include <bool.h>
+#include <mem.h>
+#include "sym.h"
+#include "types.h"
+#include "output.h"
+#include "lex.h"
+
+void yyerror (char *);
+
+%}
+
+%union {
+ int constant;
+ Symbol *sym;
+ List *list;
+ char *name;
+ Type *type;
+ StructEntry *sentry;
+ Argument *arg;
+ Bool bool;
+ unsigned flags;
+}
+
+%token T_ENUM T_STRUCT T_CONST T_UNSIGNED T_ULONG T_INT T_CHAR T_STRING
+%token T_LONG T_TYPEDEF T_OPAQUE T_IN T_OUT T_INOUT T_SPLIT T_MULTI
+%token T_SHORT T_USHORT T_UCHAR T_ASIS
+%token <name> T_IDENTIFIER T_VERBATIM T_PACKAGE
+%token <constant> T_CONSTANT
+%token <sym> T_IDCONST T_IDTYPE
+
+%type <constant> constant opt_constant
+%type <constant> param_type
+%type <sym> enumentry type_decl proc_decl
+%type <list> enumentries enumbody structbody memberdecls params
+%type <type> type
+%type <sentry> memberdecl memberdecl2
+%type <arg> param
+%type <flags> flags
+
+%start specification
+
+%%
+
+specification:
+ | specification declaration
+ | specification directive
+ | error ';'
+ ;
+
+declaration: type_decl {
+ generate_header ($1, headerfile);
+ generate_sizeof ($1, headerfile);
+ generate_function ($1, ydrfile, TRUE);
+ generate_function_prototype ($1, headerfile, TRUE);
+ generate_function ($1, ydrfile, FALSE);
+ generate_function_prototype ($1, headerfile, FALSE);
+ }
+ | proc_decl {
+ generate_client_stub ($1, clientfile, clienthdrfile);
+ generate_server_stub ($1, serverfile, serverhdrfile);
+ }
+ ;
+
+type_decl : T_ENUM T_IDENTIFIER enumbody ';'
+ { $$ = define_enum ($2, $3); }
+ | T_STRUCT T_IDENTIFIER { define_struct($2); } structbody ';'
+ { $$ = set_struct_body ($2, $4); }
+ | T_TYPEDEF memberdecl ';'
+ { $$ = define_typedef ($2); }
+ | T_CONST T_IDENTIFIER '=' constant ';'
+ { $$ = define_const ($2, $4); }
+ ;
+
+flags: { $$ = TSIMPLE; }
+ | T_SPLIT { $$ = TSPLIT; }
+ | T_MULTI { $$ = TSPLIT | TSIMPLE; }
+ ;
+
+proc_decl: T_IDENTIFIER '(' params ')' flags '=' constant ';'
+ { $$ = (Symbol *)emalloc(sizeof(Symbol));
+ $$->type = TPROC;
+ $$->name = $1;
+ $$->u.proc.arguments = $3;
+ $$->u.proc.id = $7;
+ $$->u.proc.flags = $5;
+ }
+ ;
+
+params: { $$ = listnew(); }
+ | param { $$ = listnew(); listaddhead ($$, $1); }
+ | params ',' param
+ { listaddtail ($1, $3); $$ = $1; }
+ ;
+
+param: param_type memberdecl
+ { $$ = (Argument *)emalloc(sizeof(Argument));
+ $$->argtype = $1;
+ $$->name = $2->name;
+ $$->type = $2->type;
+ free($2); }
+ ;
+
+param_type: T_IN { $$ = TIN; }
+ | T_OUT { $$ = TOUT; }
+ | T_INOUT { $$ = TINOUT; }
+ ;
+
+directive: T_PACKAGE T_IDENTIFIER
+ { package = $2; }
+ | T_VERBATIM
+ { fprintf (headerfile, "%s\n", $1); }
+ ;
+
+enumbody: '{' enumentries '}' { $$ = $2; }
+ ;
+
+enumentries: { $$ = listnew (); }
+ | enumentry
+ { $$ = listnew(); listaddhead ($$, $1); }
+ | enumentries ',' enumentry
+ { listaddtail ($1, $3); $$ = $1;}
+ ;
+
+enumentry: T_IDENTIFIER '=' constant
+ { $$ = createenumentry ($1, $3); }
+ ;
+
+memberdecl: T_ASIS memberdecl2
+ { $$ = $2; $$->type->flags |= TASIS; }
+ | memberdecl2
+ { $$ = $1; }
+ ;
+
+memberdecl2: type T_IDENTIFIER
+ { $$ = createstructentry ($2, $1); }
+ | T_STRUCT type T_IDENTIFIER
+ {
+ $$ = createstructentry ($3, $2);
+ }
+ | T_STRING T_IDENTIFIER '<' opt_constant '>'
+ { Type *t = (Type *)emalloc (sizeof(Type));
+ t->type = TSTRING;
+ t->size = $4;
+ t->flags = 0;
+ $$ = createstructentry ($2, t);
+ }
+ | type T_IDENTIFIER '[' opt_constant ']'
+ { Type *t = (Type *)emalloc(sizeof(Type));
+ t->type = TARRAY;
+ t->size = $4;
+ t->subtype = $1;
+ t->flags = 0;
+ $$ = createstructentry ($2, t); }
+ | type T_IDENTIFIER '<' opt_constant '>'
+ { Type *t = (Type *)emalloc(sizeof(Type));
+ t->type = TVARRAY;
+ t->size = $4;
+ t->subtype = $1;
+ t->indextype = NULL;
+ t->flags = 0;
+ $$ = createstructentry ($2, t); }
+ | type T_IDENTIFIER '<' type '>'
+ { Type *t = (Type *)emalloc(sizeof(Type));
+ t->type = TVARRAY;
+ t->size = 0;
+ t->subtype = $1;
+ t->indextype = $4;
+ t->flags = 0;
+ $$ = createstructentry ($2, t); }
+ ;
+
+type: long_or_int
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TLONG;
+ $$->flags = 0; }
+ | T_UNSIGNED
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TULONG;
+ $$->flags = 0; }
+ | T_ULONG
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TULONG;
+ $$->flags = 0; }
+ | T_UNSIGNED T_LONG
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TULONG;
+ $$->flags = 0; }
+ | T_CHAR
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TCHAR;
+ $$->flags = 0; }
+ | T_UCHAR
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TUCHAR;
+ $$->flags = 0; }
+ | T_UNSIGNED T_CHAR
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TUCHAR;
+ $$->flags = 0; }
+ | T_SHORT
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TSHORT;
+ $$->flags = 0; }
+ | T_USHORT
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TUSHORT;
+ $$->flags = 0; }
+ | T_UNSIGNED T_SHORT
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TUSHORT;
+ $$->flags = 0; }
+ | T_STRING
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TSTRING;
+ $$->flags = 0; }
+ | T_OPAQUE
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TOPAQUE;
+ $$->flags = 0; }
+ | type '*'
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TPOINTER;
+ $$->subtype = $1;
+ $$->flags = 0; }
+ | T_IDTYPE
+ { $$ = (Type *)emalloc(sizeof(Type));
+ $$->type = TUSERDEF;
+ $$->symbol = $1;
+ $$->flags = 0;
+ if ($$->symbol->type != TSTRUCT
+ && $$->symbol->type != TENUM
+ && $$->symbol->type != TTYPEDEF)
+ error_message ("%s used as a type\n", $$->symbol->name);
+ }
+ ;
+
+long_or_int: T_LONG
+ | T_INT
+ ;
+
+memberdecls: { $$ = listnew(); }
+ | memberdecls memberdecl ';'
+ { listaddtail ($1, $2); $$ = $1; }
+ ;
+
+structbody: '{' memberdecls '}' { $$ = $2; }
+ ;
+
+opt_constant: { $$ = 0; }
+ | constant { $$ = $1; }
+ ;
+
+constant: T_CONSTANT { $$ = $1; }
+ | T_IDCONST
+ { Symbol *s = $1;
+ if (s->type != TCONST) {
+ error_message ("%s not a constant\n", s->name);
+ } else
+ $$ = s->u.val;
+ }
+
+%%
+
+void
+yyerror (char *s)
+{
+ error_message ("%s\n", s);
+}
diff --git a/usr.sbin/afs/src/ydr/sym.h b/usr.sbin/afs/src/ydr/sym.h
new file mode 100644
index 00000000000..b6ec90f24e7
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/sym.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: sym.h,v 1.1.1.1 1998/09/14 21:53:27 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: sym.h,v 1.5 1998/02/19 05:15:52 assar Exp $ */
+
+#ifndef _SYM_
+#define _SYM_
+
+#include <bool.h>
+#include <list.h>
+
+struct Type;
+
+typedef struct Type Type;
+
+typedef enum
+{
+ TUNDEFINED, TSTRUCT, TENUM, TCONST, TENUMVAL, TTYPEDEF, TPROC
+} SymbolType;
+
+enum { TSPLIT = 1, TSIMPLE = 2};
+
+typedef struct {
+ SymbolType type;
+ char *name;
+ union {
+ List *list;
+ int val;
+ Type *type;
+ struct {
+ unsigned id;
+ List *arguments;
+ unsigned flags;
+ } proc;
+ } u;
+} Symbol;
+
+void initsym (void);
+Symbol* addsym (char *);
+Symbol* findsym (char *);
+void symiterate (Bool (*func)(void *, void *), void *arg);
+
+#endif /* _SYM_ */
diff --git a/usr.sbin/afs/src/ydr/symbol.c b/usr.sbin/afs/src/ydr/symbol.c
new file mode 100644
index 00000000000..2c1d67590b0
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/symbol.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: symbol.c,v 1.1.1.1 1998/09/14 21:53:27 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: symbol.c,v 1.4 1998/02/19 05:16:28 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mem.h>
+#include "sym.h"
+#include <hash.h>
+
+static Hashtab *hashtab;
+
+static int
+symcmp (void *a, void *b)
+{
+ Symbol *sa = (Symbol *)a;
+ Symbol *sb = (Symbol *)b;
+
+ return strcmp (sa->name, sb->name);
+}
+
+static unsigned
+symhash (void *a)
+{
+ Symbol *sa = (Symbol *)a;
+
+ return hashadd (sa->name);
+}
+
+#define HASHTABSIZE 149
+
+void
+initsym (void)
+{
+ hashtab = hashtabnew (HASHTABSIZE, symcmp, symhash);
+}
+
+Symbol *
+addsym (char *name)
+{
+ Symbol tmp;
+ Symbol *sym;
+
+ tmp.name = name;
+ sym = (Symbol *)hashtabsearch (hashtab, (void *)&tmp);
+ if (sym == NULL) {
+ sym = (Symbol *)emalloc (sizeof (Symbol));
+ sym->name = name;
+ sym->type = TUNDEFINED;
+ hashtabadd (hashtab, sym);
+ }
+ return sym;
+}
+
+Symbol *
+findsym (char *name)
+{
+ Symbol tmp;
+
+ tmp.name = name;
+ return (Symbol *)hashtabsearch (hashtab, (void *)&tmp);
+}
+
+#ifdef notyet
+static Bool
+printsymbol (void *ptr, void *arg)
+{
+ Symbol *s = (Symbol *)ptr;
+
+ switch (s->type) {
+ case TUNDEFINED :
+ printf ("undefined ");
+ break;
+ case TSTRUCT :
+ printf ("struct ");
+ break;
+ case TENUM :
+ printf ("enum ");
+ break;
+ case TENUMVAL :
+ printf ("enumval ");
+ break;
+ case TCONST :
+ printf ("const ");
+ break;
+ case TTYPEDEF :
+ printf ("typedef ");
+ break;
+ default :
+ abort ();
+ }
+ puts (s->name);
+
+ return FALSE;
+}
+#endif
+
+void
+symiterate (Bool (*func)(void *, void *), void *arg)
+{
+ hashtabforeach (hashtab, func, arg);
+}
diff --git a/usr.sbin/afs/src/ydr/types.c b/usr.sbin/afs/src/ydr/types.c
new file mode 100644
index 00000000000..0ae0e902a39
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/types.c
@@ -0,0 +1,176 @@
+/* $OpenBSD: types.c,v 1.1.1.1 1998/09/14 21:53:27 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: types.c,v 1.3 1998/02/19 05:17:08 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <mem.h>
+#include "types.h"
+#include "lex.h"
+
+Symbol *
+define_const (char *name, int value)
+{
+ Symbol *s;
+
+ s = addsym (name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TCONST;
+ s->u.val = value;
+ return s;
+}
+
+Symbol *
+define_enum (char *name, List *list)
+{
+ Symbol *s;
+
+ s = addsym (name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TENUM;
+ s->u.list = list;
+ return s;
+}
+
+Symbol *
+define_struct (char *name)
+{
+ Symbol *s;
+
+ s = addsym (name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TSTRUCT;
+ s->u.list = NULL;
+ return s;
+}
+
+Symbol *
+set_struct_body (char *name, List *list)
+{
+ Symbol *s;
+
+ s = findsym(name);
+ if (s == NULL) {
+ error_message("struct %s not declared", name);
+ return NULL;
+ }
+ s->u.list = list;
+ return s;
+}
+
+Symbol *
+define_typedef (StructEntry *entry)
+{
+ Symbol *s;
+
+ s = addsym (entry->name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TTYPEDEF;
+ s->name = entry->name;
+ s->u.type = entry->type;
+ free (entry);
+ return s;
+}
+
+
+Symbol *
+define_proc (char *name, List *args, unsigned id)
+{
+ Symbol *s;
+
+ s = addsym (name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TPROC;
+ s->u.proc.id = id;
+ s->u.proc.arguments = args;
+ return s;
+}
+
+Symbol *
+createenumentry (char *name, int value)
+{
+ Symbol *s;
+
+ s = addsym (name);
+
+ if (s->type != TUNDEFINED) {
+ error_message ("Redeclaration of %s\n", s->name);
+ return NULL;
+ }
+ s->type = TENUMVAL;
+ s->u.val = value;
+ return s;
+}
+
+StructEntry *
+createstructentry (char *name, Type *type)
+{
+ StructEntry *e;
+
+ e = (StructEntry *)emalloc (sizeof (StructEntry));
+ e->name = name;
+ e->type = type;
+ return e;
+}
+
+Symbol *
+define_proc (char *name, List *params, unsigned id);
diff --git a/usr.sbin/afs/src/ydr/types.h b/usr.sbin/afs/src/ydr/types.h
new file mode 100644
index 00000000000..ed0305dbcbb
--- /dev/null
+++ b/usr.sbin/afs/src/ydr/types.h
@@ -0,0 +1,87 @@
+/* $OpenBSD: types.h,v 1.1.1.1 1998/09/14 21:53:28 art Exp $ */
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $KTH: types.h,v 1.5 1998/05/02 02:37:30 assar Exp $ */
+
+#ifndef _TYPES_
+#define _TYPES_
+
+#include "sym.h"
+
+typedef struct {
+ char *name;
+ int val;
+} EnumEntry;
+
+typedef enum {
+ TCHAR, TUCHAR, TSHORT, TUSHORT, TLONG, TULONG, TSTRING, TOPAQUE,
+ TUSERDEF, TARRAY,
+ TVARRAY, TPOINTER
+} TypeType;
+
+struct Type {
+ TypeType type;
+ Symbol *symbol;
+ unsigned size;
+ Type *subtype;
+ Type *indextype;
+ enum { TASIS = 1 } flags;
+};
+
+typedef struct {
+ char *name;
+ Type *type;
+} StructEntry;
+
+typedef struct {
+ enum { TIN, TOUT, TINOUT } argtype;
+ char *name;
+ Type *type;
+} Argument;
+
+Symbol *define_const (char *name, int value);
+Symbol *define_enum (char *name, List *list);
+Symbol *define_struct (char *name);
+Symbol *set_struct_body(char *name, List *list);
+Symbol *define_typedef (StructEntry *entry);
+Symbol *define_proc (char *name, List *args, unsigned id);
+Symbol *createenumentry (char *name, int val);
+StructEntry *createstructentry (char *name, Type *type);
+
+#endif /* _TYPES_ */
diff --git a/usr.sbin/afs/vos/Makefile b/usr.sbin/afs/vos/Makefile
new file mode 100644
index 00000000000..f4f249c451c
--- /dev/null
+++ b/usr.sbin/afs/vos/Makefile
@@ -0,0 +1,12 @@
+PROG = vos
+MAN =
+BINDIR = /usr/sbin
+SRCS = vos.c arlalib.c fs_lib.c
+LDADD += -lkafs
+DPADD += ${LIBKAFS}
+
+.include "../Applflags.inc"
+
+.PATH: ${.CURDIR}/../src/appl
+
+.include <bsd.prog.mk> \ No newline at end of file
diff --git a/usr.sbin/afs/ydr/Makefile b/usr.sbin/afs/ydr/Makefile
new file mode 100644
index 00000000000..c99672be166
--- /dev/null
+++ b/usr.sbin/afs/ydr/Makefile
@@ -0,0 +1,22 @@
+# $OpenBSD: Makefile,v 1.1.1.1 1998/09/14 21:53:30 art Exp $
+SRCS += main.c output.c symbol.c types.c lex.c parse.c
+CLEANFILES += lex.c parse.c parse.h y.tab.h
+CFLAGS += -I. -I${.CURDIR}/../src/util -I${.CURDIR}/../src/lib/roken \
+ -I${.CURDIR}/../src/include -I${.CURDIR} -DHAVE_CONFIG_H
+CFLAGS += -DCPP='"/usr/bin/cpp"'
+MAN =
+BINDIR = ${DESTDIR}/usr/bin
+PROG = ydr
+LDADD += ../libroken/libroken.a
+DPADD += ../libroken/libroken.a
+
+.PATH: ${.CURDIR}/../src/ydr
+
+beforedepend: parse.h
+
+parse.h: y.tab.h
+ -@ln -s y.tab.h parse.h
+
+y.tab.h: parse.c
+
+.include <bsd.prog.mk> \ No newline at end of file