summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/Makefile26
-rw-r--r--usr.sbin/Makefile.inc3
-rw-r--r--usr.sbin/ac/ac.8107
-rw-r--r--usr.sbin/accton/Makefile6
-rw-r--r--usr.sbin/accton/accton.c95
-rw-r--r--usr.sbin/amd/Makefile5
-rw-r--r--usr.sbin/amd/amd/ChangeLog1169
-rw-r--r--usr.sbin/amd/amd/Makefile33
-rw-r--r--usr.sbin/amd/amd/afs_ops.c1816
-rw-r--r--usr.sbin/amd/amd/am_ops.c181
-rw-r--r--usr.sbin/amd/amd/amd.8232
-rw-r--r--usr.sbin/amd/amd/amd.c344
-rw-r--r--usr.sbin/amd/amd/amq_subr.c464
-rw-r--r--usr.sbin/amd/amd/clock.c241
-rw-r--r--usr.sbin/amd/amd/efs_ops.c135
-rw-r--r--usr.sbin/amd/amd/get_args.c336
-rw-r--r--usr.sbin/amd/amd/host_ops.c681
-rw-r--r--usr.sbin/amd/amd/ifs_ops.c195
-rw-r--r--usr.sbin/amd/amd/info_file.c276
-rw-r--r--usr.sbin/amd/amd/info_hes.c697
-rw-r--r--usr.sbin/amd/amd/info_ndbm.c123
-rw-r--r--usr.sbin/amd/amd/info_nis.c247
-rw-r--r--usr.sbin/amd/amd/info_passwd.c162
-rw-r--r--usr.sbin/amd/amd/info_union.c153
-rw-r--r--usr.sbin/amd/amd/map.c1140
-rw-r--r--usr.sbin/amd/amd/mapc.c914
-rw-r--r--usr.sbin/amd/amd/misc_rpc.c333
-rw-r--r--usr.sbin/amd/amd/mntfs.c367
-rw-r--r--usr.sbin/amd/amd/mount_fs.c273
-rw-r--r--usr.sbin/amd/amd/mtab.c108
-rw-r--r--usr.sbin/amd/amd/nfs_ops.c809
-rw-r--r--usr.sbin/amd/amd/nfs_start.c435
-rw-r--r--usr.sbin/amd/amd/nfs_subr.c552
-rw-r--r--usr.sbin/amd/amd/nfsx_ops.c516
-rw-r--r--usr.sbin/amd/amd/opts.c835
-rw-r--r--usr.sbin/amd/amd/pfs_ops.c169
-rw-r--r--usr.sbin/amd/amd/restart.c181
-rw-r--r--usr.sbin/amd/amd/rpc_fwd.c430
-rw-r--r--usr.sbin/amd/amd/sched.c325
-rw-r--r--usr.sbin/amd/amd/sfs_ops.c208
-rw-r--r--usr.sbin/amd/amd/srvr_afs.c205
-rw-r--r--usr.sbin/amd/amd/srvr_nfs.c719
-rw-r--r--usr.sbin/amd/amd/ufs_ops.c178
-rw-r--r--usr.sbin/amd/amd/umount_fs.c225
-rw-r--r--usr.sbin/amd/amd/util.c648
-rw-r--r--usr.sbin/amd/amd/wire.c281
-rw-r--r--usr.sbin/amd/amd/xutil.c491
-rw-r--r--usr.sbin/amd/amq/Makefile15
-rw-r--r--usr.sbin/amd/amq/amq.8130
-rw-r--r--usr.sbin/amd/amq/amq.c666
-rw-r--r--usr.sbin/amd/config/Configure60
-rw-r--r--usr.sbin/amd/config/Makefile.aix35
-rw-r--r--usr.sbin/amd/config/Makefile.bsd448
-rw-r--r--usr.sbin/amd/config/Makefile.config91
-rw-r--r--usr.sbin/amd/config/Makefile.hpux13
-rw-r--r--usr.sbin/amd/config/Makefile.irix10
-rw-r--r--usr.sbin/amd/config/Makefile.irix313
-rw-r--r--usr.sbin/amd/config/Makefile.irix414
-rw-r--r--usr.sbin/amd/config/Makefile.stellix10
-rw-r--r--usr.sbin/amd/config/RELEASE1
-rw-r--r--usr.sbin/amd/config/arch126
-rw-r--r--usr.sbin/amd/config/misc-aix3.h96
-rw-r--r--usr.sbin/amd/config/misc-hpux.h79
-rw-r--r--usr.sbin/amd/config/misc-irix.h50
-rw-r--r--usr.sbin/amd/config/misc-next.h44
-rw-r--r--usr.sbin/amd/config/misc-stellix.h65
-rw-r--r--usr.sbin/amd/config/misc-ultrix.h55
-rw-r--r--usr.sbin/amd/config/mount_aix.c153
-rw-r--r--usr.sbin/amd/config/mount_irix.c83
-rw-r--r--usr.sbin/amd/config/mount_stellix.c76
-rw-r--r--usr.sbin/amd/config/mtab_aix.c137
-rw-r--r--usr.sbin/amd/config/mtab_bsd.c114
-rw-r--r--usr.sbin/amd/config/mtab_file.c472
-rw-r--r--usr.sbin/amd/config/mtab_ultrix.c115
-rw-r--r--usr.sbin/amd/config/newvers.sh88
-rw-r--r--usr.sbin/amd/config/os-acis43.h83
-rw-r--r--usr.sbin/amd/config/os-aix3.h181
-rw-r--r--usr.sbin/amd/config/os-aux.h117
-rw-r--r--usr.sbin/amd/config/os-bsd44.h191
-rw-r--r--usr.sbin/amd/config/os-concentrix.h79
-rw-r--r--usr.sbin/amd/config/os-convex.h80
-rw-r--r--usr.sbin/amd/config/os-defaults.h143
-rw-r--r--usr.sbin/amd/config/os-dgux.h114
-rw-r--r--usr.sbin/amd/config/os-fpx4.h92
-rw-r--r--usr.sbin/amd/config/os-hcx.h81
-rw-r--r--usr.sbin/amd/config/os-hlh42.h89
-rw-r--r--usr.sbin/amd/config/os-hpux.h150
-rw-r--r--usr.sbin/amd/config/os-irix.h133
-rw-r--r--usr.sbin/amd/config/os-irix3.h133
-rw-r--r--usr.sbin/amd/config/os-irix4.h150
-rw-r--r--usr.sbin/amd/config/os-next.h79
-rw-r--r--usr.sbin/amd/config/os-pyrOSx.h80
-rw-r--r--usr.sbin/amd/config/os-riscix.h88
-rw-r--r--usr.sbin/amd/config/os-sos3.h79
-rw-r--r--usr.sbin/amd/config/os-sos4.h116
-rw-r--r--usr.sbin/amd/config/os-stellix.h108
-rw-r--r--usr.sbin/amd/config/os-type128
-rw-r--r--usr.sbin/amd/config/os-u2_2.h161
-rw-r--r--usr.sbin/amd/config/os-u3_0.h154
-rw-r--r--usr.sbin/amd/config/os-u4_0.h158
-rw-r--r--usr.sbin/amd/config/os-u4_2.h153
-rw-r--r--usr.sbin/amd/config/os-umax43.h79
-rw-r--r--usr.sbin/amd/config/os-utek.h49
-rw-r--r--usr.sbin/amd/config/os-utx32.h85
-rw-r--r--usr.sbin/amd/config/os-xinu43.h112
-rw-r--r--usr.sbin/amd/doc/Makefile53
-rw-r--r--usr.sbin/amd/doc/amdref.cps381
-rw-r--r--usr.sbin/amd/doc/amdref.ps6429
-rw-r--r--usr.sbin/amd/doc/amdref.texinfo4554
-rw-r--r--usr.sbin/amd/doc/texinfo.tex2192
-rw-r--r--usr.sbin/amd/fsinfo/Makefile30
-rw-r--r--usr.sbin/amd/fsinfo/conf/automounts48
-rw-r--r--usr.sbin/amd/fsinfo/conf/csg_sun318
-rw-r--r--usr.sbin/amd/fsinfo/conf/csg_vax67
-rw-r--r--usr.sbin/amd/fsinfo/conf/diskless_sun3_sos49
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/achilles.doc.ic.ac.uk116
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/bigears.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/dylan.doc.ic.ac.uk68
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/flamingo.doc.ic.ac.uk104
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/ganymede.doc.ic.ac.uk33
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/gould.doc.ic.ac.uk477
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/gummo.doc.ic.ac.uk12
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/ivax.doc.ic.ac.uk84
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/obsidian.doc.ic.ac.uk28
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/pelican.doc.ic.ac.uk208
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/rvax.doc.ic.ac.uk66
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/sky.doc.ic.ac.uk79
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/svax.doc.ic.ac.uk66
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tcsun1.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tcsun2.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tcsun3.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tcsun4.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tcsun5.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/toytown.doc.ic.ac.uk116
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/truth.doc.ic.ac.uk9
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun1.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun10.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun11.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun12.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun13.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun14.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun15.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun16.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun17.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun18.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun19.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun2.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun3.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun4.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun5.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun6.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun7.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun8.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsun9.doc.ic.ac.uk3
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/tsunfs.doc.ic.ac.uk211
-rw-r--r--usr.sbin/amd/fsinfo/conf/hosts/whoops.doc.ic.ac.uk21
-rw-r--r--usr.sbin/amd/fsinfo/conf/users106
-rw-r--r--usr.sbin/amd/fsinfo/fsi_analyze.c645
-rw-r--r--usr.sbin/amd/fsinfo/fsi_data.h236
-rw-r--r--usr.sbin/amd/fsinfo/fsi_dict.c125
-rw-r--r--usr.sbin/amd/fsinfo/fsi_gram.y394
-rw-r--r--usr.sbin/amd/fsinfo/fsi_lex.l403
-rw-r--r--usr.sbin/amd/fsinfo/fsi_util.c573
-rw-r--r--usr.sbin/amd/fsinfo/fsinfo.877
-rw-r--r--usr.sbin/amd/fsinfo/fsinfo.c275
-rw-r--r--usr.sbin/amd/fsinfo/fsinfo.h159
-rw-r--r--usr.sbin/amd/fsinfo/wr_atab.c284
-rw-r--r--usr.sbin/amd/fsinfo/wr_bparam.c101
-rw-r--r--usr.sbin/amd/fsinfo/wr_dumpset.c88
-rw-r--r--usr.sbin/amd/fsinfo/wr_exportfs.c100
-rw-r--r--usr.sbin/amd/fsinfo/wr_fstab.c303
-rw-r--r--usr.sbin/amd/include/am.h567
-rw-r--r--usr.sbin/amd/include/config.h142
-rw-r--r--usr.sbin/amd/include/fstype.h148
-rw-r--r--usr.sbin/amd/include/re.h21
-rw-r--r--usr.sbin/amd/include/remagic.h5
-rw-r--r--usr.sbin/amd/include/uwait.h83
-rw-r--r--usr.sbin/amd/maps/a_master79
-rw-r--r--usr.sbin/amd/maps/a_net3
-rw-r--r--usr.sbin/amd/mk-amd-map/Makefile11
-rw-r--r--usr.sbin/amd/mk-amd-map/mk-amd-map.859
-rw-r--r--usr.sbin/amd/mk-amd-map/mk-amd-map.c384
-rw-r--r--usr.sbin/amd/rpcx/amq.h153
-rw-r--r--usr.sbin/amd/rpcx/amq.x185
-rw-r--r--usr.sbin/amd/rpcx/amq_clnt.c181
-rw-r--r--usr.sbin/amd/rpcx/amq_svc.c136
-rw-r--r--usr.sbin/amd/rpcx/amq_xdr.c251
-rw-r--r--usr.sbin/amd/rpcx/mount.h124
-rw-r--r--usr.sbin/amd/rpcx/mount_xdr.c206
-rw-r--r--usr.sbin/amd/rpcx/nfs_prot.h389
-rw-r--r--usr.sbin/amd/rpcx/nfs_prot_svc.c198
-rw-r--r--usr.sbin/amd/rpcx/nfs_prot_xdr.c627
-rw-r--r--usr.sbin/amd/text/COPYRIGHT3
-rw-r--r--usr.sbin/amd/text/INSTALL194
-rw-r--r--usr.sbin/amd/text/README37
-rw-r--r--usr.sbin/amd/text/amd.start.ex87
-rw-r--r--usr.sbin/arp/Makefile13
-rw-r--r--usr.sbin/arp/arp.8127
-rw-r--r--usr.sbin/arp/arp.c514
-rw-r--r--usr.sbin/arp/arp4.4124
-rw-r--r--usr.sbin/bad144/Makefile7
-rw-r--r--usr.sbin/bad144/bad144.8186
-rw-r--r--usr.sbin/bad144/bad144.c662
-rw-r--r--usr.sbin/chown/Makefile9
-rw-r--r--usr.sbin/chown/chgrp.1136
-rw-r--r--usr.sbin/chown/chown.8149
-rw-r--r--usr.sbin/chown/chown.c273
-rw-r--r--usr.sbin/chroot/Makefile6
-rw-r--r--usr.sbin/chroot/chroot.879
-rw-r--r--usr.sbin/chroot/chroot.c96
-rw-r--r--usr.sbin/config.new/Makefile14
-rw-r--r--usr.sbin/config.new/config.h281
-rw-r--r--usr.sbin/config.new/config.new.8167
-rw-r--r--usr.sbin/config.new/files.c262
-rw-r--r--usr.sbin/config.new/gram.y392
-rw-r--r--usr.sbin/config.new/hash.c279
-rw-r--r--usr.sbin/config.new/main.c466
-rw-r--r--usr.sbin/config.new/mkheaders.c148
-rw-r--r--usr.sbin/config.new/mkioconf.c395
-rw-r--r--usr.sbin/config.new/mkmakefile.c364
-rw-r--r--usr.sbin/config.new/mkswap.c118
-rw-r--r--usr.sbin/config.new/pack.c520
-rw-r--r--usr.sbin/config.new/scan.l238
-rw-r--r--usr.sbin/config.new/sem.c974
-rw-r--r--usr.sbin/config.new/sem.h61
-rw-r--r--usr.sbin/config.new/util.c262
-rw-r--r--usr.sbin/config/Makefile12
-rw-r--r--usr.sbin/config/SMM.doc/0.t88
-rw-r--r--usr.sbin/config/SMM.doc/1.t61
-rw-r--r--usr.sbin/config/SMM.doc/2.t188
-rw-r--r--usr.sbin/config/SMM.doc/3.t299
-rw-r--r--usr.sbin/config/SMM.doc/4.t442
-rw-r--r--usr.sbin/config/SMM.doc/5.t271
-rw-r--r--usr.sbin/config/SMM.doc/6.t239
-rw-r--r--usr.sbin/config/SMM.doc/Makefile10
-rw-r--r--usr.sbin/config/SMM.doc/a.t162
-rw-r--r--usr.sbin/config/SMM.doc/b.t137
-rw-r--r--usr.sbin/config/SMM.doc/c.t109
-rw-r--r--usr.sbin/config/SMM.doc/d.t272
-rw-r--r--usr.sbin/config/SMM.doc/e.t114
-rw-r--r--usr.sbin/config/SMM.doc/spell.ok306
-rw-r--r--usr.sbin/config/config.8174
-rw-r--r--usr.sbin/config/config.h212
-rw-r--r--usr.sbin/config/config.y1109
-rw-r--r--usr.sbin/config/lang.l215
-rw-r--r--usr.sbin/config/main.c268
-rw-r--r--usr.sbin/config/mkglue.c400
-rw-r--r--usr.sbin/config/mkheaders.c207
-rw-r--r--usr.sbin/config/mkioconf.c1085
-rw-r--r--usr.sbin/config/mkmakefile.c623
-rw-r--r--usr.sbin/config/mkswapconf.c216
-rw-r--r--usr.sbin/config/mkubglue.c196
-rw-r--r--usr.sbin/dev_mkdb/Makefile6
-rw-r--r--usr.sbin/dev_mkdb/dev_mkdb.881
-rw-r--r--usr.sbin/dev_mkdb/dev_mkdb.c181
-rw-r--r--usr.sbin/diskpart/Makefile6
-rw-r--r--usr.sbin/diskpart/diskpart.8143
-rw-r--r--usr.sbin/diskpart/diskpart.c474
-rw-r--r--usr.sbin/edquota/Makefile6
-rw-r--r--usr.sbin/edquota/edquota.8150
-rw-r--r--usr.sbin/edquota/edquota.c722
-rw-r--r--usr.sbin/edquota/pathnames.h39
-rw-r--r--usr.sbin/eeprom/Makefile6
-rw-r--r--usr.sbin/eeprom/eeprom.869
-rw-r--r--usr.sbin/eeprom/eeprom.c204
-rw-r--r--usr.sbin/eeprom/pathnames.h45
-rw-r--r--usr.sbin/inetd/Makefile7
-rw-r--r--usr.sbin/inetd/inetd.8375
-rw-r--r--usr.sbin/inetd/inetd.c1255
-rw-r--r--usr.sbin/inetd/pathnames.h38
-rw-r--r--usr.sbin/iostat/Makefile11
-rw-r--r--usr.sbin/iostat/iostat.8142
-rw-r--r--usr.sbin/iostat/iostat.c391
-rw-r--r--usr.sbin/kgmon/Makefile14
-rw-r--r--usr.sbin/kgmon/kgmon.8122
-rw-r--r--usr.sbin/kgmon/kgmon.c520
-rw-r--r--usr.sbin/kvm_mkdb/Makefile7
-rw-r--r--usr.sbin/kvm_mkdb/extern.h38
-rw-r--r--usr.sbin/kvm_mkdb/kvm_mkdb.869
-rw-r--r--usr.sbin/kvm_mkdb/kvm_mkdb.c111
-rw-r--r--usr.sbin/kvm_mkdb/nlist.c186
-rw-r--r--usr.sbin/kvm_mkdb/testdb.c113
-rw-r--r--usr.sbin/lpr/Makefile6
-rw-r--r--usr.sbin/lpr/SMM.doc/0.t68
-rw-r--r--usr.sbin/lpr/SMM.doc/1.t77
-rw-r--r--usr.sbin/lpr/SMM.doc/2.t141
-rw-r--r--usr.sbin/lpr/SMM.doc/3.t73
-rw-r--r--usr.sbin/lpr/SMM.doc/4.t206
-rw-r--r--usr.sbin/lpr/SMM.doc/5.t116
-rw-r--r--usr.sbin/lpr/SMM.doc/6.t94
-rw-r--r--usr.sbin/lpr/SMM.doc/7.t226
-rw-r--r--usr.sbin/lpr/SMM.doc/Makefile10
-rw-r--r--usr.sbin/lpr/SMM.doc/spell.ok70
-rw-r--r--usr.sbin/lpr/common_source/common.c352
-rw-r--r--usr.sbin/lpr/common_source/displayq.c449
-rw-r--r--usr.sbin/lpr/common_source/lp.h126
-rw-r--r--usr.sbin/lpr/common_source/lp.local.h80
-rw-r--r--usr.sbin/lpr/common_source/pathnames.h50
-rw-r--r--usr.sbin/lpr/common_source/printcap.c458
-rw-r--r--usr.sbin/lpr/common_source/rmjob.c339
-rw-r--r--usr.sbin/lpr/common_source/startdaemon.c108
-rw-r--r--usr.sbin/lpr/filters/Makefile7
-rw-r--r--usr.sbin/lpr/filters/lpf.c217
-rw-r--r--usr.sbin/lpr/lpc/Makefile12
-rw-r--r--usr.sbin/lpr/lpc/cmds.c1107
-rw-r--r--usr.sbin/lpr/lpc/cmdtab.c79
-rw-r--r--usr.sbin/lpr/lpc/extern.h58
-rw-r--r--usr.sbin/lpr/lpc/lpc.8174
-rw-r--r--usr.sbin/lpr/lpc/lpc.c277
-rw-r--r--usr.sbin/lpr/lpc/lpc.h45
-rw-r--r--usr.sbin/lpr/lpd/Makefile11
-rw-r--r--usr.sbin/lpr/lpd/extern.h39
-rw-r--r--usr.sbin/lpr/lpd/lpd.8249
-rw-r--r--usr.sbin/lpr/lpd/lpd.c507
-rw-r--r--usr.sbin/lpr/lpd/lpdchar.c1066
-rw-r--r--usr.sbin/lpr/lpd/printjob.c1377
-rw-r--r--usr.sbin/lpr/lpd/recvjob.c358
-rw-r--r--usr.sbin/lpr/lpq/Makefile12
-rw-r--r--usr.sbin/lpr/lpq/lpq.1134
-rw-r--r--usr.sbin/lpr/lpq/lpq.c126
-rw-r--r--usr.sbin/lpr/lpr/Makefile12
-rw-r--r--usr.sbin/lpr/lpr/lpr.1256
-rw-r--r--usr.sbin/lpr/lpr/lpr.c744
-rw-r--r--usr.sbin/lpr/lprm/Makefile12
-rw-r--r--usr.sbin/lpr/lprm/lprm.1145
-rw-r--r--usr.sbin/lpr/lprm/lprm.c144
-rw-r--r--usr.sbin/lpr/lptest/Makefile6
-rw-r--r--usr.sbin/lpr/lptest/lptest.174
-rw-r--r--usr.sbin/lpr/lptest/lptest.c83
-rw-r--r--usr.sbin/lpr/pac/Makefile10
-rw-r--r--usr.sbin/lpr/pac/pac.8106
-rw-r--r--usr.sbin/lpr/pac/pac.c444
-rw-r--r--usr.sbin/mtree/Makefile8
-rw-r--r--usr.sbin/mtree/compare.c271
-rw-r--r--usr.sbin/mtree/create.c290
-rw-r--r--usr.sbin/mtree/extern.h44
-rw-r--r--usr.sbin/mtree/misc.c125
-rw-r--r--usr.sbin/mtree/mtree.8249
-rw-r--r--usr.sbin/mtree/mtree.c146
-rw-r--r--usr.sbin/mtree/mtree.h88
-rw-r--r--usr.sbin/mtree/spec.c280
-rw-r--r--usr.sbin/mtree/verify.c202
-rw-r--r--usr.sbin/pstat/Makefile10
-rw-r--r--usr.sbin/pstat/pstat.8321
-rw-r--r--usr.sbin/pstat/pstat.c1110
-rw-r--r--usr.sbin/pwd_mkdb/Makefile7
-rw-r--r--usr.sbin/pwd_mkdb/pw_scan.c122
-rw-r--r--usr.sbin/pwd_mkdb/pw_scan.h36
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.8128
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.c387
-rw-r--r--usr.sbin/quotaon/Makefile8
-rw-r--r--usr.sbin/quotaon/quotaon.8139
-rw-r--r--usr.sbin/quotaon/quotaon.c251
-rw-r--r--usr.sbin/repquota/Makefile6
-rw-r--r--usr.sbin/repquota/repquota.8103
-rw-r--r--usr.sbin/repquota/repquota.c379
-rw-r--r--usr.sbin/rmt/Makefile6
-rw-r--r--usr.sbin/rmt/rmt.8217
-rw-r--r--usr.sbin/rmt/rmt.c244
-rw-r--r--usr.sbin/rwhod/Makefile6
-rw-r--r--usr.sbin/rwhod/rwhod.8146
-rw-r--r--usr.sbin/rwhod/rwhod.c539
-rw-r--r--usr.sbin/sendmail/cf/cf/alpha.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/auspex.mc42
-rw-r--r--usr.sbin/sendmail/cf/cf/chez.mc44
-rw-r--r--usr.sbin/sendmail/cf/cf/cogsci.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-exposed.mc40
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-hidden.mc40
-rw-r--r--usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/osf1-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/osf1-cs-hidden.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/python.mc52
-rw-r--r--usr.sbin/sendmail/cf/cf/riscos-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/s2k.mc42
-rw-r--r--usr.sbin/sendmail/cf/cf/sample.mc40
-rw-r--r--usr.sbin/sendmail/cf/cf/sleepy.mc43
-rw-r--r--usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/udb.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc41
-rw-r--r--usr.sbin/sendmail/cf/cf/vangogh.mc44
-rw-r--r--usr.sbin/sendmail/cf/domain/Berkeley.m442
-rw-r--r--usr.sbin/sendmail/cf/domain/cs.exposed.m440
-rw-r--r--usr.sbin/sendmail/cf/domain/cs.hidden.m438
-rw-r--r--usr.sbin/sendmail/cf/domain/eecs.hidden.m438
-rw-r--r--usr.sbin/sendmail/cf/domain/s2k.m438
-rw-r--r--usr.sbin/sendmail/cf/ostype/hpux.m444
-rw-r--r--usr.sbin/sendmail/cf/ostype/irix.m441
-rw-r--r--usr.sbin/sendmail/cf/ostype/ultrix4.1.m438
-rw-r--r--usr.sbin/sendmail/contrib/rcpt-streaming305
-rw-r--r--usr.sbin/sendmail/doc/Makefile5
-rw-r--r--usr.sbin/sendmail/doc/op/spell.ok324
-rw-r--r--usr.sbin/sendmail/doc/rfc/rfc819.txt1044
-rw-r--r--usr.sbin/sendmail/doc/rfc/rfc821.txt4050
-rw-r--r--usr.sbin/sendmail/doc/rfc/rfc822.txt2901
-rw-r--r--usr.sbin/sendmail/makemap/Makefile.dist81
-rw-r--r--usr.sbin/sendmail/praliases/Makefile.dist81
-rw-r--r--usr.sbin/sendmail/src/Makefile.386BSD42
-rw-r--r--usr.sbin/sendmail/src/Makefile.AIX113
-rw-r--r--usr.sbin/sendmail/src/Makefile.AUX105
-rw-r--r--usr.sbin/sendmail/src/Makefile.BSD43123
-rw-r--r--usr.sbin/sendmail/src/Makefile.BSDI32
-rw-r--r--usr.sbin/sendmail/src/Makefile.CLIX115
-rw-r--r--usr.sbin/sendmail/src/Makefile.ConvexOS105
-rw-r--r--usr.sbin/sendmail/src/Makefile.DGUX101
-rw-r--r--usr.sbin/sendmail/src/Makefile.Dell113
-rw-r--r--usr.sbin/sendmail/src/Makefile.DomainOS123
-rw-r--r--usr.sbin/sendmail/src/Makefile.Dynix113
-rw-r--r--usr.sbin/sendmail/src/Makefile.FreeBSD50
-rw-r--r--usr.sbin/sendmail/src/Makefile.HP-UX105
-rw-r--r--usr.sbin/sendmail/src/Makefile.IRIX109
-rw-r--r--usr.sbin/sendmail/src/Makefile.Linux120
-rw-r--r--usr.sbin/sendmail/src/Makefile.Mach386107
-rw-r--r--usr.sbin/sendmail/src/Makefile.NCR3000109
-rw-r--r--usr.sbin/sendmail/src/Makefile.NeXT114
-rw-r--r--usr.sbin/sendmail/src/Makefile.NetBSD46
-rw-r--r--usr.sbin/sendmail/src/Makefile.OSF1109
-rw-r--r--usr.sbin/sendmail/src/Makefile.PTX114
-rw-r--r--usr.sbin/sendmail/src/Makefile.RISCos117
-rw-r--r--usr.sbin/sendmail/src/Makefile.SCO104
-rw-r--r--usr.sbin/sendmail/src/Makefile.SVR4113
-rw-r--r--usr.sbin/sendmail/src/Makefile.Solaris115
-rw-r--r--usr.sbin/sendmail/src/Makefile.SunOS111
-rw-r--r--usr.sbin/sendmail/src/Makefile.SunOS.4.0.3113
-rw-r--r--usr.sbin/sendmail/src/Makefile.SunOS.5.x115
-rw-r--r--usr.sbin/sendmail/src/Makefile.Titan114
-rw-r--r--usr.sbin/sendmail/src/Makefile.ULTRIX107
-rw-r--r--usr.sbin/sendmail/src/Makefile.UMAX114
-rw-r--r--usr.sbin/sendmail/src/Makefile.Utah40
-rw-r--r--usr.sbin/sendmail/src/Makefile.dist107
-rw-r--r--usr.sbin/sendmail/src/TODO287
-rw-r--r--usr.sbin/sliplogin/Makefile9
-rw-r--r--usr.sbin/sliplogin/pathnames.h46
-rw-r--r--usr.sbin/sliplogin/slip.hosts11
-rw-r--r--usr.sbin/sliplogin/slip.login12
-rw-r--r--usr.sbin/sliplogin/sliplogin.8220
-rw-r--r--usr.sbin/sliplogin/sliplogin.c381
-rw-r--r--usr.sbin/sysctl/Makefile6
-rw-r--r--usr.sbin/sysctl/pathconf.c229
-rw-r--r--usr.sbin/sysctl/sysctl.8208
-rw-r--r--usr.sbin/sysctl/sysctl.c572
-rw-r--r--usr.sbin/syslogd/Makefile9
-rw-r--r--usr.sbin/syslogd/pathnames.h40
-rw-r--r--usr.sbin/syslogd/syslog.conf.5224
-rw-r--r--usr.sbin/syslogd/syslogd.8122
-rw-r--r--usr.sbin/syslogd/syslogd.c1131
-rw-r--r--usr.sbin/timed/Makefile5
-rw-r--r--usr.sbin/timed/SMM.doc/timed/Makefile11
-rw-r--r--usr.sbin/timed/SMM.doc/timed/date53
-rw-r--r--usr.sbin/timed/SMM.doc/timed/loop54
-rw-r--r--usr.sbin/timed/SMM.doc/timed/spell.ok34
-rw-r--r--usr.sbin/timed/SMM.doc/timed/time53
-rw-r--r--usr.sbin/timed/SMM.doc/timed/timed.ms504
-rw-r--r--usr.sbin/timed/SMM.doc/timed/unused53
-rw-r--r--usr.sbin/timed/SMM.doc/timedop/Makefile7
-rw-r--r--usr.sbin/timed/SMM.doc/timedop/timed.ms279
-rw-r--r--usr.sbin/timed/timed/CHANGES144
-rw-r--r--usr.sbin/timed/timed/Makefile13
-rw-r--r--usr.sbin/timed/timed/acksend.c132
-rw-r--r--usr.sbin/timed/timed/byteorder.c86
-rw-r--r--usr.sbin/timed/timed/candidate.c167
-rw-r--r--usr.sbin/timed/timed/cksum.c87
-rw-r--r--usr.sbin/timed/timed/correct.c294
-rw-r--r--usr.sbin/timed/timed/extern.h89
-rw-r--r--usr.sbin/timed/timed/globals.h186
-rw-r--r--usr.sbin/timed/timed/master.c907
-rw-r--r--usr.sbin/timed/timed/measure.c353
-rw-r--r--usr.sbin/timed/timed/networkdelta.c264
-rw-r--r--usr.sbin/timed/timed/pathnames.h44
-rw-r--r--usr.sbin/timed/timed/readmsg.c488
-rw-r--r--usr.sbin/timed/timed/slave.c715
-rw-r--r--usr.sbin/timed/timed/timed.8219
-rw-r--r--usr.sbin/timed/timed/timed.c980
-rw-r--r--usr.sbin/timed/timedc/Makefile11
-rw-r--r--usr.sbin/timed/timedc/cmds.c526
-rw-r--r--usr.sbin/timed/timedc/cmdtab.c57
-rw-r--r--usr.sbin/timed/timedc/extern.h52
-rw-r--r--usr.sbin/timed/timedc/timedc.8145
-rw-r--r--usr.sbin/timed/timedc/timedc.c261
-rw-r--r--usr.sbin/timed/timedc/timedc.h66
-rw-r--r--usr.sbin/traceroute/Makefile8
-rw-r--r--usr.sbin/traceroute/README126
-rw-r--r--usr.sbin/traceroute/mean.awk50
-rw-r--r--usr.sbin/traceroute/median.awk67
-rw-r--r--usr.sbin/traceroute/traceroute.8336
-rw-r--r--usr.sbin/traceroute/traceroute.c835
-rw-r--r--usr.sbin/trpt/Makefile8
-rw-r--r--usr.sbin/trpt/trpt.8151
-rw-r--r--usr.sbin/trpt/trpt.c414
-rw-r--r--usr.sbin/trsp/Makefile9
-rw-r--r--usr.sbin/trsp/trsp.8141
-rw-r--r--usr.sbin/trsp/trsp.c433
-rw-r--r--usr.sbin/update/Makefile6
-rw-r--r--usr.sbin/update/update.874
-rw-r--r--usr.sbin/update/update.c75
-rw-r--r--usr.sbin/vipw/Makefile7
-rw-r--r--usr.sbin/vipw/pw_util.c204
-rw-r--r--usr.sbin/vipw/pw_util.h42
-rw-r--r--usr.sbin/vipw/vipw.893
-rw-r--r--usr.sbin/vipw/vipw.c127
504 files changed, 112536 insertions, 0 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
new file mode 100644
index 0000000..8467608
--- /dev/null
+++ b/usr.sbin/Makefile
@@ -0,0 +1,26 @@
+# @(#)Makefile 5.20 (Berkeley) 6/12/93
+
+SUBDIR= ac accton amd arp chown chroot cron dev_mkdb diskpart edquota \
+ inetd kgmon kvm_mkdb lpr mkproto mtree portmap pstat pwd_mkdb \
+ quot quotaon repquota rmt rwhod sa sendmail sliplogin sysctl \
+ syslogd traceroute trpt trsp update vipw
+
+.if make(clean) || make(cleandir)
+SUBDIR+=bad144 config config.new eeprom iostat timed
+.elif ${MACHINE} == "hp300"
+SUBDIR+=config iostat timed
+.elif ${MACHINE} == "i386"
+SUBDIR+=bad144 config iostat
+.elif ${MACHINE} == "luna68k"
+SUBDIR+=config iostat timed
+.elif ${MACHINE} == "mips"
+SUBDIR+=config iostat timed
+.elif ${MACHINE} == "sparc"
+SUBDIR+=config.new eeprom timed
+.elif ${MACHINE} == "tahoe"
+SUBDIR+=config iostat timed
+.elif ${MACHINE} == "vax"
+SUBDIR+=bad144 config iostat timed
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/Makefile.inc b/usr.sbin/Makefile.inc
new file mode 100644
index 0000000..fd92864
--- /dev/null
+++ b/usr.sbin/Makefile.inc
@@ -0,0 +1,3 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/6/93
+
+BINDIR?= /usr/sbin
diff --git a/usr.sbin/ac/ac.8 b/usr.sbin/ac/ac.8
new file mode 100644
index 0000000..0c834a7
--- /dev/null
+++ b/usr.sbin/ac/ac.8
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ac.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt AC 8
+.Os BSD 4
+.Sh NAME
+.Nm ac
+.Nd display connect time accounting
+.Sh SYNOPSIS
+.Nm ac
+.Op Fl d
+.Op Fl p
+.Op Fl w Ar file
+.Op Ar users ...
+.Sh DESCRIPTION
+If the file
+.Pa /var/log/wtmp
+exists,
+a record of individual
+login and logout times are written to it by
+.Xr init 8
+and
+.Xr login 8
+respectively.
+The program
+.Nm ac
+examines these
+records and writes the accumulated connect time for all logins to the
+standard output.
+.Pp
+Options available:
+.Bl -tag -width people
+.It Fl d
+Display the connect times in 24 hour chunks.
+.It Fl p
+Display individual user totals.
+.It Fl w Ar file
+Read raw connect time data from
+.Ar file
+instead of the default file
+.Pa /var/log/wtmp .
+.It Ar users ...
+Display totals for the given individuals
+only.
+.El
+.Pp
+If no arguments are given,
+.Nm
+displays the total amount of login time for all active accounts on the
+system.
+.Pp
+The default
+.Pa wtmp
+file is an infinitely increasing file
+unless frequently truncated. This is normally
+done by the daily daemon scripts scheduled by
+.Xr cron 8
+which rename and rotate the
+.Pa wtmp
+files before truncating them (and keeping about a weeks worth on hand).
+No login times are collected however, if the file does not exist.
+.Sh FILES
+.Bl -tag -width /var/log/wtmp.[0-7] -compact
+.It Pa /var/log/wtmp
+.It Pa /var/log/wtmp.[0-7]
+rotated files
+.El
+.Sh SEE ALSO
+.Xr init 8 ,
+.Xr sa 8 ,
+.Xr login 1 ,
+.Xr utmp 5 .
+.Sh HISTORY
+A
+.Nm
+command appeared in Version 6 AT&T UNIX.
diff --git a/usr.sbin/accton/Makefile b/usr.sbin/accton/Makefile
new file mode 100644
index 0000000..15152a6
--- /dev/null
+++ b/usr.sbin/accton/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= accton
+NOMAN= noman
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/accton/accton.c b/usr.sbin/accton/accton.c
new file mode 100644
index 0000000..c65ef68
--- /dev/null
+++ b/usr.sbin/accton/accton.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)accton.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch(argc) {
+ case 0:
+ if (acct(NULL)) {
+ (void)fprintf(stderr,
+ "accton: %s\n", strerror(errno));
+ exit(1);
+ }
+ break;
+ case 1:
+ if (acct(*argv)) {
+ (void)fprintf(stderr,
+ "accton: %s: %s\n", *argv, strerror(errno));
+ exit(1);
+ }
+ break;
+ default:
+ usage();
+ }
+ exit(0);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: accton [file]\n");
+ exit(1);
+}
diff --git a/usr.sbin/amd/Makefile b/usr.sbin/amd/Makefile
new file mode 100644
index 0000000..96405b8
--- /dev/null
+++ b/usr.sbin/amd/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+SUBDIR= amd amq fsinfo mk-amd-map
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/amd/amd/ChangeLog b/usr.sbin/amd/amd/ChangeLog
new file mode 100644
index 0000000..2cd1807
--- /dev/null
+++ b/usr.sbin/amd/amd/ChangeLog
@@ -0,0 +1,1169 @@
+Sun Jun 7 19:01:37 1992 Jan-Simon Pendry (jsp at achilles)
+
+ * Code cut for BSD 4.4 alpha.
+
+Sun May 31 17:28:52 1992 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) make sure error code is returned to user if there
+ is an immediate error in afs_lookuppn.
+
+ * (nfs_ops.c) clear out mountd port number after use.
+
+ * (nfs_ops.c) optionally (KICK_KERNEL) run lstat over the old
+ mount point. This should go somewhere else more appropriate.
+
+Sun Mar 29 16:22:01 1992 Jan-Simon Pendry (jsp at achilles)
+
+ * (mount_fs.c) FASCIST_DF_COMMAND is now defined as the fstype
+ you want df to see.
+
+ * (opts.c) fix buffer overrun in slash munging.
+
+ * (host_ops.c) add support for INFORM_MOUNTD.
+
+Sat Mar 7 10:23:04 1992 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfsx_ops.c) fix buffer overrun problem by allocating sufficient
+ memory.
+
+ * (afs_ops.c) fix dereference of free'ed memory when calling
+ assign_error_mntfs.
+
+ * (xutil.c) fix xmalloc and xrealloc to allow zero sized
+ allocation.
+
+ * (os-type) make it recognise aix3.2
+
+Sun Feb 9 13:14:54 1992 Jan-Simon Pendry (jsp at achilles)
+
+ * Release 5.3 Beta
+
+ * hpux 8 support is still missing.
+
+ * (os-bsd44.h) merged in changes for new bsd nfs code. still need
+ to add in lease and kerberos support.
+
+Sun Dec 1 16:20:21 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * (info_nis.c) changed so that it remembers if the NIS domainname
+ is set and doesn't repeatedly complain. Message changed from an
+ Error to a Warning.
+
+ * (sfs_ops.c) added linkx fstype. linkx is the same as link but
+ it also checks that the target exists. This makes it useful for
+ wildcard map entries.
+
+ * (wire.c) applied changes from Dirk Grunwald. Now stands a
+ better chance of correctly determining the network name.
+
+ * (map.c) changes in timeout_mp to cause second and subsequent
+ backgrounded unmount attempts to backoff and so reduce the chance
+ of running more than one backgrounded unmount at a time.
+
+ * (misc_rpc.c) bug fix from Martyn Johnson to avoid xdr_free'ing
+ the wrong piece of memory. This was causing random core dumps,
+ often with a stack trace through pickup_rpc_reply.
+
+Sun Sep 15 21:16:38 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * Release 5.3 alpha 14.
+
+ * (os-osf1.h) merged in OSF/1 support.
+
+Sun Aug 4 18:25:04 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * (os-stellix.h) merged in Stellix support.
+
+ * (os-u4_2.h) merged in Ultrix 4.2 support.
+
+ * (host_ops.c) made TCP the default transport protocol. Define
+ HOST_RPC_UDP somewhere to get UDP transport.
+
+ * (many) added support for ${remopts}. Suggested by Steve
+ Heimlich. remopts is the same as opts, but is used when the
+ remote server is not on the local network. If it is not set it
+ defaults to whatever value ${opts} has.
+
+Tue May 7 22:30:00 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * Checkpoint for Berkeley network tape II.
+
+Sat May 4 22:06:24 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * New Berkeley Copyright.
+
+ * (mntfs.c) more short-circuiting in realloc_mntfs().
+
+ * (host_ops.c) increase RPC timeout to 20 seconds.
+
+ * (info_hes.c) now supports lookup in other domains.
+
+ * (srvr_nfs.c) call map_flush_srvr whenever a server comes up.
+
+ * (map.c) added hook to flush hung file servers.
+
+ * (wire.c) make loop step more portable.
+
+ * (util.c) fix for compiling on rios.
+
+Sun Apr 21 21:54:52 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (util.c) ignore EINVAL returned by rmdir().
+
+ * (am_ops.c, afs_ops.c) remove SunOS4 map compat code.
+
+ * (nfsx_ops.c) don't clear MFF_MOUNTING until finished mount attempts.
+
+ * (nfsx_ops.c) don't call sched_task more than once.
+
+ * (afs_ops.c) don't call afs_bgmount if a mount is in progress.
+
+ * (info_file.c) handle case where map ends with \
+
+Fri Apr 5 19:23:50 1991 Jan-Simon Pendry (jsp at forest)
+
+ * Release 5.3 Alpha 12.
+
+ * (util.c) don't clear MFF_MOUNTING flag if mount is still in progress.
+
+ * (srvr_nfs.c) calls make_nfs_auth() as required.
+
+ * (host_ops.c) calls make_nfs_auth() as required.
+
+ * (afs_ops.c) allow foreground mounts to return pending. This is
+ used by nfsx_ops.c.
+
+ * (mapc.c) uses new RE_HDR abstraction coping with systems which
+ already have the re package installed.
+
+ * (nfsx_ops.c) automatically generates a suitable sublink to make
+ things work. Remounts now work correctly, but are done in the
+ foreground so there is a possibility that things may hang. This is
+ too hard to do differently.
+
+Wed Apr 3 17:49:05 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_ops.c) HAS_NFS_QUALIFIED_NAME is a new compile time switch
+ which puts a qualified domain name into the RPC authentication
+ instead of using the default value. Abstracted this out into new
+ routine called make_nfs_auth().
+
+ * (afs_ops.c) fixed bug which caused spurious ENOENTs to appear.
+ this was caused by some code motion which also got slightly
+ altered int the process. moral: don't make two changes at once.
+
+Sun Mar 17 12:05:27 1991 Jan-Simon Pendry (jsp at forest)
+
+ * Release 5.3 Alpha 11.
+
+ * (amq.8) Updated.
+
+ * (amq.c) Added new -v option which displays the version number of
+ the target Amd. Also added support to Amd and reworked newvers
+ script. Got rid of rcs_info.c.
+
+ * (mk-amd-map.c) Changed name of remove function to avoid clash
+ with ANSI C.
+
+ * (wire.c) Fixed to work with new 4.4BSD sockaddr's.
+
+ * Changed const to Const everywhere and added new define in config.h.
+
+ * (mk-amd-map.c) New -p option which just writes the output to
+ stdout. Useful for making NIS or Hesiod maps.
+
+ * (amdref) Small updates and clarifications.
+
+Sat Mar 16 20:35:17 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (amq_subr.c) Flush request now flushes all internal caches.
+
+ * (amq_subr.c) Changed xdr_amq_mount_tree to return only the
+ required sub-tree.
+
+ * (ifs_ops.c) Added missing return 0; to ifs_mount.
+
+Sat Mar 9 19:31:25 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (get_args.c) Output the primary network interface information
+ with the -v option.
+
+ * (mapc.c) Fixed spurious warning about "root" map not supporting
+ cache mode "all". Added new (unnamed) cache mode MAPC_ROOT.
+
+ * (info_nis.c) Fixed order number testing which was the cause of a
+ loop.
+
+Sun Mar 3 17:57:03 1991 Jan-Simon Pendry (jsp at forest)
+
+ * Release 5.3 Alpha 10.
+
+ * Introduced new inet_dquad routine which prints IP addresses in
+ dotted quad format. The C library routine is not used because it
+ uses a static buffer and it takes a structure argument on some
+ machines and unsigned longs on others. This confuses the hell out
+ of some compilers and causes SEGVs.
+
+ * task_notify becomes do_task_notify to avoid clash with Mach.
+
+ * (mntfs.c) In realloc_mntfs, the private data field wasn't being
+ cleared out when the mntfs object was being re-used. This meant
+ that the data might be used for the wrong mount, so causing
+ various obscure errors.
+
+ * (info_file.c) Reworked to provide support for map cache "sync"
+ option.
+
+ * (mapc.c) Added new "sync" option to map cache. This ensures
+ that the cached data doesn't become stale wrt the source.
+ Currently this isn't implemented for passwd and hesiod maps.
+
+Wed Feb 27 11:38:07 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (afs_ops.c) Fixed pid put in fs_hostname for toplvl mount.
+
+Sun Feb 24 19:37:55 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (wire.c) New module which determines the name of the primary
+ attached network. This could be used to determine which
+ server to use.
+
+ * (srvr_nfs.c) Changed mount daemon port mapping caching. This is
+ now much more eager to recompute the mapping than before. Will
+ also now work even if pinging is switched off (for example "tcp").
+
+ * (info_nis.c) Added back old NIS reload code to allow NIS maps to
+ support "regexp" caching.
+
+ * (mapc.c) Added support for "regexp" caching. This is a type of
+ map cache where the entries are all REs to be matched against the
+ requested key. This implies "all" since all the keys must be
+ loaded for the search to work.
+
+Sat Feb 23 15:32:43 1991 Jan-Simon Pendry (jsp at forest)
+
+ * (afs_ops.c) Avoid spurious error messages about discarding a
+ retry mntfs.
+
+ * (amq_subr.c) Removed inet_ntoa call due to disagreement between
+ gcc and libc about 4 byte structure passing.
+
+ * (xutil.c) Changed way initial logging is done to make command
+ line more usable. Default logging flags are set statically and
+ can then be modified by -x options. At the end an additional call
+ to switch_option is made to initialise xlog_level_init.
+
+ * (umount_fs.c) ENOENT now treated the same as EINVAL. If the
+ filesystem gets removed and the mountpoint deleted then just
+ assume the filesystem isn't there - which it isn't.
+
+ * (host_ops.c) Now copes with unmount failures by attempting to
+ remount the filesystems which had been unmounted.
+
+ * (host_ops.c) Added check during fhandle collection to detect
+ duplicate entries in the export list (from Stefan Petri).
+
+ * (nfsx_ops.c) Reworked to correctly keep track of what is and
+ isn't mounted.
+
+Sun Jan 27 16:58:02 1991 Jan-Simon Pendry (jsp at achilles)
+
+ * (misc-next.h) Added missing NeXT config file.
+
+ * Merged Harris HCX/UX support from Chris Metcalf.
+
+ * (ifs_ops.c) added ifs_fmount entry point to keep nfsx_ops happy.
+
+Sun Jan 13 18:19:19 1991 Jan-Simon Pendry (jsp at beauty)
+
+ * (nfsx_ops.c) play with opt_fs field to make sure it is unique.
+
+Fri Dec 21 15:35:45 1990 Jan-Simon Pendry (jsp at forest)
+
+ * Release 5.3 Alpha 9. This is still not Beta!
+
+ * (host_ops.c) use normalized hostname in mtab entries, from
+ Chris Metcalf.
+
+ * (map.c) enum ftype -> ftype, from Andrew Findlay.
+
+Mon Dec 17 01:11:25 1990 Jan-Simon Pendry (jsp at beauty)
+
+ * (amdref.texinfo) merged in fsinfo documentation from Nick.
+
+Sat Dec 15 15:39:07 1990 Jan-Simon Pendry (jsp at beauty)
+
+ * (clock.c) minor tweaks to messages.
+
+ * (sfs_ops.c) make the opt_fs field unique, rather than always
+ ".", but make sure it still begins with a "." to avoid a clash
+ with any other existing mounts.
+
+ * (amd.c) changed way local IP address is obtained to avoid using
+ a call to the name server. It was observed that if the power to
+ the building goes and everything reboots simultaneously then there
+ would be a good chance that the nameserver would not recover
+ before Amd on another machine required it. This happened :-) Now
+ use the RPC get_myaddress call.
+
+ * (info_hes.c) added hesiod_reload code from Bruce Cole.
+ Optionally compiled when HAS_HESIOD_RELOAD is defined.
+
+ * (amq_subr.c) fix "security" check.
+
+ * (amq.c) make sure a privileged port is allocated. In fact
+ RPC3.9 and newer make this guarentee but older versions don't so
+ we do it here.
+
+Sun Dec 2 21:30:07 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) fixed problem with pointer pre-increment.
+
+Mon Nov 19 00:31:28 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_ops.c) saved filehandle with mntfs structure. this allows
+ nfsx unmounts to be undone even if the filehandle cache has lost
+ the entry. all of this is bogus and deserves a rewrite...
+
+Sun Nov 18 22:55:43 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfsx_ops.c) now handles mounts of root filesystem correctly.
+
+ * (afs_ops.c) fixed dfs_ops definition to call toplvl_mounted when
+ done, so making sure that a map cache reference is set up.
+
+Sun Nov 11 21:09:34 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (fsinfo/wr_fstab.c) has per-ostype fstab rules.
+
+ * (fsinfo/fsi_lex.l) now works correctly with flex.
+
+Mon Nov 5 00:08:30 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * Release 5.3 Alpha 8. No more new features from now to 5.3Rel.
+ Call next one Beta.
+
+ * (amdref.texinfo) more updates.
+
+ * (info_union.c) reload routine now adds a wildcard pointing to
+ the last named directory so that new files get created correctly.
+
+Sun Nov 4 22:02:50 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (os-u4_0.h) Ultrix 4.0 support merged.
+
+ * (os-utek.h) Utek 4.0 support merged.
+
+ * (amdref.texinfo) fixed & updated.
+
+ * (nfsx_ops.c) reworked string munging to prevent ..//.. strings
+ from occuring.
+
+ * (util.c) am_mounted now correctly updates the am_node for
+ duplicate mounts.
+
+ * (afs_ops.c) added union fstype. derived from "toplvl" except it
+ causes all the filesystems to be mounted. cannot be used for
+ filesystem types whose mounts may be defered (eg nfs) since it
+ doesn't retry the mounts.
+
+ * (info_union.c) map type for union fstype support. currently
+ can't handle being given automounted filesystems - causes a
+ deadlock.
+
+Sun Oct 21 22:56:16 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (fsinfo/*) finally integrated the fsinfo package. currently no
+ documentation or man page. this is a pre-req to getting mmd up.
+
+Sun Oct 14 20:02:11 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (amdref.texinfo) reworking of documentation continues.
+
+ * (clock.c) reschedule_timeouts() now called in the event that the
+ system clock goes backwards. this is possible during the average
+ bootstrap juggling act with timed/xntpd etc. especially useful if
+ your machines TOY clock gets way ahead of time.
+
+Sat Oct 6 19:57:55 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (map.c) when expanding the filehandle for a server which is
+ down, don't update the ttl on the original node unless a new node
+ gets allocated. this should give the original mount a chance to
+ go away as soon as the server comes back.
+
+ * (arch, os-type) Updated.
+
+ * (nfs_ops.c) Added "noconn", "spongy" and "compress" mount
+ options for 4.4 BSD.
+
+Sun Sep 30 18:37:54 1990 Jan-Simon Pendry (jsp at beauty)
+
+ * Release 5.3 Alpha 6.
+
+ * (util.c) domain_strip now doesn't leave partial domains behind.
+ if it can't strip the complete domain it leaves the string untouched.
+
+ * (restart.c) remember to initialise opt_opts field from mtab.
+
+ * (nfs_ops.c) supports "nocto" option for SunOS4.1.
+
+ * (os-irix.h) new SGI Iris port.
+
+ * (os-next.h) new NeXT port.
+
+ * (os-dgux.h) new DG/UX port.
+
+ * (many) fixed problem where mf_opts was being used for two
+ different purposes. Now have two fields.
+
+ * (mapc.c) error map prints error message whenever used.
+
+ * (mapc.c) wildcard code rewritten.
+
+ * (util.c) slpit into two parts - some code now in xutil.c. This
+ is used by mmd (not yet shipped).
+
+Sun Aug 19 19:58:16 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (srvr_nfs.c) reduce verbosity of "nfs server yoyo is ok" messages.
+
+ * (opts.c) fix deslashification in expand.
+
+ * (nfs_start.c) amq registering done just before the server kicks
+ in. running amd with nothing to do leaves the portmapper in peace.
+
+ * (mapc.c) bootstrap code abstracted to allow AMQ_MOUNT entry point.
+
+ * (nfsx_ops.c) new filesystem type, supporting groups of nfs
+ mounts. needs abstracting to allow groups of (*) mounts.
+
+ * (am.h, *_ops.c) am_ops structure changed; corresponding changes
+ in the filesystem implemention source. Change was to allow nfsx
+ filesystem implementation.
+
+ * (amd.c) hostname defaults to "localhost" startup code re-ordered
+ so that logging still works in case things go wrong early.
+
+ * (am_ops.c) new routine to print list of available fs types; used
+ by the -v option.
+
+ * (info_file.c) bug fix to make reloads work correctly.
+
+ * (mtab_file.c) does locking on single write, to avoid trashing
+ mount table when a mount and unmount are done at the same time.
+
+ * (mount_fs.c) automount hack removed since afs_ops no longer
+ needs it.
+
+ * (afs_ops.c) split "auto" into several other filesystem types.
+ Now much cleaner.
+
+ * (amq.c) new -M option.
+
+ * (amq_subr.c) support for AMQ_MOUNT added.
+
+ * (amq.x) new AMQ_MOUNT RPC call allows mount map entries to be
+ passed in at run-time. Automount points can now be added
+ dynamically, but not yet deleted.
+
+Sat Jun 23 22:12:48 1990 Jan-Simon Pendry (jsp at beauty)
+
+ * Release 5.2 for Berkeley.
+
+ * (*) Re-organised source code layout. Now much more complicated.
+
+ * (map.c) code which flushed the kernel name cache is not really
+ needed now that the modify times on the automount directories are
+ correctly updated so ifdef the whole lot. Remove later...
+
+ * (map.c) make sure that the automount directories modify times
+ are updated when a change occurs so that the nfs client code can
+ decide when to update its name cache.
+
+ * (srvr_nfs.c) fixed bug which caused mounted filesystems to
+ appear down when they were up.
+
+ * YP becomes NIS.
+
+Mon May 28 19:50:34 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (amd.tex) substantially updated with more explanation of the
+ theory and more examples.
+
+ * (nfs_stubs.c) statfs now claims to have a single used block.
+ Avoids ambiguity between 100% and 0% full.
+
+ * (nfs_stubs.c) changed to allow the size of symlinks optionally
+ to be accurate wrt the length of the string returned. Optional
+ because it is cheaper to ignore the length when doing a getattr
+ and just send any length for the readlink. However, this breaks
+ on some systems (e.g. Ultrix).
+
+ * (mount_fs.c) automount points get marked type "nfs" instead of
+ "ignore". This is to fix an interaction with getwd(). Can go
+ away when getwd() gets re-written. Really only applies to SunOS4
+ but change applies to everything to keep consistent across platforms.
+
+ * (mount_fs.c) abstracted out mount options into a table and
+ corresponding loop.
+
+ * (srvr_nfs.c) make sure portmap information is available when
+ needed, not just after a ping has succeeded. This needed changing
+ after the ping algorithm got changed.
+
+ * (mntfs.c) fixed incorrect reference to mf_error instead of mf_flags.
+
+ * (nfs_start.c) keep track of number of fds in use, so don't run
+ select on system maximum (which is bad news if you have a large
+ system maximum).
+
+ * (host_ops.c) new NFS tree mount filesystem type (ala Sun -hosts).
+
+ * (nfs_ops.c) abstracted out NFS mount code to support host_ops.
+
+ * (afs_ops.c) dfs_readlink now returns the am_node, instead of the
+ link. This allows getattr to return the correct set of attributes
+ so keeping Ultrix happy.
+
+ * (afs_ops.c) Make certain the hostname field given to mount()
+ does not get too long - otherwise random EINVAL errors occur.
+
+ * Putting closing comments on all #endif's
+
+Sun May 13 16:07:21 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (srvr_nfs.c) second rewrite of NFS ping algorithm.
+
+Sun Apr 29 21:12:33 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_stubs.c) re-arranged readlink code to avoid need to
+ pre-mount a direct filesystem whenever possible.
+
+ * (host_ops.c) finally incorporated new module to support /net
+ mount point.
+
+Sat Mar 24 13:18:47 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_stubs.c) workaround added to rename entry point to avoid
+ arguments with NFS client code.
+
+ * (srvr_nfs.c) changed the way NFS pings are done and cleaned up
+ the process for deciding when a server is up or down. Now there
+ is just a simple time limit on a reply from the server. The limit
+ is adjusted depending on whether the state of the server is known.
+
+ * (opts.c) fixed bug with ${var/} expansion et al. Added ${varN}
+ N = 0..7 for use as scratch variables.
+
+ * (mntfs.c) fixed bug in dup_mntfs().
+
+Thu Jan 11 16:56:41 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * Release 5.1c.
+
+ * (amq*) has new options. -f flushes the map cache and -m prints
+ information about mounted filesystem and fileservers.
+
+Tue Jan 2 14:44:21 1990 Jan-Simon Pendry (jsp at achilles)
+
+ * (util.c) am_mounted() patches the path for "direct" mounted
+ filesystems - cosmetic.
+
+ * (afs_ops.c) when possible sets a small kernel attribute cache
+ timeout on the automount points.
+
+ * (nfs_stubs.c) delete() and rmdir() operations implemented. Used
+ when a mount point is timed out so the kernel name cache gets to
+ know about the changes. Fixes most ESTALE errors.
+
+ * (nfs_stubs.c) New do_readlink() function added. This is used to
+ make sure that a filesystem is mounted at the time a link is read
+ in the case of "direct" mounts. Done so that the length of the
+ link is available when the initial getattr is done on the mountpoint.
+
+ * (sfs_ops.c) Changed implementation to avoid race conditions.
+ The link target is re-arranged so that sublink points to the
+ target and fs always points at ".".
+
+ * Fixed mount flag bug on Ultrix.
+
+ * Added support from Sjoerd Mullender for Alliant FX/4 and Encore
+ Multimax.
+
+Thu Dec 7 17:55:29 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) dfs_readlink now does a new_ttl on the node it
+ returns.
+
+ * (afs_ops.c) next_nonerror_node now implements the task after
+ which it is named.
+
+Tue Nov 28 17:20:52 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Release 5.1b.
+
+ * (restart.c) Generates link nodes for any unrecognised filesystem
+ types and then marks them so that they are never deleted (since
+ they could never be automounted later).
+
+ * (os-*.h) Irrelevant #undef's deleted.
+
+ * (arch) Now knows about AIX on RTs.
+
+ * (amq.c) Rationalised the output. Now only gives you what you
+ asked for.
+
+ * (am.h) New macro: FSRV_ISDOWN(fs), which checks whether a
+ fileserver is down.
+
+ * (afs_ops.c) When a mount fails due to a timeout the underlying
+ filesystem is ripped away and replaced with an error fs. This
+ avoids the possibility of being left with a single error reference
+ to a valid mounted filesystem.
+
+Thu Nov 23 18:04:29 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_start.c) Re-order bootstrap sequence to avoid potential
+ deadlock if restart() ends up accessing one of the automount points.
+
+ * (amq.c) Don't produce default mount output if one of the -l, -x
+ or -D options was used.
+
+ * (umount_fs.c) Add alternative unmount routine for 4.4 BSD.
+
+Mon Nov 20 16:22:50 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (os-bsd44.h) Fixed redefinition of UMOUNT_FS.
+
+ * (info_ndbm.c) Added missing #include <sys/stat.h>.
+
+ * (mapc.c) Fixed typo in ifdef around gdbm config entry.
+
+Sat Nov 18 16:39:13 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (util.c) If "/" is automounted, make sure it is never timed out.
+
+ * (mtab.c) Missing clock invalidation added in read_mtab (from a file).
+
+ * (mntfs.c) realloc_mntfs simplified.
+
+ * (map.c) Closed a race condition during shutdown when second and
+ subsequent duplicate mounts were deleted prematurely.
+
+ * (afs_ops.c) Duplicate mounts are now given the correct return
+ code.
+
+Fri Nov 17 18:58:18 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.1 Release.
+
+Thu Nov 16 17:57:02 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (mntfs.c) Make sure inherit mntfs structures are not cached
+ after last reference; otherwise a second reference to the
+ inherited filesystem will get stuck on the inherit rather than the
+ (now) fully mounted filesystem.
+
+ * (am.c, nfs_start.c) After forking the server, make sure the
+ parent does not exit until the automount points are mounted. This
+ allows a clean sequence during system startup.
+
+ * Initial port to 4.4 BSD. Several new configuration abstractions
+ were added to make this port possible.
+
+Thu Nov 9 21:42:14 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c, opts.c) Added map logging to facilitate mount map
+ debugging without needing a -DDEBUG version of Amd.
+
+ * (afs_ops.c) Make sure the length of the fs_hostname mount
+ parameter does not exceed MAXHOSTNAMESZ.
+
+Wed Nov 8 13:44:02 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Change the message log format to indicate the severity of the
+ message to allow simpler analysis of the log file.
+
+Tue Nov 7 14:11:36 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 11.
+
+ * (os-bsd44.h) Initial guess at 4.4 BSD definitions.
+
+ * (os-aux.h) Port for Macintosh II from Julian Onions.
+
+ * (amq.c) Output formats cleaned up. AMQ_MNTTREE is still broken
+ in amq_subr.c though.
+
+ * (afs_ops.c) If a mount timed out, for example an NFS server was
+ down at the time, it was possible for the error code to remain
+ unset thus jamming that mount node in a state from which it could
+ not recover. Just make sure that the mf_error field gets filled
+ in when an error occurs.
+
+ * (afs_ops.c) strsplit is run over /defaults to avoid problems
+ with whitespace creeping in.
+
+Sun Nov 5 11:50:51 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (util.c) am_mounted: Added missing initialisation of stats.s_mtime.
+
+Fri Nov 3 17:33:02 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 10.
+
+ * Changed the copyright.
+
+Thu Nov 2 17:07:53 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 9.
+
+ * (opts.c) new option syntax: == != :=
+
+ * (nfs_ops.c) Less caching of filehandles. Now cached errors are
+ discarded after use.
+
+ * (mtab.c) now attempts to deal with a lack of open file slots (ENFILE).
+
+ * (mount_fs.c) automount entries in the mount table now have a
+ dev= entry in the same way as NFS and UFS.
+
+ * (mntfs.c) mntfs nodes are now cached after the last reference
+ and discarded <ALLOWED_MOUNT_TIME> seconds later. This avoids
+ thrashing during a mount.
+
+ * (mapc.c) map default cache mode is now selected with
+ "mapdefault", not "default"
+
+ * (amd.tex) numerous clarifications. Still more work required...
+
+ * (amq_subr.c) now allows the -x option of amq to operate.
+
+ * (afs_ops.c) afs_bgmount now keeps track of which filesystem
+ needed retrying and ensures that the mount node in the
+ continuation correctly points at an unmounted filesystem. This
+ fixes a problem whereby a valid mounted filesystem could appear to
+ have failed to mount.
+
+ * Configure now gives more of a running commentary and checks
+ whether os-type and arch actually worked.
+
+ * Allow spurious ';'s in a mount location.
+
+Fri Oct 27 14:03:31 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * foo=blah changed to foo:=blah, foo==blah and foo!=blah.
+
+ * -l stderr changed to -l /dev/stderr.
+
+Thu Oct 19 15:34:28 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 6.
+
+ * LOG_INFO messages have been rationalised so that some
+ statistics, graphs and so on can be generated.
+
+ * Transaction ID's for RPC calls are now allocated by the
+ individual callers, rather than from a central pool. This
+ decreases the load on mount daemons and NFS servers since the
+ same XID is used for retries when needed.
+
+ * Many fine details of the new data structures have been changed.
+ Some areas have been optimized.
+
+Fri Oct 13 12:31:26 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Restart code re-implemented to work with the new data structures.
+
+ * Fine tuning applied to new NFS server modeling code.
+
+Thu Oct 12 15:57:24 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Added ${/var} and ${var/} variable expansions. The first gives
+ the "basename" component of the variable, the latter gives the
+ "dirname" component. Additionally, spurious /'s are deleted after
+ the variable expansions is complete.
+
+ * Added new -C option to allow the machine's cluster name to be
+ given to amd. ${cluster} fetches the value and can be used as
+ another selector.
+
+ * Broken the major data struct (am_node) into three layers:
+ am_node (one for each automount node), mntfs (one for each mounted
+ filesystem) and fserver (one for each file server). Machine
+ up/down state is maintained in the fserver layer. Filesystem
+ mount/unmount state is maintained in the mntfs layer. This change
+ fixes the last known major problem caused by the lack of a central
+ focus for filesystem and fileserver status. There is a dummy file
+ server layer for local filesystems (ufs, link, program, error).
+
+Tue Oct 10 11:15:42 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 5.
+
+ * (nfs_ops.c) the filehandle cache is now flushed when a
+ filesystem is unmounted. This avoids ending up with stale
+ information if a server bounces.
+
+ * (clock.c) new module to implement callouts. Many other
+ routines changed to use callouts instead of messing with ttl
+ fields.
+
+Sun Oct 1 17:08:20 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 3 & 4.
+
+ * Numerous cleanups.
+
+Wed Sep 13 14:30:05 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 2.
+
+ * (nfs_ops.c) portmap information is not remembered beyond the
+ basic filehandle cache interval. That avoids problems when a new
+ portmap and/or rpc.mountd is started and the bound port changes.
+
+ * (mapc.c) cache reloads are automatically done every hour.
+
+ * Removed xlog macro in favour of plog() so that the log level
+ can be reflected through to syslog(). log() routine renamed to
+ plog() which takes an extra parameter indicating the log level.
+
+Tue Sep 5 20:00:19 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_ops.c) when a server is known to be down, any cached file
+ handles and port mapping informaton is flushed since that may have
+ changed when it comes back up.
+
+ * (map.c) timeout no longer attempts to unmount a hung mount point.
+
+Mon Sep 4 14:49:18 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) a mount node which timed out during mount is now
+ retained for the normal timeout interval rather than for a short
+ period. This avoids wasting time retrying mounts from a server
+ which is down.
+
+ * (afs_ops.c) hung mounts are now detected and not used as a
+ duplicate mount - something which defeated the replacement fs
+ scheme.
+
+ * (nfs_ops.c) keepalive's now back-off when a server has gone
+ down.
+
+Thu Aug 31 21:18:35 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * 5.0 Patchlevel 1.
+
+ * Fixed several bugs which showed up in the keepalive
+ implementation when a gateway went down causing
+ a different sequence of errors than usual.
+
+Wed Aug 30 11:29:21 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (amq.x) now uses a Sun assigned program number.
+
+ * Revision 5.0 - can now start using metaconfig.
+
+Tue Aug 29 14:36:48 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (os-u3_0.h, os-type) now knows about DECstations (mips).
+
+ * (nfs_stubs.c) Added hooks to readlink entry point to call
+ per-fs readlink routine if it exists, otherwise old behaviour.
+
+ * (afs_ops.c) Added implementation of "type=direct". This is
+ the same as "type=auto" but is itself the link to the
+ mount point, rather than being a directory containing a list
+ of links to mount points.
+
+Mon Aug 28 17:48:15 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) Changed readdir to workaround a problem on
+ ultrix 3 where it seems to forget that eof has been reached.
+
+Thu Aug 24 15:17:55 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Created "beta16".
+
+ * (afs_ops.c) /defaults is located along with every key.
+ this makes it possible to update the /defaults in
+ a map and get to use it.
+
+ * (mapc.c) added map cache synchronization support. if
+ a file or ndbm map is updated the cache is junked so avoiding
+ things getting out of sync.
+
+Wed Aug 23 19:17:52 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (os-u3_0.h) new file to support Ultrix 3.0
+
+ * (opts.c) allow environment variables to be accessed via
+ the same ${env} syntax used for options & selectors.
+
+Tue Aug 22 13:19:49 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (opts.c, get_args.c) added support for kernel architecture
+ type to allow /usr/kvm to be automounted under SunOS 4.x.
+
+ * (os-xinu43.h) updated for june '89 release of MORE/bsd.
+
+ * (opts.c) fixed memory allocation problems where some strings
+ may not have been strdup'ed before they were free'ed so causing
+ the malloc arena to get into a twist. This caused core dumps on
+ some machines and infinite loops on others.
+
+ * (*.c) clock handling is now done by a macro. Global variable
+ clock_valid is > 0 (ie the time) when valid, 0 if invalid.
+
+ * (map.c) timeout code survived a complete rewrite and is now
+ O(n) rather than O(n^2).
+
+ * (info_hes.c) new database hooks for Hesiod nameserver.
+
+ * (get_args.c) the local sub-domain is picked up from the
+ hostname if it is not specifed with -d. The subdomain is
+ then stripped from the hostname.
+
+ * (am.c) when a SIGTERM is received, an immediate abort
+ occurs - only the top-level automounts are unmounted; all
+ other mounts stay -- use amd -r to restart.
+
+ * (afs_ops.c) cleaned up key prefix handling. Again updated
+ the "hostname" string passed to the kernel so that includes
+ the hostname, pid and mount point.
+
+Tue Aug 8 16:05:23 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_ops.c) changed the way the file handle cache is managed.
+ No longer gets a race condition between something entering the
+ cache and being used and discard.
+
+Tue Jul 25 20:40:51 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (map.c) changed fh_to_mp2 so that it does not return
+ ESTALE during shutdown. it returns ENOENT instead which
+ avoids thrashing with the kernel.
+
+Sun Jul 23 15:06:10 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) make sure the incoming key from the kernel
+ does not contain any characters which could cause trouble
+ during macro expansion (such as `"! etc).
+
+ * (afs_ops.c) fixed contruction of "mtab" entry.
+
+Fri Jul 21 11:01:05 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) some changes to support the new startup
+ shutdown scheme.
+
+ * (map.c) startup and shutdown are now done using the
+ standard interfaces. Startup is done by creating a
+ private cache map ";root;" and then doing lookups
+ on all the names in it. Shutdown is done by forcibly
+ timing out all the mount points including the automount
+ points.
+
+ * (info_*.c) modified to provide interface required by
+ mapc.c module.
+
+ * (mapc.c) new module to implement map caching. Caching
+ can be controlled by an fs option. "all" means cache
+ the entire map (if possible). "inc" means cache things
+ incrementally. "none" means never cache things. Each
+ map type has a default caching mode which is used if
+ cache option "default" is used.
+
+Wed Jul 19 16:14:52 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (sched.c) implements a general sleep/wakeup scheme and uses
+ it for sub-process handling.
+
+ * (nfs_start.c) task_notify() called from where it used to
+ be called.
+
+ * (nfs_ops.c) now implements a non-blocking rpc library.
+ Everything in nfs_ops was changed to use it. This should
+ not be in this file and will be moved later.
+
+ * (map.c) if a mount point times out and it is deferred then
+ issue a wakeup so that it can be retried.
+
+ * (map.c) when creating a new mount point fetches the entry
+ "/defaults" from the associated map if no other options are
+ specified.
+
+ * (am.c) implements the -p (print process id) option.
+
+ * (afs_ops.c) a mount attempt now has a time-to-live of twenty
+ seconds. if only deferred attempts are waiting after that
+ interval the kernel gets sent ETIMEDOUT.
+
+ * (afs_ops.c) the name by which the kernel knows the filesystem
+ has changed from pid%d@host to /mountpoint@host. That looks
+ better to users who get hit by it.
+
+Fri Jul 14 18:46:16 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) now knows about defered mounts - mounts which
+ are not in progress, not completed, and not failed.
+
+ * (sched.c) added new entry point sched_ast(). This simulates
+ a completed job. The basic idea is to let something else return
+ to the main scheduling loop with a guarentee that it will be
+ called back when some other action has taken place.
+
+ * (nfs_ops.c) implemented a file handle cache. The nfs_init
+ routine starts up a request for the filehandle and the mount
+ routine uses it when it arrives.
+
+Thu Jul 13 18:07:58 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (afs_ops.c) found a race condition between an error occuring
+ and the am_node being timed out. Fixed by updating the
+ time-to-live and keepalive counters in the node whenever
+ AMF_MOUNTING is cleared. Also changed afs_lookuppn() so that
+ it doesn't destroy the node when it returns the error code.
+ This stops thrashing and the node is eventually timed out.
+ Now the only way a node gets deleted is by the timeout code
+ which seems more elegant.
+
+Tue Jul 11 15:36:44 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Created "beta15".
+
+ * Fixed *all* references to "u2.2". Some where missed in
+ the original change. They are now u2_2.
+
+ * (mk-amd-map.c) new command. Converts plain files into
+ ndbm databases for use by the info_ndbm module. Hooks
+ included for future support for gdbm just as soon as I
+ can get a copy.
+
+Sun Jul 9 19:00:22 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Created "beta14".
+
+ * (get_info.c) code to handle yp and files now split into
+ new files info_yp.c and info_file.c New support for ndbm
+ databases is in info_ndbm.c. A table in get_info.c controls
+ what and in which order things are searched.
+
+ * (map.c, nfs_stubs.c) better handling for hung mount points.
+ if a filehandle is passed in by the kernel which references
+ a hung node, then try to find a replacement, possibly by calling
+ lookup explicitly.
+
+ * (*.c) use new xlog(level)(message) interface
+
+Thu Jun 8 20:28:55 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (nfs_ops.c, ufs_ops.c) when compiled with DEBUG, display
+ the fs options being used.
+
+ * (am.c) make test for root a little more polite.
+
+ * (get_args.c) update Usage message to include -r option.
+
+Wed Jun 7 16:28:51 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (rpc_fwd.c) fwd_reply: if the recvfrom call fails because it
+ is interrupted then try again.
+
+Tue Jun 6 16:39:15 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Created "beta12".
+
+ * (afs_ops.c) inheriting mount option list from command line
+ is now cumulative. A -foo on the command line is prepended
+ to the default option list taken from the map. This can be
+ used to override the ``default default'' options in opts.c.
+
+ * (get_args.c, am.c) added new -r (restart) option. Restart of
+ mounted filesystems is only done if this option is specified.
+ [Should *not* be specified in /etc/rc.local of course. - wrong]
+
+ * (yp_master.c) make the enumeration error message more verbose
+ when debugging is enabled.
+
+ * (rpc_fwd.c) rearranged some declarations at the top. Removed
+ a spurious call to free which was causing grief on some systems,
+ but not on Sun's. [This problem was the reason for implementing
+ the -D mem option.]
+
+ * (opts.c) make sure opt_key and opt_path are set to a zero
+ length string unless otherwise specified. Previously they
+ were a source of dangling pointers.
+
+ * (nfs_ops.c) make sure that the allocated nfs_private identifiers
+ are unique even when some filesystem are being restarted. This mean
+ starting the basic allocation from 1, not zero.
+
+ * (am.h, get_args.c, util.c) added definition and implmentation of
+ a simple memory allocation trace (D_MEM).
+
+ * (afs_ops.c) afs_lookuppn: tightened up memory allocation and
+ delay string copying until last possible moment.
+
+Mon Jun 5 18:01:18 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * (Makefile.com) diffs: added new rule to generate diffs
+ between versions.
+
+ * (get_info.c) search_file: added a new dlog() to note when
+ wildcards are returned.
+
+ * (afs_ops.c) afs_lookuppn: call to init_map specifies efs as
+ the default ops structure. If the location list only contained
+ defaults and no real mounts then this previously caused a null
+ pointer dereference.
+
+ * (map.c) last_used_map: Added new variable. Keeps track of the
+ last used map, which may be wildly different from first_free_map.
+ This fixes bugs in several routines in this file.
+
+ * (util.c) mkdirs, rmdirs: Changed directory make/unmake. It is
+ not possible to quickly determine how many directories need to
+ be created or deleted, so we try to make as many as possible.
+
+ * (opts.c) Added default values for rfs, rhost and fs.
+ The new defaults guarentee unique names to allow the NFS
+ keepalive stuff to work.
+
+Sun Jun 4 16:12:15 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * First draft of documentation included in the next release.
+
+ * Hooks for TFS added, though this still requires a lot of work.
+
+ * Re-implemented option handling. Options are now allocated
+ dynamically on a per-mount basis in the continuation structure.
+
+ * Changed os type u2.2 to u2_2 to allow for regular expression
+ matching in selectors.
+
+ * Format of mount maps is now entirely different. Instead of
+ guessing which filesystem type is being used, it is now explicitly
+ stated along with the required options. Variable expansion is
+ done on the options and selectors are also implemented. The
+ requested name can also contain any of the selectors.
+
+Wed May 24 15:21:39 1989 Jan-Simon Pendry (jsp at achilles)
+
+ * Re-implemented NFS ping algorithm to use the new RPC forwarding
+ system. This allowed a large amount of nfs_ops specific code
+ to be removed from nfs_start.c and moved to nfs_ops.c.
+ There is still no strategy for hung file systems. At the moment
+ it will merely try to mount an alternative (or the same again)
+ to the same place in the file system.
+
+ * Added RPC forwarding package. This supports general RPC gatewaying
+ over a UDP transport. The idea is to put a packet identifier into
+ each outgoing RPC packet and then match that up in a database when
+ a reply comes in. The database records the original packet identifier
+ (so that it can be replaced), the source address for the packet and
+ a function to call to do the forwarding.
+
+ * ChangeLog added between beta8 and beta9. Should have done this sooner.
diff --git a/usr.sbin/amd/amd/Makefile b/usr.sbin/amd/amd/Makefile
new file mode 100644
index 0000000..328fd80
--- /dev/null
+++ b/usr.sbin/amd/amd/Makefile
@@ -0,0 +1,33 @@
+# @(#)Makefile 8.2 (Berkeley) 4/22/94
+
+PROG= amd
+MAN8= amd.0
+OS= bsd44
+SRCS= afs_ops.c am_ops.c clock.c util.c xutil.c \
+ efs_ops.c mapc.c info_file.c info_hes.c \
+ info_ndbm.c info_passwd.c info_nis.c \
+ info_union.c map.c srvr_afs.c srvr_nfs.c \
+ mntfs.c misc_rpc.c mount_fs.c mount_xdr.c \
+ mtab.c mtab_bsd.c nfs_ops.c nfs_prot_svc.c \
+ nfs_start.c nfs_subr.c nfs_prot_xdr.c opts.c \
+ pfs_ops.c rpc_fwd.c sched.c sfs_ops.c amq_svc.c \
+ amq_subr.c umount_fs.c host_ops.c nfsx_ops.c \
+ ufs_ops.c ifs_ops.c amd.c get_args.c restart.c wire.c
+OBJS+= vers.${PROG}.o
+LDADD+= -lrpc
+CFLAGS+=-I${.CURDIR}/../rpcx
+CFLAGS+=-I${.CURDIR}/../config
+CFLAGS+=-I${.CURDIR}/../include
+CFLAGS+=-DARCH_REP=\"${MACHINE}\"
+CFLAGS+=-DOS_REP=\"${OS}\"
+CFLAGS+=-DOS_HDR=\"os-${OS}.h\"
+CFLAGS+=${CONFIG}
+CLEANFILES+=vers.${PROG}.c vers.${PROG}.o version.amd
+
+vers.${PROG}.c: ${SRCS:.c=.o}
+ @d=${.CURDIR}/ sh ${.CURDIR}/../config/newvers.sh ${PROG} ${MACHINE} ${OS}
+
+.PATH: ${.CURDIR}/../rpcx ${.CURDIR}/../config
+.include "Makefile.config"
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/amd/amd/afs_ops.c b/usr.sbin/amd/amd/afs_ops.c
new file mode 100644
index 0000000..6dfdc14
--- /dev/null
+++ b/usr.sbin/amd/amd/afs_ops.c
@@ -0,0 +1,1816 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)afs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: afs_ops.c,v 5.2.2.4 1992/05/31 16:36:36 jsp Exp $
+ *
+ */
+
+#include "am.h"
+
+#define NFS
+#define NFSCLIENT
+
+#include <sys/stat.h>
+#ifdef NFS_3
+typedef nfs_fh fhandle_t;
+#endif /* NFS_3 */
+#ifdef NFS_HDR
+#include NFS_HDR
+#endif /* NFS_HDR */
+#include <sys/mount.h>
+#include "mount.h"
+
+/*
+ * Automount file system
+ * Direct file system
+ * Root file system
+ * Top-level file system
+ */
+
+/*
+ * Interval between forced retries of a mount.
+ */
+#define RETRY_INTERVAL 2
+
+/*
+ * AFS needs nothing in particular.
+ */
+static char *afs_match P((am_opts *fo));
+static char *afs_match(fo)
+am_opts *fo;
+{
+ char *p = fo->opt_rfs;
+ if (!fo->opt_rfs) {
+ plog(XLOG_USER, "auto: no mount point named (rfs:=)");
+ return 0;
+ }
+ if (!fo->opt_fs) {
+ plog(XLOG_USER, "auto: no map named (fs:=)");
+ return 0;
+ }
+ /*
+ * Swap round fs:= and rfs:= options
+ * ... historical (jsp)
+ */
+ fo->opt_rfs = fo->opt_fs;
+ fo->opt_fs = p;
+ /*
+ * mtab entry turns out to be the name of the mount map
+ */
+ return strdup(fo->opt_rfs ? fo->opt_rfs : ".");
+}
+
+/*
+ * Mount an automounter directory.
+ * The automounter is connected into the system
+ * as a user-level NFS server. mount_toplvl constructs
+ * the necessary NFS parameters to be given to the
+ * kernel so that it will talk back to us.
+ */
+static int mount_toplvl P((char *dir, char *opts));
+static int mount_toplvl(dir, opts)
+char *dir;
+char *opts;
+{
+ struct nfs_args nfs_args;
+ struct mntent mnt;
+ int retry;
+ struct sockaddr_in sin;
+ unsigned short port;
+ int flags;
+ extern nfs_fh *root_fh();
+ nfs_fh *fhp;
+ char fs_hostname[MAXHOSTNAMELEN+MAXPATHLEN+1];
+
+ MTYPE_TYPE type = MOUNT_TYPE_NFS;
+
+ bzero((voidp) &nfs_args, sizeof(nfs_args)); /* Paranoid */
+
+ mnt.mnt_dir = dir;
+ mnt.mnt_fsname = pid_fsname;
+ mnt.mnt_type = MNTTYPE_AUTO;
+ mnt.mnt_opts = opts;
+ mnt.mnt_freq = 0;
+ mnt.mnt_passno = 0;
+
+ retry = hasmntval(&mnt, "retry");
+ if (retry <= 0)
+ retry = 2; /* XXX */
+
+ /*
+ * get fhandle of remote path for automount point
+ */
+
+ fhp = root_fh(dir);
+ if (!fhp) {
+ plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
+ return EINVAL;
+ }
+
+ NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp);
+
+ /*
+ * Create sockaddr to point to the local machine. 127.0.0.1
+ * is not used since that will not work in HP-UX clusters and
+ * this is no more expensive.
+ */
+ bzero((voidp) &sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr = myipaddr;
+ if (port = hasmntval(&mnt, "port")) {
+ sin.sin_port = htons(port);
+ } else {
+ plog(XLOG_ERROR, "no port number specified for %s", dir);
+ return EINVAL;
+ }
+
+ /*
+ * set mount args
+ */
+ NFS_SA_DREF(nfs_args, &sin);
+
+ /*
+ * Make a ``hostname'' string for the kernel
+ */
+#ifndef HOSTNAMESZ
+#define SHORT_MOUNT_NAME
+#endif /* HOSTNAMESZ */
+#ifdef SHORT_MOUNT_NAME
+ sprintf(fs_hostname, "amd:%d", foreground ? mypid : getppid());
+#else
+ sprintf(fs_hostname, "pid%d@%s:%s", foreground ? mypid : getppid(), hostname, dir);
+#endif /* SHORT_MOUNT_NAME */
+ nfs_args.hostname = fs_hostname;
+ nfs_args.flags |= NFSMNT_HOSTNAME;
+#ifdef HOSTNAMESZ
+ /*
+ * Most kernels have a name length restriction.
+ */
+ if (strlen(fs_hostname) >= HOSTNAMESZ)
+ strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
+#endif /* HOSTNAMESZ */
+
+#ifdef NFSMNT_DUMBTIMR
+ nfs_args.flags |= NFSMNT_DUMBTIMR;
+ plog(XLOG_INFO, "defeating nfs window computation");
+#endif
+
+ /*
+ * Parse a subset of the standard nfs options. The
+ * others are probably irrelevant for this application
+ */
+ if (nfs_args.timeo = hasmntval(&mnt, "timeo"))
+ nfs_args.flags |= NFSMNT_TIMEO;
+
+ if (nfs_args.retrans = hasmntval(&mnt, "retrans"))
+ nfs_args.flags |= NFSMNT_RETRANS;
+
+#ifdef NFSMNT_BIODS
+ if (nfs_args.biods = hasmntval(&mnt, "biods"))
+ nfs_args.flags |= NFSMNT_BIODS;
+
+#endif /* NFSMNT_BIODS */
+
+#if defined(NFSMNT_ACREGMIN) && defined(NFSMNT_ACREGMAX)
+ /*
+ * Don't cache attributes - they are changing under
+ * the kernel's feet...
+ */
+ nfs_args.acregmin = nfs_args.acregmax = 1;
+ nfs_args.flags |= NFSMNT_ACREGMIN|NFSMNT_ACREGMAX;
+#endif /* defined(NFSMNT_ACREGMIN) && defined(NFSMNT_ACREGMAX) */
+ /*
+ * These two are constructed internally by the calling routine
+ */
+ if (hasmntopt(&mnt, MNTOPT_SOFT) != NULL)
+ nfs_args.flags |= NFSMNT_SOFT;
+
+#ifdef MNTOPT_INTR
+ if (hasmntopt(&mnt, MNTOPT_INTR) != NULL)
+ nfs_args.flags |= NFSMNT_INT;
+#endif /* MNTOPT_INTR */
+
+ flags = compute_mount_flags(&mnt);
+#ifdef ULTRIX_HACK
+ nfs_args.gfs_flags = flags;
+ flags &= M_RDONLY;
+ if (flags & M_RDONLY)
+ nfs_args.flags |= NFSMNT_RONLY;
+#endif /* ULTRIX_HACK */
+ return mount_fs(&mnt, flags, (caddr_t) &nfs_args, retry, type);
+}
+
+static void afs_mkcacheref P((mntfs *mf));
+static void afs_mkcacheref(mf)
+mntfs *mf;
+{
+ /*
+ * Build a new map cache for this node, or re-use
+ * an existing cache for the same map.
+ */
+ char *cache;
+ if (mf->mf_fo && mf->mf_fo->opt_cache)
+ cache = mf->mf_fo->opt_cache;
+ else
+ cache = "none";
+ mf->mf_private = (voidp) mapc_find(mf->mf_info, cache);
+ mf->mf_prfree = mapc_free;
+}
+
+/*
+ * Mount the root...
+ */
+static int root_mount P((am_node *mp));
+static int root_mount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
+ mf->mf_private = (voidp) mapc_find(mf->mf_info, "");
+ mf->mf_prfree = mapc_free;
+
+ return 0;
+}
+
+/*
+ * Mount a sub-mount
+ */
+static int afs_mount P((am_node *mp));
+static int afs_mount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ /*
+ * Pseudo-directories are used to provide some structure
+ * to the automounted directories instead
+ * of putting them all in the top-level automount directory.
+ *
+ * Here, just increment the parent's link count.
+ */
+ mp->am_parent->am_fattr.nlink++;
+ /*
+ * Info field of . means use parent's info field.
+ * Historical - not documented.
+ */
+ if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0')
+ mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_mnt->mf_info);
+ /*
+ * Compute prefix:
+ *
+ * If there is an option prefix then use that else
+ * If the parent had a prefix then use that with name
+ * of this node appended else
+ * Use the name of this node.
+ *
+ * That means if you want no prefix you must say so
+ * in the map.
+ */
+ if (mf->mf_fo->opt_pref) {
+ /*
+ * the prefix specified as an option
+ */
+ mp->am_pref = strdup(mf->mf_fo->opt_pref);
+ } else {
+ /*
+ * else the parent's prefix
+ * followed by the name
+ * followed by /
+ */
+ char *ppref = mp->am_parent->am_pref;
+ if (ppref == 0)
+ ppref = "";
+ mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/");
+ }
+
+ /*
+ * Attach a map cache
+ */
+ afs_mkcacheref(mf);
+
+ return 0;
+}
+
+/*
+ * Mount the top-level
+ */
+static int toplvl_mount P((am_node *mp));
+static int toplvl_mount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ struct stat stb;
+ char opts[256];
+ int error;
+ char *mnttype;
+
+ /*
+ * Mounting the automounter.
+ * Make sure the mount directory exists, construct
+ * the mount options and call the mount_toplvl routine.
+ */
+
+ if (stat(mp->am_path, &stb) < 0) {
+ return errno;
+ } else if ((stb.st_mode & S_IFMT) != S_IFDIR) {
+ plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
+ return ENOTDIR;
+ }
+
+ if (mf->mf_ops == &toplvl_ops) mnttype = "indirect";
+ else if (mf->mf_ops == &dfs_ops) mnttype = "direct";
+#ifdef HAS_UNION_FS
+ else if (mf->mf_ops == &union_ops) mnttype = "union";
+#endif
+ else mnttype = "auto";
+
+ /*
+ * Construct some mount options
+ */
+ sprintf(opts,
+#ifdef MNTOPT_INTR
+ "%s,%s,%s=%d,%s=%d,%s=%d,%s",
+ MNTOPT_INTR,
+#else
+ "%s,%s=%d,%s=%d,%s=%d,%s",
+#endif /* MNTOPT_INTR */
+ "rw",
+ "port", nfs_port,
+ "timeo", afs_timeo,
+ "retrans", afs_retrans,
+ mnttype);
+
+ error = mount_toplvl(mf->mf_mount, opts);
+ if (error) {
+ errno = error;
+ plog(XLOG_FATAL, "mount_toplvl: %m");
+ return error;
+ }
+
+ return 0;
+}
+
+static void toplvl_mounted P((mntfs *mf));
+static void toplvl_mounted(mf)
+mntfs *mf;
+{
+ afs_mkcacheref(mf);
+}
+
+#ifdef HAS_UNION_FS
+/*
+ * Create a reference to a union'ed entry
+ */
+static int create_union_node P((char *dir, voidp arg));
+static int create_union_node(dir, arg)
+char *dir;
+voidp arg;
+{
+ if (strcmp(dir, "/defaults") != 0) {
+ int error = 0;
+ (void) toplvl_ops.lookuppn(arg, dir, &error, VLOOK_CREATE);
+ if (error > 0) {
+ errno = error; /* XXX */
+ plog(XLOG_ERROR, "Could not mount %s: %m", dir);
+ }
+ return error;
+ }
+ return 0;
+}
+
+static void union_mounted P((mntfs *mf));
+static void union_mounted(mf)
+mntfs *mf;
+{
+ int i;
+
+ afs_mkcacheref(mf);
+
+ /*
+ * Having made the union mount point,
+ * populate all the entries...
+ */
+ for (i = 0; i <= last_used_map; i++) {
+ am_node *mp = exported_ap[i];
+ if (mp && mp->am_mnt == mf) {
+ /* return value from create_union_node is ignored by mapc_keyiter */
+ (void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private,
+ (void (*)P((char*,void*))) create_union_node, mp);
+ break;
+ }
+ }
+
+#ifdef notdef
+ /*
+ * would be nice to flush most of the cache, but we need to
+ * keep the wildcard and /defaults entries...
+ */
+ mapc_free(mf->mf_private);
+ mf->mf_private = (voidp) mapc_find(mf->mf_info, "inc");
+/* mapc_add_kv(mf->mf_private, strdup("/defaults"),
+ strdup("type:=link;opts:=nounmount;sublink:=${key}")); */
+#endif
+}
+#endif /* HAS_UNION_FS */
+
+/*
+ * Unmount an automount sub-node
+ */
+static int afs_umount P((am_node *mp));
+static int afs_umount(mp)
+am_node *mp;
+{
+ return 0;
+}
+
+/*
+ * Unmount a top-level automount node
+ */
+static int toplvl_umount P((am_node *mp));
+static int toplvl_umount(mp)
+am_node *mp;
+{
+ int error;
+
+ struct stat stb;
+again:
+ /*
+ * The lstat is needed if this mount is type=direct.
+ * When that happens, the kernel cache gets confused
+ * between the underlying type (dir) and the mounted
+ * type (link) and so needs to be re-synced before
+ * the unmount. This is all because the unmount system
+ * call follows links and so can't actually unmount
+ * a link (stupid!). It was noted that doing an ls -ld
+ * of the mount point to see why things were not working
+ * actually fixed the problem - so simulate an ls -ld here.
+ */
+ if (lstat(mp->am_path, &stb) < 0) {
+#ifdef DEBUG
+ dlog("lstat(%s): %m", mp->am_path);
+#endif /* DEBUG */
+ }
+ error = UMOUNT_FS(mp->am_path);
+ if (error == EBUSY) {
+ plog(XLOG_WARNING, "afs_unmount retrying %s in 1s", mp->am_path);
+ sleep(1); /* XXX */
+ goto again;
+ }
+
+ return error;
+}
+
+/*
+ * Unmount an automount node
+ */
+static void afs_umounted P((am_node *mp));
+static void afs_umounted(mp)
+am_node *mp;
+{
+ /*
+ * If this is a pseudo-directory then just adjust the link count
+ * in the parent, otherwise call the generic unmount routine
+ */
+ if (mp->am_parent && mp->am_parent->am_parent)
+ --mp->am_parent->am_fattr.nlink;
+}
+
+/*
+ * Mounting a file system may take a significant period of time. The
+ * problem is that if this is done in the main process thread then
+ * the entire automounter could be blocked, possibly hanging lots of
+ * processes on the system. Instead we use a continuation scheme to
+ * allow mounts to be attempted in a sub-process. When the sub-process
+ * exits we pick up the exit status (by convention a UN*X error number)
+ * and continue in a notifier. The notifier gets handed a data structure
+ * and can then determine whether the mount was successful or not. If
+ * not, it updates the data structure and tries again until there are no
+ * more ways to try the mount, or some other permanent error occurs.
+ * In the mean time no RPC reply is sent, even after the mount is succesful.
+ * We rely on the RPC retry mechanism to resend the lookup request which
+ * can then be handled.
+ */
+
+
+struct continuation {
+ char **ivec; /* Current mount info */
+ am_node *mp; /* Node we are trying to mount */
+ char *key; /* Map key */
+ char *info; /* Info string */
+ char **xivec; /* Saved strsplit vector */
+ char *auto_opts; /* Automount options */
+ am_opts fs_opts; /* Filesystem options */
+ char *def_opts; /* Default automount options */
+ int retry; /* Try again? */
+ int tried; /* Have we tried any yet? */
+ time_t start; /* Time we started this mount */
+ int callout; /* Callout identifier */
+};
+
+#define IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING)
+
+/*
+ * Discard an old continuation
+ */
+static void free_continuation P((struct continuation *cp));
+static void free_continuation(cp)
+struct continuation *cp;
+{
+ if (cp->callout)
+ untimeout(cp->callout);
+ free((voidp) cp->key);
+ free((voidp) cp->xivec);
+ free((voidp) cp->info);
+ free((voidp) cp->auto_opts);
+ free((voidp) cp->def_opts);
+ free_opts(&cp->fs_opts);
+ free((voidp) cp);
+}
+
+static int afs_bgmount P((struct continuation*, int));
+
+/*
+ * Discard the underlying mount point and replace
+ * with a reference to an error filesystem.
+ */
+static void assign_error_mntfs P((am_node *mp));
+static void assign_error_mntfs(mp)
+am_node *mp;
+{
+ if (mp->am_error > 0) {
+ /*
+ * Save the old error code
+ */
+ int error = mp->am_error;
+ if (error <= 0)
+ error = mp->am_mnt->mf_error;
+ /*
+ * Discard the old filesystem
+ */
+ free_mntfs(mp->am_mnt);
+ /*
+ * Allocate a new error reference
+ */
+ mp->am_mnt = new_mntfs();
+ /*
+ * Put back the error code
+ */
+ mp->am_mnt->mf_error = error;
+ mp->am_mnt->mf_flags |= MFF_ERROR;
+ /*
+ * Zero the error in the mount point
+ */
+ mp->am_error = 0;
+ }
+}
+
+/*
+ * The continuation function. This is called by
+ * the task notifier when a background mount attempt
+ * completes.
+ */
+static void afs_cont P((int rc, int term, voidp closure));
+static void afs_cont(rc, term, closure)
+int rc;
+int term;
+voidp closure;
+{
+ struct continuation *cp = (struct continuation *) closure;
+ mntfs *mf = cp->mp->am_mnt;
+
+ /*
+ * Definitely not trying to mount at the moment
+ */
+ mf->mf_flags &= ~MFF_MOUNTING;
+ /*
+ * While we are mounting - try to avoid race conditions
+ */
+ new_ttl(cp->mp);
+
+ /*
+ * Wakeup anything waiting for this mount
+ */
+ wakeup((voidp) mf);
+
+ /*
+ * Check for termination signal or exit status...
+ */
+ if (rc || term) {
+ am_node *xmp;
+
+ if (term) {
+ /*
+ * Not sure what to do for an error code.
+ */
+ mf->mf_error = EIO; /* XXX ? */
+ mf->mf_flags |= MFF_ERROR;
+ plog(XLOG_ERROR, "mount for %s got signal %d", cp->mp->am_path, term);
+ } else {
+ /*
+ * Check for exit status...
+ */
+ mf->mf_error = rc;
+ mf->mf_flags |= MFF_ERROR;
+ errno = rc; /* XXX */
+ plog(XLOG_ERROR, "%s: mount (afs_cont): %m", cp->mp->am_path);
+ }
+
+ /*
+ * If we get here then that attempt didn't work, so
+ * move the info vector pointer along by one and
+ * call the background mount routine again
+ */
+ amd_stats.d_merr++;
+ cp->ivec++;
+ xmp = cp->mp;
+ (void) afs_bgmount(cp, 0);
+ assign_error_mntfs(xmp);
+ } else {
+ /*
+ * The mount worked.
+ */
+ am_mounted(cp->mp);
+ free_continuation(cp);
+ }
+
+ reschedule_timeout_mp();
+}
+
+/*
+ * Retry a mount
+ */
+/*ARGSUSED*/
+static void afs_retry P((int rc, int term, voidp closure));
+static void afs_retry(rc, term, closure)
+int rc;
+int term;
+voidp closure;
+{
+ struct continuation *cp = (struct continuation *) closure;
+ int error = 0;
+
+#ifdef DEBUG
+ dlog("Commencing retry for mount of %s", cp->mp->am_path);
+#endif /* DEBUG */
+
+ new_ttl(cp->mp);
+
+ if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime()) {
+ /*
+ * The entire mount has timed out.
+ * Set the error code and skip past
+ * all the info vectors so that
+ * afs_bgmount will not have any more
+ * ways to try the mount, so causing
+ * an error.
+ */
+ plog(XLOG_INFO, "mount of \"%s\" has timed out", cp->mp->am_path);
+ error = ETIMEDOUT;
+ while (*cp->ivec)
+ cp->ivec++;
+ }
+
+ if (error || !IN_PROGRESS(cp)) {
+ (void) afs_bgmount(cp, error);
+ }
+ reschedule_timeout_mp();
+}
+
+/*
+ * Try to mount a file system. Can be called
+ * directly or in a sub-process by run_task
+ */
+static int try_mount P((voidp mvp));
+static int try_mount(mvp)
+voidp mvp;
+{
+ /*
+ * Mount it!
+ */
+ int error;
+ am_node *mp = (am_node *) mvp;
+ mntfs *mf = mp->am_mnt;
+
+ /*
+ * If the directory is not yet made and
+ * it needs to be made, then make it!
+ * This may be run in a backgroun process
+ * in which case the flag setting won't be
+ * noticed later - but it is set anyway
+ * just after run_task is called. It
+ * should probably go away totally...
+ */
+ if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_ops->fs_flags & FS_MKMNT) {
+ error = mkdirs(mf->mf_mount, 0555);
+ if (!error)
+ mf->mf_flags |= MFF_MKMNT;
+ }
+
+ error = mount_node(mp);
+#ifdef DEBUG
+ if (error > 0) {
+ errno = error;
+ dlog("afs call to mount_node failed: %m");
+ }
+#endif /* DEBUG */
+ return error;
+}
+
+/*
+ * Pick a file system to try mounting and
+ * do that in the background if necessary
+ *
+For each location:
+ if it is new -defaults then
+ extract and process
+ continue;
+ fi
+ if it is a cut then
+ if a location has been tried then
+ break;
+ fi
+ continue;
+ fi
+ parse mount location
+ discard previous mount location if required
+ find matching mounted filesystem
+ if not applicable then
+ this_error = No such file or directory
+ continue
+ fi
+ if the filesystem failed to be mounted then
+ this_error = error from filesystem
+ elif the filesystem is mounting or unmounting then
+ this_error = -1
+ elif the fileserver is down then
+ this_error = -1
+ elif the filesystem is already mounted
+ this_error = 0
+ break
+ fi
+ if no error on this mount then
+ this_error = initialise mount point
+ fi
+ if no error on this mount and mount is delayed then
+ this_error = -1
+ fi
+ if this_error < 0 then
+ retry = true
+ fi
+ if no error on this mount then
+ make mount point if required
+ fi
+ if no error on this mount then
+ if mount in background then
+ run mount in background
+ return -1
+ else
+ this_error = mount in foreground
+ fi
+ fi
+ if an error occured on this mount then
+ update stats
+ save error in mount point
+ fi
+endfor
+ */
+
+static int afs_bgmount P((struct continuation *cp, int mpe));
+static int afs_bgmount(cp, mpe)
+struct continuation *cp;
+int mpe;
+{
+ mntfs *mf = cp->mp->am_mnt; /* Current mntfs */
+ mntfs *mf_retry = 0; /* First mntfs which needed retrying */
+ int this_error = -1; /* Per-mount error */
+ int hard_error = -1;
+ int mp_error = mpe;
+
+ /*
+ * Try to mount each location.
+ * At the end:
+ * hard_error == 0 indicates something was mounted.
+ * hard_error > 0 indicates everything failed with a hard error
+ * hard_error < 0 indicates nothing could be mounted now
+ */
+ for (; this_error && *cp->ivec; cp->ivec++) {
+ am_ops *p;
+ am_node *mp = cp->mp;
+ char *link_dir;
+ int dont_retry;
+
+ if (hard_error < 0)
+ hard_error = this_error;
+
+ this_error = -1;
+
+ if (**cp->ivec == '-') {
+ /*
+ * Pick up new defaults
+ */
+ if (cp->auto_opts && *cp->auto_opts)
+ cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec+1);
+ else
+ cp->def_opts = strealloc(cp->def_opts, *cp->ivec+1);
+#ifdef DEBUG
+ dlog("Setting def_opts to \"%s\"", cp->def_opts);
+#endif /* DEBUG */
+ continue;
+ }
+
+ /*
+ * If a mount has been attempted, and we find
+ * a cut then don't try any more locations.
+ */
+ if (strcmp(*cp->ivec, "/") == 0 || strcmp(*cp->ivec, "||") == 0) {
+ if (cp->tried) {
+#ifdef DEBUG
+ dlog("Cut: not trying any more locations for %s",
+ mp->am_path);
+#endif /* DEBUG */
+ break;
+ }
+ continue;
+ }
+
+#ifdef SUNOS4_COMPAT
+#ifdef nomore
+ /*
+ * By default, you only get this bit on SunOS4.
+ * If you want this anyway, then define SUNOS4_COMPAT
+ * in the relevant "os-blah.h" file.
+ *
+ * We make the observation that if the local key line contains
+ * no '=' signs then either it is sick, or it is a SunOS4-style
+ * "host:fs[:link]" line. In the latter case the am_opts field
+ * is also assumed to be in old-style, so you can't mix & match.
+ * You can use ${} expansions for the fs and link bits though...
+ *
+ * Actually, this doesn't really cover all the possibilities for
+ * the latest SunOS automounter and it is debatable whether there
+ * is any point bothering.
+ */
+ if (strchr(*cp->ivec, '=') == 0)
+ p = sunos4_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);
+ else
+#endif
+#endif /* SUNOS4_COMPAT */
+ p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);
+
+ /*
+ * Find a mounted filesystem for this node.
+ */
+ mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts, cp->fs_opts.opt_fs,
+ cp->fs_opts.fs_mtab, cp->auto_opts, cp->fs_opts.opt_opts, cp->fs_opts.opt_remopts);
+
+ p = mf->mf_ops;
+#ifdef DEBUG
+ dlog("Got a hit with %s", p->fs_type);
+#endif /* DEBUG */
+ /*
+ * Note whether this is a real mount attempt
+ */
+ if (p == &efs_ops) {
+ plog(XLOG_MAP, "Map entry %s for %s failed to match", *cp->ivec, mp->am_path);
+ if (this_error <= 0)
+ this_error = ENOENT;
+ continue;
+ } else {
+ if (cp->fs_opts.fs_mtab) {
+ plog(XLOG_MAP, "Trying mount of %s on %s fstype %s",
+ cp->fs_opts.fs_mtab, mp->am_path, p->fs_type);
+ }
+ cp->tried = TRUE;
+ }
+
+ this_error = 0;
+ dont_retry = FALSE;
+
+ if (mp->am_link) {
+ free(mp->am_link);
+ mp->am_link = 0;
+ }
+
+ link_dir = mf->mf_fo->opt_sublink;
+
+ if (link_dir && *link_dir) {
+ if (*link_dir == '/') {
+ mp->am_link = strdup(link_dir);
+ } else {
+ mp->am_link = str3cat((char *) 0,
+ mf->mf_fo->opt_fs, "/", link_dir);
+ normalize_slash(mp->am_link);
+ }
+ }
+
+ if (mf->mf_error > 0) {
+ this_error = mf->mf_error;
+ } else if (mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)) {
+ /*
+ * Still mounting - retry later
+ */
+#ifdef DEBUG
+ dlog("Duplicate pending mount fstype %s", p->fs_type);
+#endif /* DEBUG */
+ this_error = -1;
+ } else if (FSRV_ISDOWN(mf->mf_server)) {
+ /*
+ * Would just mount from the same place
+ * as a hung mount - so give up
+ */
+#ifdef DEBUG
+ dlog("%s is already hung - giving up", mf->mf_mount);
+#endif /* DEBUG */
+ mp_error = EWOULDBLOCK;
+ dont_retry = TRUE;
+ this_error = -1;
+ } else if (mf->mf_flags & MFF_MOUNTED) {
+#ifdef DEBUG
+ dlog("duplicate mount of \"%s\" ...", mf->mf_info);
+#endif /* DEBUG */
+ /*
+ * Just call mounted()
+ */
+ am_mounted(mp);
+
+ this_error = 0;
+ break;
+ }
+
+ /*
+ * Will usually need to play around with the mount nodes
+ * file attribute structure. This must be done here.
+ * Try and get things initialised, even if the fileserver
+ * is not known to be up. In the common case this will
+ * progress things faster.
+ */
+ if (!this_error) {
+ /*
+ * Fill in attribute fields.
+ */
+ if (mf->mf_ops->fs_flags & FS_DIRECTORY)
+ mk_fattr(mp, NFDIR);
+ else
+ mk_fattr(mp, NFLNK);
+
+ mp->am_fattr.fileid = mp->am_gen;
+
+ if (p->fs_init)
+ this_error = (*p->fs_init)(mf);
+ }
+
+ /*
+ * Make sure the fileserver is UP before doing any more work
+ */
+ if (!FSRV_ISUP(mf->mf_server)) {
+#ifdef DEBUG
+ dlog("waiting for server %s to become available", mf->mf_server->fs_host);
+#endif
+ this_error = -1;
+ }
+
+ if (!this_error && mf->mf_fo->opt_delay) {
+ /*
+ * If there is a delay timer on the mount
+ * then don't try to mount if the timer
+ * has not expired.
+ */
+ int i = atoi(mf->mf_fo->opt_delay);
+ if (i > 0 && clocktime() < (cp->start + i)) {
+#ifdef DEBUG
+ dlog("Mount of %s delayed by %ds", mf->mf_mount, i - clocktime() + cp->start);
+#endif /* DEBUG */
+ this_error = -1;
+ }
+ }
+
+ if (this_error < 0 && !dont_retry) {
+ if (!mf_retry)
+ mf_retry = dup_mntfs(mf);
+ cp->retry = TRUE;
+ }
+
+ if (!this_error)
+ if (p->fs_flags & FS_MBACKGROUND) {
+ mf->mf_flags |= MFF_MOUNTING; /*XXX*/
+#ifdef DEBUG
+ dlog("backgrounding mount of \"%s\"", mf->mf_mount);
+#endif /* DEBUG */
+ if (cp->callout) {
+ untimeout(cp->callout);
+ cp->callout = 0;
+ }
+ run_task(try_mount, (voidp) mp, afs_cont, (voidp) cp);
+ mf->mf_flags |= MFF_MKMNT; /* XXX */
+ if (mf_retry) free_mntfs(mf_retry);
+ return -1;
+ } else {
+#ifdef DEBUG
+ dlog("foreground mount of \"%s\" ...", mf->mf_info);
+#endif /* DEBUG */
+ this_error = try_mount((voidp) mp);
+ if (this_error < 0) {
+ if (!mf_retry)
+ mf_retry = dup_mntfs(mf);
+ cp->retry = TRUE;
+ }
+ }
+
+ if (this_error >= 0) {
+ if (this_error > 0) {
+ amd_stats.d_merr++;
+ if (mf != mf_retry) {
+ mf->mf_error = this_error;
+ mf->mf_flags |= MFF_ERROR;
+ }
+ }
+ /*
+ * Wakeup anything waiting for this mount
+ */
+ wakeup((voidp) mf);
+ }
+ }
+
+ if (this_error && cp->retry) {
+ free_mntfs(mf);
+ mf = cp->mp->am_mnt = mf_retry;
+ /*
+ * Not retrying again (so far)
+ */
+ cp->retry = FALSE;
+ cp->tried = FALSE;
+ /*
+ * Start at the beginning.
+ * Rewind the location vector and
+ * reset the default options.
+ */
+ cp->ivec = cp->xivec;
+ cp->def_opts = strealloc(cp->def_opts, cp->auto_opts);
+ /*
+ * Arrange that afs_bgmount is called
+ * after anything else happens.
+ */
+#ifdef DEBUG
+ dlog("Arranging to retry mount of %s", cp->mp->am_path);
+#endif /* DEBUG */
+ sched_task(afs_retry, (voidp) cp, (voidp) mf);
+ if (cp->callout)
+ untimeout(cp->callout);
+ cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf);
+
+ cp->mp->am_ttl = clocktime() + RETRY_INTERVAL;
+
+ /*
+ * Not done yet - so don't return anything
+ */
+ return -1;
+ }
+
+ if (hard_error < 0 || this_error == 0)
+ hard_error = this_error;
+
+ /*
+ * Discard handle on duff filesystem.
+ * This should never happen since it
+ * should be caught by the case above.
+ */
+ if (mf_retry) {
+ if (hard_error)
+ plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount);
+ free_mntfs(mf_retry);
+ }
+
+ /*
+ * If we get here, then either the mount succeeded or
+ * there is no more mount information available.
+ */
+ if (hard_error < 0 && mp_error)
+ hard_error = cp->mp->am_error = mp_error;
+ if (hard_error > 0) {
+ /*
+ * Set a small(ish) timeout on an error node if
+ * the error was not a time out.
+ */
+ switch (hard_error) {
+ case ETIMEDOUT:
+ case EWOULDBLOCK:
+ cp->mp->am_timeo = 5;
+ break;
+ default:
+ cp->mp->am_timeo = 17;
+ break;
+ }
+ new_ttl(cp->mp);
+ }
+
+ /*
+ * Make sure that the error value in the mntfs has a
+ * reasonable value.
+ */
+ if (mf->mf_error < 0) {
+ mf->mf_error = hard_error;
+ if (hard_error)
+ mf->mf_flags |= MFF_ERROR;
+ }
+
+ /*
+ * In any case we don't need the continuation any more
+ */
+ free_continuation(cp);
+
+ return hard_error;
+}
+
+/*
+ * Automount interface to RPC lookup routine
+ */
+static am_node *afs_lookuppn P((am_node *mp, char *fname, int *error_return, int op));
+static am_node *afs_lookuppn(mp, fname, error_return, op)
+am_node *mp;
+char *fname;
+int *error_return;
+int op;
+{
+#define ereturn(x) { *error_return = x; return 0; }
+
+ /*
+ * Find the corresponding entry and return
+ * the file handle for it.
+ */
+ am_node *ap, *new_mp, *ap_hung;
+ char *info; /* Mount info - where to get the file system */
+ char **ivec, **xivec; /* Split version of info */
+ char *auto_opts; /* Automount options */
+ int error = 0; /* Error so far */
+ char path_name[MAXPATHLEN]; /* General path name buffer */
+ char *pfname; /* Path for database lookup */
+ struct continuation *cp; /* Continuation structure if we need to mount */
+ int in_progress = 0; /* # of (un)mount in progress */
+ char *dflts;
+ mntfs *mf;
+
+#ifdef DEBUG
+ dlog("in afs_lookuppn");
+#endif /* DEBUG */
+
+ /*
+ * If the server is shutting down
+ * then don't return information
+ * about the mount point.
+ */
+ if (amd_state == Finishing) {
+#ifdef DEBUG
+ if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &dfs_ops)
+ dlog("%s mount ignored - going down", fname);
+ else
+ dlog("%s/%s mount ignored - going down", mp->am_path, fname);
+#endif /* DEBUG */
+ ereturn(ENOENT);
+ }
+
+ /*
+ * Handle special case of "." and ".."
+ */
+ if (fname[0] == '.') {
+ if (fname[1] == '\0')
+ return mp; /* "." is the current node */
+ if (fname[1] == '.' && fname[2] == '\0') {
+ if (mp->am_parent) {
+#ifdef DEBUG
+ dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
+#endif /* DEBUG */
+ return mp->am_parent; /* ".." is the parent node */
+ }
+ ereturn(ESTALE);
+ }
+ }
+
+ /*
+ * Check for valid key name.
+ * If it is invalid then pretend it doesn't exist.
+ */
+ if (!valid_key(fname)) {
+ plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
+ ereturn(ENOENT);
+ }
+
+ /*
+ * Expand key name.
+ * fname is now a private copy.
+ */
+ fname = expand_key(fname);
+
+ for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) {
+ /*
+ * Otherwise search children of this node
+ */
+ if (FSTREQ(ap->am_name, fname)) {
+ mf = ap->am_mnt;
+ if (ap->am_error) {
+ error = ap->am_error;
+ continue;
+ }
+
+ /*
+ * If the error code is undefined then it must be
+ * in progress.
+ */
+ if (mf->mf_error < 0)
+ goto in_progrss;
+
+ /*
+ * Check for a hung node
+ */
+ if (FSRV_ISDOWN(mf->mf_server)) {
+#ifdef DEBUG
+ dlog("server hung");
+#endif /* DEBUG */
+ error = ap->am_error;
+ ap_hung = ap;
+ continue;
+ }
+
+ /*
+ * If there was a previous error with this node
+ * then return that error code.
+ */
+ if (mf->mf_flags & MFF_ERROR) {
+ error = mf->mf_error;
+ continue;
+ }
+
+ if (!(mf->mf_flags & MFF_MOUNTED) /*|| (mf->mf_flags & MFF_UNMOUNTING)*/) {
+in_progrss:
+ /*
+ * If the fs is not mounted or it is unmounting then there
+ * is a background (un)mount in progress. In this case
+ * we just drop the RPC request (return nil) and
+ * wait for a retry, by which time the (un)mount may
+ * have completed.
+ */
+#ifdef DEBUG
+ dlog("ignoring mount of %s in %s -- in progress",
+ fname, mf->mf_mount);
+#endif /* DEBUG */
+ in_progress++;
+ continue;
+ }
+
+ /*
+ * Otherwise we have a hit: return the current mount point.
+ */
+#ifdef DEBUG
+ dlog("matched %s in %s", fname, ap->am_path);
+#endif /* DEBUG */
+ free(fname);
+ return ap;
+ }
+ }
+
+ if (in_progress) {
+#ifdef DEBUG
+ dlog("Waiting while %d mount(s) in progress", in_progress);
+#endif /* DEBUG */
+ free(fname);
+ ereturn(-1);
+ }
+
+ /*
+ * If an error occured then return it.
+ */
+ if (error) {
+#ifdef DEBUG
+ errno = error; /* XXX */
+ dlog("Returning error: %m", error);
+#endif /* DEBUG */
+ free(fname);
+ ereturn(error);
+ }
+
+ /*
+ * If doing a delete then don't create again!
+ */
+ switch (op) {
+ case VLOOK_DELETE:
+ ereturn(ENOENT);
+ break;
+
+ case VLOOK_CREATE:
+ break;
+
+ default:
+ plog(XLOG_FATAL, "Unknown op to afs_lookuppn: 0x%x", op);
+ ereturn(EINVAL);
+ break;
+ }
+
+ /*
+ * If the server is going down then just return,
+ * don't try to mount any more file systems
+ */
+ if ((int)amd_state >= (int)Finishing) {
+#ifdef DEBUG
+ dlog("not found - server going down anyway");
+#endif /* DEBUG */
+ free(fname);
+ ereturn(ENOENT);
+ }
+
+ /*
+ * If we get there then this is a reference to an,
+ * as yet, unknown name so we need to search the mount
+ * map for it.
+ */
+ if (mp->am_pref) {
+ sprintf(path_name, "%s%s", mp->am_pref, fname);
+ pfname = path_name;
+ } else {
+ pfname = fname;
+ }
+
+ mf = mp->am_mnt;
+
+#ifdef DEBUG
+ dlog("will search map info in %s to find %s", mf->mf_info, pfname);
+#endif /* DEBUG */
+ /*
+ * Consult the oracle for some mount information.
+ * info is malloc'ed and belongs to this routine.
+ * It ends up being free'd in free_continuation().
+ *
+ * Note that this may return -1 indicating that information
+ * is not yet available.
+ */
+ error = mapc_search((mnt_map*) mf->mf_private, pfname, &info);
+ if (error) {
+ if (error > 0)
+ plog(XLOG_MAP, "No map entry for %s", pfname);
+ else
+ plog(XLOG_MAP, "Waiting on map entry for %s", pfname);
+ free(fname);
+ ereturn(error);
+ }
+
+#ifdef DEBUG
+ dlog("mount info is %s", info);
+#endif /* DEBUG */
+
+ /*
+ * Split info into an argument vector.
+ * The vector is malloc'ed and belongs to
+ * this routine. It is free'd in free_continuation()
+ */
+ xivec = ivec = strsplit(info, ' ', '\"');
+
+ /*
+ * Default error code...
+ */
+ if (ap_hung)
+ error = EWOULDBLOCK;
+ else
+ error = ENOENT;
+
+ /*
+ * Allocate a new map
+ */
+ new_mp = exported_ap_alloc();
+ if (new_mp == 0) {
+ free((voidp) xivec);
+ free((voidp) info);
+ free((voidp) fname);
+ ereturn(ENOSPC);
+ }
+
+ if (mf->mf_auto)
+ auto_opts = mf->mf_auto;
+ else
+ auto_opts = "";
+
+ auto_opts = strdup(auto_opts);
+
+#ifdef DEBUG
+ dlog("searching for /defaults entry");
+#endif /* DEBUG */
+ if (mapc_search((mnt_map*) mf->mf_private, "/defaults", &dflts) == 0) {
+ char *dfl;
+ char **rvec;
+#ifdef DEBUG
+ dlog("/defaults gave %s", dflts);
+#endif /* DEBUG */
+ if (*dflts == '-')
+ dfl = dflts+1;
+ else
+ dfl = dflts;
+
+ /*
+ * Chop the defaults up
+ */
+ rvec = strsplit(dfl, ' ', '\"');
+ /*
+ * Extract first value
+ */
+ dfl = rvec[0];
+
+ /*
+ * If there were any values at all...
+ */
+ if (dfl) {
+ /*
+ * Log error if there were other values
+ */
+ if (rvec[1]) {
+#ifdef DEBUG
+ dlog("/defaults chopped into %s", dfl);
+#endif /* DEBUG */
+ plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info);
+ }
+
+ /*
+ * Prepend to existing defaults if they exist,
+ * otherwise just use these defaults.
+ */
+ if (*auto_opts && *dfl) {
+ char *nopts = (char *) xmalloc(strlen(auto_opts)+strlen(dfl)+2);
+ sprintf(nopts, "%s;%s", dfl, auto_opts);
+ free(auto_opts);
+ auto_opts = nopts;
+ } else if (*dfl) {
+ auto_opts = strealloc(auto_opts, dfl);
+ }
+ }
+ free(dflts);
+ /*
+ * Don't need info vector any more
+ */
+ free((voidp) rvec);
+ }
+
+ /*
+ * Fill it in
+ */
+ init_map(new_mp, fname);
+
+ /*
+ * Put it in the table
+ */
+ insert_am(new_mp, mp);
+
+ /*
+ * Fill in some other fields,
+ * path and mount point.
+ *
+ * bugfix: do not prepend old am_path if direct map
+ * <wls@astro.umd.edu> William Sebok
+ */
+ new_mp->am_path = str3cat(new_mp->am_path,
+ mf->mf_ops == &dfs_ops ? "" : mp->am_path,
+ *fname == '/' ? "" : "/", fname);
+
+#ifdef DEBUG
+ dlog("setting path to %s", new_mp->am_path);
+#endif /* DEBUG */
+
+ /*
+ * Take private copy of pfname
+ */
+ pfname = strdup(pfname);
+
+ /*
+ * Construct a continuation
+ */
+ cp = ALLOC(continuation);
+ cp->mp = new_mp;
+ cp->xivec = xivec;
+ cp->ivec = ivec;
+ cp->info = info;
+ cp->key = pfname;
+ cp->auto_opts = auto_opts;
+ cp->retry = FALSE;
+ cp->tried = FALSE;
+ cp->start = clocktime();
+ cp->def_opts = strdup(auto_opts);
+ bzero((voidp) &cp->fs_opts, sizeof(cp->fs_opts));
+
+ /*
+ * Try and mount the file system
+ * If this succeeds immediately (possible
+ * for a ufs file system) then return
+ * the attributes, otherwise just
+ * return an error.
+ */
+ error = afs_bgmount(cp, error);
+ reschedule_timeout_mp();
+ if (!error) {
+ free(fname);
+ return new_mp;
+ }
+
+ if (error && (cp->mp->am_mnt->mf_ops == &efs_ops))
+ cp->mp->am_error = error;
+
+ assign_error_mntfs(new_mp);
+
+ free(fname);
+
+ ereturn(error);
+#undef ereturn
+}
+
+/*
+ * Locate next node in sibling list which is mounted
+ * and is not an error node.
+ */
+static am_node *next_nonerror_node P((am_node *xp));
+static am_node *next_nonerror_node(xp)
+am_node *xp;
+{
+ mntfs *mf;
+
+ /*
+ * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
+ * Fixes a race condition when mounting direct automounts.
+ * Also fixes a problem when doing a readdir on a directory
+ * containing hung automounts.
+ */
+ while (xp &&
+ (!(mf = xp->am_mnt) || /* No mounted filesystem */
+ mf->mf_error != 0 || /* There was a mntfs error */
+ xp->am_error != 0 || /* There was a mount error */
+ !(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */
+ (mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */
+ )
+ xp = xp->am_osib;
+
+ return xp;
+}
+
+static int afs_readdir P((am_node *mp, nfscookie cookie, struct dirlist *dp, struct entry *ep, int count));
+static int afs_readdir(mp, cookie, dp, ep, count)
+am_node *mp;
+nfscookie cookie;
+struct dirlist *dp;
+struct entry *ep;
+int count;
+{
+ unsigned int gen = *(unsigned int*) cookie;
+ am_node *xp;
+
+ dp->eof = FALSE;
+
+ if (gen == 0) {
+ /*
+ * In the default instance (which is used to
+ * start a search) we return "." and "..".
+ *
+ * This assumes that the count is big enough
+ * to allow both "." and ".." to be returned in
+ * a single packet. If it isn't (which would
+ * be fairly unbelievable) then tough.
+ */
+#ifdef DEBUG
+ dlog("default search");
+#endif /* DEBUG */
+ /*
+ * Check for enough room. This is extremely
+ * approximate but is more than enough space.
+ * Really need 2 times:
+ * 4byte fileid
+ * 4byte cookie
+ * 4byte name length
+ * 4byte name
+ * plus the dirlist structure
+ */
+ if (count <
+ (2 * (2 * (sizeof(*ep) + sizeof("..") + 4)
+ + sizeof(*dp))))
+ return EINVAL;
+
+ xp = next_nonerror_node(mp->am_child);
+ dp->entries = ep;
+
+ /* construct "." */
+ ep[0].fileid = mp->am_gen;
+ ep[0].name = ".";
+ ep[0].nextentry = &ep[1];
+ *(unsigned int *) ep[0].cookie = 0;
+
+ /* construct ".." */
+ if (mp->am_parent)
+ ep[1].fileid = mp->am_parent->am_gen;
+ else
+ ep[1].fileid = mp->am_gen;
+ ep[1].name = "..";
+ ep[1].nextentry = 0;
+ *(unsigned int *) ep[1].cookie =
+ xp ? xp->am_gen : ~(unsigned int)0;
+
+ if (!xp) dp->eof = TRUE;
+ return 0;
+ }
+
+#ifdef DEBUG
+ dlog("real child");
+#endif /* DEBUG */
+
+ if (gen == ~(unsigned int)0) {
+#ifdef DEBUG
+ dlog("End of readdir in %s", mp->am_path);
+#endif /* DEBUG */
+ dp->eof = TRUE;
+ dp->entries = 0;
+ return 0;
+ }
+
+ xp = mp->am_child;
+ while (xp && xp->am_gen != gen)
+ xp = xp->am_osib;
+
+ if (xp) {
+ int nbytes = count / 2; /* conservative */
+ int todo = MAX_READDIR_ENTRIES;
+ dp->entries = ep;
+ do {
+ am_node *xp_next = next_nonerror_node(xp->am_osib);
+
+ if (xp_next) {
+ *(unsigned int *) ep->cookie = xp_next->am_gen;
+ } else {
+ *(unsigned int *) ep->cookie = ~(unsigned int)0;
+ dp->eof = TRUE;
+ }
+
+ ep->fileid = xp->am_gen;
+ ep->name = xp->am_name;
+ nbytes -= sizeof(*ep) + strlen(xp->am_name) + 1;
+
+ xp = xp_next;
+
+ if (nbytes > 0 && !dp->eof && todo > 1) {
+ ep->nextentry = ep + 1;
+ ep++;
+ --todo;
+ } else {
+ todo = 0;
+ }
+ } while (todo > 0);
+
+ ep->nextentry = 0;
+
+ return 0;
+ }
+
+ return ESTALE;
+
+}
+
+static am_node *dfs_readlink P((am_node *mp, int *error_return));
+static am_node *dfs_readlink(mp, error_return)
+am_node *mp;
+int *error_return;
+{
+ am_node *xp;
+ int rc = 0;
+
+ xp = next_nonerror_node(mp->am_child);
+ if (!xp) {
+ if (!mp->am_mnt->mf_private)
+ afs_mkcacheref(mp->am_mnt); /* XXX */
+ xp = afs_lookuppn(mp, mp->am_path+1, &rc, VLOOK_CREATE);
+ }
+
+ if (xp) {
+ new_ttl(xp); /* (7/12/89) from Rein Tollevik */
+ return xp;
+ }
+ if (amd_state == Finishing)
+ rc = ENOENT;
+ *error_return = rc;
+ return 0;
+}
+
+/*
+ * Ops structure
+ */
+am_ops root_ops = {
+ "root",
+ 0, /* root_match */
+ 0, /* root_init */
+ root_mount,
+ 0,
+ afs_umount,
+ 0,
+ afs_lookuppn,
+ afs_readdir,
+ 0, /* root_readlink */
+ 0, /* root_mounted */
+ 0, /* root_umounted */
+ find_afs_srvr,
+ FS_NOTIMEOUT|FS_AMQINFO|FS_DIRECTORY
+};
+
+am_ops afs_ops = {
+ "auto",
+ afs_match,
+ 0, /* afs_init */
+ afs_mount,
+ 0,
+ afs_umount,
+ 0,
+ afs_lookuppn,
+ afs_readdir,
+ 0, /* afs_readlink */
+ 0, /* afs_mounted */
+ afs_umounted,
+ find_afs_srvr,
+ FS_AMQINFO|FS_DIRECTORY
+};
+
+am_ops toplvl_ops = {
+ "toplvl",
+ afs_match,
+ 0, /* afs_init */
+ toplvl_mount,
+ 0,
+ toplvl_umount,
+ 0,
+ afs_lookuppn,
+ afs_readdir,
+ 0, /* toplvl_readlink */
+ toplvl_mounted,
+ 0, /* toplvl_umounted */
+ find_afs_srvr,
+ FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY
+};
+
+am_ops dfs_ops = {
+ "direct",
+ afs_match,
+ 0, /* dfs_init */
+ toplvl_mount,
+ 0,
+ toplvl_umount,
+ 0,
+ efs_lookuppn,
+ efs_readdir,
+ dfs_readlink,
+ toplvl_mounted,
+ 0, /* afs_umounted */
+ find_afs_srvr,
+ FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO
+};
+
+#ifdef HAS_UNION_FS
+am_ops union_ops = {
+ "union",
+ afs_match,
+ 0, /* afs_init */
+ toplvl_mount,
+ 0,
+ toplvl_umount,
+ 0,
+ afs_lookuppn,
+ afs_readdir,
+ 0, /* toplvl_readlink */
+ union_mounted,
+ 0, /* toplvl_umounted */
+ find_afs_srvr,
+ FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY
+};
+#endif /* HAS_UNION_FS */
diff --git a/usr.sbin/amd/amd/am_ops.c b/usr.sbin/amd/amd/am_ops.c
new file mode 100644
index 0000000..4360110
--- /dev/null
+++ b/usr.sbin/amd/amd/am_ops.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)am_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: am_ops.c,v 5.2.2.1 1992/02/09 15:08:17 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+static am_ops *vops[] = {
+#ifdef HAS_UFS
+ &ufs_ops,
+#endif
+#ifdef HAS_NFS
+ &nfs_ops,
+#endif
+#ifdef HAS_NFSX
+ &nfsx_ops,
+#endif
+#ifdef HAS_HOST
+ &host_ops,
+#endif
+#ifdef HAS_SFS
+ &sfs_ops,
+#endif
+#ifdef HAS_SFSX
+ &sfsx_ops,
+#endif
+#ifdef HAS_LOFS
+ &lofs_ops,
+#endif
+#ifdef HAS_PFS
+ &pfs_ops,
+#endif
+#ifdef HAS_UNION_FS
+ &union_ops,
+#endif
+ &afs_ops, /* These four should be last ... */
+ &dfs_ops, /* ... */
+ &toplvl_ops, /* ... */
+ &efs_ops, /* ... in the order afs; dfs; toplvl; efs */
+ 0
+};
+
+void ops_showfstypes P((FILE *fp));
+void ops_showfstypes(fp)
+FILE *fp;
+{
+ struct am_ops **ap;
+ int l = 0;
+
+ for (ap = vops; *ap; ap++) {
+ fputs((*ap)->fs_type, fp);
+ if (ap[1]) fputs(", ", fp);
+ l += strlen((*ap)->fs_type) + 2;
+ if (l > 60) { l = 0; fputs("\n ", fp); }
+ }
+}
+
+#ifdef SUNOS4_COMPAT
+#ifdef nomore
+/*
+ * Crack a SunOS4-style host:fs:sub-link line
+ * Construct an amd-style line and call the
+ * normal amd matcher.
+ */
+am_ops *sunos4_match(fo, key, g_key, path, keym, map)
+am_opts *fo;
+char *key;
+char *g_key;
+char *path;
+char *keym;
+char *map;
+{
+ char *host = key;
+ char *fs = strchr(host, ':');
+ char *sublink = fs ? strchr(fs+1, ':') : 0;
+ char keybuf[MAXPATHLEN];
+
+ sprintf(keybuf, "type:=nfs;rhost:=%s;rfs:=%s;sublink:=%s;opts:=%s", host,
+ fs ? fs+1 : "",
+ sublink ? sublink+1 : "",
+ g_key);
+ return ops_match(fo, keybuf, "", path, keym, map);
+}
+#endif
+#endif /* SUNOS4_COMPAT */
+
+am_ops *ops_match(fo, key, g_key, path, keym, map)
+am_opts *fo;
+char *key;
+char *g_key;
+char *path;
+char *keym;
+char *map;
+{
+ am_ops **vp;
+ am_ops *rop = 0;
+
+ /*
+ * First crack the global opts and the local opts
+ */
+ if (!eval_fs_opts(fo, key, g_key, path, keym, map)) {
+ rop = &efs_ops;
+ } else if (fo->opt_type == 0) {
+ plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map);
+ rop = &efs_ops;
+ } else {
+ /*
+ * Next find the correct filesystem type
+ */
+ for (vp = vops; rop = *vp; vp++)
+ if (strcmp(rop->fs_type, fo->opt_type) == 0)
+ break;
+
+ if (!rop) {
+ plog(XLOG_USER, "fs type \"%s\" not recognised", fo->opt_type);
+ rop = &efs_ops;
+ }
+ }
+
+ /*
+ * Make sure we have a default mount option.
+ * Otherwise skip past any leading '-'.
+ */
+ if (fo->opt_opts == 0)
+ fo->opt_opts = "rw,defaults";
+ else if (*fo->opt_opts == '-')
+ fo->opt_opts++;
+
+ /*
+ * Check the filesystem is happy
+ */
+ if (fo->fs_mtab)
+ free((voidp) fo->fs_mtab);
+
+ if (fo->fs_mtab = (*rop->fs_match)(fo))
+ return rop;
+
+ /*
+ * Return error file system
+ */
+ fo->fs_mtab = (*efs_ops.fs_match)(fo);
+ return &efs_ops;
+}
diff --git a/usr.sbin/amd/amd/amd.8 b/usr.sbin/amd/amd/amd.8
new file mode 100644
index 0000000..9fa01a2
--- /dev/null
+++ b/usr.sbin/amd/amd/amd.8
@@ -0,0 +1,232 @@
+.\"
+.\" Copyright (c) 1989 Jan-Simon Pendry
+.\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jan-Simon Pendry at Imperial College, London.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)amd.8 5.10 (Berkeley) 4/19/94
+.\"
+.\" $Id: amd.8,v 5.2.2.1 1992/02/09 15:11:39 jsp beta $
+.\"
+.Dd "April 19, 1994"
+.Dt AMD 8
+.Os
+.Sh NAME
+.Nm amd
+.Nd automatically mount file systems
+.Sh SYNOPSIS
+.Nm amd
+.Op Fl nprv
+.Op Fl a Ar mount_point
+.Op Fl c Ar duration
+.Op Fl d Ar domain
+.Bk -words
+.Op Fl k Ar kernel-arch
+.Ek
+.Op Fl l Ar logfile
+.Op Fl t Ar interval.interval
+.Bk -words
+.Op Fl w Ar interval
+.Ek
+.Op Fl x Ar log-option
+.Op Fl y Ar YP-domain
+.Bk -words
+.Op Fl C Ar cluster-name
+.Ek
+.Op Fl D Ar option
+.Oo
+.Ar directory mapname
+.Op Fl map-options
+.Oc
+.Ar ...
+.Sh DESCRIPTION
+.Nm Amd
+is a daemon that automatically mounts filesystems
+whenever a file or directory
+within that filesystem is accessed.
+Filesystems are automatically unmounted when they
+appear to be quiescent.
+.Pp
+.Nm Amd
+operates by attaching itself as an
+.Tn NFS
+server to each of the specified
+.Ar directories .
+Lookups within the specified directories
+are handled by
+.Nm amd ,
+which uses the map defined by
+.Ar mapname
+to determine how to resolve the lookup.
+Generally, this will be a host name, some filesystem information
+and some mount options for the given filesystem.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl a Ar temporary-directory
+Specify an alternative location for the real mount points.
+The default is
+.Pa /a .
+.It Fl c Ar duration
+Specify a
+.Ar duration ,
+in seconds, that a looked up name remains
+cached when not in use. The default is 5 minutes.
+.It Fl d Ar domain
+Specify the local domain name. If this option is not
+given the domain name is determined from the hostname.
+.It Fl k Ar kernel-arch
+Specifies the kernel architecture. This is used solely
+to set the ${karch} selector.
+.It Fl l Ar logfile
+Specify a logfile in which to record mount and unmount events.
+If
+.Ar logfile
+is the string
+.Em syslog ,
+the log messages will be sent to the system log daemon by
+.Xr syslog 3 .
+.It Fl n
+Normalize hostnames.
+The name referred to by ${rhost} is normalized relative to the
+host database before being used. The effect is to translate
+aliases into ``official'' names.
+.It Fl p
+Print
+.Em PID .
+Outputs the process-id of
+.Nm amd
+to standard output where it can be saved into a file.
+.It Fl r
+Restart existing mounts.
+.Nm Amd
+will scan the mount file table to determine which filesystems
+are currently mounted. Whenever one of these would have
+been auto-mounted,
+.Nm amd
+.Em inherits
+it.
+.It Fl t Ar interval.interval
+Specify the
+.Ar interval ,
+in tenths of a second, between
+.Tn NFS/RPC/UDP
+retries.
+The default is 0.8 seconds.
+The second values alters the retransmit counter.
+Useful defaults are supplied if either or both
+values are missing.
+.It Fl v
+Version. Displays version and configuration information on standard error.
+.It Fl w Ar interval
+Specify an
+.Ar interval ,
+in seconds, between attempts to dismount
+filesystems that have exceeded their cached times.
+The default is 2 minutes.
+.It Fl y Ar domain
+Specify an alternative
+.Tn NIS
+domain from which to fetch the
+.Tn NIS
+maps.
+The default is the system domain name.
+This option is ignored if
+.Tn NIS
+support is not available.
+.It Fl x Ar options
+Specify run-time logging options. The options are a comma separated
+list chosen from: fatal, error, user, warn, info, map, stats, all.
+.It Fl D Ar option
+Select from a variety of debug options. Prefixing an
+option with the string
+.Em no
+reverses the effect of that option. Options are cumulative.
+The most useful option is
+.Ar all .
+.El
+.Pp
+Since
+.Fl D
+is only used for debugging other options are not documented here:
+the current supported set of options is listed by the
+.Fl v
+option
+and a fuller description is available in the program source.
+.Sh FILES
+.Bl -tag -width /axx
+.It Pa /a
+directory under which filesystems are dynamically mounted
+.El
+.Sh CAVEATS
+Some care may be required when creating a mount map.
+.Pp
+Symbolic links on an
+.Tn NFS
+filesystem can be incredibly inefficient.
+In most implementations of
+.Tn NFS ,
+their interpolations are not cached by
+the kernel and each time a symbolic link is
+encountered during a
+.Em lookuppn
+translation it costs an
+.Tn RPC
+call to the
+.Tn NFS
+server.
+A large improvement in real-time
+performance could be gained by adding a cache somewhere.
+Replacing
+.Xr symlinks 2
+with a suitable incarnation of the auto-mounter
+results in a large real-time speedup, but also causes a large
+number of process context switches.
+.Pp
+A weird imagination is most useful to gain full advantage of all
+the features.
+.Sh SEE ALSO
+.Xr amq 8 ,
+.Xr hostname 1 ,
+.Xr mount 8 ,
+.Xr umount 8 ,
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
+.Sh AUTHOR
+.An Jan-Simon Pendry
+<jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
+.Sh HISTORY
+The
+.Nm amd
+utility first appeared in 4.4BSD.
diff --git a/usr.sbin/amd/amd/amd.c b/usr.sbin/amd/amd/amd.c
new file mode 100644
index 0000000..c3b2b61
--- /dev/null
+++ b/usr.sbin/amd/amd/amd.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amd.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amd.c,v 5.2.2.1 1992/02/09 15:08:15 jsp beta $
+ *
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+/*
+ * Automounter
+ */
+
+#include "am.h"
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <setjmp.h>
+
+char pid_fsname[16 + MAXHOSTNAMELEN]; /* "kiska.southseas.nz:(pid%d)" */
+char *progname; /* "amd" */
+#ifdef HAS_HOST
+#ifdef HOST_EXEC
+char *host_helper;
+#endif /* HOST_EXEC */
+#endif /* HAS_HOST */
+char *auto_dir = "/a";
+char *hostdomain = "unknown.domain";
+char hostname[MAXHOSTNAMELEN] = "localhost"; /* Hostname */
+char hostd[2*MAXHOSTNAMELEN]; /* Host+domain */
+char *op_sys = OS_REP; /* Name of current op_sys */
+char *arch = ARCH_REP; /* Name of current architecture */
+char *endian = ARCH_ENDIAN; /* Big or Little endian */
+char *wire;
+int foreground = 1; /* This is the top-level server */
+int mypid; /* Current process id */
+int immediate_abort; /* Should close-down unmounts be retried */
+struct in_addr myipaddr; /* (An) IP address of this host */
+serv_state amd_state;
+struct amd_stats amd_stats; /* Server statistics */
+time_t do_mapc_reload = 0; /* mapc_reload() call required? */
+jmp_buf select_intr;
+int select_intr_valid;
+int orig_umask;
+
+/*
+ * Signal handler:
+ * SIGINT - tells amd to do a full shutdown, including unmounting all filesystem.
+ * SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes.
+ */
+static void sigterm(sig)
+int sig;
+{
+#ifdef SYS5_SIGNALS
+ signal(sig, sigterm);
+#endif /* SYS5_SIGNALS */
+
+ switch (sig) {
+ case SIGINT:
+ immediate_abort = 15;
+ break;
+
+ case SIGTERM:
+ immediate_abort = -1;
+ /* fall through... */
+
+ default:
+ plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
+ break;
+ }
+ if (select_intr_valid)
+ longjmp(select_intr, sig);
+}
+
+/*
+ * Hook for cache reload.
+ * When a SIGHUP arrives it schedules a call to mapc_reload
+ */
+/*ARGSUSED*/
+static void sighup(sig)
+int sig;
+{
+#ifdef SYS5_SIGNALS
+ signal(sig, sighup);
+#endif /* SYS5_SIGNALS */
+
+#ifdef DEBUG
+ if (sig != SIGHUP)
+ dlog("spurious call to sighup");
+#endif /* DEBUG */
+ /*
+ * Force a reload by zero'ing the timer
+ */
+ if (amd_state == Run)
+ do_mapc_reload = 0;
+}
+
+/*ARGSUSED*/
+static void parent_exit(sig)
+int sig;
+{
+ exit(0);
+}
+
+static int daemon_mode(P_void)
+{
+ int bgpid;
+
+ signal(SIGQUIT, parent_exit);
+ bgpid = background();
+
+ if (bgpid != 0) {
+ if (print_pid) {
+ printf("%d\n", bgpid);
+ fflush(stdout);
+ }
+ /*
+ * Now wait for the automount points to
+ * complete.
+ */
+ for (;;)
+ pause();
+ }
+
+ signal(SIGQUIT, SIG_DFL);
+
+ /*
+ * Pretend we are in the foreground again
+ */
+ foreground = 1;
+
+#ifdef TIOCNOTTY
+ {
+ int t = open("/dev/tty", O_RDWR);
+ if (t < 0) {
+ if (errno != ENXIO) /* not an error if already no controlling tty */
+ plog(XLOG_WARNING, "Could not open controlling tty: %m");
+ } else {
+ if (ioctl(t, TIOCNOTTY, 0) < 0 && errno != ENOTTY)
+ plog(XLOG_WARNING, "Could not disassociate tty (TIOCNOTTY): %m");
+ (void) close(t);
+ }
+ }
+#else
+ (void) setpgrp();
+#endif /* TIOCNOTTY */
+
+ return getppid();
+}
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char *domdot;
+ int ppid = 0;
+ int error;
+
+ /*
+ * Make sure some built-in assumptions are true before we start
+ */
+ assert(sizeof(nfscookie) >= sizeof (unsigned int));
+ assert(sizeof(int) >= 4);
+
+ /*
+ * Set processing status.
+ */
+ amd_state = Start;
+
+ /*
+ * Determine program name
+ */
+ if (argv[0]) {
+ progname = strrchr(argv[0], '/');
+ if (progname && progname[1])
+ progname++;
+ else
+ progname = argv[0];
+ }
+
+ if (!progname)
+ progname = "amd";
+
+ /*
+ * Initialise process id. This is kept
+ * cached since it is used for generating
+ * and using file handles.
+ */
+ mypid = getpid();
+
+ /*
+ * Get local machine name
+ */
+ if (gethostname(hostname, sizeof(hostname)) < 0) {
+ plog(XLOG_FATAL, "gethostname: %m");
+ going_down(1);
+ }
+ /*
+ * Check it makes sense
+ */
+ if (!*hostname) {
+ plog(XLOG_FATAL, "host name is not set");
+ going_down(1);
+ }
+ /*
+ * Partially initialise hostd[]. This
+ * is completed in get_args().
+ */
+ if (domdot = strchr(hostname, '.')) {
+ /*
+ * Hostname already contains domainname.
+ * Split out hostname and domainname
+ * components
+ */
+ *domdot++ = '\0';
+ hostdomain = domdot;
+ }
+ strcpy(hostd, hostname);
+
+ /*
+ * Trap interrupts for shutdowns.
+ */
+ (void) signal(SIGINT, sigterm);
+
+ /*
+ * Hangups tell us to reload the cache
+ */
+ (void) signal(SIGHUP, sighup);
+
+ /*
+ * Trap Terminate so that we can shutdown gracefully (some chance)
+ */
+ (void) signal(SIGTERM, sigterm);
+ /*
+ * Trap Death-of-a-child. These allow us to
+ * pick up the exit status of backgrounded mounts.
+ * See "sched.c".
+ */
+ (void) signal(SIGCHLD, sigchld);
+
+ /*
+ * Fix-up any umask problems. Most systems default
+ * to 002 which is not too convenient for our purposes
+ */
+ orig_umask = umask(0);
+
+ /*
+ * Figure out primary network name
+ */
+ wire = getwire();
+
+ /*
+ * Determine command-line arguments
+ */
+ get_args(argc, argv);
+
+ /*
+ * Get our own IP address so that we
+ * can mount the automounter.
+ */
+ { struct sockaddr_in sin;
+ get_myaddress(&sin);
+ myipaddr.s_addr = sin.sin_addr.s_addr;
+ }
+
+ /*
+ * Now check we are root.
+ */
+ if (geteuid() != 0) {
+ plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %d)", geteuid());
+ going_down(1);
+ }
+
+#ifdef HAS_NIS_MAPS
+ /*
+ * If the domain was specified then bind it here
+ * to circumvent any default bindings that may
+ * be done in the C library.
+ */
+ if (domain && yp_bind(domain)) {
+ plog(XLOG_FATAL, "Can't bind to domain \"%s\"", domain);
+ going_down(1);
+ }
+#endif /* HAS_NIS_MAPS */
+
+#ifdef DEBUG
+ Debug(D_DAEMON)
+#endif /* DEBUG */
+ ppid = daemon_mode();
+
+ sprintf(pid_fsname, "%s:(pid%d)", hostname, mypid);
+
+ do_mapc_reload = clocktime() + ONE_HOUR;
+
+ /*
+ * Register automounter with system
+ */
+ error = mount_automounter(ppid);
+ if (error && ppid)
+ kill(SIGALRM, ppid);
+ going_down(error);
+
+ abort();
+}
diff --git a/usr.sbin/amd/amd/amq_subr.c b/usr.sbin/amd/amd/amq_subr.c
new file mode 100644
index 0000000..cf04d9d
--- /dev/null
+++ b/usr.sbin/amd/amd/amq_subr.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq_subr.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq_subr.c,v 5.2.2.1 1992/02/09 15:08:18 jsp beta $
+ *
+ */
+/*
+ * Auxilliary routines for amq tool
+ */
+
+#include "am.h"
+#include "amq.h"
+#include <ctype.h>
+
+/*ARGSUSED*/
+voidp
+amqproc_null_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static char res;
+
+ return (voidp) &res;
+}
+
+/*
+ * Return a sub-tree of mounts
+ */
+/*ARGSUSED*/
+amq_mount_tree_p *
+amqproc_mnttree_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static am_node *mp;
+ mp = find_ap(*(char **) argp);
+ return (amq_mount_tree_p *) &mp;
+}
+
+/*
+ * Unmount a single node
+ */
+/*ARGSUSED*/
+voidp
+amqproc_umnt_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static char res;
+ am_node *mp = find_ap(*(char **) argp);
+ if (mp)
+ forcibly_timeout_mp(mp);
+
+ return (voidp) &res;
+}
+
+/*
+ * Return global statistics
+ */
+/*ARGSUSED*/
+amq_mount_stats *
+amqproc_stats_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ return (amq_mount_stats *) &amd_stats;
+}
+
+/*
+ * Return the entire tree of mount nodes
+ */
+/*ARGSUSED*/
+amq_mount_tree_list *
+amqproc_export_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static amq_mount_tree_list aml;
+
+ aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0];
+ aml.amq_mount_tree_list_len = 1; /* XXX */
+
+ return &aml;
+}
+
+int *
+amqproc_setopt_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static int rc;
+
+ amq_setopt *opt = (amq_setopt *) argp;
+
+ rc = 0;
+ switch (opt->as_opt) {
+ case AMOPT_DEBUG:
+#ifdef DEBUG
+ if (debug_option(opt->as_str))
+ rc = EINVAL;
+#else
+ rc = EINVAL;
+#endif /* DEBUG */
+ break;
+
+ case AMOPT_LOGFILE:
+#ifdef not_yet
+ if (switch_to_logfile(opt->as_str))
+ rc = EINVAL;
+#else
+ rc = EACCES;
+#endif /* not_yet */
+ break;
+
+ case AMOPT_XLOG:
+ if (switch_option(opt->as_str))
+ rc = EINVAL;
+ break;
+
+ case AMOPT_FLUSHMAPC:
+ if (amd_state == Run) {
+ plog(XLOG_INFO, "amq says flush cache");
+ do_mapc_reload = 0;
+ flush_nfs_fhandle_cache((fserver *) 0);
+ flush_srvr_nfs_cache();
+ }
+ break;
+ }
+ return &rc;
+}
+
+amq_mount_info_list *
+amqproc_getmntfs_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+extern qelem mfhead;
+ return (amq_mount_info_list *) &mfhead; /* XXX */
+}
+
+static int ok_security(rqstp)
+struct svc_req *rqstp;
+{
+ struct sockaddr_in *sin;
+
+ sin = svc_getcaller(rqstp->rq_xprt);
+ if (ntohs(sin->sin_port) >= 1024 ||
+ !(sin->sin_addr.s_addr == htonl(0x7f000001) ||
+ sin->sin_addr.s_addr == myipaddr.s_addr)) {
+ char dq[20];
+ plog(XLOG_INFO, "AMQ request from %s.%d DENIED",
+ inet_dquad(dq, sin->sin_addr.s_addr),
+ ntohs(sin->sin_port));
+ return(0);
+ }
+ return(1);
+}
+
+int *
+amqproc_mount_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static int rc;
+ char *s = *(amq_string *) argp;
+ char *cp;
+
+ plog(XLOG_INFO, "amq requested mount of %s", s);
+ /*
+ * Minimalist security check.
+ */
+ if (!ok_security(rqstp)) {
+ rc = EACCES;
+ return &rc;
+ }
+
+ /*
+ * Find end of key
+ */
+ for (cp = (char *) s; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
+ ;
+
+ if (!*cp) {
+ plog(XLOG_INFO, "amqproc_mount: Invalid arguments");
+ rc = EINVAL;
+ return &rc;
+ }
+ *cp++ = '\0';
+
+ /*
+ * Find start of value
+ */
+ while (*cp && isascii(*cp) && isspace(*cp))
+ cp++;
+
+ root_newmap(s, cp, (char *) 0);
+ rc = mount_auto_node(s, (voidp) root_node);
+ if (rc < 0)
+ return 0;
+ return &rc;
+}
+
+amq_string *
+amqproc_getvers_1(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+static amq_string res;
+ res = version;
+ return &res;
+}
+
+/*
+ * XDR routines.
+ */
+bool_t
+xdr_amq_string(xdrs, objp)
+ XDR *xdrs;
+ amq_string *objp;
+{
+ if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_amq_setopt(xdrs, objp)
+ XDR *xdrs;
+ amq_setopt *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)&objp->as_opt)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * More XDR routines - Should be used for OUTPUT ONLY.
+ */
+bool_t
+xdr_amq_mount_tree_node(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree *objp;
+{
+ am_node *mp = (am_node *) objp;
+
+ if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &mp->am_path)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &mp->am_stats.s_mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_amq_mount_subtree(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree *objp;
+{
+ am_node *mp = (am_node *) objp;
+
+ if (!xdr_amq_mount_tree_node(xdrs, objp)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&mp->am_osib, sizeof(amq_mount_tree), xdr_amq_mount_subtree)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&mp->am_child, sizeof(amq_mount_tree), xdr_amq_mount_subtree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_amq_mount_tree(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree *objp;
+{
+ am_node *mp = (am_node *) objp;
+ am_node *mnil = 0;
+
+ if (!xdr_amq_mount_tree_node(xdrs, objp)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&mnil, sizeof(amq_mount_tree), xdr_amq_mount_subtree)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&mp->am_child, sizeof(amq_mount_tree), xdr_amq_mount_subtree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_amq_mount_tree_p(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree_p *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_stats(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_stats *objp;
+{
+ if (!xdr_int(xdrs, &objp->as_drops)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_stale)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_mok)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_merr)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_uerr)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_tree_list(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree_list *objp;
+{
+ if (!xdr_array(xdrs, (char **)&objp->amq_mount_tree_list_val, (u_int *)&objp->amq_mount_tree_list_len, ~0, sizeof(amq_mount_tree_p), xdr_amq_mount_tree_p)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_amq_mount_info_qelem(xdrs, qhead)
+ XDR *xdrs;
+ qelem *qhead;
+{
+ /*
+ * Compute length of list
+ */
+ mntfs *mf;
+ u_int len = 0;
+ for (mf = LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
+ if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+ continue;
+ len++;
+ }
+ xdr_u_int(xdrs, &len);
+
+ /*
+ * Send individual data items
+ */
+ for (mf = LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
+ int up;
+ if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+ continue;
+
+ if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &mf->mf_mount)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &mf->mf_info)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mf->mf_error)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &mf->mf_refc)) {
+ return (FALSE);
+ }
+ if (mf->mf_server->fs_flags & FSF_ERROR)
+ up = 0;
+ else switch (mf->mf_server->fs_flags & (FSF_DOWN|FSF_VALID)) {
+ case FSF_DOWN|FSF_VALID: up = 0; break;
+ case FSF_VALID: up = 1; break;
+ default: up = -1; break;
+ }
+ if (!xdr_int(xdrs, &up)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
diff --git a/usr.sbin/amd/amd/clock.c b/usr.sbin/amd/amd/clock.c
new file mode 100644
index 0000000..91e11ee
--- /dev/null
+++ b/usr.sbin/amd/amd/clock.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)clock.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: clock.c,v 5.2.2.1 1992/02/09 15:08:20 jsp beta $
+ *
+ */
+
+/*
+ * Callouts.
+ *
+ * Modelled on kernel object of the same name.
+ * See usual references.
+ *
+ * Use of a heap-based mechanism was rejected:
+ * 1. more complex implementation needed.
+ * 2. not obvious that a list is too slow for Amd.
+ */
+
+#include "am.h"
+
+typedef struct callout callout;
+struct callout {
+ callout *c_next; /* List of callouts */
+ void (*c_fn)(); /* Function to call */
+ voidp c_closure; /* Closure to pass to call */
+ time_t c_time; /* Time of call */
+ int c_id; /* Unique identifier */
+};
+
+static callout callouts; /* List of pending callouts */
+static callout *free_callouts; /* Cache of free callouts */
+static int nfree_callouts; /* Number on free list */
+static int callout_id; /* Next free callout identifier */
+time_t next_softclock; /* Time of next call to softclock() */
+
+/*
+ * Number of callout slots we keep on the free list
+ */
+#define CALLOUT_FREE_SLOP 10
+
+/*
+ * Global assumption: valid id's are non-zero.
+ */
+#define CID_ALLOC() (++callout_id)
+#define CID_UNDEF (0)
+
+static callout *alloc_callout(P_void);
+static callout *alloc_callout()
+{
+ callout *cp = free_callouts;
+ if (cp) {
+ --nfree_callouts;
+ free_callouts = free_callouts->c_next;
+ return cp;
+ }
+ return ALLOC(callout);
+}
+
+static void free_callout P((callout *cp));
+static void free_callout(cp)
+callout *cp;
+{
+ if (nfree_callouts > CALLOUT_FREE_SLOP) {
+ free((voidp) cp);
+ } else {
+ cp->c_next = free_callouts;
+ free_callouts = cp;
+ nfree_callouts++;
+ }
+}
+
+/*
+ * Schedule a callout.
+ *
+ * (*fn)(closure) will be called at clocktime() + secs
+ */
+int timeout P((unsigned int secs, void (*fn)(), voidp closure));
+int timeout(secs, fn, closure)
+unsigned int secs;
+void (*fn)();
+voidp closure;
+{
+ callout *cp, *cp2;
+ time_t t = clocktime() + secs;
+
+ /*
+ * Allocate and fill in a new callout structure
+ */
+ callout *cpnew = alloc_callout();
+ cpnew->c_closure = closure;
+ cpnew->c_fn = fn;
+ cpnew->c_time = t;
+ cpnew->c_id = CID_ALLOC();
+
+ if (t < next_softclock)
+ next_softclock = t;
+
+ /*
+ * Find the correct place in the list
+ */
+ for (cp = &callouts; cp2 = cp->c_next; cp = cp2)
+ if (cp2->c_time >= t)
+ break;
+
+ /*
+ * And link it in
+ */
+ cp->c_next = cpnew;
+ cpnew->c_next = cp2;
+
+ /*
+ * Return callout identifier
+ */
+ return cpnew->c_id;
+}
+
+/*
+ * De-schedule a callout
+ */
+void untimeout P((int id));
+void untimeout(id)
+int id;
+{
+ callout *cp, *cp2;
+ for (cp = &callouts; cp2 = cp->c_next; cp = cp2) {
+ if (cp2->c_id == id) {
+ cp->c_next = cp2->c_next;
+ free_callout(cp2);
+ break;
+ }
+ }
+}
+
+/*
+ * Reschedule after clock changed
+ */
+void reschedule_timeouts P((time_t now, time_t then));
+void reschedule_timeouts(now, then)
+time_t now;
+time_t then;
+{
+ callout *cp;
+
+ for (cp = callouts.c_next; cp; cp = cp->c_next) {
+ if (cp->c_time >= now && cp->c_time <= then) {
+ plog(XLOG_WARNING, "job %d rescheduled to run immediately", cp->c_id);
+#ifdef DEBUG
+ dlog("rescheduling job %d back %d seconds",
+ cp->c_id, cp->c_time - now);
+#endif
+ next_softclock = cp->c_time = now;
+ }
+ }
+}
+
+/*
+ * Clock handler
+ */
+int softclock(P_void);
+int softclock()
+{
+ time_t now;
+ callout *cp;
+
+ do {
+ if (task_notify_todo)
+ do_task_notify();
+
+ now = clocktime();
+
+ /*
+ * While there are more callouts waiting...
+ */
+ while ((cp = callouts.c_next) && cp->c_time <= now) {
+ /*
+ * Extract first from list, save fn & closure and
+ * unlink callout from list and free.
+ * Finally call function.
+ *
+ * The free is done first because
+ * it is quite common that the
+ * function will call timeout()
+ * and try to allocate a callout
+ */
+ void (*fn)() = cp->c_fn;
+ voidp closure = cp->c_closure;
+
+ callouts.c_next = cp->c_next;
+ free_callout(cp);
+#ifdef DEBUG
+ /*dlog("Calling %#x(%#x)", fn, closure);*/
+#endif /* DEBUG */
+ (*fn)(closure);
+ }
+
+ } while (task_notify_todo);
+
+ /*
+ * Return number of seconds to next event,
+ * or 0 if there is no event.
+ */
+ if (cp = callouts.c_next)
+ return cp->c_time - now;
+ return 0;
+}
diff --git a/usr.sbin/amd/amd/efs_ops.c b/usr.sbin/amd/amd/efs_ops.c
new file mode 100644
index 0000000..6630277
--- /dev/null
+++ b/usr.sbin/amd/amd/efs_ops.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)efs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: efs_ops.c,v 5.2.2.1 1992/02/09 15:08:21 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_EFS
+
+/*
+ * Error file system.
+ * This is used as a last resort catchall if
+ * nothing else worked. EFS just returns lots
+ * of error codes, except for unmount which
+ * always works of course.
+ */
+
+/*
+ * EFS file system always matches
+ */
+static char *efs_match(fo)
+am_opts *fo;
+{
+ return strdup("(error-hook)");
+}
+
+/*ARGSUSED*/
+static int efs_fmount(mf)
+mntfs *mf;
+{
+ return ENOENT;
+}
+
+/*ARGSUSED*/
+static int efs_fumount(mf)
+mntfs *mf;
+{
+ /*
+ * Always succeed
+ */
+
+ return 0;
+}
+
+/*
+ * EFS interface to RPC lookup() routine.
+ * Should never get here in the automounter.
+ * If we do then just give an error.
+ */
+/*ARGSUSED*/
+am_node *efs_lookuppn(mp, fname, error_return, op)
+am_node *mp;
+char *fname;
+int *error_return;
+int op;
+{
+ *error_return = ESTALE;
+ return 0;
+}
+
+/*
+ * EFS interface to RPC readdir() routine.
+ * Should never get here in the automounter.
+ * If we do then just give an error.
+ */
+/*ARGSUSED*/
+int efs_readdir(mp, cookie, dp, ep, count)
+am_node *mp;
+nfscookie cookie;
+dirlist *dp;
+entry *ep;
+int count;
+{
+ return ESTALE;
+}
+
+/*
+ * Ops structure
+ */
+am_ops efs_ops = {
+ "error",
+ efs_match,
+ 0, /* efs_init */
+ auto_fmount,
+ efs_fmount,
+ auto_fumount,
+ efs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* efs_readlink */
+ 0, /* efs_mounted */
+ 0, /* efs_umounted */
+ find_afs_srvr,
+ FS_DISCARD
+};
+
+#endif /* HAS_EFS */
diff --git a/usr.sbin/amd/amd/get_args.c b/usr.sbin/amd/amd/get_args.c
new file mode 100644
index 0000000..0567d5d
--- /dev/null
+++ b/usr.sbin/amd/amd/get_args.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)get_args.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: get_args.c,v 5.2.2.1 1992/02/09 15:08:23 jsp beta $
+ *
+ */
+
+/*
+ * Argument decode
+ */
+
+#include "am.h"
+#ifdef HAS_SYSLOG
+#include <syslog.h>
+#endif /* HAS_SYSLOG */
+#include <sys/stat.h>
+
+extern int optind;
+extern char *optarg;
+
+#if defined(DEBUG) && defined(PARANOID)
+char **gargv;
+#endif /* defined(DEBUG) && defined(PARANOID) */
+int restart_existing_mounts;
+int print_pid;
+int normalize_hosts;
+char *karch; /* Kernel architecture */
+char *cluster; /* Cluster name */
+#ifdef HAS_NIS_MAPS
+char *domain; /* YP domain */
+#endif /* HAS_NIS_MAPS */
+#ifdef UPDATE_MTAB
+char *mtab;
+#endif /* UPDATE_MTAB */
+int afs_timeo = -1;
+int afs_retrans = -1;
+int am_timeo = AM_TTL;
+int am_timeo_w = AM_TTL_W;
+
+#ifdef DEBUG
+/*
+ * List of debug options.
+ */
+static struct opt_tab dbg_opt[] = {
+ { "all", D_ALL }, /* All */
+ { "amq", D_AMQ }, /* Register for AMQ program */
+ { "daemon", D_DAEMON }, /* Enter daemon mode */
+ { "full", D_FULL }, /* Program trace */
+ { "mem", D_MEM }, /* Trace memory allocations */
+ { "mtab", D_MTAB }, /* Use local mtab file */
+ { "str", D_STR }, /* Debug string munging */
+ { "test", D_TEST }, /* Full debug - but no daemon */
+ { "trace", D_TRACE }, /* Protocol trace */
+ { 0, 0 }
+};
+
+int debug_flags = D_AMQ /* Register AMQ */
+ |D_DAEMON /* Enter daemon mode */
+ ;
+
+/*
+ * Switch on/off debug options
+ */
+int debug_option(opt)
+char *opt;
+{
+ return cmdoption(opt, dbg_opt, &debug_flags);
+}
+#endif /* DEBUG */
+
+void get_args(c, v)
+int c;
+char *v[];
+{
+ int opt_ch;
+ int usage = 0;
+ char *logfile = 0;
+ char *sub_domain = 0;
+
+ while ((opt_ch = getopt(c, v, "mnprva:c:d:h:k:l:t:w:x:y:C:D:")) != EOF)
+ switch (opt_ch) {
+ case 'a':
+ if (*optarg != '/') {
+ fprintf(stderr, "%s: -a option must begin with a '/'\n",
+ progname);
+ exit(1);
+ }
+ auto_dir = optarg;
+ break;
+
+ case 'c':
+ am_timeo = atoi(optarg);
+ if (am_timeo <= 0)
+ am_timeo = AM_TTL;
+ break;
+
+ case 'd':
+ sub_domain = optarg;
+ break;
+
+ case 'h':
+#if defined(HAS_HOST) && defined(HOST_EXEC)
+ host_helper = optarg;
+#else
+ plog(XLOG_USER, "-h: option ignored. HOST_EXEC is not enabled.");
+ break;
+#endif /* defined(HAS_HOST) && defined(HOST_EXEC) */
+
+ case 'k':
+ karch = optarg;
+ break;
+
+ case 'l':
+ logfile = optarg;
+ break;
+
+ case 'm':
+ plog(XLOG_USER, "The -m option is no longer supported.");
+ plog(XLOG_USER, "... Use `ypcat -k am.master` on the command line instead");
+ break;
+
+ case 'n':
+ normalize_hosts = 1;
+ break;
+
+ case 'p':
+ print_pid = 1;
+ break;
+
+ case 'r':
+ restart_existing_mounts = 1;
+ break;
+
+ case 't':
+ /* timeo.retrans */
+ { char *dot = strchr(optarg, '.');
+ if (dot) *dot = '\0';
+ if (*optarg) {
+ afs_timeo = atoi(optarg);
+ }
+ if (dot) {
+ afs_retrans = atoi(dot+1);
+ *dot = '.';
+ }
+ }
+ break;
+
+ case 'v':
+ fprintf(stderr, "%s%s (%s-endian).\n", copyright, version, endian);
+ fputs("Map support for: ", stderr);
+ mapc_showtypes(stderr);
+ fputs(".\nFS: ", stderr);
+ ops_showfstypes(stderr);
+ fputs(".\n", stderr);
+ fprintf(stderr, "Primary network is %s.\n", wire);
+ exit(0);
+ break;
+
+ case 'w':
+ am_timeo_w = atoi(optarg);
+ if (am_timeo_w <= 0)
+ am_timeo_w = AM_TTL_W;
+ break;
+
+ case 'x':
+ usage += switch_option(optarg);
+ break;
+
+ case 'y':
+#ifdef HAS_NIS_MAPS
+ domain = optarg;
+#else
+ plog(XLOG_USER, "-y: option ignored. No NIS support available.");
+#endif /* HAS_NIS_MAPS */
+ break;
+
+ case 'C':
+ cluster = optarg;
+ break;
+
+ case 'D':
+#ifdef DEBUG
+ usage += debug_option(optarg);
+#else
+ fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", progname);
+#endif /* DEBUG */
+ break;
+
+ default:
+ usage = 1;
+ break;
+ }
+
+ if (xlog_level_init == ~0) {
+ (void) switch_option("");
+#ifdef DEBUG
+ usage += switch_option("debug");
+#endif /* DEBUG */
+ } else {
+#ifdef DEBUG
+ usage += switch_option("debug");
+#endif /* DEBUG */
+ }
+
+ if (usage)
+ goto show_usage;
+
+ while (optind <= c-2) {
+ char *dir = v[optind++];
+ char *map = v[optind++];
+ char *opts = "";
+ if (v[optind] && *v[optind] == '-')
+ opts = &v[optind++][1];
+
+ root_newmap(dir, opts, map);
+ }
+
+ if (optind == c) {
+#ifdef hpux
+ /*
+ * HP-UX can't handle ./mtab
+ * That system is sick - really.
+ */
+#ifdef DEBUG
+ debug_option("nomtab");
+#endif /* DEBUG */
+#endif /* hpux */
+
+ /*
+ * Append domain name to hostname.
+ * sub_domain overrides hostdomain
+ * if given.
+ */
+ if (sub_domain)
+ hostdomain = sub_domain;
+ if (*hostdomain == '.')
+ hostdomain++;
+ strcat(hostd, ".");
+ strcat(hostd, hostdomain);
+
+#ifdef UPDATE_MTAB
+#ifdef DEBUG
+ if (debug_flags & D_MTAB)
+ mtab = DEBUG_MTAB;
+ else
+#endif /* DEBUG */
+ mtab = MOUNTED;
+#else
+#ifdef DEBUG
+ { if (debug_flags & D_MTAB) {
+ dlog("-D mtab option ignored");
+ } }
+#endif /* DEBUG */
+#endif /* UPDATE_MTAB */
+
+ if (switch_to_logfile(logfile) != 0)
+ plog(XLOG_USER, "Cannot switch logfile");
+
+ /*
+ * If the kernel architecture was not specified
+ * then use the machine architecture.
+ */
+ if (karch == 0)
+ karch = arch;
+
+ if (cluster == 0)
+ cluster = hostdomain;
+
+ if (afs_timeo <= 0)
+ afs_timeo = AFS_TIMEO;
+ if (afs_retrans <= 0)
+ afs_retrans = AFS_RETRANS;
+ if (afs_retrans <= 0)
+ afs_retrans = 3; /* XXX */
+ return;
+ }
+
+show_usage:
+ fprintf(stderr,
+"Usage: %s [-mnprv] [-a mnt_point] [-c cache_time] [-d domain]\n\
+\t[-k kernel_arch] [-l logfile|\"syslog\"] [-t afs_timeout]\n\
+\t[-w wait_timeout] [-C cluster_name]", progname);
+
+#if defined(HAS_HOST) && defined(HOST_EXEC)
+ fputs(" [-h host_helper]\n", stderr);
+#endif /* defined(HAS_HOST) && defined(HOST_EXEC) */
+
+#ifdef HAS_NIS_MAPS
+ fputs(" [-y nis-domain]\n", stderr);
+#else
+ fputc('\n', stderr);
+#endif /* HAS_NIS_MAPS */
+
+ show_opts('x', xlog_opt);
+#ifdef DEBUG
+ show_opts('D', dbg_opt);
+#endif /* DEBUG */
+ fprintf(stderr, "\t{directory mapname [-map_options]} ...\n");
+ exit(1);
+}
diff --git a/usr.sbin/amd/amd/host_ops.c b/usr.sbin/amd/amd/host_ops.c
new file mode 100644
index 0000000..ba0dedb
--- /dev/null
+++ b/usr.sbin/amd/amd/host_ops.c
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)host_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: host_ops.c,v 5.2.2.2 1992/05/31 16:36:08 jsp Exp $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_HOST
+
+#include "mount.h"
+#include <sys/stat.h>
+
+/*
+ * NFS host file system.
+ * Mounts all exported filesystems from a given host.
+ * This has now degenerated into a mess but will not
+ * be rewritten. Amd 6 will support the abstractions
+ * needed to make this work correctly.
+ */
+
+/*
+ * Define HOST_RPC_UDP to use dgram instead of stream RPC.
+ * Datagrams are generally much faster.
+ */
+/*#define HOST_RPC_UDP*/
+
+/*
+ * Define HOST_MKDIRS to make Amd automatically try
+ * to create the mount points.
+ */
+#define HOST_MKDIRS
+
+/*
+ * Determine the mount point
+ */
+#define MAKE_MNTPT(mntpt, ex, mf) { \
+ if (strcmp((ex)->ex_dir, "/") == 0) \
+ strcpy((mntpt), (mf)->mf_mount); \
+ else \
+ sprintf((mntpt), "%s%s", (mf)->mf_mount, (ex)->ex_dir); \
+}
+
+/*
+ * Execute needs the same as NFS plus a helper command
+ */
+static char *host_match P((am_opts *fo));
+static char *host_match(fo)
+am_opts *fo;
+{
+#ifdef HOST_EXEC
+ if (!host_helper) {
+ plog(XLOG_USER, "No host helper command given");
+ return FALSE;
+ }
+#endif /* HOST_EXEC */
+
+ /*
+ * Make sure rfs is specified to keep nfs_match happy...
+ */
+ if (!fo->opt_rfs)
+ fo->opt_rfs = "/";
+
+
+ return (*nfs_ops.fs_match)(fo);
+}
+
+static int host_init(mf)
+mntfs *mf;
+{
+ if (strchr(mf->mf_info, ':') == 0)
+ return ENOENT;
+ return 0;
+}
+
+/*
+ * Two implementations:
+ * HOST_EXEC gets you the external version. The program specified with
+ * the -h option is called. The external program is not published...
+ * roll your own.
+ *
+ * Otherwise you get the native version. Faster but makes the program
+ * bigger.
+ */
+
+#ifndef HOST_EXEC
+
+static bool_t
+xdr_pri_free(xdr_args, args_ptr)
+xdrproc_t xdr_args;
+caddr_t args_ptr;
+{
+ XDR xdr;
+ xdr.x_op = XDR_FREE;
+ return ((*xdr_args)(&xdr, args_ptr));
+}
+
+static int do_mount P((fhstatus *fhp, char *dir, char *fs_name, char *opts, mntfs *mf));
+static int do_mount(fhp, dir, fs_name, opts, mf)
+fhstatus *fhp;
+char *dir;
+char *fs_name;
+char *opts;
+mntfs *mf;
+{
+ struct stat stb;
+#ifdef DEBUG
+ dlog("host: mounting fs %s on %s\n", fs_name, dir);
+#endif /* DEBUG */
+#ifdef HOST_MKDIRS
+ (void) mkdirs(dir, 0555);
+#endif /* HOST_MKDIRS */
+ if (stat(dir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
+ plog(XLOG_ERROR, "No mount point for %s - skipping", dir);
+ return ENOENT;
+ }
+
+ return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
+}
+
+static int sortfun P((exports *a, exports *b));
+static int sortfun(a, b)
+exports *a,*b;
+{
+ return strcmp((*a)->ex_dir, (*b)->ex_dir);
+}
+
+/*
+ * Get filehandle
+ */
+static int fetch_fhandle P((CLIENT *client, char *dir, fhstatus *fhp));
+static int fetch_fhandle(client, dir, fhp)
+CLIENT *client;
+char *dir;
+fhstatus *fhp;
+{
+ struct timeval tv;
+ enum clnt_stat clnt_stat;
+
+ /*
+ * Pick a number, any number...
+ */
+ tv.tv_sec = 20;
+ tv.tv_usec = 0;
+
+#ifdef DEBUG
+ dlog("Fetching fhandle for %s", dir);
+#endif /* DEBUG */
+ /*
+ * Call the mount daemon on the remote host to
+ * get the filehandle.
+ */
+ clnt_stat = clnt_call(client, MOUNTPROC_MNT, xdr_dirpath, &dir, xdr_fhstatus, fhp, tv);
+ if (clnt_stat != RPC_SUCCESS) {
+ extern char *clnt_sperrno();
+ char *msg = clnt_sperrno(clnt_stat);
+ plog(XLOG_ERROR, "mountd rpc failed: %s", msg);
+ return EIO;
+ }
+ /*
+ * Check status of filehandle
+ */
+ if (fhp->fhs_status) {
+#ifdef DEBUG
+ errno = fhp->fhs_status;
+ dlog("fhandle fetch failed: %m");
+#endif /* DEBUG */
+ return fhp->fhs_status;
+ }
+ return 0;
+}
+
+/*
+ * Scan mount table to see if something already mounted
+ */
+static int already_mounted P((mntlist *mlist, char*dir));
+static int already_mounted(mlist, dir)
+mntlist *mlist;
+char *dir;
+{
+ mntlist *ml;
+
+ for (ml = mlist; ml; ml = ml->mnext)
+ if (strcmp(ml->mnt->mnt_dir, dir) == 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * Mount the export tree from a host
+ */
+static int host_fmount P((mntfs *mf));
+static int host_fmount(mf)
+mntfs *mf;
+{
+ struct timeval tv2;
+ CLIENT *client;
+ enum clnt_stat clnt_stat;
+ int n_export;
+ int j, k;
+ exports exlist = 0, ex;
+ exports *ep = 0;
+ fhstatus *fp = 0;
+ char *host = mf->mf_server->fs_host;
+ int error = 0;
+ struct sockaddr_in sin;
+ int sock = RPC_ANYSOCK;
+ int ok = FALSE;
+ mntlist *mlist;
+ char fs_name[MAXPATHLEN], *rfs_dir;
+ char mntpt[MAXPATHLEN];
+ struct timeval tv;
+ tv.tv_sec = 10; tv.tv_usec = 0;
+
+ /*
+ * Read the mount list
+ */
+ mlist = read_mtab(mf->mf_mount);
+
+ /*
+ * Unlock the mount list
+ */
+ unlock_mntlist();
+
+ /*
+ * Take a copy of the server address
+ */
+ sin = *mf->mf_server->fs_ip;
+
+ /*
+ * Zero out the port - make sure we recompute
+ */
+ sin.sin_port = 0;
+ /*
+ * Make a client end-point.
+ * Try TCP first
+ */
+ if ((client = clnttcp_create(&sin, MOUNTPROG, MOUNTVERS, &sock, 0, 0)) == NULL &&
+ (client = clntudp_create(&sin, MOUNTPROG, MOUNTVERS, tv, &sock)) == NULL) {
+ plog(XLOG_ERROR, "Failed to make rpc connection to mountd on %s", host);
+ error = EIO;
+ goto out;
+ }
+
+ if (!nfs_auth) {
+ error = make_nfs_auth();
+ if (error)
+ goto out;
+ }
+
+ client->cl_auth = nfs_auth;
+
+#ifdef DEBUG
+ dlog("Fetching export list from %s", host);
+#endif /* DEBUG */
+
+ /*
+ * Fetch the export list
+ */
+ tv2.tv_sec = 10; tv2.tv_usec = 0;
+ clnt_stat = clnt_call(client, MOUNTPROC_EXPORT, xdr_void, 0, xdr_exports, &exlist, tv2);
+ if (clnt_stat != RPC_SUCCESS) {
+ /*clnt_perror(client, "rpc");*/
+ error = EIO;
+ goto out;
+ }
+
+ /*
+ * Figure out how many exports were returned
+ */
+ for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) {
+ /*printf("export %s\n", ex->ex_dir);*/
+ n_export++;
+ }
+#ifdef DEBUG
+ /*dlog("%d exports returned\n", n_export);*/
+#endif /* DEBUG */
+
+ /*
+ * Allocate an array of pointers into the list
+ * so that they can be sorted. If the filesystem
+ * is already mounted then ignore it.
+ */
+ ep = (exports *) xmalloc(n_export * sizeof(exports));
+ for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
+ MAKE_MNTPT(mntpt, ex, mf);
+ if (!already_mounted(mlist, mntpt))
+ ep[j++] = ex;
+ }
+ n_export = j;
+
+ /*
+ * Sort into order.
+ * This way the mounts are done in order down the tree,
+ * instead of any random order returned by the mount
+ * daemon (the protocol doesn't specify...).
+ */
+ qsort(ep, n_export, sizeof(exports), sortfun);
+
+ /*
+ * Allocate an array of filehandles
+ */
+ fp = (fhstatus *) xmalloc(n_export * sizeof(fhstatus));
+
+ /*
+ * Try to obtain filehandles for each directory.
+ * If a fetch fails then just zero out the array
+ * reference but discard the error.
+ */
+ for (j = k = 0; j < n_export; j++) {
+ /* Check and avoid a duplicated export entry */
+ if (j > k && ep[k] && strcmp(ep[j]->ex_dir, ep[k]->ex_dir) == 0) {
+#ifdef DEBUG
+ dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
+#endif
+ ep[j] = 0;
+ } else {
+ k = j;
+ if (error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j]))
+ ep[j] = 0;
+ }
+ }
+
+ /*
+ * Mount each filesystem for which we have a filehandle.
+ * If any of the mounts succeed then mark "ok" and return
+ * error code 0 at the end. If they all fail then return
+ * the last error code.
+ */
+ strncpy(fs_name, mf->mf_info, sizeof(fs_name));
+ if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
+ plog(XLOG_FATAL, "host_fmount: mf_info has no colon");
+ error = EINVAL;
+ goto out;
+ }
+ ++rfs_dir;
+ for (j = 0; j < n_export; j++) {
+ ex = ep[j];
+ if (ex) {
+ strcpy(rfs_dir, ex->ex_dir);
+ MAKE_MNTPT(mntpt, ex, mf);
+ if (do_mount(&fp[j], mntpt, fs_name, mf->mf_mopts, mf) == 0)
+ ok = TRUE;
+ }
+ }
+
+ /*
+ * Clean up and exit
+ */
+out:
+ discard_mntlist(mlist);
+ if (ep)
+ free(ep);
+ if (fp)
+ free(fp);
+ if (client)
+ clnt_destroy(client);
+ if (exlist)
+ xdr_pri_free(xdr_exports, &exlist);
+ if (ok)
+ return 0;
+ return error;
+}
+
+/*
+ * Return true if pref is a directory prefix of dir.
+ *
+ * TODO:
+ * Does not work if pref is "/".
+ */
+static int directory_prefix P((char *pref, char *dir));
+static int directory_prefix(pref, dir)
+char *pref;
+char *dir;
+{
+ int len = strlen(pref);
+ if (strncmp(pref, dir, len) != 0)
+ return FALSE;
+ if (dir[len] == '/' || dir[len] == '\0')
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Unmount a mount tree
+ */
+static int host_fumount P((mntfs *mf));
+static int host_fumount(mf)
+mntfs *mf;
+{
+ mntlist *ml, *mprev;
+ int xerror = 0;
+
+ /*
+ * Read the mount list
+ */
+ mntlist *mlist = read_mtab(mf->mf_mount);
+
+ /*
+ * Unlock the mount list
+ */
+ unlock_mntlist();
+
+ /*
+ * Reverse list...
+ */
+ ml = mlist;
+ mprev = 0;
+ while (ml) {
+ mntlist *ml2 = ml->mnext;
+ ml->mnext = mprev;
+ mprev = ml;
+ ml = ml2;
+ }
+ mlist = mprev;
+
+ /*
+ * Unmount all filesystems...
+ */
+ for (ml = mlist; ml && !xerror; ml = ml->mnext) {
+ char *dir = ml->mnt->mnt_dir;
+ if (directory_prefix(mf->mf_mount, dir)) {
+ int error;
+#ifdef DEBUG
+ dlog("host: unmounts %s", dir);
+#endif /* DEBUG */
+ /*
+ * Unmount "dir"
+ */
+ error = UMOUNT_FS(dir);
+ /*
+ * Keep track of errors
+ */
+ if (error) {
+ if (!xerror)
+ xerror = error;
+ if (error != EBUSY) {
+ errno = error;
+ plog("Tree unmount of %s failed: %m", ml->mnt->mnt_dir);
+ }
+ } else {
+#ifdef HOST_MKDIRS
+ (void) rmdirs(dir);
+#endif /* HOST_MKDIRS */
+ }
+ }
+ }
+
+ /*
+ * Throw away mount list
+ */
+ discard_mntlist(mlist);
+
+ /*
+ * Try to remount, except when we are shutting down.
+ */
+ if (xerror && amd_state != Finishing) {
+ xerror = host_fmount(mf);
+ if (!xerror) {
+ /*
+ * Don't log this - it's usually too verbose
+ plog(XLOG_INFO, "Remounted host %s", mf->mf_info);
+ */
+ xerror = EBUSY;
+ }
+ }
+ return xerror;
+}
+
+/*
+ * Tell mountd we're done.
+ * This is not quite right, because we may still
+ * have other filesystems mounted, but the existing
+ * mountd protocol is badly broken anyway.
+ */
+static void host_umounted(mp)
+am_node *mp;
+{
+#ifdef INFORM_MOUNTD
+ mntfs *mf = mp->am_mnt;
+ char *host;
+ CLIENT *client;
+ enum clnt_stat clnt_stat;
+ struct sockaddr_in sin;
+ int sock = RPC_ANYSOCK;
+ struct timeval tv;
+ tv.tv_sec = 10; tv.tv_usec = 0;
+
+ if (mf->mf_error || mf->mf_refc > 1 || ! mf->mf_server)
+ return;
+
+ host = mf->mf_server->fs_host;
+ sin = *mf->mf_server->fs_ip;
+
+ /*
+ * Zero out the port - make sure we recompute
+ */
+ sin.sin_port = 0;
+ /*
+ * Make a client end-point.
+ * Try TCP first
+ */
+ if ((client = clnttcp_create(&sin, MOUNTPROG, MOUNTVERS, &sock, 0, 0)) == NULL &&
+ (client = clntudp_create(&sin, MOUNTPROG, MOUNTVERS, tv, &sock)) == NULL) {
+ plog(XLOG_ERROR, "Failed to make rpc connection to mountd on %s", host);
+ goto out;
+ }
+
+ if (!nfs_auth) {
+ if (make_nfs_auth())
+ goto out;
+ }
+
+ client->cl_auth = nfs_auth;
+
+#ifdef DEBUG
+ dlog("Unmounting all from %s", host);
+#endif /* DEBUG */
+
+ clnt_stat = clnt_call(client, MOUNTPROC_UMNTALL, xdr_void, 0, xdr_void, 0, tv);
+ if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_SYSTEMERROR) {
+ /* RPC_SYSTEMERROR seems to be returned for no good reason ...*/
+ extern char *clnt_sperrno();
+ char *msg = clnt_sperrno(clnt_stat);
+ plog(XLOG_ERROR, "unmount all from %s rpc failed: %s", host, msg, clnt_stat);
+ goto out;
+ }
+
+out:
+ if (client)
+ clnt_destroy(client);
+
+#endif /* INFORM_MOUNTD */
+}
+
+
+#else /* HOST_EXEC */
+
+static int host_exec P((char*op, char*host, char*fs, char*opts));
+static int host_exec(op, host, fs, opts)
+char *op;
+char *host;
+char *fs;
+char *opts;
+{
+ int error;
+ char *argv[7];
+
+ /*
+ * Build arg vector
+ */
+ argv[0] = host_helper;
+ argv[1] = host_helper;
+ argv[2] = op;
+ argv[3] = host;
+ argv[4] = fs;
+ argv[5] = opts && *opts ? opts : "rw,default";
+ argv[6] = 0;
+
+ /*
+ * Put stdout to stderr
+ */
+ (void) fclose(stdout);
+ (void) dup(fileno(logfp));
+ if (fileno(logfp) != fileno(stderr)) {
+ (void) fclose(stderr);
+ (void) dup(fileno(logfp));
+ }
+ /*
+ * Try the exec
+ */
+#ifdef DEBUG
+ Debug(D_FULL) {
+ char **cp = argv;
+ plog(XLOG_DEBUG, "executing (un)mount command...");
+ while (*cp) {
+ plog(XLOG_DEBUG, "arg[%d] = '%s'", cp-argv, *cp);
+ cp++;
+ }
+ }
+#endif /* DEBUG */
+ if (argv[0] == 0 || argv[1] == 0) {
+ errno = EINVAL;
+ plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
+ } else {
+ (void) execv(argv[0], argv+1);
+ }
+ /*
+ * Save error number
+ */
+ error = errno;
+ plog(XLOG_ERROR, "exec %s failed: %m", argv[0]);
+
+ /*
+ * Return error
+ */
+ return error;
+}
+
+static int host_mount P((am_node *mp));
+static int host_mount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ return host_exec("mount", mf->mf_server->fs_host, mf->mf_mount, mf->mf_opts);
+}
+
+static int host_umount P((am_node *mp));
+static int host_umount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ return host_exec("unmount", mf->mf_server->fs_host, mf->mf_mount, "xxx");
+}
+
+#endif /* HOST_EXEC */
+
+/*
+ * Ops structure
+ */
+am_ops host_ops = {
+ "host",
+ host_match,
+ host_init,
+ auto_fmount,
+ host_fmount,
+ auto_fumount,
+ host_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* host_readlink */
+ 0, /* host_mounted */
+#ifdef HOST_EXEC
+ 0, /* host_umounted */
+#else
+ host_umounted,
+#endif
+ find_nfs_srvr,
+ FS_MKMNT|FS_BACKGROUND|FS_AMQINFO
+};
+
+#endif /* HAS_HOST */
diff --git a/usr.sbin/amd/amd/ifs_ops.c b/usr.sbin/amd/amd/ifs_ops.c
new file mode 100644
index 0000000..14df832
--- /dev/null
+++ b/usr.sbin/amd/amd/ifs_ops.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)ifs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: ifs_ops.c,v 5.2.2.1 1992/02/09 15:08:26 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_IFS
+
+/*
+ * Inheritance file system.
+ * This implements a filesystem restart.
+ *
+ * This is a *gross* hack - it knows far too
+ * much about the way other parts of the
+ * sytem work. See restart.c too.
+ */
+static char not_a_filesystem[] = "Attempting to inherit not-a-filesystem";
+/*
+ * This should never be called.
+ */
+/*ARGSUSED*/
+static char *ifs_match P((am_opts *fo));
+static char *ifs_match(fo)
+am_opts *fo;
+{
+ plog(XLOG_FATAL, "ifs_match called!");
+ return 0;
+}
+
+static int ifs_init P((mntfs *mf));
+static int ifs_init(mf)
+mntfs *mf;
+{
+ mntfs *mf_link = (mntfs *) mf->mf_private;
+ if (mf_link == 0) {
+ plog(XLOG_FATAL, not_a_filesystem);
+ return EINVAL;
+ }
+#ifdef notdef
+ /*
+ * Fill in attribute fields
+ */
+ mf_link->mf_fattr.type = NFLNK;
+ mf_link->mf_fattr.mode = NFSMODE_LNK | 0777;
+ mf_link->mf_fattr.nlink = 1;
+ mf_link->mf_fattr.size = MAXPATHLEN / 4;
+#endif
+ if (mf_link->mf_ops->fs_init)
+ return (*mf_link->mf_ops->fs_init)(mf_link);
+ return 0;
+}
+
+static mntfs *ifs_inherit P((mntfs *mf));
+static mntfs *ifs_inherit(mf)
+mntfs *mf;
+{
+ /*
+ * Take the linked mount point and
+ * propogate.
+ */
+ mntfs *mf_link = (mntfs *) mf->mf_private;
+ if (mf_link == 0) {
+ plog(XLOG_FATAL, not_a_filesystem);
+ return 0; /*XXX*/
+ }
+
+ mf_link->mf_fo = mf->mf_fo;
+#ifdef notdef
+ mf_link->mf_fattr.fileid = mf->mf_fattr.fileid;
+#endif /* notdef */
+
+ /*
+ * Discard the old map.
+ * Don't call am_unmounted since this
+ * node was never really mounted in the
+ * first place.
+ */
+ mf->mf_private = 0;
+ free_mntfs(mf);
+ /*
+ * Free the dangling reference
+ * to the mount link.
+ */
+ free_mntfs(mf_link);
+ /*
+ * Get a hold of the other entry
+ */
+ mf_link->mf_flags &= ~MFF_RESTART;
+
+ /* Say what happened */
+ plog(XLOG_INFO, "restarting %s on %s", mf_link->mf_info, mf_link->mf_mount);
+
+ return mf_link;
+}
+
+static int ifs_mount P((am_node *mp));
+static int ifs_mount(mp)
+am_node *mp;
+{
+ mntfs *newmf = ifs_inherit(mp->am_mnt);
+ if (newmf) {
+ mp->am_mnt = newmf;
+ /*
+ * XXX - must do the am_mounted call here
+ */
+ if (newmf->mf_ops->fs_flags & FS_MBACKGROUND)
+ am_mounted(mp);
+
+ new_ttl(mp);
+ return 0;
+ }
+ return EINVAL;
+}
+
+static int ifs_fmount P((mntfs *mf));
+static int ifs_fmount(mf)
+mntfs *mf;
+{
+ am_node *mp = find_mf(mf);
+ if (mp)
+ return ifs_mount(mp);
+ return ifs_inherit(mf) ? 0 : EINVAL;
+}
+
+/*ARGSUSED*/
+static int ifs_fumount P((mntfs *mf));
+static int ifs_fumount(mf)
+mntfs *mf;
+{
+ /*
+ * Always succeed
+ */
+ return 0;
+}
+
+/*
+ * Ops structure
+ */
+am_ops ifs_ops = {
+ "inherit",
+ ifs_match,
+ ifs_init,
+ ifs_mount,
+ ifs_fmount,
+ auto_fumount,
+ ifs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* ifs_readlink */
+ 0, /* ifs_mounted */
+ 0, /* ifs_umounted */
+ find_afs_srvr,
+ FS_DISCARD
+};
+
+#endif /* HAS_IFS */
diff --git a/usr.sbin/amd/amd/info_file.c b/usr.sbin/amd/amd/info_file.c
new file mode 100644
index 0000000..c43b2a7
--- /dev/null
+++ b/usr.sbin/amd/amd/info_file.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_file.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_file.c,v 5.2.2.1 1992/02/09 15:08:28 jsp beta $
+ *
+ */
+
+/*
+ * Get info from file
+ */
+
+#include "am.h"
+
+#ifdef HAS_FILE_MAPS
+#include <ctype.h>
+#include <sys/stat.h>
+
+#define MAX_LINE_LEN 2048
+
+static int read_line P((char *buf, int size, FILE *fp));
+static int read_line(buf, size, fp)
+char *buf;
+int size;
+FILE *fp;
+{
+ int done = 0;
+
+ do {
+ while (fgets(buf, size, fp)) {
+ int len = strlen(buf);
+ done += len;
+ if (len > 1 && buf[len-2] == '\\' &&
+ buf[len-1] == '\n') {
+ int ch;
+ buf += len - 2;
+ size -= len - 2;
+ *buf = '\n'; buf[1] = '\0';
+ /*
+ * Skip leading white space on next line
+ */
+ while ((ch = getc(fp)) != EOF &&
+ isascii(ch) && isspace(ch))
+ ;
+ (void) ungetc(ch, fp);
+ } else {
+ return done;
+ }
+ }
+ } while (size > 0 && !feof(fp));
+
+ return done;
+}
+
+/*
+ * Try to locate a key in a file
+ */
+static int search_or_reload_file P((FILE *fp, char *map, char *key, char **val, mnt_map *m, void (*fn)(mnt_map *m, char*, char*)));
+static int search_or_reload_file(fp, map, key, val, m, fn)
+FILE *fp;
+char *map;
+char *key;
+char **val;
+mnt_map *m;
+void (*fn) P((mnt_map*, char*, char*));
+{
+ char key_val[MAX_LINE_LEN];
+ int chuck = 0;
+ int line_no = 0;
+
+ while (read_line(key_val, sizeof(key_val), fp)) {
+ char *kp;
+ char *cp;
+ char *hash;
+ int len = strlen(key_val);
+ line_no++;
+
+ /*
+ * Make sure we got the whole line
+ */
+ if (key_val[len-1] != '\n') {
+ plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
+ chuck = 1;
+ } else {
+ key_val[len-1] = '\0';
+ }
+
+ /*
+ * Strip comments
+ */
+ hash = strchr(key_val, '#');
+ if (hash)
+ *hash = '\0';
+
+ /*
+ * Find start of key
+ */
+ for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
+ ;
+
+ /*
+ * Ignore blank lines
+ */
+ if (!*kp)
+ goto again;
+
+ /*
+ * Find end of key
+ */
+ for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
+ ;
+
+ /*
+ * Check whether key matches
+ */
+ if (*cp)
+ *cp++ = '\0';
+
+ if (fn || (*key == *kp && strcmp(key, kp) == 0)) {
+ while (*cp && isascii(*cp) && isspace(*cp))
+ cp++;
+ if (*cp) {
+ /*
+ * Return a copy of the data
+ */
+ char *dc = strdup(cp);
+ if (fn) {
+ (*fn)(m, strdup(kp), dc);
+ } else {
+ *val = dc;
+#ifdef DEBUG
+ dlog("%s returns %s", key, dc);
+#endif /* DEBUG */
+ }
+ if (!fn)
+ return 0;
+ } else {
+ plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
+ }
+ }
+
+again:
+ /*
+ * If the last read didn't get a whole line then
+ * throw away the remainder before continuing...
+ */
+ if (chuck) {
+ while (fgets(key_val, sizeof(key_val), fp) &&
+ !strchr(key_val, '\n'))
+ ;
+ chuck = 0;
+ }
+ }
+
+ return fn ? 0 : ENOENT;
+}
+
+static FILE *file_open P((char *map, time_t *tp));
+static FILE *file_open(map, tp)
+char *map;
+time_t *tp;
+{
+ FILE *mapf = fopen(map, "r");
+ if (mapf && tp) {
+ struct stat stb;
+ if (fstat(fileno(mapf), &stb) < 0)
+ *tp = clocktime();
+ else
+ *tp = stb.st_mtime;
+ }
+ return mapf;
+}
+
+int file_init P((char *map, time_t *tp));
+int file_init(map, tp)
+char *map;
+time_t *tp;
+{
+ FILE *mapf = file_open(map, tp);
+ if (mapf) {
+ (void) fclose(mapf);
+ return 0;
+ }
+ return errno;
+}
+
+int file_reload P((mnt_map *m, char *map, void (*fn)()));
+int file_reload(m, map, fn)
+mnt_map *m;
+char *map;
+void (*fn)();
+{
+ FILE *mapf = file_open(map, (time_t *) 0);
+ if (mapf) {
+ int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
+ (void) fclose(mapf);
+ return error;
+ }
+
+ return errno;
+}
+
+int file_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
+int file_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ time_t t;
+ FILE *mapf = file_open(map, &t);
+ if (mapf) {
+ int error;
+ if (*tp < t) {
+ *tp = t;
+ error = -1;
+ } else {
+ error = search_or_reload_file(mapf, map, key, pval, 0, 0);
+ }
+ (void) fclose(mapf);
+ return error;
+ }
+
+ return errno;
+}
+
+int file_mtime P((char *map, time_t *tp));
+int file_mtime(map, tp)
+char *map;
+time_t *tp;
+{
+ FILE *mapf = file_open(map, tp);
+ if (mapf) {
+ (void) fclose(mapf);
+ return 0;
+ }
+
+ return errno;
+}
+#endif /* HAS_FILE_MAPS */
diff --git a/usr.sbin/amd/amd/info_hes.c b/usr.sbin/amd/amd/info_hes.c
new file mode 100644
index 0000000..875cfe7
--- /dev/null
+++ b/usr.sbin/amd/amd/info_hes.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_hes.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_hes.c,v 5.2.2.1 1992/02/09 15:08:29 jsp beta $
+ *
+ */
+
+/*
+ * Get info from Hesiod
+ *
+ * Zone transfer code from Bruce Cole <cole@cs.wisc.edu>
+ */
+
+#include "am.h"
+
+#ifdef HAS_HESIOD_MAPS
+#include <hesiod.h>
+
+#define HES_PREFIX "hesiod."
+#define HES_PREFLEN 7
+
+#ifdef HAS_HESIOD_RELOAD
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <sys/uio.h>
+#include <netdb.h>
+
+/*
+ * Patch up broken system include files
+ */
+#ifndef C_HS
+#define C_HS 4
+#endif
+#ifndef T_TXT
+#define T_TXT 16
+#endif
+
+static int soacnt;
+static struct timeval hs_timeout;
+static int servernum;
+#endif /* HAS_HESIOD_RELOAD */
+
+/*
+ * No easy way to probe the server - check the map name begins with "hesiod."
+ */
+int hesiod_init P((char *map, time_t *tp));
+int hesiod_init(map, tp)
+char *map;
+time_t *tp;
+{
+#ifdef DEBUG
+ dlog("hesiod_init(%s)", map);
+#endif
+ *tp = 0;
+ return strncmp(map, HES_PREFIX, HES_PREFLEN) == 0 ? 0 : ENOENT;
+}
+
+
+/*
+ * Make Hesiod name. Skip past the "hesiod."
+ * at the start of the map name and append
+ * ".automount". The net effect is that a lookup
+ * of /defaults in hesiod.home will result in a
+ * call to hes_resolve("/defaults", "home.automount");
+ */
+#ifdef notdef
+#define MAKE_HES_NAME(dest, src) sprintf(dest, "%s%s", src + HES_PREFLEN, ".automount")
+#endif
+
+/*
+ * Do a Hesiod nameserver call.
+ * Modify time is ignored by Hesiod - XXX
+ */
+int hesiod_search P((mnt_map *m, char *map, char **pval, time_t *tp));
+int hesiod_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ int error;
+ char hes_key[MAXPATHLEN];
+ char **rvec;
+#ifdef DEBUG
+ dlog("hesiod_search(m=%x, map=%s, key=%s, pval=%x tp=%x)", m, map, key, pval, tp);
+#endif
+ /*MAKE_HES_NAME(hes_map, map);*/
+ sprintf(hes_key, "%s.%s", key, map+HES_PREFLEN);
+
+ /*
+ * Call the resolver
+ */
+#ifdef DEBUG
+ dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, "automount");
+#ifdef HAS_HESIOD_RELOAD
+ if (debug_flags & D_FULL)
+ _res.options |= RES_DEBUG;
+#endif
+#endif
+ rvec = hes_resolve(hes_key, "automount");
+ /*
+ * If a reply was forthcoming then return
+ * it (and free subsequent replies)
+ */
+ if (rvec && *rvec) {
+ *pval = *rvec;
+ while (*++rvec)
+ free(*rvec);
+ return 0;
+ }
+
+ /*
+ * Otherwise reflect the hesiod error into a Un*x error
+ */
+#ifdef DEBUG
+ dlog("hesiod_search: Error: %d", hes_error());
+#endif
+ switch (hes_error()) {
+ case HES_ER_NOTFOUND: error = ENOENT; break;
+ case HES_ER_CONFIG: error = EIO; break;
+ case HES_ER_NET: error = ETIMEDOUT; break;
+ default: error = EINVAL; break;
+ }
+#ifdef DEBUG
+ dlog("hesiod_search: Returning: %d", error);
+#endif
+ return error;
+}
+
+#ifdef HAS_HESIOD_RELOAD
+/*
+ * Zone transfer...
+ */
+
+#define MAXHSNS 8
+#define MAX_NSADDR 16
+
+static char *hs_domain;
+static mnt_map *hs_map;
+static int hs_nscount;
+static char nsaddr_list[MAX_NSADDR][sizeof(struct in_addr)];
+
+int hesiod_reload P((mnt_map *m, char *map, void (*fn)()));
+int hesiod_reload(m, map, fn)
+mnt_map *m;
+char *map;
+void (*fn)();
+{
+ char *zone_name, *cp;
+ short domainlen;
+ int status;
+
+#ifdef DEBUG
+ dlog("hesiod_reload (%x %s %x)", m, map, fn);
+#endif DEBUG
+ if (status = res_init()) {
+#ifdef DEBUG
+ dlog("hesiod_reload: res_init failed with %d", status);
+#endif
+ return(status);
+ }
+ _res.retrans = 90;
+ hs_map = m;
+ domainlen = strlen(hostdomain);
+ zone_name = hes_to_bind(map+HES_PREFLEN, "automount");
+ if (*zone_name == '.')
+ zone_name++;
+ hs_domain = zone_name;
+ /* Traverse the DNS tree until we find an SOA we can transfer from.
+ (Our initial zone_name is likely to just be a subtree of a
+ real zone). */
+ do {
+ /* If we can't find any NS records, go up a level in the
+ DNS tree */
+ if (hs_get_ns_list(zone_name) == 0 &&
+ hs_zone_transfer(zone_name) == 0)
+ return(0);
+ /* Move up DNS tree by one component */
+ if (cp = strchr(zone_name, '.'))
+ zone_name = ++cp;
+ else
+ break;
+ } while (strlen(zone_name) >= domainlen);
+#ifdef DEBUG
+ dlog("hesiod_reload: Giving up on %s", hs_domain);
+#endif
+ return(-1);
+}
+
+hs_zone_transfer(domain)
+char *domain;
+{
+ int status, len;
+ char buf[PACKETSZ];
+ /* Want to make sure ansbuf is well alligned */
+ long ansbuf[PACKETSZ/sizeof(long)];
+
+#ifdef DEBUG
+ dlog("hs_zone_transfer (%s)", domain);
+#endif
+ if ((len = res_mkquery(QUERY, domain, C_HS, T_AXFR,
+ (char *)NULL, 0, NULL, buf, PACKETSZ)) == -1) {
+#ifdef DEBUG
+ dlog("hs_zone_transfer: res_mkquery failed");
+#endif
+ errno = 0;
+ return(-1);
+ }
+ if ((status = hs_res_send(buf, len, (char *)ansbuf, PACKETSZ)) == -1) {
+#ifdef DEBUG
+ dlog("hs_zone_transfer: hs_res_send failed. status %d errno %d",
+ status, errno);
+#endif
+ errno = 0;
+ return(-1);
+ }
+ return(0);
+}
+
+#define hs_server_addr(ns) ((struct in_addr *) nsaddr_list[ns])
+
+hs_res_send(buf, buflen, answer, anslen)
+char *buf;
+int buflen;
+char *answer;
+int anslen;
+{
+ int retry, ns;
+ u_short id, len;
+ HEADER *hp = (HEADER *) buf;
+ struct iovec iov[2];
+ static int s = -1;
+ int status;
+ struct sockaddr_in server;
+
+ soacnt = 0;
+ id = hp->id;
+ /*
+ * Send request, RETRY times, or until successful
+ */
+ for (retry = _res.retry; retry > 0; retry--) {
+ for (ns = 0; ns < hs_nscount; ns++) {
+ hs_timeout.tv_sec =
+ (_res.retrans << (_res.retry - retry))
+ / hs_nscount;
+ if (hs_timeout.tv_sec <= 0)
+ hs_timeout.tv_sec = 1;
+ hs_timeout.tv_usec = 0;
+ if (s < 0) {
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ continue;
+ }
+ servernum = ns;
+ bcopy(hs_server_addr(ns), &server.sin_addr,
+ sizeof(struct in_addr));
+ server.sin_family = AF_INET;
+ server.sin_port = htons(NAMESERVER_PORT);
+
+ if (connect(s, &server,
+ sizeof(struct sockaddr)) < 0) {
+ (void) close(s);
+ s = -1;
+ continue;
+ }
+ }
+ /*
+ * Send length & message
+ */
+ len = htons((u_short)buflen);
+ iov[0].iov_base = (caddr_t)&len;
+ iov[0].iov_len = sizeof(len);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = buflen;
+ if (writev(s, iov, 2) != sizeof(len) + buflen) {
+ (void) close(s);
+ s = -1;
+ continue;
+ }
+ status = 0;
+ while (s != -1 && soacnt < 2 && status != -2) {
+ if ((status =
+ hs_readresp(s, answer, anslen)) == -1) {
+ (void) close(s);
+ s = -1;
+ continue;
+ }
+ }
+ if (status == -2) {
+ /* There was a permanent error transfering this
+ zone. Give up. */
+ if (s != -1) {
+ (void) close(s);
+ s = -1;
+ }
+ return(-1);
+ }
+ if (s == -1)
+ continue;
+ return (0);
+ }
+ }
+ if (errno == 0)
+ errno = ETIMEDOUT;
+ return (-1);
+}
+
+/* Returns:
+ 0: Success
+ -1: Error
+ -2: Permanent failure
+*/
+hs_readresp(s, answer, anslen)
+int s;
+char *answer;
+int anslen;
+{
+ register int len, n;
+ char *cp;
+
+ cp = answer;
+ len = sizeof(short);
+ while (len != 0 &&
+ (n = hs_res_vcread(s, (char *)cp, (int)len, &hs_timeout)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0)
+ return(-1);
+ cp = answer;
+ if ((len = _getshort(cp)) > anslen) {
+#ifdef DEBUG
+ dlog("hs_readresp: response too long: %d", len);
+#endif
+ return(-1);
+ }
+ while (len != 0 &&
+ (n = hs_res_vcread(s, (char *)cp, (int)len, &hs_timeout)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0)
+ return(-1);
+ return(hs_parse(answer, answer+PACKETSZ));
+}
+
+hs_res_vcread(sock, buf, buflen, timeout)
+int sock, buflen;
+char *buf;
+struct timeval *timeout;
+{
+ register int n;
+
+ if ((n = hs_res_selwait(sock, timeout)) > 0)
+ return(read(sock, buf, buflen));
+ else
+ return(n);
+}
+
+hs_res_selwait(sock, timeout)
+int sock;
+struct timeval *timeout;
+{
+ fd_set dsmask;
+ register int n;
+
+ /*
+ * Wait for reply
+ */
+ FD_ZERO(&dsmask);
+ FD_SET(sock, &dsmask);
+ n = select(sock+1, &dsmask, (fd_set *)NULL,
+ (fd_set *)NULL, timeout);
+ return(n);
+}
+
+/* Returns:
+ 0: Success
+ -1: Error
+ -2: Permanent failure
+*/
+hs_parse(msg, eom)
+char *msg, *eom;
+{
+ register char *cp;
+ register HEADER *hp;
+ register int n, len;
+ int qdcount, ancount;
+ char key[PACKETSZ];
+ char *key_cpy, *value, *hs_make_value();
+ short type;
+
+ hp = (HEADER *)msg;
+ if (hp->rcode != NOERROR || hp->opcode != QUERY) {
+ char dq[20];
+#ifdef DEBUG
+ dlog("Bad response (%d) from nameserver %s", hp->rcode, inet_dquad(dq, hs_server_addr(servernum)->s_addr));
+#endif DEBUG
+ return(-1);
+ }
+ cp = msg + sizeof(HEADER);
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ while (qdcount-- > 0)
+ cp += dn_skipname(cp, eom) + QFIXEDSZ;
+ if (soacnt == 0 && ancount == 0) {
+ /* XXX We should look for NS records to find SOA */
+#ifdef DEBUG
+ dlog("No SOA found");
+#endif
+ return(-2);
+ }
+ while (ancount-- > 0 && cp < eom) {
+ if ((n = dn_expand(msg, eom, cp, key, PACKETSZ)) < 0)
+ break;
+ cp += n;
+ if ((type = _getshort(cp)) == T_SOA) {
+ soacnt++;
+ }
+ cp += 2*sizeof(u_short) + sizeof(u_long);
+ len = _getshort(cp);
+ cp += sizeof(u_short);
+ /* Check to see if key is in our domain */
+ if (type == T_TXT && hs_strip_our_domain(key)) {
+ value = hs_make_value(cp, len);
+ if (value == NULL)
+ return(-1);
+ key_cpy = strdup(key);
+#ifdef DEBUG
+ dlog("hs_parse: Parsed key: %s, value: %s", key,
+ value);
+#endif
+ mapc_add_kv(hs_map, key_cpy, value);
+ }
+ cp += len;
+ errno = 0;
+ }
+ return(0);
+}
+
+/* Check to see if the domain name in the supplied argument matches
+ hs_domain. Strip hs_domain from supplied argument if so. */
+hs_strip_our_domain(name)
+char *name;
+{
+ char *end_pos;
+ short targ_len, cur_len;
+
+ targ_len = strlen(hs_domain);
+ cur_len = strlen(name);
+ if (cur_len <= targ_len)
+ return(0);
+ end_pos = &name[cur_len - targ_len];
+ if (strcmp(end_pos, hs_domain) != 0)
+ return(0);
+ if (*--end_pos != '.')
+ return(0);
+ *end_pos = '\0';
+ return(1);
+}
+
+#define MAXDATA 8*1024
+
+char *
+hs_make_value(cp, len)
+char *cp;
+int len;
+{
+ char *value, *cpcpy, *valuep;
+ int cnt, nextcnt, totalcnt, lencpy;
+#ifdef DEBUG
+ char *dbgname;
+
+ dbgname = &cp[1];
+#endif DEBUG
+
+ lencpy = len;
+ cpcpy = cp;
+ totalcnt = 0;
+ cnt = *cpcpy++;
+ while (cnt) {
+ totalcnt += cnt;
+ lencpy -= cnt+1;
+ if (lencpy == 0)
+ break;
+ nextcnt = cpcpy[cnt];
+ cpcpy = &cpcpy[cnt+1];
+ cnt = nextcnt;
+ }
+ if (totalcnt < 1 || totalcnt > MAXDATA || totalcnt > len) {
+#ifdef DEBUG
+ dlog("TXT RR not of expected length (%d %d): %s", totalcnt,
+ len, dbgname);
+#endif DEBUG
+ return(NULL);
+ }
+ /* Allocate null terminated string */
+ value = (char *) xmalloc(totalcnt+1);
+ value[totalcnt] = '\0';
+ cnt = *cp++;
+ valuep = value;
+ while (cnt) {
+ bcopy(cp, valuep, cnt);
+ len -= cnt+1;
+ if (len == 0)
+ break;
+ valuep = &valuep[cnt];
+ nextcnt = cp[cnt];
+ cp = &cp[cnt+1];
+ cnt = nextcnt;
+ }
+ return(value);
+}
+
+hs_make_ns_query(domain, ansbuf)
+char *domain;
+char *ansbuf;
+{
+ int status, len;
+ char buf[PACKETSZ];
+
+ if ((len = res_mkquery(QUERY, domain, C_HS, T_NS,
+ (char *)NULL, 0, NULL, buf, PACKETSZ)) == -1) {
+#ifdef DEBUG
+ dlog("hs_get_ns_list: res_mkquery failed");
+#endif
+ errno = 0;
+ return(-1);
+ }
+ if ((status = res_send(buf, len, (char *)ansbuf, PACKETSZ)) == -1) {
+#ifdef DEBUG
+ dlog("hs_get_ns_list: res_send failed. status %d errno %d",
+ status, errno);
+#endif
+ errno = 0;
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+add_address(addr)
+struct in_addr *addr;
+{
+ char dq[20];
+ bcopy((char *)addr, nsaddr_list[hs_nscount++], sizeof(struct in_addr));
+#ifdef DEBUG
+ dlog("Adding NS address %s", inet_dquad(dq, addr->s_addr));
+#endif DEBUG
+}
+
+hs_get_ns_list(domain)
+char *domain;
+{
+ register HEADER *hp;
+ int qdcount, nscount;
+ register char *cp;
+ register int n, len;
+ char key[PACKETSZ], name[PACKETSZ], msg[PACKETSZ], *eom;
+ register long **hptr;
+ struct hostent *ghp;
+ int numns;
+ char nsname[MAXHSNS][MAXDATA];
+ int nshaveaddr[MAXHSNS], i;
+ short type;
+
+ if (hs_make_ns_query(domain, msg) == -1)
+ return(-1);
+ numns = hs_nscount = 0;
+ eom = &msg[PACKETSZ];
+ bzero(nsname, sizeof(nsname));
+ hp = (HEADER *)msg;
+ if (hp->rcode != NOERROR || hp->opcode != QUERY) {
+#ifdef DEBUG
+ dlog("Bad response (%d) from nameserver %#x", hp->rcode,
+ hs_server_addr(servernum)->s_addr);
+#endif DEBUG
+ return(-1);
+ }
+ cp = msg + sizeof(HEADER);
+ qdcount = ntohs(hp->qdcount);
+ while (qdcount-- > 0)
+ cp += dn_skipname(cp, eom) + QFIXEDSZ;
+ nscount = ntohs(hp->ancount) + ntohs(hp->nscount) + ntohs(hp->arcount);
+#ifdef DEBUG
+ dlog("hs_get_ns_list: Processing %d response records", nscount);
+#endif
+ for (;nscount; nscount--) {
+ if ((n = dn_expand(msg, eom, cp, key, PACKETSZ)) < 0)
+ break;
+ cp += n;
+ type = _getshort(cp);
+ cp += 2*sizeof(u_short) + sizeof(u_long);
+ len = _getshort(cp);
+ cp += sizeof(u_short);
+#ifdef DEBUG
+ dlog("hs_get_ns_list: Record type: %d", type);
+#endif
+ switch (type) {
+ case T_NS:
+ if (numns >= MAXHSNS || strcasecmp(domain, key) != 0)
+ break;
+ if ((n = dn_expand(msg, eom, cp, name, PACKETSZ)) < 0)
+ break;
+#ifdef DEBUG
+ dlog("hs_get_ns_list: NS name: %s", name);
+#endif
+ for (i = 0; i < numns; i++)
+ if (strcasecmp(nsname[i], name) == 0)
+ break;
+ if (i == numns) {
+#ifdef DEBUG
+ dlog("hs_get_ns_list: Saving name %s", name);
+#endif
+ strncpy(nsname[numns], name, MAXDATA);
+ nshaveaddr[numns] = 0;
+ numns++;
+ }
+ break;
+ case T_A:
+ if (hs_nscount == MAX_NSADDR)
+ break;
+ for (i = 0; i < numns; i++) {
+ if (strcasecmp(nsname[i], domain) == 0) {
+ nshaveaddr[i]++;
+ add_address((struct in_addr *) cp);
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (hs_nscount == MAX_NSADDR)
+ break;
+ cp += len;
+ errno = 0;
+ }
+#ifdef DEBUG
+ dlog("hs_get_ns_list: Found %d NS records", numns);
+#endif
+ for (i = 0; i < numns; i++) {
+ if (nshaveaddr[i])
+ continue;
+ if ((ghp = gethostbyname(nsname[i])) == 0)
+ continue;
+ for (hptr = (long **)ghp->h_addr_list;
+ *hptr && hs_nscount < MAX_NSADDR; hptr++) {
+ add_address((struct in_addr *) *hptr);
+ }
+ }
+ if (hs_nscount)
+ return(0);
+#ifdef DEBUG
+ dlog("No NS records found for %s", domain);
+ return(-1);
+#endif DEBUG
+}
+#endif /* HAS_HESIOD_RELOAD */
+#endif /* HAS_HESIOD_MAPS */
diff --git a/usr.sbin/amd/amd/info_ndbm.c b/usr.sbin/amd/amd/info_ndbm.c
new file mode 100644
index 0000000..d3deaa1
--- /dev/null
+++ b/usr.sbin/amd/amd/info_ndbm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_ndbm.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_ndbm.c,v 5.2.2.1 1992/02/09 15:08:31 jsp beta $
+ *
+ */
+
+/*
+ * Get info from NDBM map
+ */
+
+#include "am.h"
+
+#ifdef HAS_NDBM_MAPS
+
+#include <ndbm.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+static int search_ndbm P((DBM *db, char *key, char **val));
+static int search_ndbm(db, key, val)
+DBM *db;
+char *key;
+char **val;
+{
+ datum k, v;
+ k.dptr = key;
+ k.dsize = strlen(key) + 1;
+ v = dbm_fetch(db, k);
+ if (v.dptr) {
+ *val = strdup(v.dptr);
+ return 0;
+ }
+ return ENOENT;
+}
+
+int ndbm_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
+int ndbm_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ DBM *db;
+
+ db = dbm_open(map, O_RDONLY, 0);
+ if (db) {
+ struct stat stb;
+ int error;
+ error = fstat(dbm_pagfno(db), &stb);
+ if (!error && *tp < stb.st_mtime) {
+ *tp = stb.st_mtime;
+ error = -1;
+ } else {
+ error = search_ndbm(db, key, pval);
+ }
+ (void) dbm_close(db);
+ return error;
+ }
+
+ return errno;
+}
+
+int ndbm_init P((char *map, time_t *tp));
+int ndbm_init(map, tp)
+char *map;
+time_t *tp;
+{
+ DBM *db;
+
+ db = dbm_open(map, O_RDONLY, 0);
+ if (db) {
+ struct stat stb;
+
+ if (fstat(dbm_pagfno(db), &stb) < 0)
+ *tp = clocktime();
+ else
+ *tp = stb.st_mtime;
+ dbm_close(db);
+ return 0;
+ }
+
+ return errno;
+}
+
+#endif /* HAS_NDBM_MAPS */
diff --git a/usr.sbin/amd/amd/info_nis.c b/usr.sbin/amd/amd/info_nis.c
new file mode 100644
index 0000000..ac80f5f
--- /dev/null
+++ b/usr.sbin/amd/amd/info_nis.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_nis.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_nis.c,v 5.2.2.1 1992/02/09 15:08:32 jsp beta $
+ *
+ */
+
+/*
+ * Get info from NIS map
+ */
+
+#include "am.h"
+
+#ifdef HAS_NIS_MAPS
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+/*
+ * Figure out the nis domain name
+ */
+static int determine_nis_domain(P_void)
+{
+static int nis_not_running = 0;
+
+ char default_domain[YPMAXDOMAIN];
+
+ if (nis_not_running)
+ return ENOENT;
+
+ if (getdomainname(default_domain, sizeof(default_domain)) < 0) {
+ nis_not_running = 1;
+ plog(XLOG_ERROR, "getdomainname: %m");
+ return EIO;
+ }
+
+ if (!*default_domain) {
+ nis_not_running = 1;
+ plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored.");
+ return ENOENT;
+ }
+
+ domain = strdup(default_domain);
+
+ return 0;
+}
+
+
+#ifdef HAS_NIS_RELOAD
+struct nis_callback_data {
+ mnt_map *ncd_m;
+ char *ncd_map;
+ void (*ncd_fn)();
+};
+
+/*
+ * Callback from yp_all
+ */
+static int callback(status, key, kl, val, vl, data)
+int status;
+char *key;
+int kl;
+char *val;
+int vl;
+struct nis_callback_data *data;
+{
+ if (status == YP_TRUE) {
+ /*
+ * Add to list of maps
+ */
+ char *kp = strnsave(key, kl);
+ char *vp = strnsave(val, vl);
+ (*data->ncd_fn)(data->ncd_m, kp, vp);
+
+ /*
+ * We want more ...
+ */
+ return FALSE;
+ } else {
+ /*
+ * NOMORE means end of map - otherwise log error
+ */
+ if (status != YP_NOMORE) {
+ /*
+ * Check what went wrong
+ */
+ int e = ypprot_err(status);
+
+#ifdef DEBUG
+ plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
+ data->ncd_map, yperr_string(e), status, e);
+#else
+ plog(XLOG_ERROR, "yp enumeration of %s: %s", data->ncd_map, yperr_string(e));
+#endif
+ }
+
+ return TRUE;
+ }
+}
+
+int nis_reload P((mnt_map *m, char *map, void (*fn)()));
+int nis_reload(m, map, fn)
+mnt_map *m;
+char *map;
+void (*fn)();
+{
+ struct ypall_callback cbinfo;
+ int error;
+ struct nis_callback_data data;
+
+ if (!domain) {
+ error = determine_nis_domain();
+ if (error)
+ return error;
+ }
+
+ data.ncd_m = m;
+ data.ncd_map = map;
+ data.ncd_fn = fn;
+ cbinfo.data = (voidp) &data;
+ cbinfo.foreach = callback;
+
+ error = yp_all(domain, map, &cbinfo);
+
+ if (error)
+ plog(XLOG_ERROR, "error grabbing nis map of %s: %s", map, yperr_string(ypprot_err(error)));
+
+ return error;
+}
+#endif /* HAS_NIS_RELOAD */
+
+/*
+ * Try to locate a key using NIS.
+ */
+int nis_search P((mnt_map *m, char *map, char *key, char **val, time_t *tp));
+int nis_search(m, map, key, val, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **val;
+time_t *tp;
+{
+ int outlen;
+ int res;
+ int order;
+
+ /*
+ * Make sure domain initialised
+ */
+ if (!domain) {
+ int error = determine_nis_domain();
+ if (error)
+ return error;
+ }
+
+ /*
+ * Check if map has changed
+ */
+ if (yp_order(domain, map, &order))
+ return EIO;
+ if ((time_t) order > *tp) {
+ *tp = (time_t) order;
+ return -1;
+ }
+
+ /*
+ * Lookup key
+ */
+ res = yp_match(domain, map, key, strlen(key), val, &outlen);
+
+ /*
+ * Do something interesting with the return code
+ */
+ switch (res) {
+ case 0:
+ return 0;
+
+ case YPERR_KEY:
+ return ENOENT;
+
+ default:
+ plog(XLOG_ERROR, "%s: %s", map, yperr_string(res));
+ return EIO;
+ }
+}
+
+int nis_init P((char *map, time_t *tp));
+int nis_init(map, tp)
+char *map;
+time_t *tp;
+{
+ int order;
+
+ if (!domain) {
+ int error = determine_nis_domain();
+ if (error)
+ return error;
+ }
+
+ /*
+ * To see if the map exists, try to find
+ * a master for it.
+ */
+ if (yp_order(domain, map, &order))
+ return ENOENT;
+ *tp = (time_t) order;
+#ifdef DEBUG
+ dlog("NIS master for %s@%s has order %d", map, domain, order);
+#endif
+ return 0;
+}
+#endif /* HAS_NIS_MAPS */
diff --git a/usr.sbin/amd/amd/info_passwd.c b/usr.sbin/amd/amd/info_passwd.c
new file mode 100644
index 0000000..3123e38
--- /dev/null
+++ b/usr.sbin/amd/amd/info_passwd.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_passwd.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_passwd.c,v 5.2.2.1 1992/02/09 15:08:33 jsp beta $
+ *
+ */
+
+/*
+ * Get info from password "file"
+ *
+ * This is experimental and probably doesn't
+ * do what you expect.
+ */
+
+#include "am.h"
+
+#ifdef HAS_PASSWD_MAPS
+#include <pwd.h>
+
+#define PASSWD_MAP "/etc/passwd"
+
+/*
+ * Nothing to probe - check the map name is PASSWD_MAP.
+ */
+int passwd_init P((char *map, time_t *tp));
+int passwd_init(map, tp)
+char *map;
+time_t *tp;
+{
+ *tp = 0;
+ return strcmp(map, PASSWD_MAP) == 0 ? 0 : ENOENT;
+}
+
+
+/*
+ * Grab the entry via the getpwname routine
+ * Modify time is ignored by passwd - XXX
+ */
+int passwd_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
+int passwd_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ char *dir = 0;
+ struct passwd *pw;
+ if (strcmp(key, "/defaults") == 0) {
+ *pval = strdup("type:=nfs");
+ return 0;
+ }
+
+ pw = getpwnam(key);
+ if (pw) {
+ /*
+ * We chop the home directory up as follows:
+ * /anydir/dom1/dom2/dom3/user
+ *
+ * and return
+ * rfs:=/anydir/dom3;rhost:=dom3.dom2.dom1;sublink:=user
+ *
+ * This allows cross-domain entries in your passwd file.
+ * ... but forget about security!
+ */
+ char *user;
+ char *p, *q;
+ char val[MAXPATHLEN];
+ char rhost[MAXHOSTNAMELEN];
+ dir = strdup(pw->pw_dir);
+ /*
+ * Find user name. If no / then Invalid...
+ */
+ user = strrchr(dir, '/');
+ if (!user)
+ goto enoent;
+ *user++ = '\0';
+ /*
+ * Find start of host "path". If no / then Invalid...
+ */
+ p = strchr(dir+1, '/');
+ if (!p)
+ goto enoent;
+ *p++ = '\0';
+ /*
+ * At this point, p is dom1/dom2/dom3
+ * Copy, backwards, into rhost replacing
+ * / with .
+ */
+ rhost[0] = '\0';
+ do {
+ q = strrchr(p, '/');
+ if (q) {
+ strcat(rhost, q + 1);
+ strcat(rhost, ".");
+ *q = '\0';
+ } else {
+ strcat(rhost, p);
+ }
+ } while (q);
+ /*
+ * Sanity check
+ */
+ if (*rhost == '\0' || *user == '\0' || *dir == '\0')
+ goto enoent;
+ /*
+ * Make up return string
+ */
+ q = strchr(rhost, '.');
+ if (q)
+ *q = '\0';
+ sprintf(val, "rfs:=%s/%s;rhost:=%s;sublink:=%s;fs:=${autodir}%s",
+ dir, rhost, rhost, user, pw->pw_dir);
+ if (q)
+ *q = '.';
+ *pval = strdup(val);
+ return 0;
+ }
+
+enoent:
+ if (dir)
+ free(dir);
+
+ return ENOENT;
+}
+#endif /* HAS_PASSWD_MAPS */
diff --git a/usr.sbin/amd/amd/info_union.c b/usr.sbin/amd/amd/info_union.c
new file mode 100644
index 0000000..e3062ad
--- /dev/null
+++ b/usr.sbin/amd/amd/info_union.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)info_union.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: info_union.c,v 5.2.2.1 1992/02/09 15:08:34 jsp beta $
+ *
+ */
+
+/*
+ * Get info from the system namespace
+ *
+ * NOTE: Cannot handle reads back through the automounter.
+ * THIS WILL CAUSE A DEADLOCK!
+ */
+
+#include "am.h"
+
+#ifdef HAS_UNION_MAPS
+
+#ifdef _POSIX_SOURCE
+#include <dirent.h>
+#define DIRENT struct dirent
+#else
+#include <sys/dir.h>
+#define DIRENT struct direct
+#endif
+
+#define UNION_PREFIX "union:"
+#define UNION_PREFLEN 6
+
+/*
+ * No way to probe - check the map name begins with "union:"
+ */
+int union_init P((char *map, time_t *tp));
+int union_init(map, tp)
+char *map;
+time_t *tp;
+{
+ *tp = 0;
+ return strncmp(map, UNION_PREFIX, UNION_PREFLEN) == 0 ? 0 : ENOENT;
+}
+
+int union_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
+int union_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ char *mapd = strdup(map + UNION_PREFLEN);
+ char **v = strsplit(mapd, ':', '\"');
+ char **p;
+ for (p = v; p[1]; p++)
+ ;
+ *pval = xmalloc(strlen(*p) + 5);
+ sprintf(*pval, "fs:=%s", *p);
+ free(mapd);
+ free(v);
+ return 0;
+}
+
+int union_reload P((mnt_map *m, char *map, void (*fn)()));
+int union_reload(m, map, fn)
+mnt_map *m;
+char *map;
+void (*fn)();
+{
+ char *mapd = strdup(map + UNION_PREFLEN);
+ char **v = strsplit(mapd, ':', '\"');
+ char **dir;
+
+ /*
+ * Add fake /defaults entry
+ */
+ (*fn)(m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
+
+ for (dir = v; *dir; dir++) {
+ int dlen;
+ DIRENT *dp;
+ DIR *dirp = opendir(*dir);
+ if (!dirp) {
+ plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
+ continue;
+ }
+ dlen = strlen(*dir);
+#ifdef DEBUG
+ dlog("Reading directory %s...", *dir);
+#endif
+ while (dp = readdir(dirp)) {
+ char *val;
+ if (dp->d_name[0] == '.' &&
+ (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+
+#ifdef DEBUG
+ dlog("... gives %s", dp->d_name);
+#endif
+ val = xmalloc(dlen + 5);
+ sprintf(val, "fs:=%s", *dir);
+ (*fn)(m, strdup(dp->d_name), val);
+ }
+ closedir(dirp);
+ }
+ /*
+ * Add wildcard entry
+ */
+ { char *val = xmalloc(strlen(dir[-1]) + 5);
+ sprintf(val, "fs:=%s", dir[-1]);
+ (*fn)(m, strdup("*"), val);
+ }
+ free(mapd);
+ free(v);
+ return 0;
+}
+
+#endif /* HAS_UNION_MAPS */
diff --git a/usr.sbin/amd/amd/map.c b/usr.sbin/amd/amd/map.c
new file mode 100644
index 0000000..6f2acb3
--- /dev/null
+++ b/usr.sbin/amd/amd/map.c
@@ -0,0 +1,1140 @@
+/*-
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: map.c,v 5.2.2.1 1992/02/09 15:08:36 jsp beta $
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "am.h"
+
+/*
+ * Generation Numbers.
+ *
+ * Generation numbers are allocated to every node created
+ * by amd. When a filehandle is computed and sent to the
+ * kernel, the generation number makes sure that it is safe
+ * to reallocate a node slot even when the kernel has a cached
+ * reference to its old incarnation.
+ * No garbage collection is done, since it is assumed that
+ * there is no way that 2^32 generation numbers could ever
+ * be allocated by a single run of amd - there is simply
+ * not enough cpu time available.
+ */
+static unsigned int am_gen = 2; /* Initial generation number */
+#define new_gen() (am_gen++)
+
+am_node **exported_ap = (am_node **) 0;
+int exported_ap_size = 0;
+int first_free_map = 0; /* First available free slot */
+int last_used_map = -1; /* Last unavailable used slot */
+static int timeout_mp_id; /* Id from last call to timeout */
+
+/*
+ * This is the default attributes field which
+ * is copied into every new node to be created.
+ * The individual filesystem fs_init() routines
+ * patch the copy to represent the particular
+ * details for the relevant filesystem type
+ */
+static struct fattr gen_fattr = {
+ NFLNK, /* type */
+ NFSMODE_LNK | 0777, /* mode */
+ 1, /* nlink */
+ 0, /* uid */
+ 0, /* gid */
+ 0, /* size */
+ 4096, /* blocksize */
+ 0, /* rdev */
+ 1, /* blocks */
+ 0, /* fsid */
+ 0, /* fileid */
+ { 0, 0 }, /* atime */
+ { 0, 0 }, /* mtime */
+ { 0, 0 }, /* ctime */
+};
+
+/*
+ * Resize exported_ap map
+ */
+static int exported_ap_realloc_map P((int nsize));
+static int exported_ap_realloc_map(nsize)
+int nsize;
+{
+#ifdef notdef
+ /*
+ * If a second realloc occasionally causes Amd to die
+ * in then include this check.
+ */
+ if (exported_ap_size != 0) /* XXX */
+ return 0;
+#endif
+
+ /*
+ * this shouldn't happen, but...
+ */
+ if (nsize < 0 || nsize == exported_ap_size)
+ return 0;
+
+ exported_ap = (am_node **) xrealloc((voidp) exported_ap, nsize * sizeof(am_node*));
+
+ if (nsize > exported_ap_size)
+ bzero((char*) (exported_ap+exported_ap_size),
+ (nsize - exported_ap_size) * sizeof(am_node*));
+ exported_ap_size = nsize;
+
+ return 1;
+}
+
+
+/*
+ * The root of the mount tree.
+ */
+am_node *root_node;
+
+/*
+ * Allocate a new mount slot and create
+ * a new node.
+ * Fills in the map number of the node,
+ * but leaves everything else uninitialised.
+ */
+am_node *exported_ap_alloc(P_void)
+{
+ am_node *mp, **mpp;
+
+ /*
+ * First check if there are any slots left, realloc if needed
+ */
+ if (first_free_map >= exported_ap_size)
+ if (!exported_ap_realloc_map(exported_ap_size + NEXP_AP))
+ return 0;
+
+ /*
+ * Grab the next free slot
+ */
+ mpp = exported_ap + first_free_map;
+ mp = *mpp = ALLOC(am_node);
+ bzero((char *) mp, sizeof(*mp));
+
+ mp->am_mapno = first_free_map++;
+
+ /*
+ * Update free pointer
+ */
+ while (first_free_map < exported_ap_size && exported_ap[first_free_map])
+ first_free_map++;
+
+ if (first_free_map > last_used_map)
+ last_used_map = first_free_map - 1;
+
+ /*
+ * Shrink exported_ap if reasonable
+ */
+ if (last_used_map < exported_ap_size - (NEXP_AP + NEXP_AP_MARGIN))
+ exported_ap_realloc_map(exported_ap_size - NEXP_AP);
+
+#ifdef DEBUG
+ /*dlog("alloc_exp: last_used_map = %d, first_free_map = %d\n",
+ last_used_map, first_free_map);*/
+#endif /* DEBUG */
+
+ return mp;
+}
+
+/*
+ * Free a mount slot
+ */
+void exported_ap_free P((am_node *mp));
+void exported_ap_free(mp)
+am_node *mp;
+{
+ /*
+ * Sanity check
+ */
+ if (!mp)
+ return;
+
+ /*
+ * Zero the slot pointer to avoid double free's
+ */
+ exported_ap[mp->am_mapno] = 0;
+
+ /*
+ * Update the free and last_used indices
+ */
+ if (mp->am_mapno == last_used_map)
+ while (last_used_map >= 0 && exported_ap[last_used_map] == 0)
+ --last_used_map;
+
+ if (first_free_map > mp->am_mapno)
+ first_free_map = mp->am_mapno;
+
+#ifdef DEBUG
+ /*dlog("free_exp: last_used_map = %d, first_free_map = %d\n",
+ last_used_map, first_free_map);*/
+#endif /* DEBUG */
+
+ /*
+ * Free the mount node
+ */
+ free((voidp) mp);
+}
+
+/*
+ * Insert mp into the correct place,
+ * where p_mp is its parent node.
+ * A new node gets placed as the youngest sibling
+ * of any other children, and the parent's child
+ * pointer is adjusted to point to the new child node.
+ */
+void insert_am(mp, p_mp)
+am_node *mp;
+am_node *p_mp;
+{
+ /*
+ * If this is going in at the root then flag it
+ * so that it cannot be unmounted by amq.
+ */
+ if (p_mp == root_node)
+ mp->am_flags |= AMF_ROOT;
+ /*
+ * Fill in n-way links
+ */
+ mp->am_parent = p_mp;
+ mp->am_osib = p_mp->am_child;
+ if (mp->am_osib)
+ mp->am_osib->am_ysib = mp;
+ p_mp->am_child = mp;
+}
+
+/*
+ * Remove am from its place in the mount tree
+ */
+void remove_am(mp)
+am_node *mp;
+{
+ /*
+ * 1. Consistency check
+ */
+ if (mp->am_child && mp->am_parent) {
+ plog(XLOG_WARNING, "children of \"%s\" still exist - deleting anyway", mp->am_path);
+ }
+
+ /*
+ * 2. Update parent's child pointer
+ */
+ if (mp->am_parent && mp->am_parent->am_child == mp)
+ mp->am_parent->am_child = mp->am_osib;
+
+ /*
+ * 3. Unlink from sibling chain
+ */
+ if (mp->am_ysib)
+ mp->am_ysib->am_osib = mp->am_osib;
+ if (mp->am_osib)
+ mp->am_osib->am_ysib = mp->am_ysib;
+}
+
+/*
+ * Compute a new time to live value for a node.
+ */
+void new_ttl(mp)
+am_node *mp;
+{
+ mp->am_timeo_w = 0;
+
+ mp->am_ttl = clocktime();
+ mp->am_fattr.atime.seconds = mp->am_ttl;
+ mp->am_ttl += mp->am_timeo; /* sun's -tl option */
+}
+
+void mk_fattr P((am_node *mp, ftype vntype));
+void mk_fattr(mp, vntype)
+am_node *mp;
+ftype vntype;
+{
+ switch (vntype) {
+ case NFDIR:
+ mp->am_fattr.type = NFDIR;
+ mp->am_fattr.mode = NFSMODE_DIR | 0555;
+ mp->am_fattr.nlink = 2;
+ mp->am_fattr.size = 512;
+ break;
+ case NFLNK:
+ mp->am_fattr.type = NFLNK;
+ mp->am_fattr.mode = NFSMODE_LNK | 0777;
+ mp->am_fattr.nlink = 1;
+ mp->am_fattr.size = 0;
+ break;
+ default:
+ plog(XLOG_FATAL, "Unknown fattr type %d - ignored", vntype);
+ break;
+ }
+}
+
+/*
+ * Initialise an allocated mount node.
+ * It is assumed that the mount node was bzero'd
+ * before getting here so anything that would
+ * be set to zero isn't done here.
+ */
+void init_map(mp, dir)
+am_node *mp;
+char *dir;
+{
+ /* mp->am_mapno initalised by exported_ap_alloc */
+ mp->am_mnt = new_mntfs();
+ mp->am_name = strdup(dir);
+ mp->am_path = strdup(dir);
+ /*mp->am_link = 0;*/
+ /*mp->am_parent = 0;*/
+ /*mp->am_ysib = 0;*/
+ /*mp->am_osib = 0;*/
+ /*mp->am_child = 0;*/
+ /*mp->am_flags = 0;*/
+ /*mp->am_error = 0;*/
+ mp->am_gen = new_gen();
+ /*mp->am_pref = 0;*/
+
+ mp->am_timeo = am_timeo;
+ mp->am_attr.status = NFS_OK;
+ mp->am_fattr = gen_fattr;
+ mp->am_fattr.fsid = 42;
+ mp->am_fattr.fileid = 0;
+ mp->am_fattr.atime.seconds = clocktime();
+ mp->am_fattr.atime.useconds = 0;
+ mp->am_fattr.mtime = mp->am_fattr.ctime = mp->am_fattr.atime;
+
+ new_ttl(mp);
+ mp->am_stats.s_mtime = mp->am_fattr.atime.seconds;
+ /*mp->am_private = 0;*/
+}
+
+/*
+ * Free a mount node.
+ * The node must be already unmounted.
+ */
+void free_map(mp)
+am_node *mp;
+{
+ remove_am(mp);
+
+ if (mp->am_link)
+ free(mp->am_link);
+ if (mp->am_name)
+ free(mp->am_name);
+ if (mp->am_path)
+ free(mp->am_path);
+ if (mp->am_pref)
+ free(mp->am_pref);
+
+ if (mp->am_mnt)
+ free_mntfs(mp->am_mnt);
+
+ exported_ap_free(mp);
+}
+
+/*
+ * Convert from file handle to
+ * automount node.
+ */
+am_node *fh_to_mp3(fhp, rp, c_or_d)
+nfs_fh *fhp;
+int *rp;
+int c_or_d;
+{
+ struct am_fh *fp = (struct am_fh *) fhp;
+ am_node *ap = 0;
+
+ /*
+ * Check process id matches
+ * If it doesn't then it is probably
+ * from an old kernel cached filehandle
+ * which is now out of date.
+ */
+ if (fp->fhh_pid != mypid)
+ goto drop;
+
+ /*
+ * Make sure the index is valid before
+ * exported_ap is referenced.
+ */
+ if (fp->fhh_id < 0 || fp->fhh_id >= exported_ap_size)
+ goto drop;
+
+ /*
+ * Get hold of the supposed mount node
+ */
+ ap = exported_ap[fp->fhh_id];
+
+ /*
+ * If it exists then maybe...
+ */
+ if (ap) {
+ /*
+ * Check the generation number in the node
+ * matches the one from the kernel. If not
+ * then the old node has been timed out and
+ * a new one allocated.
+ */
+ if (ap->am_gen != fp->fhh_gen) {
+ ap = 0;
+ goto drop;
+ }
+
+ /*
+ * If the node is hung then locate a new node
+ * for it. This implements the replicated filesystem
+ * retries.
+ */
+ if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
+ int error;
+ am_node *orig_ap = ap;
+#ifdef DEBUG
+ dlog("fh_to_mp3: %s (%s) is hung:- call lookup",
+ orig_ap->am_path, orig_ap->am_mnt->mf_info);
+#endif /* DEBUG */
+ /*
+ * Update modify time of parent node.
+ * With any luck the kernel will re-stat
+ * the child node and get new information.
+ */
+ orig_ap->am_fattr.mtime.seconds = clocktime();
+
+ /*
+ * Call the parent's lookup routine for an object
+ * with the same name. This may return -1 in error
+ * if a mount is in progress. In any case, if no
+ * mount node is returned the error code is propagated
+ * to the caller.
+ */
+ if (c_or_d == VLOOK_CREATE) {
+ ap = (*orig_ap->am_parent->am_mnt->mf_ops->lookuppn)(orig_ap->am_parent,
+ orig_ap->am_name, &error, c_or_d);
+ } else {
+ ap = 0;
+ error = ESTALE;
+ }
+ if (ap == 0) {
+ if (error < 0 && amd_state == Finishing)
+ error = ENOENT;
+ *rp = error;
+ return 0;
+ }
+ /*
+ * Update last access to original node. This
+ * avoids timing it out and so sending ESTALE
+ * back to the kernel.
+ * XXX - Not sure we need this anymore (jsp, 90/10/6).
+ */
+ new_ttl(orig_ap);
+
+ }
+ /*
+ * Disallow references to objects being unmounted, unless
+ * they are automount points.
+ */
+ if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
+ !(ap->am_flags & AMF_ROOT)) {
+ if (amd_state == Finishing)
+ *rp = ENOENT;
+ else
+ *rp = -1;
+ return 0;
+ }
+ new_ttl(ap);
+ }
+
+drop:
+ if (!ap || !ap->am_mnt) {
+ /*
+ * If we are shutting down then it is likely
+ * that this node has disappeared because of
+ * a fast timeout. To avoid things thrashing
+ * just pretend it doesn't exist at all. If
+ * ESTALE is returned, some NFS clients just
+ * keep retrying (stupid or what - if it's
+ * stale now, what's it going to be in 5 minutes?)
+ */
+ if (amd_state == Finishing)
+ *rp = ENOENT;
+ else
+ *rp = ESTALE;
+ amd_stats.d_stale++;
+ }
+
+ return ap;
+}
+
+am_node *fh_to_mp(fhp)
+nfs_fh *fhp;
+{
+ int dummy;
+ return fh_to_mp2(fhp, &dummy);
+}
+
+/*
+ * Convert from automount node to
+ * file handle.
+ */
+void mp_to_fh(mp, fhp)
+am_node *mp;
+struct nfs_fh *fhp;
+{
+ struct am_fh *fp = (struct am_fh *) fhp;
+
+ /*
+ * Take the process id
+ */
+ fp->fhh_pid = mypid;
+ /*
+ * .. the map number
+ */
+ fp->fhh_id = mp->am_mapno;
+ /*
+ * .. and the generation number
+ */
+ fp->fhh_gen = mp->am_gen;
+ /*
+ * .. to make a "unique" triple that will never
+ * be reallocated except across reboots (which doesn't matter)
+ * or if we are unlucky enough to be given the same
+ * pid as a previous amd (very unlikely).
+ */
+}
+
+static am_node *find_ap2 P((char *dir, am_node *mp));
+static am_node *find_ap2(dir, mp)
+char *dir;
+am_node *mp;
+{
+ if (mp) {
+ am_node *mp2;
+ if (strcmp(mp->am_path, dir) == 0)
+ return mp;
+
+ if ((mp->am_mnt->mf_flags & MFF_MOUNTED) &&
+ strcmp(mp->am_mnt->mf_mount, dir) == 0)
+ return mp;
+
+ mp2 = find_ap2(dir, mp->am_osib);
+ if (mp2)
+ return mp2;
+ return find_ap2(dir, mp->am_child);
+ }
+
+ return 0;
+}
+
+/*
+ * Find the mount node corresponding
+ * to dir. dir can match either the
+ * automount path or, if the node is
+ * mounted, the mount location.
+ */
+am_node *find_ap P((char *dir));
+am_node *find_ap(dir)
+char *dir;
+{
+ int i;
+
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ if (mp && (mp->am_flags & AMF_ROOT)) {
+ mp = find_ap2(dir, exported_ap[i]);
+ if (mp)
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Find the mount node corresponding
+ * to the mntfs structure.
+ */
+am_node *find_mf P((mntfs *mf));
+am_node *find_mf(mf)
+mntfs *mf;
+{
+ int i;
+
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ if (mp && mp->am_mnt == mf)
+ return mp;
+ }
+ return 0;
+}
+
+/*
+ * Get the filehandle for a particular named directory.
+ * This is used during the bootstrap to tell the kernel
+ * the filehandles of the initial automount points.
+ */
+nfs_fh *root_fh(dir)
+char *dir;
+{
+ static nfs_fh nfh;
+ am_node *mp = root_ap(dir, TRUE);
+ if (mp) {
+ mp_to_fh(mp, &nfh);
+ /*
+ * Patch up PID to match main server...
+ */
+ if (!foreground) {
+ long pid = getppid();
+ ((struct am_fh *) &nfh)->fhh_pid = pid;
+#ifdef DEBUG
+ dlog("root_fh substitutes pid %d", pid);
+#endif
+ }
+ return &nfh;
+ }
+
+ /*
+ * Should never get here...
+ */
+ plog(XLOG_ERROR, "Can't find root filehandle for %s", dir);
+ return 0;
+}
+
+am_node *root_ap(dir, path)
+char *dir;
+int path;
+{
+ am_node *mp = find_ap(dir);
+ if (mp && mp->am_parent == root_node)
+ return mp;
+
+ return 0;
+}
+
+/*
+ * Timeout all nodes waiting on
+ * a given Fserver.
+ */
+void map_flush_srvr P((fserver *fs));
+void map_flush_srvr(fs)
+fserver *fs;
+{
+ int i;
+ int done = 0;
+
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) {
+ plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host);
+ mp->am_ttl = clocktime();
+ done = 1;
+ }
+ }
+ if (done)
+ reschedule_timeout_mp();
+}
+
+/*
+ * Mount a top level automount node
+ * by calling lookup in the parent
+ * (root) node which will cause the
+ * automount node to be automounted.
+ */
+int mount_auto_node P((char *dir, voidp arg));
+int mount_auto_node(dir, arg)
+char *dir;
+voidp arg;
+{
+ int error = 0;
+ (void) afs_ops.lookuppn((am_node *) arg, dir, &error, VLOOK_CREATE);
+ if (error > 0) {
+ errno = error; /* XXX */
+ plog(XLOG_ERROR, "Could not mount %s: %m", dir);
+ }
+ return error;
+}
+
+/*
+ * Cause all the top-level mount nodes
+ * to be automounted
+ */
+int mount_exported P((void));
+int mount_exported()
+{
+ /*
+ * Iterate over all the nodes to be started
+ */
+ return root_keyiter((void (*)P((char*,void*))) mount_auto_node, root_node);
+}
+
+/*
+ * Construct top-level node
+ */
+void make_root_node P((void));
+void make_root_node()
+{
+ mntfs *root_mnt;
+ char *rootmap = ROOT_MAP;
+ root_node = exported_ap_alloc();
+
+ /*
+ * Allocate a new map
+ */
+ init_map(root_node, "");
+ /*
+ * Allocate a new mounted filesystem
+ */
+ root_mnt = find_mntfs(&root_ops, (am_opts *) 0, "", rootmap, "", "", "");
+ /*
+ * Replace the initial null reference
+ */
+ free_mntfs(root_node->am_mnt);
+ root_node->am_mnt = root_mnt;
+
+ /*
+ * Initialise the root
+ */
+ if (root_mnt->mf_ops->fs_init)
+ (*root_mnt->mf_ops->fs_init)(root_mnt);
+
+ /*
+ * Mount the root
+ */
+ root_mnt->mf_error = (*root_mnt->mf_ops->mount_fs)(root_node);
+}
+
+/*
+ * Cause all the nodes to be unmounted by timing
+ * them out.
+ */
+void umount_exported(P_void)
+{
+ int i;
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ if (mp) {
+ mntfs *mf = mp->am_mnt;
+ if (mf->mf_flags & MFF_UNMOUNTING) {
+ /*
+ * If this node is being unmounted then
+ * just ignore it. However, this could
+ * prevent amd from finishing if the
+ * unmount gets blocked since the am_node
+ * will never be free'd. am_unmounted needs
+ * telling about this possibility. - XXX
+ */
+ continue;
+ }
+ if (mf && !(mf->mf_ops->fs_flags & FS_DIRECTORY)) {
+ /*
+ * When shutting down this had better
+ * look like a directory, otherwise it
+ * can't be unmounted!
+ */
+ mk_fattr(mp, NFDIR);
+ }
+ if ((--immediate_abort < 0 && !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
+ (mf->mf_flags & MFF_RESTART)) {
+ /*
+ * Just throw this node away without
+ * bothering to unmount it. If the
+ * server is not known to be up then
+ * don't discard the mounted on directory
+ * or Amd might hang...
+ */
+ if (mf->mf_server &&
+ (mf->mf_server->fs_flags & (FSF_DOWN|FSF_VALID)) != FSF_VALID)
+ mf->mf_flags &= ~MFF_MKMNT;
+ am_unmounted(mp);
+ } else {
+ /*
+ * Any other node gets forcibly
+ * timed out
+ */
+ mp->am_flags &= ~AMF_NOTIMEOUT;
+ mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
+ mp->am_ttl = 0;
+ mp->am_timeo = 1;
+ mp->am_timeo_w = 0;
+ }
+ }
+ }
+}
+
+static int unmount_node P((am_node *mp));
+static int unmount_node(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ int error;
+
+ if ((mf->mf_flags & MFF_ERROR) || mf->mf_refc > 1) {
+ /*
+ * Just unlink
+ */
+#ifdef DEBUG
+ if (mf->mf_flags & MFF_ERROR)
+ dlog("No-op unmount of error node %s", mf->mf_info);
+#endif /* DEBUG */
+ error = 0;
+ } else {
+#ifdef DEBUG
+ dlog("Unmounting %s (%s)", mf->mf_mount, mf->mf_info);
+#endif /* DEBUG */
+ error = (*mf->mf_ops->umount_fs)(mp);
+ }
+
+ if (error) {
+#ifdef DEBUG
+ errno = error; /* XXX */
+ dlog("%s: unmount: %m", mf->mf_mount);
+#endif /* DEBUG */
+ }
+
+ return error;
+}
+
+#ifdef FLUSH_KERNEL_NAME_CACHE
+static void flush_kernel_name_cache P((am_node*));
+static void flush_kernel_name_cache(mp)
+am_node *mp;
+{
+ int islink = (mp->am_mnt->mf_fattr.type == NFLNK);
+ int isdir = (mp->am_mnt->mf_fattr.type == NFDIR);
+ int elog = 0;
+ if (islink) {
+ if (unlink(mp->am_path) < 0)
+ elog = 1;
+ } else if (isdir) {
+ if (rmdir(mp->am_path) < 0)
+ elog = 1;
+ }
+ if (elog)
+ plog(XLOG_WARNING, "failed to clear \"%s\" from dnlc: %m", mp->am_path);
+}
+#endif /* FLUSH_KERNEL_NAME_CACHE */
+
+static int unmount_node_wrap P((voidp vp));
+static int unmount_node_wrap(vp)
+voidp vp;
+{
+#ifndef FLUSH_KERNEL_NAME_CACHE
+ return unmount_node((am_node*) vp);
+#else /* FLUSH_KERNEL_NAME_CACHE */
+ /*
+ * This code should just say:
+ * return unmount_node((am_node *) vp);
+ *
+ * However...
+ * The kernel keeps a cached copy of filehandles,
+ * and doesn't ever uncache them (apparently). So
+ * when Amd times out a node the kernel will have a
+ * stale filehandle. When the kernel next uses the
+ * filehandle it gets ESTALE.
+ *
+ * The workaround:
+ * Arrange that when a node is removed an unlink or
+ * rmdir is done on that path so that the kernel
+ * cache is done. Yes - yuck.
+ *
+ * This can all be removed (and the background
+ * unmount flag in sfs_ops) if/when the kernel does
+ * something smarter.
+ *
+ * If the unlink or rmdir failed then just log a warning,
+ * don't fail the unmount. This can occur if the kernel
+ * client code decides that the object is still referenced
+ * and should be renamed rather than discarded.
+ *
+ * There is still a race condition here...
+ * if another process is trying to access the same
+ * filesystem at the time we get here, then
+ * it will block, since the MF_UNMOUNTING flag will
+ * be set. That may, or may not, cause the entire
+ * system to deadlock. Hmmm...
+ */
+ am_node *mp = (am_node *) vp;
+ int isauto = mp->am_parent && (mp->am_parent->am_mnt->mf_fattr.type == NFDIR);
+ int error = unmount_node(mp);
+ if (error)
+ return error;
+ if (isauto && (int)amd_state < (int)Finishing)
+ flush_kernel_name_cache(mp);
+
+ return 0;
+#endif /* FLUSH_KERNEL_NAME_CACHE */
+}
+
+static void free_map_if_success(rc, term, closure)
+int rc;
+int term;
+voidp closure;
+{
+ am_node *mp = (am_node *) closure;
+ mntfs *mf = mp->am_mnt;
+
+ /*
+ * Not unmounting any more
+ */
+ mf->mf_flags &= ~MFF_UNMOUNTING;
+
+ /*
+ * If a timeout was defered because the underlying filesystem
+ * was busy then arrange for a timeout as soon as possible.
+ */
+ if (mf->mf_flags & MFF_WANTTIMO) {
+ mf->mf_flags &= ~MFF_WANTTIMO;
+ reschedule_timeout_mp();
+ }
+
+ if (term) {
+ plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term);
+#if defined(DEBUG) && defined(SIGTRAP)
+ /*
+ * dbx likes to put a trap on exit().
+ * Pretend it succeeded for now...
+ */
+ if (term == SIGTRAP) {
+ am_unmounted(mp);
+ }
+#endif /* DEBUG */
+ amd_stats.d_uerr++;
+ } else if (rc) {
+ if (rc == EBUSY) {
+ plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount);
+ } else {
+ errno = rc; /* XXX */
+ plog(XLOG_ERROR, "%s: unmount: %m", mp->am_path);
+ }
+ amd_stats.d_uerr++;
+ } else {
+ am_unmounted(mp);
+ }
+
+ /*
+ * Wakeup anything waiting for this mount
+ */
+ wakeup((voidp) mf);
+}
+
+static int unmount_mp(mp)
+am_node *mp;
+{
+ int was_backgrounded = 0;
+ mntfs *mf = mp->am_mnt;
+
+#ifdef notdef
+ plog(XLOG_INFO, "\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+#endif /* notdef */
+
+ if ((mf->mf_ops->fs_flags & FS_UBACKGROUND) &&
+ (mf->mf_flags & MFF_MOUNTED)) {
+ if (mf->mf_refc == 1 && !FSRV_ISUP(mf->mf_server)) {
+ /*
+ * Don't try to unmount from a server that is known to be down
+ */
+ if (!(mf->mf_flags & MFF_LOGDOWN)) {
+ /* Only log this once, otherwise gets a bit boring */
+ plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path);
+ mf->mf_flags |= MFF_LOGDOWN;
+ }
+ } else {
+ /* Clear logdown flag - since the server must be up */
+ mf->mf_flags &= ~MFF_LOGDOWN;
+#ifdef DEBUG
+ dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+ /*dlog("Will background the unmount attempt");*/
+#endif /* DEBUG */
+ /*
+ * Note that we are unmounting this node
+ */
+ mf->mf_flags |= MFF_UNMOUNTING;
+ run_task(unmount_node_wrap, (voidp) mp,
+ free_map_if_success, (voidp) mp);
+ was_backgrounded = 1;
+#ifdef DEBUG
+ dlog("unmount attempt backgrounded");
+#endif /* DEBUG */
+ }
+ } else {
+#ifdef DEBUG
+ dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+ dlog("Trying unmount in foreground");
+#endif
+ mf->mf_flags |= MFF_UNMOUNTING;
+ free_map_if_success(unmount_node(mp), 0, (voidp) mp);
+#ifdef DEBUG
+ dlog("unmount attempt done");
+#endif /* DEBUG */
+ }
+
+ return was_backgrounded;
+}
+
+void timeout_mp()
+{
+#define NEVER (time_t) 0
+#define smallest_t(t1, t2) \
+ (t1 != NEVER ? (t2 != NEVER ? (t1 < t2 ? t1 : t2) : t1) : t2)
+#define IGNORE_FLAGS (MFF_MOUNTING|MFF_UNMOUNTING|MFF_RESTART)
+
+ int i;
+ time_t t = NEVER;
+ time_t now = clocktime();
+ int backoff = 0;
+
+#ifdef DEBUG
+ dlog("Timing out automount points...");
+#endif /* DEBUG */
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ mntfs *mf;
+ /*
+ * Just continue if nothing mounted, or can't be timed out.
+ */
+ if (!mp || (mp->am_flags & AMF_NOTIMEOUT))
+ continue;
+ /*
+ * Pick up mounted filesystem
+ */
+ mf = mp->am_mnt;
+ if (!mf)
+ continue;
+ /*
+ * Don't delete last reference to a restarted filesystem.
+ */
+ if ((mf->mf_flags & MFF_RSTKEEP) && mf->mf_refc == 1)
+ continue;
+ /*
+ * If there is action on this filesystem then ignore it
+ */
+ if (!(mf->mf_flags & IGNORE_FLAGS)) {
+ int expired = 0;
+ mf->mf_flags &= ~MFF_WANTTIMO;
+#ifdef DEBUG
+ /*dlog("t is initially @%d, zero in %d secs", t, t - now);*/
+#endif /* DEBUG */
+ if (now >= mp->am_ttl) {
+ if (!backoff) {
+ expired = 1;
+ /*
+ * Move the ttl forward to avoid thrashing effects
+ * on the next call to timeout!
+ */
+ /* sun's -tw option */
+ if (mp->am_timeo_w < 4 * am_timeo_w)
+ mp->am_timeo_w += am_timeo_w;
+ mp->am_ttl = now + mp->am_timeo_w;
+ } else {
+ /*
+ * Just backoff this unmount for
+ * a couple of seconds to avoid
+ * many multiple unmounts being
+ * started in parallel.
+ */
+ mp->am_ttl = now + backoff + 1;
+ }
+ }
+ /*
+ * If the next ttl is smallest, use that
+ */
+ t = smallest_t(t, mp->am_ttl);
+
+#ifdef DEBUG
+ /*dlog("after ttl t is @%d, zero in %d secs", t, t - now);*/
+#endif /* DEBUG */
+
+ if (!mp->am_child && mf->mf_error >= 0 && expired) {
+ /*
+ * If the unmount was backgrounded then
+ * bump the backoff counter.
+ */
+ if (unmount_mp(mp)) {
+ backoff = 2;
+#ifdef DEBUG
+ /*dlog("backing off subsequent unmounts by at least %d seconds", backoff);*/
+#endif
+ }
+ }
+ } else if (mf->mf_flags & MFF_UNMOUNTING) {
+ mf->mf_flags |= MFF_WANTTIMO;
+ }
+ }
+
+ if (t == NEVER) {
+#ifdef DEBUG
+ dlog("No further timeouts");
+#endif /* DEBUG */
+ t = now + ONE_HOUR;
+ }
+
+ /*
+ * Sanity check to avoid runaways.
+ * Absolutely should never get this but
+ * if you do without this trap amd will thrash.
+ */
+ if (t <= now) {
+ t = now + 6; /* XXX */
+ plog(XLOG_ERROR, "Got a zero interval in timeout_mp()!");
+ }
+ /*
+ * XXX - when shutting down, make things happen faster
+ */
+ if ((int)amd_state >= (int)Finishing)
+ t = now + 1;
+#ifdef DEBUG
+ dlog("Next mount timeout in %ds", t - now);
+#endif /* DEBUG */
+
+ timeout_mp_id = timeout(t - now, timeout_mp, 0);
+
+#undef NEVER
+#undef smallest_t
+#undef IGNORE_FLAGS
+}
+
+/*
+ * Cause timeout_mp to be called soonest
+ */
+void reschedule_timeout_mp()
+{
+ if (timeout_mp_id)
+ untimeout(timeout_mp_id);
+ timeout_mp_id = timeout(0, timeout_mp, 0);
+}
diff --git a/usr.sbin/amd/amd/mapc.c b/usr.sbin/amd/amd/mapc.c
new file mode 100644
index 0000000..2155f19
--- /dev/null
+++ b/usr.sbin/amd/amd/mapc.c
@@ -0,0 +1,914 @@
+/*-
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: mapc.c,v 5.2.2.1 1992/02/09 15:08:38 jsp beta $
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mapc.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Mount map cache
+ */
+
+#include "am.h"
+#ifdef HAS_REGEXP
+#include RE_HDR
+#endif
+
+/*
+ * Hash table size
+ */
+#define NKVHASH (1 << 2) /* Power of two */
+
+/*
+ * Wildcard key
+ */
+static char wildcard[] = "*";
+
+/*
+ * Map cache types
+ * default, none, incremental, all, regexp
+ * MAPC_RE implies MAPC_ALL and must be numerically
+ * greater.
+ */
+#define MAPC_DFLT 0x000
+#define MAPC_NONE 0x001
+#define MAPC_INC 0x002
+#define MAPC_ROOT 0x004
+#define MAPC_ALL 0x010
+#ifdef HAS_REGEXP
+#define MAPC_RE 0x020
+#define MAPC_ISRE(m) ((m)->alloc == MAPC_RE)
+#else
+#define MAPC_ISRE(m) FALSE
+#endif
+#define MAPC_CACHE_MASK 0x0ff
+#define MAPC_SYNC 0x100
+
+static struct opt_tab mapc_opt[] = {
+ { "all", MAPC_ALL },
+ { "default", MAPC_DFLT },
+ { "inc", MAPC_INC },
+ { "mapdefault", MAPC_DFLT },
+ { "none", MAPC_NONE },
+#ifdef HAS_REGEXP
+ { "re", MAPC_RE },
+ { "regexp", MAPC_RE },
+#endif
+ { "sync", MAPC_SYNC },
+ { 0, 0 }
+};
+
+/*
+ * Lookup recursion
+ */
+#define MREC_FULL 2
+#define MREC_PART 1
+#define MREC_NONE 0
+
+/*
+ * Cache map operations
+ */
+typedef void add_fn P((mnt_map*, char*, char*));
+typedef int init_fn P((char*, time_t*));
+typedef int search_fn P((mnt_map*, char*, char*, char**, time_t*));
+typedef int reload_fn P((mnt_map*, char*, add_fn*));
+typedef int mtime_fn P((char*, time_t*));
+
+static void mapc_sync P((mnt_map*));
+
+/*
+ * Map type
+ */
+typedef struct map_type map_type;
+struct map_type {
+ char *name; /* Name of this map type */
+ init_fn *init; /* Initialisation */
+ reload_fn *reload; /* Reload or fill */
+ search_fn *search; /* Search for new entry */
+ mtime_fn *mtime; /* Find modify time */
+ int def_alloc; /* Default allocation mode */
+};
+
+/*
+ * Key-value pair
+ */
+typedef struct kv kv;
+struct kv {
+ kv *next;
+ char *key;
+ char *val;
+};
+
+struct mnt_map {
+ qelem hdr;
+ int refc; /* Reference count */
+ short flags; /* Allocation flags */
+ short alloc; /* Allocation mode */
+ time_t modify; /* Modify time of map */
+ char *map_name; /* Name of this map */
+ char *wildcard; /* Wildcard value */
+ reload_fn *reload; /* Function to be used for reloads */
+ search_fn *search; /* Function to be used for searching */
+ mtime_fn *mtime; /* Modify time function */
+ kv *kvhash[NKVHASH]; /* Cached data */
+};
+
+/*
+ * Map for root node
+ */
+static mnt_map *root_map;
+
+/*
+ * List of known maps
+ */
+extern qelem map_list_head;
+qelem map_list_head = { &map_list_head, &map_list_head };
+
+/*
+ * Configuration
+ */
+
+/* ROOT MAP */
+static int root_init P((char*, time_t*));
+
+/* FILE MAPS */
+#ifdef HAS_FILE_MAPS
+extern int file_init P((char*, time_t*));
+extern int file_reload P((mnt_map*, char*, add_fn*));
+extern int file_search P((mnt_map*, char*, char*, char**, time_t*));
+extern int file_mtime P((char*, time_t*));
+#endif /* HAS_FILE_MAPS */
+
+/* Network Information Service (NIS) MAPS */
+#ifdef HAS_NIS_MAPS
+extern int nis_init P((char*, time_t*));
+#ifdef HAS_NIS_RELOAD
+extern int nis_reload P((mnt_map*, char*, add_fn*));
+#else
+#define nis_reload error_reload
+#endif
+extern int nis_search P((mnt_map*, char*, char*, char**, time_t*));
+#define nis_mtime nis_init
+#endif /* HAS_NIS_MAPS */
+
+/* NDBM MAPS */
+#ifdef HAS_NDBM_MAPS
+#ifdef OS_HAS_NDBM
+extern int ndbm_init P((char*, time_t*));
+extern int ndbm_search P((mnt_map*, char*, char*, char**, time_t*));
+#define ndbm_mtime ndbm_init
+#endif /* OS_HAS_NDBM */
+#endif /* HAS_NDBM_MAPS */
+
+/* PASSWD MAPS */
+#ifdef HAS_PASSWD_MAPS
+extern int passwd_init P((char*, time_t*));
+extern int passwd_search P((mnt_map*, char*, char*, char**, time_t*));
+#endif /* HAS_PASSWD_MAPS */
+
+/* HESIOD MAPS */
+#ifdef HAS_HESIOD_MAPS
+extern int hesiod_init P((char*, time_t*));
+#ifdef HAS_HESIOD_RELOAD
+extern int hesiod_reload P((mnt_map*, char*, add_fn*));
+#else
+#define hesiod_reload error_reload
+#endif
+extern int hesiod_search P((mnt_map*, char*, char*, char**, time_t*));
+#endif /* HAS_HESIOD_MAPS */
+
+/* UNION MAPS */
+#ifdef HAS_UNION_MAPS
+extern int union_init P((char*, time_t*));
+extern int union_search P((mnt_map*, char*, char*, char**, time_t*));
+extern int union_reload P((mnt_map*, char*, add_fn*));
+#endif /* HAS_UNION_MAPS */
+
+/* ERROR MAP */
+static int error_init P((char*, time_t*));
+static int error_reload P((mnt_map*, char*, add_fn*));
+static int error_search P((mnt_map*, char*, char*, char**, time_t*));
+static int error_mtime P((char*, time_t*));
+
+static map_type maptypes[] = {
+ { "root", root_init, error_reload, error_search, error_mtime, MAPC_ROOT },
+
+#ifdef HAS_PASSWD_MAPS
+ { "passwd", passwd_init, error_reload, passwd_search, error_mtime, MAPC_INC },
+#endif
+
+#ifdef HAS_HESIOD_MAPS
+ { "hesiod", hesiod_init, hesiod_reload, hesiod_search, error_mtime, MAPC_ALL },
+#endif
+
+#ifdef HAS_UNION_MAPS
+ { "union", union_init, union_reload, union_search, error_mtime, MAPC_ALL },
+#endif
+
+#ifdef HAS_NIS_MAPS
+ { "nis", nis_init, nis_reload, nis_search, nis_mtime, MAPC_INC },
+#endif
+
+#ifdef HAS_NDBM_MAPS
+ { "ndbm", ndbm_init, error_reload, ndbm_search, ndbm_mtime, MAPC_INC },
+#endif
+
+#ifdef HAS_FILE_MAPS
+ { "file", file_init, file_reload, file_search, file_mtime, MAPC_ALL },
+#endif
+
+ { "error", error_init, error_reload, error_search, error_mtime, MAPC_NONE },
+};
+
+/*
+ * Hash function
+ */
+static unsigned int kvhash_of P((char *key));
+static unsigned int kvhash_of(key)
+char *key;
+{
+ unsigned int i, j;
+
+ for (i = 0; j = *key++; i += j)
+ ;
+
+ return i % NKVHASH;
+}
+
+void mapc_showtypes P((FILE *fp));
+void mapc_showtypes(fp)
+FILE *fp;
+{
+ map_type *mt;
+ char *sep = "";
+ for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++) {
+ fprintf(fp, "%s%s", sep, mt->name);
+ sep = ", ";
+ }
+}
+
+static Const char *reg_error = "?";
+void regerror P((Const char *m));
+void regerror(m)
+Const char *m;
+{
+ reg_error = m;
+}
+
+/*
+ * Add key and val to the map m.
+ * key and val are assumed to be safe copies
+ */
+void mapc_add_kv P((mnt_map *m, char *key, char *val));
+void mapc_add_kv(m, key, val)
+mnt_map *m;
+char *key;
+char *val;
+{
+ kv **h;
+ kv *n;
+ int hash = kvhash_of(key);
+
+#ifdef DEBUG
+ dlog("add_kv: %s -> %s", key, val);
+#endif
+
+#ifdef HAS_REGEXP
+ if (MAPC_ISRE(m)) {
+ char keyb[MAXPATHLEN];
+ regexp *re;
+ /*
+ * Make sure the string is bound to the start and end
+ */
+ sprintf(keyb, "^%s$", key);
+ re = regcomp(keyb);
+ if (re == 0) {
+ plog(XLOG_USER, "error compiling RE \"%s\": %s", keyb, reg_error);
+ return;
+ } else {
+ free(key);
+ key = (char *) re;
+ }
+ }
+#endif
+
+ h = &m->kvhash[hash];
+ n = ALLOC(kv);
+ n->key = key;
+ n->val = val;
+ n->next = *h;
+ *h = n;
+}
+
+void mapc_repl_kv P((mnt_map *m, char *key, char *val));
+void mapc_repl_kv(m, key, val)
+mnt_map *m;
+char *key;
+char *val;
+{
+ kv *k;
+
+ /*
+ * Compute the hash table offset
+ */
+ k = m->kvhash[kvhash_of(key)];
+
+ /*
+ * Scan the linked list for the key
+ */
+ while (k && !FSTREQ(k->key, key))
+ k = k->next;
+
+ if (k) {
+ free(k->val);
+ k->val = val;
+ } else {
+ mapc_add_kv(m, key, val);
+ }
+
+}
+
+/*
+ * Search a map for a key.
+ * Calls map specific search routine.
+ * While map is out of date, keep re-syncing.
+ */
+static int search_map P((mnt_map *m, char *key, char **valp));
+static int search_map(m, key, valp)
+mnt_map *m;
+char *key;
+char **valp;
+{
+ int rc;
+ do {
+ rc = (*m->search)(m, m->map_name, key, valp, &m->modify);
+ if (rc < 0) {
+ plog(XLOG_MAP, "Re-synchronizing cache for map %s", m->map_name);
+ mapc_sync(m);
+ }
+ } while (rc < 0);
+
+ return rc;
+}
+
+/*
+ * Do a wildcard lookup in the map and
+ * save the result.
+ */
+static void mapc_find_wildcard P((mnt_map *m));
+static void mapc_find_wildcard(m)
+mnt_map *m;
+{
+ /*
+ * Attempt to find the wildcard entry
+ */
+ int rc = search_map(m, wildcard, &m->wildcard);
+
+ if (rc != 0)
+ m->wildcard = 0;
+}
+
+/*
+ * Make a duplicate reference to an existing map
+ */
+#define mapc_dup(m) ((m)->refc++, (m))
+
+/*
+ * Do a map reload
+ */
+static int mapc_reload_map(m)
+mnt_map *m;
+{
+ int error;
+#ifdef DEBUG
+ dlog("calling map reload on %s", m->map_name);
+#endif
+ error = (*m->reload)(m, m->map_name, mapc_add_kv);
+ if (error)
+ return error;
+ m->wildcard = 0;
+#ifdef DEBUG
+ dlog("calling mapc_search for wildcard");
+#endif
+ error = mapc_search(m, wildcard, &m->wildcard);
+ if (error)
+ m->wildcard = 0;
+ return 0;
+}
+
+/*
+ * Create a new map
+ */
+static mnt_map *mapc_create P((char *map, char *opt));
+static mnt_map *mapc_create(map, opt)
+char *map;
+char *opt;
+{
+ mnt_map *m = ALLOC(mnt_map);
+ map_type *mt;
+ time_t modify;
+ int alloc = 0;
+
+ (void) cmdoption(opt, mapc_opt, &alloc);
+
+ for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++)
+ if ((*mt->init)(map, &modify) == 0)
+ break;
+ /* assert: mt in maptypes */
+
+ m->flags = alloc & ~MAPC_CACHE_MASK;
+ alloc &= MAPC_CACHE_MASK;
+
+ if (alloc == MAPC_DFLT)
+ alloc = mt->def_alloc;
+ switch (alloc) {
+ default:
+ plog(XLOG_USER, "Ambiguous map cache type \"%s\"; using \"inc\"", opt);
+ alloc = MAPC_INC;
+ /* fallthrough... */
+ case MAPC_NONE:
+ case MAPC_INC:
+ case MAPC_ROOT:
+ break;
+ case MAPC_ALL:
+ /*
+ * If there is no support for reload and it was requested
+ * then back off to incremental instead.
+ */
+ if (mt->reload == error_reload) {
+ plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"; using \"inc\"", mt->name);
+ alloc = MAPC_INC;
+ }
+ break;
+#ifdef HAS_REGEXP
+ case MAPC_RE:
+ if (mt->reload == error_reload) {
+ plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"re\"", mt->name);
+ mt = &maptypes[sizeof(maptypes)/sizeof(maptypes[0]) - 1];
+ /* assert: mt->name == "error" */
+ }
+ break;
+#endif
+ }
+
+#ifdef DEBUG
+ dlog("Map for %s coming from maptype %s", map, mt->name);
+#endif
+
+ m->alloc = alloc;
+ m->reload = mt->reload;
+ m->modify = modify;
+ m->search = alloc >= MAPC_ALL ? error_search : mt->search;
+ m->mtime = mt->mtime;
+ bzero((voidp) m->kvhash, sizeof(m->kvhash));
+ m->map_name = strdup(map);
+ m->refc = 1;
+ m->wildcard = 0;
+
+ /*
+ * synchronize cache with reality
+ */
+ mapc_sync(m);
+
+ return m;
+}
+
+/*
+ * Free the cached data in a map
+ */
+static void mapc_clear P((mnt_map *m));
+static void mapc_clear(m)
+mnt_map *m;
+{
+ int i;
+
+ /*
+ * For each of the hash slots, chain
+ * along free'ing the data.
+ */
+ for (i = 0; i < NKVHASH; i++) {
+ kv *k = m->kvhash[i];
+ while (k) {
+ kv *n = k->next;
+ free((voidp) k->key);
+ if (k->val)
+ free((voidp) k->val);
+ free((voidp) k);
+ k = n;
+ }
+ }
+ /*
+ * Zero the hash slots
+ */
+ bzero((voidp) m->kvhash, sizeof(m->kvhash));
+ /*
+ * Free the wildcard if it exists
+ */
+ if (m->wildcard) {
+ free(m->wildcard);
+ m->wildcard = 0;
+ }
+}
+
+/*
+ * Find a map, or create one if it does not exist
+ */
+mnt_map *mapc_find P((char *map, char *opt));
+mnt_map *mapc_find(map, opt)
+char *map;
+char *opt;
+{
+ mnt_map *m;
+
+ /*
+ * Search the list of known maps to see if
+ * it has already been loaded. If it is found
+ * then return a duplicate reference to it.
+ * Otherwise make a new map as required and
+ * add it to the list of maps
+ */
+ ITER(m, mnt_map, &map_list_head)
+ if (STREQ(m->map_name, map))
+ return mapc_dup(m);
+
+ m = mapc_create(map, opt);
+ ins_que(&m->hdr, &map_list_head);
+ return m;
+}
+
+/*
+ * Free a map.
+ */
+void mapc_free P((mnt_map *m));
+void mapc_free(m)
+mnt_map *m;
+{
+ /*
+ * Decrement the reference count.
+ * If the reference count hits zero
+ * then throw the map away.
+ */
+ if (m && --m->refc == 0) {
+ mapc_clear(m);
+ free((voidp) m->map_name);
+ rem_que(&m->hdr);
+ free((voidp) m);
+ }
+}
+
+/*
+ * Search the map for the key.
+ * Put a safe copy in *pval or return
+ * an error code
+ */
+int mapc_meta_search P((mnt_map *m, char *key, char **pval, int recurse));
+int mapc_meta_search(m, key, pval, recurse)
+mnt_map *m;
+char *key;
+char **pval;
+int recurse;
+{
+ int error = 0;
+ kv *k = 0;
+
+ /*
+ * Firewall
+ */
+ if (!m) {
+ plog(XLOG_ERROR, "Null map request for %s", key);
+ return ENOENT;
+ }
+
+ if (m->flags & MAPC_SYNC) {
+ /*
+ * Get modify time...
+ */
+ time_t t;
+ error = (*m->mtime)(m->map_name, &t);
+ if (error || t > m->modify) {
+ m->modify = t;
+ plog(XLOG_INFO, "Map %s is out of date", m->map_name);
+ mapc_sync(m);
+ }
+ }
+
+ if (!MAPC_ISRE(m)) {
+ /*
+ * Compute the hash table offset
+ */
+ k = m->kvhash[kvhash_of(key)];
+
+ /*
+ * Scan the linked list for the key
+ */
+ while (k && !FSTREQ(k->key, key)) k = k->next;
+
+ }
+#ifdef HAS_REGEXP
+ else if (recurse == MREC_FULL) {
+ /*
+ * Try for an RE match against the entire map.
+ * Note that this will be done in a "random"
+ * order.
+ */
+
+ int i;
+
+ for (i = 0; i < NKVHASH; i++) {
+ k = m->kvhash[i];
+ while (k) {
+ if (regexec((regexp *) k->key, key))
+ break;
+ k = k->next;
+ }
+ if (k)
+ break;
+ }
+ }
+#endif
+
+ /*
+ * If found then take a copy
+ */
+ if (k) {
+ if (k->val)
+ *pval = strdup(k->val);
+ else
+ error = ENOENT;
+ } else if (m->alloc >= MAPC_ALL) {
+ /*
+ * If the entire map is cached then this
+ * key does not exist.
+ */
+ error = ENOENT;
+ } else {
+ /*
+ * Otherwise search the map. If we are
+ * in incremental mode then add the key
+ * to the cache.
+ */
+ error = search_map(m, key, pval);
+ if (!error && m->alloc == MAPC_INC)
+ mapc_add_kv(m, strdup(key), strdup(*pval));
+ }
+
+ /*
+ * If an error, and a wildcard exists,
+ * and the key is not internal then
+ * return a copy of the wildcard.
+ */
+ if (error > 0) {
+ if (recurse == MREC_FULL && !MAPC_ISRE(m)) {
+ char wildname[MAXPATHLEN];
+ char *subp;
+ if (*key == '/')
+ return error;
+ /*
+ * Keep chopping sub-directories from the RHS
+ * and replacing with "/ *" and repeat the lookup.
+ * For example:
+ * "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
+ */
+ strcpy(wildname, key);
+ while (error && (subp = strrchr(wildname, '/'))) {
+ strcpy(subp, "/*");
+#ifdef DEBUG
+ dlog("mapc recurses on %s", wildname);
+#endif
+ error = mapc_meta_search(m, wildname, pval, MREC_PART);
+ if (error)
+ *subp = 0;
+ }
+ if (error > 0 && m->wildcard) {
+ *pval = strdup(m->wildcard);
+ error = 0;
+ }
+ }
+ }
+
+ return error;
+}
+
+int mapc_search P((mnt_map *m, char *key, char **pval));
+int mapc_search(m, key, pval)
+mnt_map *m;
+char *key;
+char **pval;
+{
+ return mapc_meta_search(m, key, pval, MREC_FULL);
+}
+
+/*
+ * Get map cache in sync with physical representation
+ */
+static void mapc_sync P((mnt_map *m));
+static void mapc_sync(m)
+mnt_map *m;
+{
+ if (m->alloc != MAPC_ROOT) {
+ mapc_clear(m);
+
+ if (m->alloc >= MAPC_ALL)
+ if (mapc_reload_map(m))
+ m->alloc = MAPC_INC;
+ /*
+ * Attempt to find the wildcard entry
+ */
+ if (m->alloc < MAPC_ALL)
+ mapc_find_wildcard(m);
+ }
+}
+
+/*
+ * Reload all the maps
+ * Called when Amd gets hit by a SIGHUP.
+ */
+void mapc_reload(P_void);
+void mapc_reload()
+{
+ mnt_map *m;
+
+ /*
+ * For all the maps,
+ * Throw away the existing information.
+ * Do a reload
+ * Find the wildcard
+ */
+ ITER(m, mnt_map, &map_list_head)
+ mapc_sync(m);
+}
+
+/*
+ * Root map.
+ * The root map is used to bootstrap amd.
+ * All the require top-level mounts are added
+ * into the root map and then the map is iterated
+ * and a lookup is done on all the mount points.
+ * This causes the top level mounts to be automounted.
+ */
+
+static int root_init P((char *map, time_t *tp));
+static int root_init(map, tp)
+char *map;
+time_t *tp;
+{
+ *tp = clocktime();
+ return strcmp(map, ROOT_MAP) == 0 ? 0 : ENOENT;
+}
+
+/*
+ * Add a new entry to the root map
+ *
+ * dir - directory (key)
+ * opts - mount options
+ * map - map name
+ */
+void root_newmap P((char *dir, char *opts, char *map));
+void root_newmap(dir, opts, map)
+char *dir;
+char *opts;
+char *map;
+{
+ char str[MAXPATHLEN];
+
+ /*
+ * First make sure we have a root map to talk about...
+ */
+ if (!root_map)
+ root_map = mapc_find(ROOT_MAP, "mapdefault");
+
+ /*
+ * Then add the entry...
+ */
+ dir = strdup(dir);
+ if (map)
+ sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
+ map, opts ? opts : "");
+ else
+ strcpy(str, opts);
+ mapc_repl_kv(root_map, dir, strdup(str));
+}
+
+int mapc_keyiter P((mnt_map *m, void (*fn)(char*,voidp), voidp arg));
+int mapc_keyiter(m, fn, arg)
+mnt_map *m;
+void (*fn)P((char*, voidp));
+voidp arg;
+{
+ int i;
+ int c = 0;
+
+ for (i = 0; i < NKVHASH; i++) {
+ kv *k = m->kvhash[i];
+ while (k) {
+ (*fn)(k->key, arg);
+ k = k->next;
+ c++;
+ }
+ }
+
+ return c;
+}
+
+/*
+ * Iterate of the the root map
+ * and call (*fn)() on the key
+ * of all the nodes.
+ * Finally throw away the root map.
+ */
+int root_keyiter P((void (*fn)(char*,voidp), voidp arg));
+int root_keyiter(fn, arg)
+void (*fn)P((char*,voidp));
+voidp arg;
+{
+ if (root_map) {
+ int c = mapc_keyiter(root_map, fn, arg);
+#ifdef notdef
+ mapc_free(root_map);
+ root_map = 0;
+#endif
+ return c;
+ }
+ return 0;
+}
+
+/*
+ * Error map
+ */
+static int error_init P((char *map, time_t *tp));
+static int error_init(map, tp)
+char *map;
+time_t *tp;
+{
+ plog(XLOG_USER, "No source data for map %s", map);
+ *tp = 0;
+ return 0;
+}
+
+/*ARGSUSED*/
+static int error_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
+static int error_search(m, map, key, pval, tp)
+mnt_map *m;
+char *map;
+char *key;
+char **pval;
+time_t *tp;
+{
+ return ENOENT;
+}
+
+/*ARGSUSED*/
+static int error_reload P((mnt_map *m, char *map, add_fn *fn));
+static int error_reload(m, map, fn)
+mnt_map *m;
+char *map;
+add_fn *fn;
+{
+ return ENOENT;
+}
+
+static int error_mtime P((char *map, time_t *tp));
+static int error_mtime(map, tp)
+char *map;
+time_t *tp;
+{
+ *tp = 0;
+ return 0;
+}
diff --git a/usr.sbin/amd/amd/misc_rpc.c b/usr.sbin/amd/amd/misc_rpc.c
new file mode 100644
index 0000000..0fb10c8
--- /dev/null
+++ b/usr.sbin/amd/amd/misc_rpc.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc_rpc.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc_rpc.c,v 5.2.2.1 1992/02/09 15:08:40 jsp beta $
+ *
+ */
+
+/*
+ * Additions to Sun RPC.
+ */
+
+#include "am.h"
+
+void rpc_msg_init P((struct rpc_msg *mp, u_long prog, u_long vers, u_long proc));
+void rpc_msg_init(mp, prog, vers, proc)
+struct rpc_msg *mp;
+unsigned long prog, vers, proc;
+{
+ /*
+ * Initialise the message
+ */
+ bzero((voidp) mp, sizeof(*mp));
+ mp->rm_xid = 0;
+ mp->rm_direction = CALL;
+ mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ mp->rm_call.cb_prog = prog;
+ mp->rm_call.cb_vers = vers;
+ mp->rm_call.cb_proc = proc;
+}
+
+/*
+ * Field reply to call to mountd
+ */
+int pickup_rpc_reply P((voidp pkt, int len, voidp where, xdrproc_t where_xdr));
+int pickup_rpc_reply(pkt, len, where, where_xdr)
+voidp pkt;
+int len;
+voidp where;
+xdrproc_t where_xdr;
+{
+ XDR reply_xdr;
+ int ok;
+ struct rpc_err err;
+ struct rpc_msg reply_msg;
+ int error = 0;
+
+ /*bzero((voidp) &err, sizeof(err));*/
+ bzero((voidp) &reply_msg, sizeof(reply_msg));
+
+ reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
+ reply_msg.acpted_rply.ar_results.proc = where_xdr;
+
+ xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
+
+ ok = xdr_replymsg(&reply_xdr, &reply_msg);
+ if (!ok) {
+ error = EIO;
+ goto drop;
+ }
+ _seterr_reply(&reply_msg, &err);
+ if (err.re_status != RPC_SUCCESS) {
+ error = EIO;
+ goto drop;
+ }
+
+drop:
+ if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
+ reply_msg.acpted_rply.ar_verf.oa_base) {
+ reply_xdr.x_op = XDR_FREE;
+ (void)xdr_opaque_auth(&reply_xdr,
+ &reply_msg.acpted_rply.ar_verf);
+ }
+ xdr_destroy(&reply_xdr);
+
+ return error;
+}
+
+int make_rpc_packet P((char *buf, int buflen, unsigned long proc,
+ struct rpc_msg *mp, voidp arg, xdrproc_t arg_xdr, AUTH *auth));
+int make_rpc_packet(buf, buflen, proc, mp, arg, arg_xdr, auth)
+char *buf;
+int buflen;
+unsigned long proc;
+struct rpc_msg *mp;
+voidp arg;
+xdrproc_t arg_xdr;
+AUTH *auth;
+{
+ XDR msg_xdr;
+ int len;
+
+ xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
+ /*
+ * Basic protocol header
+ */
+ if (!xdr_callhdr(&msg_xdr, mp))
+ return -EIO;
+ /*
+ * Called procedure number
+ */
+ if (!xdr_enum(&msg_xdr, &proc))
+ return -EIO;
+ /*
+ * Authorization
+ */
+ if (!AUTH_MARSHALL(auth, &msg_xdr))
+ return -EIO;
+ /*
+ * Arguments
+ */
+ if (!(*arg_xdr)(&msg_xdr, arg))
+ return -EIO;
+ /*
+ * Determine length
+ */
+ len = xdr_getpos(&msg_xdr);
+ /*
+ * Throw away xdr
+ */
+ xdr_destroy(&msg_xdr);
+ return len;
+}
+
+
+/*
+ * Early RPC seems to be missing these..
+ * Extracted from the RPC 3.9 sources as indicated
+ */
+
+#ifdef NEED_XDR_POINTER
+/* @(#)xdr_reference.c 1.1 87/11/04 3.9 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ * What's sent is actually a union:
+ *
+ * union object_pointer switch (boolean b) {
+ * case TRUE: object_data data;
+ * case FALSE: void nothing;
+ * }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
+ register XDR *xdrs;
+ char **objpp;
+ u_int obj_size;
+ xdrproc_t xdr_obj;
+{
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (! xdr_bool(xdrs,&more_data)) {
+ return (FALSE);
+ }
+ if (! more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+ return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
+#endif /* NEED_XDR_POINTER */
+
+#ifdef NEED_CLNT_SPERRNO
+/* @(#)clnt_perror.c 1.1 87/11/04 3.9 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+struct rpc_errtab {
+ enum clnt_stat status;
+ char *message;
+};
+
+static struct rpc_errtab rpc_errlist[] = {
+ { RPC_SUCCESS,
+ "RPC: Success" },
+ { RPC_CANTENCODEARGS,
+ "RPC: Can't encode arguments" },
+ { RPC_CANTDECODERES,
+ "RPC: Can't decode result" },
+ { RPC_CANTSEND,
+ "RPC: Unable to send" },
+ { RPC_CANTRECV,
+ "RPC: Unable to receive" },
+ { RPC_TIMEDOUT,
+ "RPC: Timed out" },
+ { RPC_VERSMISMATCH,
+ "RPC: Incompatible versions of RPC" },
+ { RPC_AUTHERROR,
+ "RPC: Authentication error" },
+ { RPC_PROGUNAVAIL,
+ "RPC: Program unavailable" },
+ { RPC_PROGVERSMISMATCH,
+ "RPC: Program/version mismatch" },
+ { RPC_PROCUNAVAIL,
+ "RPC: Procedure unavailable" },
+ { RPC_CANTDECODEARGS,
+ "RPC: Server can't decode arguments" },
+ { RPC_SYSTEMERROR,
+ "RPC: Remote system error" },
+ { RPC_UNKNOWNHOST,
+ "RPC: Unknown host" },
+/* { RPC_UNKNOWNPROTO,
+ "RPC: Unknown protocol" },*/
+ { RPC_PMAPFAILURE,
+ "RPC: Port mapper failure" },
+ { RPC_PROGNOTREGISTERED,
+ "RPC: Program not registered"},
+ { RPC_FAILED,
+ "RPC: Failed (unspecified error)"}
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(stat)
+ enum clnt_stat stat;
+{
+ int i;
+
+ for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
+ if (rpc_errlist[i].status == stat) {
+ return (rpc_errlist[i].message);
+ }
+ }
+ return ("RPC: (unknown error code)");
+}
+
+#endif /* NEED_CLNT_SPERRNO */
+
diff --git a/usr.sbin/amd/amd/mntfs.c b/usr.sbin/amd/amd/mntfs.c
new file mode 100644
index 0000000..ef8f17f
--- /dev/null
+++ b/usr.sbin/amd/amd/mntfs.c
@@ -0,0 +1,367 @@
+/*-
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: mntfs.c,v 5.2.2.1 1992/02/09 15:08:42 jsp beta $
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mntfs.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+
+#include "am.h"
+
+extern qelem mfhead;
+qelem mfhead = { &mfhead, &mfhead };
+
+int mntfs_allocated;
+
+#ifdef notdef
+/*
+ * This is the default attributes field which
+ * is copied into every new node to be created.
+ * The individual filesystem fs_init() routines
+ * patch the copy to represent the particular
+ * details for the relevant filesystem type
+ */
+static struct fattr gen_fattr = {
+ NFDIR, /* type */
+ NFSMODE_DIR | 0555, /* mode */
+ 2, /* nlink */
+ 0, /* uid */
+ 0, /* gid */
+ 512, /* size */
+ 4096, /* blocksize */
+ 0, /* rdev */
+ 1, /* blocks */
+ 0, /* fsid */
+ 0, /* fileid */
+ { 0, 0 }, /* atime */
+ { 0, 0 }, /* mtime */
+ { 0, 0 }, /* ctime */
+};
+#endif /* notdef */
+
+mntfs *dup_mntfs(mf)
+mntfs *mf;
+{
+ if (mf->mf_refc == 0) {
+ if (mf->mf_cid)
+ untimeout(mf->mf_cid);
+ mf->mf_cid = 0;
+#ifdef notdef
+ mf->mf_error = -1;
+ mf->mf_flags &= ~MFF_ERROR;
+#endif
+ }
+ mf->mf_refc++;
+ return mf;
+}
+
+static void init_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
+static void init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts)
+mntfs *mf;
+am_ops *ops;
+am_opts *mo;
+char *mp;
+char *info;
+char *auto_opts;
+char *mopts;
+char *remopts;
+{
+ mf->mf_ops = ops;
+ mf->mf_fo = mo;
+ mf->mf_mount = strdup(mp);
+ mf->mf_info = strdup(info);
+ mf->mf_auto = strdup(auto_opts);
+ mf->mf_mopts = strdup(mopts);
+ mf->mf_remopts = strdup(remopts);
+ mf->mf_refc = 1;
+ mf->mf_flags = 0;
+ mf->mf_error = -1;
+ mf->mf_cid = 0;
+ mf->mf_private = 0;
+ mf->mf_prfree = 0;
+#ifdef notdef
+ mf->mf_attr.status = NFS_OK;
+ mf->mf_fattr = gen_fattr;
+ mf->mf_fattr.fsid = 42;
+ mf->mf_fattr.fileid = 0;
+ mf->mf_fattr.atime.seconds = clocktime();
+ mf->mf_fattr.atime.useconds = 0;
+ mf->mf_fattr.mtime = mf->mf_fattr.ctime = mf->mf_fattr.atime;
+#endif
+
+ if (ops->ffserver)
+ mf->mf_server = (*ops->ffserver)(mf);
+ else
+ mf->mf_server = 0;
+}
+
+static mntfs *alloc_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
+static mntfs *alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts)
+am_ops *ops;
+am_opts *mo;
+char *mp;
+char *info;
+char *auto_opts;
+char *mopts;
+char *remopts;
+{
+ mntfs *mf = ALLOC(mntfs);
+ init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts);
+ ins_que(&mf->mf_q, &mfhead);
+ mntfs_allocated++;
+
+ return mf;
+}
+
+mntfs *find_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
+mntfs *find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts)
+am_ops *ops;
+am_opts *mo;
+char *mp;
+char *info;
+char *auto_opts;
+char *mopts;
+char *remopts;
+{
+ mntfs *mf;
+
+#ifdef DEBUG
+ dlog("Locating mntfs reference to %s", mp);
+#endif /* DEBUG */
+ ITER(mf, mntfs, &mfhead) {
+ if (STREQ(mf->mf_mount, mp)) {
+ /*
+ * Handle cases where error ops are involved
+ */
+ if (ops == &efs_ops) {
+ /*
+ * If the existing ops are not efs_ops
+ * then continue...
+ */
+ if (mf->mf_ops != &efs_ops)
+ continue;
+ } else /* ops != &efs_ops */ {
+ /*
+ * If the existing ops are efs_ops
+ * then continue...
+ */
+ if (mf->mf_ops == &efs_ops)
+ continue;
+ }
+
+ if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
+ /*
+ * Restart a previously mounted filesystem.
+ */
+ mntfs *mf2 = alloc_mntfs(&ifs_ops, mo, mp, info, auto_opts, mopts, remopts);
+#ifdef DEBUG
+ dlog("Restarting filesystem %s", mf->mf_mount);
+#endif /* DEBUG */
+ /*
+ * Remember who we are restarting
+ */
+ mf2->mf_private = (voidp) dup_mntfs(mf);
+ mf2->mf_prfree = free_mntfs;
+ return mf2;
+ }
+ mf->mf_fo = mo;
+ if (!(mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))) {
+ fserver *fs;
+ mf->mf_flags &= ~MFF_ERROR;
+ mf->mf_error = -1;
+ mf->mf_auto = strealloc(mf->mf_auto, auto_opts);
+ mf->mf_mopts = strealloc(mf->mf_mopts, mopts);
+ mf->mf_remopts = strealloc(mf->mf_remopts, remopts);
+ mf->mf_info = strealloc(mf->mf_info, info);
+ if (mf->mf_private && mf->mf_prfree) {
+ (*mf->mf_prfree)(mf->mf_private);
+ mf->mf_private = 0;
+ }
+ fs = ops->ffserver ? (*ops->ffserver)(mf) : (fserver *) 0;
+ if (mf->mf_server)
+ free_srvr(mf->mf_server);
+ mf->mf_server = fs;
+ }
+ return dup_mntfs(mf);
+ }
+ }
+
+ return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
+}
+
+mntfs *new_mntfs()
+{
+ return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
+}
+
+static void uninit_mntfs(mf, rmd)
+mntfs *mf;
+int rmd;
+{
+ if (mf->mf_mount) free((voidp) mf->mf_mount);
+ if (mf->mf_auto) free((voidp) mf->mf_auto);
+ if (mf->mf_mopts) free((voidp) mf->mf_mopts);
+ if (mf->mf_remopts) free((voidp) mf->mf_remopts);
+ if (mf->mf_info) free((voidp) mf->mf_info);
+ if (mf->mf_private && mf->mf_prfree)
+ (*mf->mf_prfree)(mf->mf_private);
+ /*
+ * Clean up any directories that were made
+ */
+ if (rmd && (mf->mf_flags & MFF_MKMNT))
+ rmdirs(mf->mf_mount);
+
+ /*
+ * Clean up the file server
+ */
+ if (mf->mf_server)
+ free_srvr(mf->mf_server);
+
+ /*
+ * Don't do a callback on this mount
+ */
+ if (mf->mf_cid) {
+ untimeout(mf->mf_cid);
+ mf->mf_cid = 0;
+ }
+}
+
+static void discard_mntfs(mf)
+mntfs *mf;
+{
+ rem_que(&mf->mf_q);
+ /*
+ * Free memory
+ */
+ uninit_mntfs(mf, TRUE);
+ free((voidp) mf);
+
+ --mntfs_allocated;
+}
+
+void flush_mntfs()
+{
+ mntfs *mf;
+
+ mf = FIRST(mntfs, &mfhead);
+ while (mf != HEAD(mntfs, &mfhead)) {
+ mntfs *mf2 = mf;
+ mf = NEXT(mntfs, mf);
+ if (mf2->mf_refc == 0 && mf2->mf_cid)
+ discard_mntfs(mf2);
+ }
+}
+
+void free_mntfs(mf)
+mntfs *mf;
+{
+ if (--mf->mf_refc == 0) {
+ if (mf->mf_flags & MFF_MOUNTED) {
+ int quoted;
+ mf->mf_flags &= ~MFF_MOUNTED;
+
+ /*
+ * Record for posterity
+ */
+ quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */
+ plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s",
+ quoted ? "\"" : "",
+ mf->mf_info,
+ quoted ? "\"" : "",
+ mf->mf_error ? "discard" : "unmount",
+ mf->mf_ops->fs_type, mf->mf_mount);
+ }
+
+ if (mf->mf_ops->fs_flags & FS_DISCARD) {
+#ifdef DEBUG
+ dlog("Immediately discarding mntfs for %s", mf->mf_mount);
+#endif /* DEBUG */
+ discard_mntfs(mf);
+ } else {
+#ifdef DEBUG
+ if (mf->mf_flags & MFF_RESTART) {
+ dlog("Discarding remount hook for %s", mf->mf_mount);
+ } else {
+ dlog("Discarding last mntfs reference to %s fstype %s",
+ mf->mf_mount, mf->mf_ops->fs_type);
+ }
+ if (mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))
+ dlog("mntfs reference for %s still active", mf->mf_mount);
+#endif /* DEBUG */
+ mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf);
+ }
+ }
+}
+
+mntfs *realloc_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
+mntfs *realloc_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts)
+mntfs *mf;
+am_ops *ops;
+am_opts *mo;
+char *mp;
+char *info;
+char *auto_opts;
+char *mopts;
+char *remopts;
+{
+ mntfs *mf2;
+ if (mf->mf_refc == 1 && mf->mf_ops == &ifs_ops && STREQ(mf->mf_mount, mp)) {
+ /*
+ * If we are inheriting then just return
+ * the same node...
+ */
+ return mf;
+ }
+
+ /*
+ * Re-use the existing mntfs if it is mounted.
+ * This traps a race in nfsx.
+ */
+ if (mf->mf_ops != &efs_ops &&
+ (mf->mf_flags & MFF_MOUNTED) &&
+ !FSRV_ISDOWN(mf->mf_server)) {
+ mf->mf_fo = mo;
+ return mf;
+ }
+
+ mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
+ free_mntfs(mf);
+ return mf2;
+}
diff --git a/usr.sbin/amd/amd/mount_fs.c b/usr.sbin/amd/amd/mount_fs.c
new file mode 100644
index 0000000..43a0625
--- /dev/null
+++ b/usr.sbin/amd/amd/mount_fs.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount_fs.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mount_fs.c,v 5.2.2.2 1992/05/31 16:35:45 jsp Exp $
+ *
+ */
+
+#include "am.h"
+#ifdef NFS_3
+typedef nfs_fh fhandle_t;
+#endif /* NFS_3 */
+#include <sys/mount.h>
+
+#include <sys/stat.h>
+
+/*
+ * Standard mount flags
+ */
+#ifdef hpux
+/*
+ * HP-UX has an annoying feature of printing
+ * error msgs on /dev/console
+ */
+#undef M_NOSUID
+#endif /* hpux */
+
+struct opt_tab mnt_flags[] = {
+ { "ro", M_RDONLY },
+#ifdef M_CACHE
+ { "nocache", M_NOCACHE },
+#endif /* M_CACHE */
+#ifdef M_GRPID
+ { "grpid", M_GRPID },
+#endif /* M_GRPID */
+#ifdef M_MULTI
+ { "multi", M_MULTI },
+#endif /* M_MULTI */
+#ifdef M_NODEV
+ { "nodev", M_NODEV },
+#endif /* M_NODEV */
+#ifdef M_NOEXEC
+ { "noexec", M_NOEXEC },
+#endif /* M_NOEXEC */
+#ifdef M_NOSUB
+ { "nosub", M_NOSUB },
+#endif /* M_NOSUB */
+#ifdef M_NOSUID
+ { "nosuid", M_NOSUID },
+#endif /* M_NOSUID */
+#ifdef M_SYNC
+ { "sync", M_SYNC },
+#endif /* M_SYNC */
+ { 0, 0 }
+};
+
+int compute_mount_flags(mnt)
+struct mntent *mnt;
+{
+ struct opt_tab *opt;
+ int flags;
+#ifdef NFS_4
+ flags = M_NEWTYPE;
+#else
+ flags = 0;
+#endif /* NFS_4 */
+
+ /*
+ * Crack basic mount options
+ */
+ for (opt = mnt_flags; opt->opt; opt++)
+ flags |= hasmntopt(mnt, opt->opt) ? opt->flag : 0;
+
+ return flags;
+}
+
+int mount_fs P((struct mntent *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type));
+int mount_fs(mnt, flags, mnt_data, retry, type)
+struct mntent *mnt;
+int flags;
+caddr_t mnt_data;
+int retry;
+MTYPE_TYPE type;
+{
+ int error = 0;
+#ifdef MNTINFO_DEV
+ struct stat stb;
+ char *xopts = 0;
+#endif /* MNTINFO_DEV */
+
+#ifdef DEBUG
+#ifdef NFS_4
+ dlog("%s fstype %s (%s) flags %#x (%s)",
+ mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
+#else
+ dlog("%s fstype %d (%s) flags %#x (%s)",
+ mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
+#endif /* NFS_4 */
+#endif /* DEBUG */
+
+ /*
+ * Fake some mount table entries for the automounter
+ */
+#ifdef FASCIST_DF_COMMAND
+ /*
+ * Some systems have a df command which blows up when
+ * presented with an unknown mount type.
+ */
+ if (STREQ(mnt->mnt_type, MNTTYPE_AUTO)) {
+ /*
+ * Try it with the normal name
+ */
+ mnt->mnt_type = FASCIST_DF_COMMAND;
+ }
+#endif /* FASCIST_DF_COMMAND */
+
+again:
+ clock_valid = 0;
+ error = MOUNT_TRAP(type, mnt, flags, mnt_data);
+ if (error < 0)
+ plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
+ if (error < 0 && --retry > 0) {
+ sleep(1);
+ goto again;
+ }
+ if (error < 0) {
+#ifdef notdef
+ if (automount)
+ going_down(errno);
+#endif
+ return errno;
+ }
+
+#ifdef UPDATE_MTAB
+#ifdef MNTINFO_DEV
+ /*
+ * Add the extra dev= field to the mount table.
+ */
+ if (lstat(mnt->mnt_dir, &stb) == 0) {
+ char *zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 32);
+ xopts = mnt->mnt_opts;
+ if (sizeof(stb.st_dev) == 2) {
+ /* e.g. SunOS 4.1 */
+ sprintf(zopts, "%s,%s=%s%04lx", xopts, MNTINFO_DEV,
+ MNTINFO_PREF, (u_long) stb.st_dev & 0xffff);
+ } else {
+ /* e.g. System Vr4 */
+ sprintf(zopts, "%s,%s=%s%08lx", xopts, MNTINFO_DEV,
+ MNTINFO_PREF, (u_long) stb.st_dev);
+ }
+ mnt->mnt_opts = zopts;
+ }
+#endif /* MNTINFO_DEV */
+
+#ifdef FIXUP_MNTENT
+ /*
+ * Additional fields in struct mntent
+ * are fixed up here
+ */
+ FIXUP_MNTENT(mnt);
+#endif
+
+ write_mntent(mnt);
+#ifdef MNTINFO_DEV
+ if (xopts) {
+ free(mnt->mnt_opts);
+ mnt->mnt_opts = xopts;
+ }
+#endif /* MNTINFO_DEV */
+#endif /* UPDATE_MTAB */
+
+ return 0;
+}
+
+#ifdef NEED_MNTOPT_PARSER
+/*
+ * Some systems don't provide these to the user,
+ * but amd needs them, so...
+ *
+ * From: Piete Brooks <pb@cl.cam.ac.uk>
+ */
+
+#include <ctype.h>
+
+static char *nextmntopt(p)
+char **p;
+{
+ char *cp = *p;
+ char *rp;
+ /*
+ * Skip past white space
+ */
+ while (*cp && isspace(*cp))
+ cp++;
+ /*
+ * Word starts here
+ */
+ rp = cp;
+ /*
+ * Scan to send of string or separator
+ */
+ while (*cp && *cp != ',')
+ cp++;
+ /*
+ * If separator found the overwrite with nul char.
+ */
+ if (*cp) {
+ *cp = '\0';
+ cp++;
+ }
+ /*
+ * Return value for next call
+ */
+ *p = cp;
+ return rp;
+}
+
+char *hasmntopt(mnt, opt)
+struct mntent *mnt;
+char *opt;
+{
+ char t[MNTMAXSTR];
+ char *f;
+ char *o = t;
+ int l = strlen(opt);
+ strcpy(t, mnt->mnt_opts);
+
+ while (*(f = nextmntopt(&o)))
+ if (strncmp(opt, f, l) == 0)
+ return f - t + mnt->mnt_opts;
+
+ return 0;
+}
+#endif /* NEED_MNTOPT_PARSER */
+
+#ifdef MOUNT_HELPER_SOURCE
+#include MOUNT_HELPER_SOURCE
+#endif /* MOUNT_HELPER_SOURCE */
diff --git a/usr.sbin/amd/amd/mtab.c b/usr.sbin/amd/amd/mtab.c
new file mode 100644
index 0000000..43b3a26
--- /dev/null
+++ b/usr.sbin/amd/amd/mtab.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mtab.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mtab.c,v 5.2.2.1 1992/02/09 15:08:45 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+/*
+ * Firewall /etc/mtab entries
+ */
+void mnt_free P((struct mntent *mp));
+void mnt_free(mp)
+struct mntent *mp;
+{
+ free(mp->mnt_fsname);
+ free(mp->mnt_dir);
+ free(mp->mnt_type);
+ free(mp->mnt_opts);
+ free((voidp) mp);
+}
+
+/*
+ * Discard memory allocated for mount list
+ */
+void discard_mntlist P((mntlist *mp));
+void discard_mntlist(mp)
+mntlist *mp;
+{
+ mntlist *mp2;
+
+ while (mp2 = mp) {
+ mp = mp->mnext;
+ if (mp2->mnt)
+ mnt_free(mp2->mnt);
+ free((voidp) mp2);
+ }
+}
+
+/*
+ * Throw away a mount list
+ */
+void free_mntlist P((mntlist *mp));
+void free_mntlist(mp)
+mntlist *mp;
+{
+ discard_mntlist(mp);
+ unlock_mntlist();
+}
+
+/*
+ * Utility routine which determines the value of a
+ * numeric option in the mount options (such as port=%d).
+ * Returns 0 if the option is not specified.
+ */
+int hasmntval P((struct mntent *mnt, char *opt));
+int hasmntval(mnt, opt)
+struct mntent *mnt;
+char *opt;
+{
+ char *str = hasmntopt(mnt, opt);
+ if (str) {
+ char *eq = strchr(str, '=');
+ if (eq)
+ return atoi(eq+1);
+ else
+ plog(XLOG_USER, "bad numeric option \"%s\" in \"%s\"", opt, str);
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/amd/amd/nfs_ops.c b/usr.sbin/amd/amd/nfs_ops.c
new file mode 100644
index 0000000..bcfd7a5
--- /dev/null
+++ b/usr.sbin/amd/amd/nfs_ops.c
@@ -0,0 +1,809 @@
+/*-
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: nfs_ops.c,v 5.2.2.2 1992/05/31 16:35:05 jsp Exp $
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)nfs_ops.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "am.h"
+#include <sys/stat.h>
+
+#ifdef HAS_NFS
+
+#define NFS
+#define NFSCLIENT
+#ifdef NFS_3
+typedef nfs_fh fhandle_t;
+#endif /* NFS_3 */
+#ifdef NFS_HDR
+#include NFS_HDR
+#endif /* NFS_HDR */
+#include <sys/mount.h>
+#include "mount.h"
+
+/*
+ * Network file system
+ */
+
+/*
+ * Convert from nfsstat to UN*X error code
+ */
+#define unx_error(e) ((int)(e))
+
+/*
+ * The NFS layer maintains a cache of file handles.
+ * This is *fundamental* to the implementation and
+ * also allows quick remounting when a filesystem
+ * is accessed soon after timing out.
+ *
+ * The NFS server layer knows to flush this cache
+ * when a server goes down so avoiding stale handles.
+ *
+ * Each cache entry keeps a hard reference to
+ * the corresponding server. This ensures that
+ * the server keepalive information is maintained.
+ *
+ * The copy of the sockaddr_in here is taken so
+ * that the port can be twiddled to talk to mountd
+ * instead of portmap or the NFS server as used
+ * elsewhere.
+ * The port# is flushed if a server goes down.
+ * The IP address is never flushed - we assume
+ * that the address of a mounted machine never
+ * changes. If it does, then you have other
+ * problems...
+ */
+typedef struct fh_cache fh_cache;
+struct fh_cache {
+ qelem fh_q; /* List header */
+ voidp fh_wchan; /* Wait channel */
+ int fh_error; /* Valid data? */
+ int fh_id; /* Unique id */
+ int fh_cid; /* Callout id */
+ struct fhstatus fh_handle; /* Handle on filesystem */
+ struct sockaddr_in fh_sin; /* Address of mountd */
+ fserver *fh_fs; /* Server holding filesystem */
+ char *fh_path; /* Filesystem on host */
+};
+
+/*
+ * FH_TTL is the time a file handle will remain in the cache since
+ * last being used. If the file handle becomes invalid, then it
+ * will be flushed anyway.
+ */
+#define FH_TTL (5 * 60) /* five minutes */
+#define FH_TTL_ERROR (30) /* 30 seconds */
+
+static int fh_id = 0;
+#define FHID_ALLOC() (++fh_id)
+extern qelem fh_head;
+qelem fh_head = { &fh_head, &fh_head };
+
+static int call_mountd P((fh_cache*, unsigned long, fwd_fun, voidp));
+
+AUTH *nfs_auth;
+
+static fh_cache *find_nfs_fhandle_cache P((voidp idv, int done));
+static fh_cache *find_nfs_fhandle_cache(idv, done)
+voidp idv;
+int done;
+{
+ fh_cache *fp, *fp2 = 0;
+ int id = (int) idv;
+
+ ITER(fp, fh_cache, &fh_head) {
+ if (fp->fh_id == id) {
+ fp2 = fp;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ if (fp2) {
+ dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);
+ } else {
+ dlog("fh cache search failed");
+ }
+#endif /* DEBUG */
+
+ if (fp2 && !done) {
+ fp2->fh_error = ETIMEDOUT;
+ return 0;
+ }
+
+ return fp2;
+}
+
+/*
+ * Called when a filehandle appears
+ */
+static void got_nfs_fh P((voidp pkt, int len, struct sockaddr_in *sa,
+ struct sockaddr_in *ia, voidp idv, int done));
+static void got_nfs_fh(pkt, len, sa, ia, idv, done)
+voidp pkt;
+int len;
+struct sockaddr_in *sa, *ia;
+voidp idv;
+int done;
+{
+ fh_cache *fp = find_nfs_fhandle_cache(idv, done);
+ if (fp) {
+ fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_handle, xdr_fhstatus);
+ if (!fp->fh_error) {
+#ifdef DEBUG
+ dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+#endif /* DEBUG */
+ /*
+ * Wakeup anything sleeping on this filehandle
+ */
+ if (fp->fh_wchan) {
+#ifdef DEBUG
+ dlog("Calling wakeup on %#x", fp->fh_wchan);
+#endif /* DEBUG */
+ wakeup(fp->fh_wchan);
+ }
+ }
+ }
+}
+
+void flush_nfs_fhandle_cache P((fserver *fs));
+void flush_nfs_fhandle_cache(fs)
+fserver *fs;
+{
+ fh_cache *fp;
+ ITER(fp, fh_cache, &fh_head) {
+ if (fp->fh_fs == fs || fs == 0) {
+ fp->fh_sin.sin_port = (u_short) 0;
+ fp->fh_error = -1;
+ }
+ }
+}
+
+static void discard_fh P((fh_cache *fp));
+static void discard_fh(fp)
+fh_cache *fp;
+{
+ rem_que(&fp->fh_q);
+#ifdef DEBUG
+ dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+#endif /* DEBUG */
+ free_srvr(fp->fh_fs);
+ free((voidp) fp->fh_path);
+ free((voidp) fp);
+}
+
+/*
+ * Determine the file handle for a node
+ */
+static int prime_nfs_fhandle_cache P((char *path, fserver *fs, struct fhstatus *fhbuf, voidp wchan));
+static int prime_nfs_fhandle_cache(path, fs, fhbuf, wchan)
+char *path;
+fserver *fs;
+struct fhstatus *fhbuf;
+voidp wchan;
+{
+ fh_cache *fp, *fp_save = 0;
+ int error;
+ int reuse_id = FALSE;
+
+#ifdef DEBUG
+ dlog("Searching cache for %s:%s", fs->fs_host, path);
+#endif /* DEBUG */
+
+ /*
+ * First search the cache
+ */
+ ITER(fp, fh_cache, &fh_head) {
+ if (fs == fp->fh_fs && strcmp(path, fp->fh_path) == 0) {
+ switch (fp->fh_error) {
+ case 0:
+ error = fp->fh_error = unx_error(fp->fh_handle.fhs_status);
+ if (error == 0) {
+ if (fhbuf)
+ bcopy((voidp) &fp->fh_handle, (voidp) fhbuf,
+ sizeof(fp->fh_handle));
+ if (fp->fh_cid)
+ untimeout(fp->fh_cid);
+ fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
+ } else if (error == EACCES) {
+ /*
+ * Now decode the file handle return code.
+ */
+ plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
+ fs->fs_host, path);
+ } else {
+ errno = error; /* XXX */
+ plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
+ fs->fs_host, path);
+ }
+
+ /*
+ * The error was returned from the remote mount daemon.
+ * Policy: this error will be cached for now...
+ */
+ return error;
+
+ case -1:
+ /*
+ * Still thinking about it, but we can re-use.
+ */
+ fp_save = fp;
+ reuse_id = TRUE;
+ break;
+
+ default:
+ /*
+ * Return the error.
+ * Policy: make sure we recompute if required again
+ * in case this was caused by a network failure.
+ * This can thrash mountd's though... If you find
+ * your mountd going slowly then:
+ * 1. Add a fork() loop to main.
+ * 2. Remove the call to innetgr() and don't use
+ * netgroups, especially if you don't use YP.
+ */
+ error = fp->fh_error;
+ fp->fh_error = -1;
+ return error;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Not in cache
+ */
+ if (fp_save) {
+ fp = fp_save;
+ /*
+ * Re-use existing slot
+ */
+ untimeout(fp->fh_cid);
+ free_srvr(fp->fh_fs);
+ free(fp->fh_path);
+ } else {
+ fp = ALLOC(fh_cache);
+ bzero((voidp) fp, sizeof(*fp));
+ ins_que(&fp->fh_q, &fh_head);
+ }
+ if (!reuse_id)
+ fp->fh_id = FHID_ALLOC();
+ fp->fh_wchan = wchan;
+ fp->fh_error = -1;
+ fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
+
+ /*
+ * If the address has changed then don't try to re-use the
+ * port information
+ */
+ if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
+ fp->fh_sin = *fs->fs_ip;
+ fp->fh_sin.sin_port = 0;
+ }
+ fp->fh_fs = dup_srvr(fs);
+ fp->fh_path = strdup(path);
+
+ error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
+ if (error) {
+ /*
+ * Local error - cache for a short period
+ * just to prevent thrashing.
+ */
+ untimeout(fp->fh_cid);
+ fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
+ discard_fh, (voidp) fp);
+ fp->fh_error = error;
+ } else {
+ error = fp->fh_error;
+ }
+ return error;
+}
+
+int make_nfs_auth P((void))
+{
+#ifdef HAS_NFS_QUALIFIED_NAMES
+ /*
+ * From: Chris Metcalf <metcalf@masala.lcs.mit.edu>
+ * Use hostd, not just hostname. Note that uids
+ * and gids and the gidlist are type *int* and not the
+ * system uid_t and gid_t types.
+ */
+ static int group_wheel = 0;
+ nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);
+#else
+ nfs_auth = authunix_create_default();
+#endif
+ if (!nfs_auth)
+ return ENOBUFS;
+ return 0;
+}
+
+static int call_mountd P((fh_cache *fp, u_long proc, fwd_fun f, voidp wchan));
+static int call_mountd(fp, proc, f, wchan)
+fh_cache *fp;
+u_long proc;
+fwd_fun f;
+voidp wchan;
+{
+ struct rpc_msg mnt_msg;
+ int len;
+ char iobuf[8192];
+ int error;
+
+ if (!nfs_auth) {
+ error = make_nfs_auth();
+ if (error)
+ return error;
+ }
+
+ if (fp->fh_sin.sin_port == 0) {
+ u_short port;
+ error = nfs_srvr_port(fp->fh_fs, &port, wchan);
+ if (error)
+ return error;
+ fp->fh_sin.sin_port = port;
+ }
+
+ rpc_msg_init(&mnt_msg, MOUNTPROG, MOUNTVERS, (unsigned long) 0);
+ len = make_rpc_packet(iobuf, sizeof(iobuf), proc,
+ &mnt_msg, (voidp) &fp->fh_path, xdr_nfspath, nfs_auth);
+
+ if (len > 0) {
+ error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
+ (voidp) iobuf, len, &fp->fh_sin, &fp->fh_sin, (voidp) fp->fh_id, f);
+ } else {
+ error = -len;
+ }
+/*
+ * It may be the case that we're sending to the wrong MOUNTD port. This
+ * occurs if mountd is restarted on the server after the port has been
+ * looked up and stored in the filehandle cache somewhere. The correct
+ * solution, if we're going to cache port numbers is to catch the ICMP
+ * port unreachable reply from the server and cause the portmap request
+ * to be redone. The quick solution here is to invalidate the MOUNTD
+ * port.
+ */
+ fp->fh_sin.sin_port = 0;
+
+ return error;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * NFS needs the local filesystem, remote filesystem
+ * remote hostname.
+ * Local filesystem defaults to remote and vice-versa.
+ */
+static char *nfs_match(fo)
+am_opts *fo;
+{
+ char *xmtab;
+ if (fo->opt_fs && !fo->opt_rfs)
+ fo->opt_rfs = fo->opt_fs;
+ if (!fo->opt_rfs) {
+ plog(XLOG_USER, "nfs: no remote filesystem specified");
+ return FALSE;
+ }
+ if (!fo->opt_rhost) {
+ plog(XLOG_USER, "nfs: no remote host specified");
+ return FALSE;
+ }
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ xmtab = (char *) xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
+ sprintf(xmtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
+#ifdef DEBUG
+ dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
+ fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
+#endif /* DEBUG */
+
+ return xmtab;
+}
+
+/*
+ * Initialise am structure for nfs
+ */
+static int nfs_init(mf)
+mntfs *mf;
+{
+ if (!mf->mf_private) {
+ int error;
+ struct fhstatus fhs;
+
+ char *colon = strchr(mf->mf_info, ':');
+ if (colon == 0)
+ return ENOENT;
+
+ error = prime_nfs_fhandle_cache(colon+1, mf->mf_server, &fhs, (voidp) mf);
+ if (!error) {
+ mf->mf_private = (voidp) ALLOC(fhstatus);
+ mf->mf_prfree = (void (*)()) free;
+ bcopy((voidp) &fhs, mf->mf_private, sizeof(fhs));
+ }
+ return error;
+ }
+
+ return 0;
+}
+
+int mount_nfs_fh P((struct fhstatus *fhp, char *dir, char *fs_name, char *opts, mntfs *mf));
+int mount_nfs_fh(fhp, dir, fs_name, opts, mf)
+struct fhstatus *fhp;
+char *dir;
+char *fs_name;
+char *opts;
+mntfs *mf;
+{
+ struct nfs_args nfs_args;
+ struct mntent mnt;
+ int retry;
+ char *colon;
+ /*char *path;*/
+ char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
+ fserver *fs = mf->mf_server;
+ int flags;
+ char *xopts;
+ int error;
+#ifdef notdef
+ unsigned short port;
+#endif /* notdef */
+
+ MTYPE_TYPE type = MOUNT_TYPE_NFS;
+
+ bzero((voidp) &nfs_args, sizeof(nfs_args)); /* Paranoid */
+
+ /*
+ * Extract host name to give to kernel
+ */
+ if (!(colon = strchr(fs_name, ':')))
+ return ENOENT;
+#ifndef NFS_ARGS_NEEDS_PATH
+ *colon = '\0';
+#endif
+ strncpy(host, fs_name, sizeof(host));
+#ifndef NFS_ARGS_NEEDS_PATH
+ *colon = ':';
+#endif /* NFS_ARGS_NEEDS_PATH */
+ /*path = colon + 1;*/
+
+ if (mf->mf_remopts && *mf->mf_remopts && !islocalnet(fs->fs_ip->sin_addr.s_addr))
+ xopts = strdup(mf->mf_remopts);
+ else
+ xopts = strdup(opts);
+
+ bzero((voidp) &nfs_args, sizeof(nfs_args));
+
+ mnt.mnt_dir = dir;
+ mnt.mnt_fsname = fs_name;
+ mnt.mnt_type = MTAB_TYPE_NFS;
+ mnt.mnt_opts = xopts;
+ mnt.mnt_freq = 0;
+ mnt.mnt_passno = 0;
+
+ retry = hasmntval(&mnt, "retry");
+ if (retry <= 0)
+ retry = 1; /* XXX */
+
+/*again:*/
+
+ /*
+ * set mount args
+ */
+ NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp->fhstatus_u.fhs_fhandle);
+
+#ifdef ULTRIX_HACK
+ nfs_args.optstr = mnt.mnt_opts;
+#endif /* ULTRIX_HACK */
+
+ nfs_args.hostname = host;
+ nfs_args.flags |= NFSMNT_HOSTNAME;
+#ifdef HOSTNAMESZ
+ /*
+ * Most kernels have a name length restriction.
+ */
+ if (strlen(host) >= HOSTNAMESZ)
+ strcpy(host + HOSTNAMESZ - 3, "..");
+#endif /* HOSTNAMESZ */
+
+ if (nfs_args.rsize = hasmntval(&mnt, "rsize"))
+ nfs_args.flags |= NFSMNT_RSIZE;
+
+ if (nfs_args.wsize = hasmntval(&mnt, "wsize"))
+ nfs_args.flags |= NFSMNT_WSIZE;
+
+ if (nfs_args.timeo = hasmntval(&mnt, "timeo"))
+ nfs_args.flags |= NFSMNT_TIMEO;
+
+ if (nfs_args.retrans = hasmntval(&mnt, "retrans"))
+ nfs_args.flags |= NFSMNT_RETRANS;
+
+#ifdef NFSMNT_BIODS
+ if (nfs_args.biods = hasmntval(&mnt, "biods"))
+ nfs_args.flags |= NFSMNT_BIODS;
+
+#endif /* NFSMNT_BIODS */
+
+#ifdef NFSMNT_MAXGRPS
+ if (nfs_args.maxgrouplist = hasmntval(&mnt, "maxgroups"))
+ nfs_args.flags |= NFSMNT_MAXGRPS;
+#endif /* NFSMNT_MAXGRPS */
+
+#ifdef notdef
+/*
+ * This isn't supported by the ping algorithm yet.
+ * In any case, it is all done in nfs_init().
+ */
+ if (port = hasmntval(&mnt, "port"))
+ sin.sin_port = htons(port);
+ else
+ sin.sin_port = htons(NFS_PORT); /* XXX should use portmapper */
+#endif /* notdef */
+
+ if (hasmntopt(&mnt, MNTOPT_SOFT) != NULL)
+ nfs_args.flags |= NFSMNT_SOFT;
+
+#ifdef NFSMNT_SPONGY
+ if (hasmntopt(&mnt, "spongy") != NULL) {
+ nfs_args.flags |= NFSMNT_SPONGY;
+ if (nfs_args.flags & NFSMNT_SOFT) {
+ plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
+ nfs_args.flags &= ~NFSMNT_SOFT;
+ }
+ }
+#endif /* MNTOPT_SPONGY */
+
+#ifdef MNTOPT_INTR
+ if (hasmntopt(&mnt, MNTOPT_INTR) != NULL)
+ nfs_args.flags |= NFSMNT_INT;
+#endif /* MNTOPT_INTR */
+
+#ifdef MNTOPT_NODEVS
+ if (hasmntopt(&mnt, MNTOPT_NODEVS) != NULL)
+ nfs_args.flags |= NFSMNT_NODEVS;
+#endif /* MNTOPT_NODEVS */
+
+#ifdef MNTOPT_COMPRESS
+ if (hasmntopt(&mnt, "compress") != NULL)
+ nfs_args.flags |= NFSMNT_COMPRESS;
+#endif /* MNTOPT_COMPRESS */
+
+#ifdef MNTOPT_NOCONN
+ if (hasmntopt(&mnt, "noconn") != NULL)
+ nfs_args.flags |= NFSMNT_NOCONN;
+#endif /* MNTOPT_NOCONN */
+
+#ifdef NFSMNT_PGTHRESH
+ if (nfs_args.pg_thresh = hasmntval(&mnt, "pgthresh"))
+ nfs_args.flags |= NFSMNT_PGTHRESH;
+#endif /* NFSMNT_PGTHRESH */
+
+ NFS_SA_DREF(nfs_args, fs->fs_ip);
+
+ flags = compute_mount_flags(&mnt);
+
+#ifdef NFSMNT_NOCTO
+ if (hasmntopt(&mnt, "nocto") != NULL)
+ nfs_args.flags |= NFSMNT_NOCTO;
+#endif /* NFSMNT_NOCTO */
+
+#ifdef HAS_TCP_NFS
+ if (hasmntopt(&mnt, "tcp") != NULL)
+ nfs_args.sotype = SOCK_STREAM;
+#endif /* HAS_TCP_NFS */
+
+
+#ifdef ULTRIX_HACK
+ /*
+ * Ultrix passes the flags argument as part of the
+ * mount data structure, rather than using the
+ * flags argument to the system call. This is
+ * confusing...
+ */
+ if (!(nfs_args.flags & NFSMNT_PGTHRESH)) {
+ nfs_args.pg_thresh = 64; /* 64k - XXX */
+ nfs_args.flags |= NFSMNT_PGTHRESH;
+ }
+ nfs_args.gfs_flags = flags;
+ flags &= M_RDONLY;
+ if (flags & M_RDONLY)
+ nfs_args.flags |= NFSMNT_RONLY;
+#endif /* ULTRIX_HACK */
+
+ error = mount_fs(&mnt, flags, (caddr_t) &nfs_args, retry, type);
+ free(xopts);
+ return error;
+}
+
+static int mount_nfs(dir, fs_name, opts, mf)
+char *dir;
+char *fs_name;
+char *opts;
+mntfs *mf;
+{
+#ifdef notdef
+ int error;
+ struct fhstatus fhs;
+ char *colon;
+
+ if (!(colon = strchr(fs_name, ':')))
+ return ENOENT;
+
+#ifdef DEBUG
+ dlog("locating fhandle for %s", fs_name);
+#endif /* DEBUG */
+ error = prime_nfs_fhandle_cache(colon+1, mf->mf_server, &fhs, (voidp) 0);
+
+ if (error)
+ return error;
+
+ return mount_nfs_fh(&fhs, dir, fs_name, opts, mf);
+#endif
+ if (!mf->mf_private) {
+ plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
+ return EINVAL;
+ }
+
+ return mount_nfs_fh((struct fhstatus *) mf->mf_private, dir, fs_name, opts, mf);
+}
+
+static int nfs_fmount(mf)
+mntfs *mf;
+{
+ int error;
+
+ error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
+
+#ifdef DEBUG
+ if (error) {
+ errno = error;
+ dlog("mount_nfs: %m");
+ }
+#endif /* DEBUG */
+ return error;
+}
+
+static int nfs_fumount(mf)
+mntfs *mf;
+{
+ int error = UMOUNT_FS(mf->mf_mount);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static void nfs_umounted(mp)
+am_node *mp;
+{
+#ifdef INFORM_MOUNTD
+ /*
+ * Don't bother to inform remote mountd
+ * that we are finished. Until a full
+ * track of filehandles is maintained
+ * the mountd unmount callback cannot
+ * be done correctly anyway...
+ */
+
+ mntfs *mf = mp->am_mnt;
+ fserver *fs;
+ char *colon, *path;
+
+ if (mf->mf_error || mf->mf_refc > 1)
+ return;
+
+ fs = mf->mf_server;
+
+ /*
+ * Call the mount daemon on the server to
+ * announce that we are not using the fs any more.
+ *
+ * This is *wrong*. The mountd should be called
+ * when the fhandle is flushed from the cache, and
+ * a reference held to the cached entry while the
+ * fs is mounted...
+ */
+ colon = path = strchr(mf->mf_info, ':');
+ if (fs && colon) {
+ fh_cache f;
+#ifdef DEBUG
+ dlog("calling mountd for %s", mf->mf_info);
+#endif /* DEBUG */
+ *path++ = '\0';
+ f.fh_path = path;
+ f.fh_sin = *fs->fs_ip;
+ f.fh_sin.sin_port = (u_short) 0;
+ f.fh_fs = fs;
+ f.fh_id = 0;
+ f.fh_error = 0;
+ (void) prime_nfs_fhandle_cache(colon+1, mf->mf_server, (struct fhstatus *) 0, (voidp) mf);
+ (void) call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
+ *colon = ':';
+ }
+#endif /* INFORM_MOUNTD */
+
+#ifdef KICK_KERNEL
+ /* This should go into the mainline code, not in nfs_ops... */
+
+ /*
+ * Run lstat over the underlying directory in
+ * case this was a direct mount. This will
+ * get the kernel back in sync with reality.
+ */
+ if (mp->am_parent && mp->am_parent->am_path &&
+ STREQ(mp->am_parent->am_mnt->mf_ops->fs_type, "direct")) {
+ struct stat stb;
+ int pid;
+ if ((pid = background()) == 0) {
+ if (lstat(mp->am_parent->am_path, &stb) < 0) {
+ plog(XLOG_ERROR, "lstat(%s) after unmount: %m", mp->am_parent->am_path);
+#ifdef DEBUG
+ } else {
+ dlog("hack lstat(%s): ok", mp->am_parent->am_path);
+#endif /* DEBUG */
+ }
+ _exit(0);
+ }
+ }
+#endif /* KICK_KERNEL */
+}
+
+/*
+ * Network file system
+ */
+am_ops nfs_ops = {
+ "nfs",
+ nfs_match,
+ nfs_init,
+ auto_fmount,
+ nfs_fmount,
+ auto_fumount,
+ nfs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* nfs_readlink */
+ 0, /* nfs_mounted */
+ nfs_umounted,
+ find_nfs_srvr,
+ FS_MKMNT|FS_BACKGROUND|FS_AMQINFO
+};
+
+#endif /* HAS_NFS */
diff --git a/usr.sbin/amd/amd/nfs_start.c b/usr.sbin/amd/amd/nfs_start.c
new file mode 100644
index 0000000..13d36a1
--- /dev/null
+++ b/usr.sbin/amd/amd/nfs_start.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfs_start.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfs_start.c,v 5.2.2.1 1992/02/09 15:08:51 jsp beta $
+ *
+ */
+
+#include "am.h"
+#include "amq.h"
+#include <sys/signal.h>
+#include <setjmp.h>
+extern jmp_buf select_intr;
+extern int select_intr_valid;
+
+#ifdef HAS_TFS
+/*
+ * Use replacement for RPC/UDP transport
+ * so that we do NFS gatewaying.
+ */
+#define svcudp_create svcudp2_create
+extern SVCXPRT *svcudp2_create P((int));
+#endif /* HAS_TFS */
+
+extern void nfs_program_2();
+extern void amq_program_1();
+
+unsigned short nfs_port;
+SVCXPRT *nfsxprt;
+
+extern int fwd_sock;
+int max_fds = -1;
+
+#define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
+
+#ifdef DEBUG
+/*
+ * Check that we are not burning resources
+ */
+static void checkup(P_void)
+{
+
+static int max_fd = 0;
+static char *max_mem = 0;
+
+ int next_fd = dup(0);
+ extern caddr_t sbrk P((int));
+ caddr_t next_mem = sbrk(0);
+ close(next_fd);
+
+ /*if (max_fd < 0) {
+ max_fd = next_fd;
+ } else*/ if (max_fd < next_fd) {
+ dlog("%d new fds allocated; total is %d",
+ next_fd - max_fd, next_fd);
+ max_fd = next_fd;
+ }
+
+ /*if (max_mem == 0) {
+ max_mem = next_mem;
+ } else*/ if (max_mem < next_mem) {
+ dlog("%#x bytes of memory allocated; total is %#x (%d pages)",
+ next_mem - max_mem,
+ next_mem,
+ ((int)next_mem+getpagesize()-1)/getpagesize());
+ max_mem = next_mem;
+ }
+}
+#endif /* DEBUG */
+
+static int do_select(smask, fds, fdp, tvp)
+int smask;
+int fds;
+int *fdp;
+struct timeval *tvp;
+{
+ int sig;
+ int nsel;
+ if (sig = setjmp(select_intr)) {
+ select_intr_valid = 0;
+ /* Got a signal */
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ amd_state = Finishing;
+ reschedule_timeout_mp();
+ break;
+ }
+ nsel = -1;
+ errno = EINTR;
+ } else {
+ select_intr_valid = 1;
+ /*
+ * Invalidate the current clock value
+ */
+ clock_valid = 0;
+ /*
+ * Allow interrupts. If a signal
+ * occurs, then it will cause a longjmp
+ * up above.
+ */
+ (void) sigsetmask(smask);
+ /*
+ * Wait for input
+ */
+ nsel = select(fds, fdp, (int *) 0, (int *) 0,
+ tvp->tv_sec ? tvp : (struct timeval *) 0);
+
+ }
+
+ (void) sigblock(MASKED_SIGS);
+
+ /*
+ * Perhaps reload the cache?
+ */
+ if (do_mapc_reload < clocktime()) {
+ mapc_reload();
+ do_mapc_reload = clocktime() + ONE_HOUR;
+ }
+ return nsel;
+}
+
+/*
+ * Determine whether anything is left in
+ * the RPC input queue.
+ */
+static int rpc_pending_now()
+{
+ struct timeval tvv;
+ int nsel;
+#ifdef FD_SET
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(fwd_sock, &readfds);
+#else
+ int readfds = (1 << fwd_sock);
+#endif /* FD_SET */
+
+ tvv.tv_sec = tvv.tv_usec = 0;
+ nsel = select(max_fds+1, &readfds, (int *) 0, (int *) 0, &tvv);
+ if (nsel < 1)
+ return(0);
+#ifdef FD_SET
+ if (FD_ISSET(fwd_sock, &readfds))
+ return(1);
+#else
+ if (readfds & (1 << fwd_sock))
+ return(1);
+#endif
+ return(0);
+}
+
+static serv_state run_rpc(P_void)
+{
+ int dtbsz = max_fds + 1;
+ int smask = sigblock(MASKED_SIGS);
+
+ next_softclock = clocktime();
+
+ amd_state = Run;
+
+ /*
+ * Keep on trucking while we are in Run mode. This state
+ * is switched to Quit after all the file systems have
+ * been unmounted.
+ */
+ while ((int)amd_state <= (int)Finishing) {
+ struct timeval tvv;
+ int nsel;
+ time_t now;
+#ifdef RPC_4
+ fd_set readfds;
+ readfds = svc_fdset;
+ FD_SET(fwd_sock, &readfds);
+#else
+#ifdef FD_SET
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ readfds.fds_bits[0] = svc_fds;
+ FD_SET(fwd_sock, &readfds);
+#else
+ int readfds = svc_fds | (1 << fwd_sock);
+#endif /* FD_SET */
+#endif /* RPC_4 */
+
+#ifdef DEBUG
+ checkup();
+#endif /* DEBUG */
+
+ /*
+ * If the full timeout code is not called,
+ * then recompute the time delta manually.
+ */
+ now = clocktime();
+
+ if (next_softclock <= now) {
+ if (amd_state == Finishing)
+ umount_exported();
+ tvv.tv_sec = softclock();
+ } else {
+ tvv.tv_sec = next_softclock - now;
+ }
+ tvv.tv_usec = 0;
+
+ if (amd_state == Finishing && last_used_map < 0) {
+ flush_mntfs();
+ amd_state = Quit;
+ break;
+ }
+
+#ifdef DEBUG
+ if (tvv.tv_sec)
+ dlog("Select waits for %ds", tvv.tv_sec);
+ else
+ dlog("Select waits for Godot");
+#endif /* DEBUG */
+
+ nsel = do_select(smask, dtbsz, &readfds, &tvv);
+
+
+ switch (nsel) {
+ case -1:
+ if (errno == EINTR) {
+#ifdef DEBUG
+ dlog("select interrupted");
+#endif /* DEBUG */
+ continue;
+ }
+ perror("select");
+ break;
+
+ case 0:
+#ifdef DEBUG
+ /*dlog("select returned 0");*/
+#endif /* DEBUG */
+ break;
+
+ default:
+ /* Read all pending NFS responses at once to avoid
+ having responses queue up as a consequence of
+ retransmissions. */
+#ifdef FD_SET
+ if (FD_ISSET(fwd_sock, &readfds)) {
+ FD_CLR(fwd_sock, &readfds);
+#else
+ if (readfds & (1 << fwd_sock)) {
+ readfds &= ~(1 << fwd_sock);
+#endif
+ --nsel;
+ do {
+ fwd_reply();
+ } while (rpc_pending_now() > 0);
+ }
+
+ if (nsel) {
+ /*
+ * Anything left must be a normal
+ * RPC request.
+ */
+#ifdef RPC_4
+ svc_getreqset(&readfds);
+#else
+#ifdef FD_SET
+ svc_getreq(readfds.fds_bits[0]);
+#else
+ svc_getreq(readfds);
+#endif /* FD_SET */
+#endif /* RPC_4 */
+ }
+ break;
+ }
+ }
+
+ (void) sigsetmask(smask);
+
+ if (amd_state == Quit)
+ amd_state = Done;
+
+ return amd_state;
+}
+
+static int bindnfs_port(so)
+int so;
+{
+ unsigned short port;
+ int error = bind_resv_port(so, &port);
+ if (error == 0)
+ nfs_port = port;
+ return error;
+}
+
+void unregister_amq(P_void)
+{
+#ifdef DEBUG
+ Debug(D_AMQ)
+#endif /* DEBUG */
+ (void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION);
+}
+
+int mount_automounter(ppid)
+int ppid;
+{
+ int so = socket(AF_INET, SOCK_DGRAM, 0);
+ SVCXPRT *amqp;
+ int nmount;
+
+ if (so < 0 || bindnfs_port(so) < 0) {
+ perror("Can't create privileged nfs port");
+ return 1;
+ }
+
+ if ((nfsxprt = svcudp_create(so)) == NULL ||
+ (amqp = svcudp_create(so)) == NULL) {
+ plog(XLOG_FATAL, "cannot create rpc/udp service");
+ return 2;
+ }
+
+ if (!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0)) {
+ plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
+ return 3;
+ }
+
+ /*
+ * Start RPC forwarding
+ */
+ if (fwd_init() != 0)
+ return 3;
+
+ /*
+ * One or other of so, fwd_sock
+ * must be the highest fd on
+ * which to select.
+ */
+ if (so > max_fds)
+ max_fds = so;
+ if (fwd_sock > max_fds)
+ max_fds = fwd_sock;
+
+ /*
+ * Construct the root automount node
+ */
+ make_root_node();
+
+ /*
+ * Pick up the pieces from a previous run
+ * This is likely to (indirectly) need the rpc_fwd package
+ * so it *must* come after the call to fwd_init().
+ */
+ if (restart_existing_mounts)
+ restart();
+
+ /*
+ * Mount the top-level auto-mountpoints
+ */
+ nmount = mount_exported();
+
+ /*
+ * Now safe to tell parent that we are up and running
+ */
+ if (ppid)
+ kill(ppid, SIGQUIT);
+
+ if (nmount == 0) {
+ plog(XLOG_FATAL, "No work to do - quitting");
+ amd_state = Done;
+ return 0;
+ }
+
+#ifdef DEBUG
+ Debug(D_AMQ) {
+#endif /* DEBUG */
+ /*
+ * Register with amq
+ */
+ unregister_amq();
+
+ if (!svc_register(amqp, AMQ_PROGRAM, AMQ_VERSION, amq_program_1, IPPROTO_UDP)) {
+ plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)");
+ return 3;
+ }
+#ifdef DEBUG
+ }
+#endif /* DEBUG */
+
+ /*
+ * Start timeout_mp rolling
+ */
+ reschedule_timeout_mp();
+
+ /*
+ * Start the server
+ */
+ if (run_rpc() != Done) {
+ plog(XLOG_FATAL, "run_rpc failed");
+ amd_state = Done;
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/amd/amd/nfs_subr.c b/usr.sbin/amd/amd/nfs_subr.c
new file mode 100644
index 0000000..297cf93
--- /dev/null
+++ b/usr.sbin/amd/amd/nfs_subr.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfs_subr.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfs_subr.c,v 5.2.2.1 1992/02/09 15:08:53 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+/*
+ * Convert from UN*X to NFS error code
+ */
+#ifdef NFS_ERROR_MAPPING
+NFS_ERROR_MAPPING
+#define nfs_error(e) \
+ ((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
+ nfs_errormap[(e) - NFS_LOMAP] : (e)))
+#else
+#define nfs_error(e) ((nfsstat)(e))
+#endif /* NFS_ERROR_MAPPING */
+
+static char *do_readlink P((am_node *mp, int *error_return, struct attrstat **attrpp));
+static char *do_readlink(mp, error_return, attrpp)
+am_node *mp;
+int *error_return;
+struct attrstat **attrpp;
+{
+ char *ln;
+
+ /*
+ * If there is a readlink method, then use
+ * that, otherwise if a link exists use
+ * that, otherwise use the mount point.
+ */
+ if (mp->am_mnt->mf_ops->readlink) {
+ int retry = 0;
+ mp = (*mp->am_mnt->mf_ops->readlink)(mp, &retry);
+ if (mp == 0) {
+ *error_return = retry;
+ return 0;
+ }
+ /*reschedule_timeout_mp();*/
+ }
+ if (mp->am_link) {
+ ln = mp->am_link;
+ } else {
+ ln = mp->am_mnt->mf_mount;
+ }
+ if (attrpp)
+ *attrpp = &mp->am_attr;
+ return ln;
+}
+
+/*ARGSUSED*/
+voidp
+nfsproc_null_2(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static char res;
+
+ return (voidp) &res;
+}
+
+
+/*ARGSUSED*/
+struct attrstat *
+nfsproc_getattr_2(argp, rqstp)
+struct nfs_fh *argp;
+struct svc_req *rqstp;
+{
+ static struct attrstat res;
+ am_node *mp;
+ int retry;
+
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "gettattr:");
+#endif /* DEBUG */
+
+ mp = fh_to_mp2(argp, &retry);
+ if (mp == 0) {
+#ifdef PRECISE_SYMLINKS
+getattr_retry:
+#endif /* PRECISE_SYMLINKS */
+
+ if (retry < 0)
+ return 0;
+ res.status = nfs_error(retry);
+ } else {
+ struct attrstat *attrp = &mp->am_attr;
+#ifdef PRECISE_SYMLINKS
+ if (mp->am_fattr.type == NFLNK) {
+ /*
+ * Make sure we can read the link,
+ * and then determine the length.
+ */
+ char *ln = do_readlink(mp, &retry, &attrp);
+ if (ln == 0)
+ goto getattr_retry;
+ }
+#endif /* PRECISE_SYMLINKS */
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, attrp->attrstat_u.attributes.size);
+#endif /* DEBUG */
+ mp->am_stats.s_getattr++;
+ return attrp;
+ }
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+struct attrstat *
+nfsproc_setattr_2(argp, rqstp)
+struct sattrargs *argp;
+struct svc_req *rqstp;
+{
+ static struct attrstat res;
+
+ if (!fh_to_mp(&argp->file))
+ res.status = nfs_error(ESTALE);
+ else
+ res.status = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+voidp
+nfsproc_root_2(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static char res;
+
+ return (voidp)&res;
+}
+
+
+/*ARGSUSED*/
+struct diropres *
+nfsproc_lookup_2(argp, rqstp)
+struct diropargs *argp;
+struct svc_req *rqstp;
+{
+ static struct diropres res;
+ am_node *mp;
+ int retry;
+
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "lookup:");
+#endif /* DEBUG */
+
+ mp = fh_to_mp2(&argp->dir, &retry);
+ if (mp == 0) {
+ if (retry < 0)
+ return 0;
+ res.status = nfs_error(retry);
+ } else {
+ int error;
+ am_node *ap;
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->name);
+#endif /* DEBUG */
+ ap = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &error, VLOOK_CREATE);
+ if (ap == 0) {
+ if (error < 0) {
+#ifdef DEBUG
+ dlog("Not sending RPC reply");
+#endif /* DEBUG */
+ amd_stats.d_drops++;
+ return 0;
+ }
+ res.status = nfs_error(error);
+ } else {
+ mp_to_fh(ap, &res.diropres_u.diropres.file);
+ res.diropres_u.diropres.attributes = ap->am_fattr;
+ res.status = NFS_OK;
+ }
+ mp->am_stats.s_lookup++;
+ /*reschedule_timeout_mp();*/
+ }
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+struct readlinkres *
+nfsproc_readlink_2(argp, rqstp)
+struct nfs_fh *argp;
+struct svc_req *rqstp;
+{
+ static struct readlinkres res;
+ am_node *mp;
+ int retry;
+
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "readlink:");
+#endif /* DEBUG */
+
+ mp = fh_to_mp2(argp, &retry);
+ if (mp == 0) {
+readlink_retry:
+ if (retry < 0)
+ return 0;
+ res.status = nfs_error(retry);
+ } else {
+ char *ln = do_readlink(mp, &retry, (struct attrstat **) 0);
+ if (ln == 0)
+ goto readlink_retry;
+ res.status = NFS_OK;
+#ifdef DEBUG
+ Debug(D_TRACE)
+ if (ln)
+ plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
+#endif /* DEBUG */
+ res.readlinkres_u.data = ln;
+ mp->am_stats.s_readlink++;
+ }
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+struct readres *
+nfsproc_read_2(argp, rqstp)
+struct readargs *argp;
+struct svc_req *rqstp;
+{
+ static struct readres res;
+
+ bzero((char *)&res, sizeof(res));
+
+ res.status = nfs_error(EACCES);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+voidp
+nfsproc_writecache_2(argp, rqstp)
+voidp argp;
+struct svc_req *rqstp;
+{
+ static char res;
+
+ return (voidp) &res;
+}
+
+
+/*ARGSUSED*/
+struct attrstat *
+nfsproc_write_2(argp, rqstp)
+writeargs *argp;
+struct svc_req *rqstp;
+{
+ static struct attrstat res;
+
+ if (!fh_to_mp(&argp->file))
+ res.status = nfs_error(ESTALE);
+ else
+ res.status = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+struct diropres *
+nfsproc_create_2(argp, rqstp)
+createargs *argp;
+struct svc_req *rqstp;
+{
+ static struct diropres res;
+
+ if (!fh_to_mp(&argp->where.dir))
+ res.status = nfs_error(ESTALE);
+ else
+ res.status = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+static nfsstat *
+unlink_or_rmdir(argp, rqstp, unlinkp)
+struct diropargs *argp;
+struct svc_req *rqstp;
+int unlinkp;
+{
+ static nfsstat res;
+ int retry;
+ /*mntfs *mf;*/
+ am_node *mp = fh_to_mp3(&argp->dir, &retry, VLOOK_DELETE);
+ if (mp == 0) {
+ if (retry < 0)
+ return 0;
+ res = nfs_error(retry);
+ goto out;
+ }
+ /*mf = mp->am_mnt;*/
+ if (mp->am_fattr.type != NFDIR) {
+ res = nfs_error(ENOTDIR);
+ goto out;
+ }
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->name);
+#endif /* DEBUG */
+ mp = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &retry, VLOOK_DELETE);
+ if (mp == 0) {
+ /*
+ * Ignore retries...
+ */
+ if (retry < 0)
+ retry = 0;
+ /*
+ * Usual NFS workaround...
+ */
+ else if (retry == ENOENT)
+ retry = 0;
+ res = nfs_error(retry);
+ } else {
+ forcibly_timeout_mp(mp);
+ res = NFS_OK;
+ }
+
+out:
+ return &res;
+}
+
+
+/*ARGSUSED*/
+nfsstat *
+nfsproc_remove_2(argp, rqstp)
+struct diropargs *argp;
+struct svc_req *rqstp;
+{
+ return unlink_or_rmdir(argp, rqstp, TRUE);
+}
+
+/*ARGSUSED*/
+nfsstat *
+nfsproc_rename_2(argp, rqstp)
+renameargs *argp;
+struct svc_req *rqstp;
+{
+ static nfsstat res;
+ if (!fh_to_mp(&argp->from.dir) || !fh_to_mp(&argp->to.dir))
+ res = nfs_error(ESTALE);
+ /*
+ * If the kernel is doing clever things with referenced files
+ * then let it pretend...
+ */
+ else if (strncmp(argp->to.name, ".nfs", 4) == 0)
+ res = NFS_OK;
+ /*
+ * otherwise a failure
+ */
+ else
+ res = nfs_error(EROFS);
+ return &res;
+}
+
+
+/*ARGSUSED*/
+nfsstat *
+nfsproc_link_2(argp, rqstp)
+linkargs *argp;
+struct svc_req *rqstp;
+{
+ static nfsstat res;
+ if (!fh_to_mp(&argp->from) || !fh_to_mp(&argp->to.dir))
+ res = nfs_error(ESTALE);
+ else
+ res = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+nfsstat *
+nfsproc_symlink_2(argp, rqstp)
+symlinkargs *argp;
+struct svc_req *rqstp;
+{
+ static nfsstat res;
+ if (!fh_to_mp(&argp->from.dir))
+ res = nfs_error(ESTALE);
+ else
+ res = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+struct diropres *
+nfsproc_mkdir_2(argp, rqstp)
+createargs *argp;
+struct svc_req *rqstp;
+{
+ static struct diropres res;
+ if (!fh_to_mp(&argp->where.dir))
+ res.status = nfs_error(ESTALE);
+ else
+ res.status = nfs_error(EROFS);
+
+ return &res;
+}
+
+
+/*ARGSUSED*/
+nfsstat *
+nfsproc_rmdir_2(argp, rqstp)
+struct diropargs *argp;
+struct svc_req *rqstp;
+{
+ return unlink_or_rmdir(argp, rqstp, FALSE);
+}
+
+
+/*ARGSUSED*/
+struct readdirres *
+nfsproc_readdir_2(argp, rqstp)
+readdirargs *argp;
+struct svc_req *rqstp;
+{
+ static readdirres res;
+ static entry e_res[MAX_READDIR_ENTRIES];
+ am_node *mp;
+ int retry;
+
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "readdir:");
+#endif /* DEBUG */
+
+ mp = fh_to_mp2(&argp->dir, &retry);
+ if (mp == 0) {
+ if (retry < 0)
+ return 0;
+ res.status = nfs_error(retry);
+ } else {
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
+#endif /* DEBUG */
+ res.status = nfs_error((*mp->am_mnt->mf_ops->readdir)(mp, argp->cookie,
+ &res.readdirres_u.reply, e_res, argp->count));
+ mp->am_stats.s_readdir++;
+ }
+
+ return &res;
+}
+
+/*ARGSUSED*/
+struct statfsres *
+nfsproc_statfs_2(argp, rqstp)
+struct nfs_fh *argp;
+struct svc_req *rqstp;
+{
+ static statfsres res;
+ am_node *mp;
+ int retry;
+
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "statfs:");
+#endif /* DEBUG */
+
+ mp = fh_to_mp2(argp, &retry);
+ if (mp == 0) {
+ if (retry < 0)
+ return 0;
+ res.status = nfs_error(retry);
+ } else {
+ statfsokres *fp;
+#ifdef DEBUG
+ Debug(D_TRACE)
+ plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
+#endif /* DEBUG */
+ /*
+ * just return faked up file system information
+ */
+
+ fp = &res.statfsres_u.reply;
+
+ fp->tsize = 1024;
+ fp->bsize = 4096;
+#ifdef HAS_EMPTY_AUTOMOUNTS
+ fp->blocks = 0;
+#else
+ fp->blocks = 1;
+#endif
+ fp->bfree = 0;
+ fp->bavail = 0;
+
+ res.status = NFS_OK;
+ mp->am_stats.s_statfs++;
+ }
+
+ return &res;
+}
diff --git a/usr.sbin/amd/amd/nfsx_ops.c b/usr.sbin/amd/amd/nfsx_ops.c
new file mode 100644
index 0000000..ba18cdc
--- /dev/null
+++ b/usr.sbin/amd/amd/nfsx_ops.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfsx_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfsx_ops.c,v 5.2.2.3 1992/05/31 16:13:07 jsp Exp $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_NFSX
+
+/*
+ * NFS hierarchical mounts
+ *
+ * TODO: Re-implement.
+ */
+
+/*
+ * The rfs field contains a list of mounts to be done from
+ * the remote host.
+ */
+typedef struct nfsx_mnt {
+ mntfs *n_mnt;
+ int n_error;
+} nfsx_mnt;
+
+struct nfsx {
+ int nx_c; /* Number of elements in nx_v */
+ nfsx_mnt *nx_v; /* Underlying mounts */
+ nfsx_mnt *nx_try;
+};
+
+static int nfsx_fmount P((mntfs*));
+
+static char *nfsx_match(fo)
+am_opts *fo;
+{
+ char *xmtab;
+ char *ptr;
+ int len;
+
+ if (!fo->opt_rfs) {
+ plog(XLOG_USER, "nfsx: no remote filesystem specified");
+ return FALSE;
+ }
+ if (!fo->opt_rhost) {
+ plog(XLOG_USER, "nfsx: no remote host specified");
+ return FALSE;
+ }
+
+#ifdef notdef
+ /* fiddle sublink, must be last... */
+ if (fo->opt_sublink) {
+ plog(XLOG_WARNING, "nfsx: sublink %s ignored", fo->opt_sublink);
+ free((voidp) fo->opt_sublink);
+ fo->opt_sublink = 0;
+ }
+#endif
+
+ /* set default sublink */
+ if (fo->opt_sublink == 0) {
+ ptr = strchr(fo->opt_rfs, ',');
+ if (ptr && ptr != (fo->opt_rfs + 1))
+ fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
+ }
+
+ /*
+ * Remove trailing ",..." from ${fs}
+ * After deslashifying, overwrite the end of ${fs} with "/"
+ * to make sure it is unique.
+ */
+ if (ptr = strchr(fo->opt_fs, ','))
+ *ptr = '\0';
+ deslashify(fo->opt_fs);
+ /*
+ * Bump string length to allow trailing /
+ */
+ len = strlen(fo->opt_fs);
+ fo->opt_fs = xrealloc(fo->opt_fs, len + 1 + 1);
+ ptr = fo->opt_fs + len;
+ /*
+ * Make unique...
+ */
+ *ptr++ = '/';
+ *ptr = '\0';
+
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
+#ifdef DEBUG
+ dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
+ fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
+#endif /* DEBUG */
+
+ return xmtab;
+}
+
+static void nfsx_prfree P((voidp vp));
+static void nfsx_prfree(vp)
+voidp vp;
+{
+ struct nfsx *nx = (struct nfsx *) vp;
+ int i;
+
+ for (i = 0; i < nx->nx_c; i++) {
+ mntfs *m = nx->nx_v[i].n_mnt;
+ if (m)
+ free_mntfs(m);
+ }
+
+ free((voidp) nx->nx_v);
+ free((voidp) nx);
+}
+
+static int nfsx_init(mf)
+mntfs *mf;
+{
+ /*
+ * mf_info has the form:
+ * host:/prefix/path,sub,sub,sub
+ */
+ int i;
+ int glob_error;
+ struct nfsx *nx;
+ int asked_for_wakeup = 0;
+
+ nx = (struct nfsx *) mf->mf_private;
+
+ if (nx == 0) {
+ char **ivec;
+ char *info = 0;
+ char *host;
+ char *pref;
+ int error = 0;
+
+ info = strdup(mf->mf_info);
+ host = strchr(info, ':');
+ if (!host) {
+ error = EINVAL;
+ goto errexit;
+ }
+
+ pref = host+1;
+ host = info;
+
+ /*
+ * Split the prefix off from the suffices
+ */
+ ivec = strsplit(pref, ',', '\'');
+
+ /*
+ * Count array size
+ */
+ for (i = 0; ivec[i]; i++)
+ ;
+
+ nx = ALLOC(nfsx);
+ mf->mf_private = (voidp) nx;
+ mf->mf_prfree = nfsx_prfree;
+
+ nx->nx_c = i - 1; /* i-1 because we don't want the prefix */
+ nx->nx_v = (nfsx_mnt *) xmalloc(nx->nx_c * sizeof(nfsx_mnt));
+ { char *mp = 0;
+ char *xinfo = 0;
+ char *fs = mf->mf_fo->opt_fs;
+ char *rfs = 0;
+ for (i = 0; i < nx->nx_c; i++) {
+ char *path = ivec[i+1];
+ rfs = str3cat(rfs, pref, "/", path);
+ /*
+ * Determine the mount point.
+ * If this is the root, then don't remove
+ * the trailing slash to avoid mntfs name clashes.
+ */
+ mp = str3cat(mp, fs, "/", rfs);
+ normalize_slash(mp);
+ deslashify(mp);
+ /*
+ * Determine the mount info
+ */
+ xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
+ normalize_slash(xinfo);
+ if (pref[1] != '\0')
+ deslashify(xinfo);
+#ifdef DEBUG
+ dlog("nfsx: init mount for %s on %s", xinfo, mp);
+#endif
+ nx->nx_v[i].n_error = -1;
+ nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
+ }
+ if (rfs) free(rfs);
+ if (mp) free(mp);
+ if (xinfo) free(xinfo);
+ }
+
+ free((voidp) ivec);
+errexit:
+ if (info)
+ free(info);
+ if (error)
+ return error;
+ }
+
+ /*
+ * Iterate through the mntfs's and call
+ * the underlying init routine on each
+ */
+ glob_error = 0;
+ for (i = 0; i < nx->nx_c; i++) {
+ nfsx_mnt *n = &nx->nx_v[i];
+ mntfs *m = n->n_mnt;
+ int error = (*m->mf_ops->fs_init)(m);
+ /*
+ * If HARD_NFSX_ERRORS is defined, make any
+ * initialisation failure a hard error and
+ * fail the entire group. Otherwise only fail
+ * if none of the group is mountable (see nfsx_fmount).
+ */
+#ifdef HARD_NFSX_ERRORS
+ if (error > 0)
+ return error;
+#else
+ if (error > 0)
+ n->n_error = error;
+#endif
+ else if (error < 0) {
+ glob_error = -1;
+ if (!asked_for_wakeup) {
+ asked_for_wakeup = 1;
+ sched_task(wakeup_task, (voidp) mf, (voidp) m);
+ }
+ }
+ }
+
+ return glob_error;
+}
+
+static void nfsx_cont P((int rc, int term, voidp closure));
+static void nfsx_cont(rc, term, closure)
+int rc;
+int term;
+voidp closure;
+{
+ mntfs *mf = (mntfs *) closure;
+ struct nfsx *nx = (struct nfsx *) mf->mf_private;
+ nfsx_mnt *n = nx->nx_try;
+
+ n->n_mnt->mf_flags &= ~(MFF_ERROR|MFF_MOUNTING);
+ mf->mf_flags &= ~MFF_ERROR;
+
+ /*
+ * Wakeup anything waiting for this mount
+ */
+ wakeup((voidp) n->n_mnt);
+
+ if (rc || term) {
+ if (term) {
+ /*
+ * Not sure what to do for an error code.
+ */
+ plog(XLOG_ERROR, "mount for %s got signal %d", n->n_mnt->mf_mount, term);
+ n->n_error = EIO;
+ } else {
+ /*
+ * Check for exit status
+ */
+ errno = rc; /* XXX */
+ plog(XLOG_ERROR, "%s: mount (nfsx_cont): %m", n->n_mnt->mf_mount);
+ n->n_error = rc;
+ }
+ free_mntfs(n->n_mnt);
+ n->n_mnt = new_mntfs();
+ n->n_mnt->mf_error = n->n_error;
+ n->n_mnt->mf_flags |= MFF_ERROR;
+ } else {
+ /*
+ * The mount worked.
+ */
+ mf_mounted(n->n_mnt);
+ n->n_error = 0;
+ }
+
+ /*
+ * Do the remaining bits
+ */
+ if (nfsx_fmount(mf) >= 0) {
+ wakeup((voidp) mf);
+ mf->mf_flags &= ~MFF_MOUNTING;
+ mf_mounted(mf);
+ }
+}
+
+static int try_nfsx_mount P((voidp mv));
+static int try_nfsx_mount(mv)
+voidp mv;
+{
+ mntfs *mf = (mntfs *) mv;
+ int error;
+
+ mf->mf_flags |= MFF_MOUNTING;
+ error = (*mf->mf_ops->fmount_fs)(mf);
+ mf->mf_flags &= ~MFF_MOUNTING;
+ return error;
+}
+
+static int nfsx_remount P((mntfs *mf, int fg));
+static int nfsx_remount(mf, fg)
+mntfs *mf;
+int fg;
+{
+ struct nfsx *nx = (struct nfsx *) mf->mf_private;
+ nfsx_mnt *n;
+ int glob_error = -1;
+
+ for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
+ mntfs *m = n->n_mnt;
+ if (n->n_error < 0) {
+ if (!(m->mf_flags & MFF_MKMNT) && m->mf_ops->fs_flags & FS_MKMNT) {
+ int error = mkdirs(m->mf_mount, 0555);
+ if (!error)
+ m->mf_flags |= MFF_MKMNT;
+ }
+ }
+ }
+
+ /*
+ * Iterate through the mntfs's and mount each filesystem
+ * which is not yet mounted.
+ */
+ for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
+ mntfs *m = n->n_mnt;
+ if (n->n_error < 0) {
+ /*
+ * Check fmount entry pt. exists
+ * and then mount...
+ */
+ if (!m->mf_ops->fmount_fs) {
+ n->n_error = EINVAL;
+ } else {
+#ifdef DEBUG
+ dlog("calling underlying fmount on %s", m->mf_mount);
+#endif
+ if (!fg && foreground && (m->mf_ops->fs_flags & FS_MBACKGROUND)) {
+ m->mf_flags |= MFF_MOUNTING; /* XXX */
+#ifdef DEBUG
+ dlog("backgrounding mount of \"%s\"", m->mf_info);
+#endif
+ nx->nx_try = n;
+ run_task(try_nfsx_mount, (voidp) m, nfsx_cont, (voidp) mf);
+ n->n_error = -1;
+ return -1;
+ } else {
+#ifdef DEBUG
+ dlog("foreground mount of \"%s\" ...", mf->mf_info);
+#endif
+ n->n_error = (*m->mf_ops->fmount_fs)(m);
+ }
+ }
+#ifdef DEBUG
+ if (n->n_error > 0) {
+ errno = n->n_error; /* XXX */
+ dlog("underlying fmount of %s failed: %m", m->mf_mount);
+ }
+#endif
+ if (n->n_error == 0) {
+ glob_error = 0;
+ } else if (glob_error < 0) {
+ glob_error = n->n_error;
+ }
+ }
+ }
+
+ return glob_error < 0 ? 0 : glob_error;
+}
+
+static int nfsx_fmount P((mntfs *mf));
+static int nfsx_fmount(mf)
+mntfs *mf;
+{
+ return nfsx_remount(mf, FALSE);
+}
+
+/*
+ * Unmount an NFS hierarchy.
+ * Note that this is called in the foreground
+ * and so may hang under extremely rare conditions.
+ */
+static int nfsx_fumount(mf)
+mntfs *mf;
+{
+ struct nfsx *nx = (struct nfsx *) mf->mf_private;
+ nfsx_mnt *n;
+ int glob_error = 0;
+
+ /*
+ * Iterate in reverse through the mntfs's and unmount each filesystem
+ * which is mounted.
+ */
+ for (n = nx->nx_v + nx->nx_c - 1; n >= nx->nx_v; --n) {
+ mntfs *m = n->n_mnt;
+ /*
+ * If this node has not been messed with
+ * and there has been no error so far
+ * then try and unmount.
+ * If an error had occured then zero
+ * the error code so that the remount
+ * only tries to unmount those nodes
+ * which had been successfully unmounted.
+ */
+ if (n->n_error == 0) {
+#ifdef DEBUG
+ dlog("calling underlying fumount on %s", m->mf_mount);
+#endif
+ n->n_error = (*m->mf_ops->fumount_fs)(m);
+ if (n->n_error) {
+ glob_error = n->n_error;
+ n->n_error = 0;
+ } else {
+ /*
+ * Make sure remount gets this node
+ */
+ n->n_error = -1;
+ }
+ }
+ }
+
+ /*
+ * If any unmounts failed then remount the
+ * whole lot...
+ */
+ if (glob_error) {
+ glob_error = nfsx_remount(mf, TRUE);
+ if (glob_error) {
+ errno = glob_error; /* XXX */
+ plog(XLOG_USER, "nfsx: remount of %s failed: %m", mf->mf_mount);
+ }
+ glob_error = EBUSY;
+ } else {
+ /*
+ * Remove all the mount points
+ */
+ for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
+ mntfs *m = n->n_mnt;
+ if (n->n_error < 0) {
+ if (m->mf_ops->fs_flags & FS_MKMNT) {
+ (void) rmdirs(m->mf_mount);
+ m->mf_flags &= ~MFF_MKMNT;
+ }
+ }
+ free_mntfs(m);
+ n->n_mnt = 0;
+ n->n_error = -1;
+ }
+ }
+
+ return glob_error;
+}
+
+/*
+ * Ops structure
+ */
+am_ops nfsx_ops = {
+ "nfsx",
+ nfsx_match,
+ nfsx_init,
+ auto_fmount,
+ nfsx_fmount,
+ auto_fumount,
+ nfsx_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* nfsx_readlink */
+ 0, /* nfsx_mounted */
+ 0, /* nfsx_umounted */
+ find_nfs_srvr, /* XXX */
+ /*FS_UBACKGROUND|*/FS_AMQINFO
+};
+
+#endif /* HAS_NFSX */
diff --git a/usr.sbin/amd/amd/opts.c b/usr.sbin/amd/amd/opts.c
new file mode 100644
index 0000000..54c9675
--- /dev/null
+++ b/usr.sbin/amd/amd/opts.c
@@ -0,0 +1,835 @@
+/*-
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: opts.c,v 5.2.2.3 1992/05/31 16:34:13 jsp Exp $
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)opts.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "am.h"
+
+extern char *getenv P((const char *));
+
+/*
+ * static copy of the options with
+ * which to play
+ */
+static struct am_opts fs_static;
+
+static char *opt_host = hostname;
+static char *opt_hostd = hostd;
+static char nullstr[] = "";
+static char *opt_key = nullstr;
+static char *opt_map = nullstr;
+static char *opt_path = nullstr;
+
+static char *vars[8];
+
+/*
+ * Length of longest option name
+ */
+#define NLEN 16 /* conservative */
+#define S(x) (x) , (sizeof(x)-1)
+static struct opt {
+ char *name; /* Name of the option */
+ int nlen; /* Length of option name */
+ char **optp; /* Pointer to option value string */
+ char **sel_p; /* Pointer to selector value string */
+} opt_fields[] = {
+ /* Options in something corresponding to frequency of use */
+ { S("opts"), &fs_static.opt_opts, 0 },
+ { S("host"), 0, &opt_host },
+ { S("hostd"), 0, &opt_hostd },
+ { S("type"), &fs_static.opt_type, 0 },
+ { S("rhost"), &fs_static.opt_rhost, 0 },
+ { S("rfs"), &fs_static.opt_rfs, 0 },
+ { S("fs"), &fs_static.opt_fs, 0 },
+ { S("key"), 0, &opt_key },
+ { S("map"), 0, &opt_map },
+ { S("sublink"), &fs_static.opt_sublink, 0 },
+ { S("arch"), 0, &arch },
+ { S("dev"), &fs_static.opt_dev, 0 },
+ { S("pref"), &fs_static.opt_pref, 0 },
+ { S("path"), 0, &opt_path },
+ { S("autodir"), 0, &auto_dir },
+ { S("delay"), &fs_static.opt_delay, 0 },
+ { S("domain"), 0, &hostdomain },
+ { S("karch"), 0, &karch },
+ { S("cluster"), 0, &cluster },
+ { S("wire"), 0, &wire },
+ { S("byte"), 0, &endian },
+ { S("os"), 0, &op_sys },
+ { S("remopts"), &fs_static.opt_remopts, 0 },
+ { S("mount"), &fs_static.opt_mount, 0 },
+ { S("unmount"), &fs_static.opt_unmount, 0 },
+ { S("cache"), &fs_static.opt_cache, 0 },
+ { S("user"), &fs_static.opt_user, 0 },
+ { S("group"), &fs_static.opt_group, 0 },
+ { S("var0"), &vars[0], 0 },
+ { S("var1"), &vars[1], 0 },
+ { S("var2"), &vars[2], 0 },
+ { S("var3"), &vars[3], 0 },
+ { S("var4"), &vars[4], 0 },
+ { S("var5"), &vars[5], 0 },
+ { S("var6"), &vars[6], 0 },
+ { S("var7"), &vars[7], 0 },
+ { 0, 0, 0, 0 },
+};
+
+typedef struct opt_apply opt_apply;
+struct opt_apply {
+ char **opt;
+ char *val;
+};
+
+/*
+ * Specially expand the remote host name first
+ */
+static opt_apply rhost_expansion[] = {
+ { &fs_static.opt_rhost, "${host}" },
+ { 0, 0 },
+};
+/*
+ * List of options which need to be expanded
+ * Note that this the order here _may_ be important.
+ */
+static opt_apply expansions[] = {
+/* { &fs_static.opt_dir, 0 }, */
+ { &fs_static.opt_sublink, 0 },
+ { &fs_static.opt_rfs, "${path}" },
+ { &fs_static.opt_fs, "${autodir}/${rhost}${rfs}" },
+ { &fs_static.opt_opts, "rw" },
+ { &fs_static.opt_remopts, "${opts}" },
+ { &fs_static.opt_mount, 0 },
+ { &fs_static.opt_unmount, 0 },
+ { 0, 0 },
+};
+
+/*
+ * List of options which need to be free'ed before re-use
+ */
+static opt_apply to_free[] = {
+ { &fs_static.fs_glob, 0 },
+ { &fs_static.fs_local, 0 },
+ { &fs_static.fs_mtab, 0 },
+/* { &fs_static.opt_dir, 0 }, */
+ { &fs_static.opt_sublink, 0 },
+ { &fs_static.opt_rfs, 0 },
+ { &fs_static.opt_fs, 0 },
+ { &fs_static.opt_rhost, 0 },
+ { &fs_static.opt_opts, 0 },
+ { &fs_static.opt_remopts, 0 },
+ { &fs_static.opt_mount, 0 },
+ { &fs_static.opt_unmount, 0 },
+ { &vars[0], 0 },
+ { &vars[1], 0 },
+ { &vars[2], 0 },
+ { &vars[3], 0 },
+ { &vars[4], 0 },
+ { &vars[5], 0 },
+ { &vars[6], 0 },
+ { &vars[7], 0 },
+ { 0, 0 },
+};
+
+/*
+ * Skip to next option in the string
+ */
+static char *opt P((char**));
+static char *opt(p)
+char **p;
+{
+ char *cp = *p;
+ char *dp = cp;
+ char *s = cp;
+
+top:
+ while (*cp && *cp != ';') {
+ if (*cp == '\"') {
+ /*
+ * Skip past string
+ */
+ cp++;
+ while (*cp && *cp != '\"')
+ *dp++ = *cp++;
+ if (*cp)
+ cp++;
+ } else {
+ *dp++ = *cp++;
+ }
+ }
+
+ /*
+ * Skip past any remaining ';'s
+ */
+ while (*cp == ';')
+ cp++;
+
+ /*
+ * If we have a zero length string
+ * and there are more fields, then
+ * parse the next one. This allows
+ * sequences of empty fields.
+ */
+ if (*cp && dp == s)
+ goto top;
+
+ *dp = '\0';
+
+ *p = cp;
+ return s;
+}
+
+static int eval_opts P((char*, char*));
+static int eval_opts(opts, mapkey)
+char *opts;
+char *mapkey;
+{
+ /*
+ * Fill in the global structure fs_static by
+ * cracking the string opts. opts may be
+ * scribbled on at will.
+ */
+ char *o = opts;
+ char *f;
+
+ /*
+ * For each user-specified option
+ */
+ while (*(f = opt(&o))) {
+ struct opt *op;
+ enum vs_opt { OldSyn, SelEQ, SelNE, VarAss } vs_opt;
+ char *eq = strchr(f, '=');
+ char *opt;
+ if (!eq || eq[1] == '\0' || eq == f) {
+ /*
+ * No value, just continue
+ */
+ plog(XLOG_USER, "key %s: No value component in \"%s\"", mapkey, f);
+ continue;
+ }
+
+ /*
+ * Check what type of operation is happening
+ * !=, =! is SelNE
+ * == is SelEQ
+ * := is VarAss
+ * = is OldSyn (either SelEQ or VarAss)
+ */
+ if (eq[-1] == '!') { /* != */
+ vs_opt = SelNE;
+ eq[-1] = '\0';
+ opt = eq + 1;
+ } else if (eq[-1] == ':') { /* := */
+ vs_opt = VarAss;
+ eq[-1] = '\0';
+ opt = eq + 1;
+ } else if (eq[1] == '=') { /* == */
+ vs_opt = SelEQ;
+ eq[0] = '\0';
+ opt = eq + 2;
+ } else if (eq[1] == '!') { /* =! */
+ vs_opt = SelNE;
+ eq[0] = '\0';
+ opt = eq + 2;
+ } else { /* = */
+ vs_opt = OldSyn;
+ eq[0] = '\0';
+ opt = eq + 1;
+ }
+
+ /*
+ * For each recognised option
+ */
+ for (op = opt_fields; op->name; op++) {
+ /*
+ * Check whether they match
+ */
+ if (FSTREQ(op->name, f)) {
+ switch (vs_opt) {
+#if AMD_COMPAT <= 5000108
+ case OldSyn:
+ plog(XLOG_WARNING, "key %s: Old syntax selector found: %s=%s", mapkey, f, opt);
+ if (!op->sel_p) {
+ *op->optp = opt;
+ break;
+ }
+ /* fall through ... */
+#endif /* 5000108 */
+ case SelEQ:
+ case SelNE:
+ if (op->sel_p && (STREQ(*op->sel_p, opt) == (vs_opt == SelNE))) {
+ plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",
+ mapkey,
+ op->name,
+ *op->sel_p,
+ vs_opt == SelNE ? "not " : "",
+ opt);
+ return 0;
+ }
+ break;
+
+ case VarAss:
+ if (op->sel_p) {
+ plog(XLOG_USER, "key %s: Can't assign to a selector (%s)", mapkey, op->name);
+ return 0;
+ }
+ *op->optp = opt;
+ break;
+ }
+ break;
+ }
+ }
+
+ if (!op->name)
+ plog(XLOG_USER, "key %s: Unrecognised key/option \"%s\"", mapkey, f);
+ }
+
+ return 1;
+}
+
+/*
+ * Free an option
+ */
+static void free_op P((opt_apply*, int));
+/*ARGSUSED*/
+static void free_op(p, b)
+opt_apply *p;
+int b;
+{
+ if (*p->opt) {
+ free(*p->opt);
+ *p->opt = 0;
+ }
+}
+
+/*
+ * Normalize slashes in the string.
+ */
+void normalize_slash P((char *p));
+void normalize_slash(p)
+char *p;
+{
+ char *f = strchr(p, '/');
+ char *f0 = f;
+ if (f) {
+ char *t = f;
+ do {
+ /* assert(*f == '/'); */
+ if (f == f0 && f[0] == '/' && f[1] == '/') {
+ /* copy double slash iff first */
+ *t++ = *f++;
+ *t++ = *f++;
+ } else {
+ /* copy a single / across */
+ *t++ = *f++;
+ }
+
+ /* assert(f[-1] == '/'); */
+ /* skip past more /'s */
+ while (*f == '/')
+ f++;
+
+ /* assert(*f != '/'); */
+ /* keep copying up to next / */
+ while (*f && *f != '/') {
+ *t++ = *f++;
+ }
+
+ /* assert(*f == 0 || *f == '/'); */
+
+ } while (*f);
+ *t = 0; /* derived from fix by Steven Glassman */
+ }
+}
+
+/*
+ * Macro-expand an option. Note that this does not
+ * handle recursive expansions. They will go badly wrong.
+ * If sel is true then old expand selectors, otherwise
+ * don't expand selectors.
+ */
+static void expand_op P((opt_apply*, int));
+static void expand_op(p, sel_p)
+opt_apply *p;
+int sel_p;
+{
+/*
+ * The BUFSPACE macros checks that there is enough space
+ * left in the expansion buffer. If there isn't then we
+ * give up completely. This is done to avoid crashing the
+ * automounter itself (which would be a bad thing to do).
+ */
+#define BUFSPACE(ep, len) (((ep) + (len)) < expbuf+MAXPATHLEN)
+static char expand_error[] = "No space to expand \"%s\"";
+
+ char expbuf[MAXPATHLEN+1];
+ char nbuf[NLEN+1];
+ char *ep = expbuf;
+ char *cp = *p->opt;
+ char *dp;
+#ifdef DEBUG
+ char *cp_orig = *p->opt;
+#endif /* DEBUG */
+ struct opt *op;
+
+ while (dp = strchr(cp, '$')) {
+ char ch;
+ /*
+ * First copy up to the $
+ */
+ { int len = dp - cp;
+ if (BUFSPACE(ep, len)) {
+ strncpy(ep, cp, len);
+ ep += len;
+ } else {
+ plog(XLOG_ERROR, expand_error, *p->opt);
+ goto out;
+ }
+ }
+ cp = dp + 1;
+ ch = *cp++;
+ if (ch == '$') {
+ if (BUFSPACE(ep, 1)) {
+ *ep++ = '$';
+ } else {
+ plog(XLOG_ERROR, expand_error, *p->opt);
+ goto out;
+ }
+ } else if (ch == '{') {
+ /* Expansion... */
+ enum { E_All, E_Dir, E_File, E_Domain, E_Host } todo;
+ /*
+ * Find closing brace
+ */
+ char *br_p = strchr(cp, '}');
+ int len;
+ /*
+ * Check we found it
+ */
+ if (!br_p) {
+ /*
+ * Just give up
+ */
+ plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt);
+ goto out;
+ }
+ len = br_p - cp;
+ /*
+ * Figure out which part of the variable to grab.
+ */
+ if (*cp == '/') {
+ /*
+ * Just take the last component
+ */
+ todo = E_File;
+ cp++;
+ --len;
+ } else if (br_p[-1] == '/') {
+ /*
+ * Take all but the last component
+ */
+ todo = E_Dir;
+ --len;
+ } else if (*cp == '.') {
+ /*
+ * Take domain name
+ */
+ todo = E_Domain;
+ cp++;
+ --len;
+ } else if (br_p[-1] == '.') {
+ /*
+ * Take host name
+ */
+ todo = E_Host;
+ --len;
+ } else {
+ /*
+ * Take the whole lot
+ */
+ todo = E_All;
+ }
+ /*
+ * Truncate if too long. Since it won't
+ * match anyway it doesn't matter that
+ * it has been cut short.
+ */
+ if (len > NLEN)
+ len = NLEN;
+ /*
+ * Put the string into another buffer so
+ * we can do comparisons.
+ */
+ strncpy(nbuf, cp, len);
+ nbuf[len] = '\0';
+ /*
+ * Advance cp
+ */
+ cp = br_p + 1;
+ /*
+ * Search the option array
+ */
+ for (op = opt_fields; op->name; op++) {
+ /*
+ * Check for match
+ */
+ if (len == op->nlen && STREQ(op->name, nbuf)) {
+ char xbuf[NLEN+3];
+ char *val;
+ /*
+ * Found expansion. Copy
+ * the correct value field.
+ */
+ if (!(!op->sel_p == !sel_p)) {
+ /*
+ * Copy the string across unexpanded
+ */
+ sprintf(xbuf, "${%s%s%s}",
+ todo == E_File ? "/" :
+ todo == E_Domain ? "." : "",
+ nbuf,
+ todo == E_Dir ? "/" :
+ todo == E_Host ? "." : "");
+ val = xbuf;
+ /*
+ * Make sure expansion doesn't
+ * munge the value!
+ */
+ todo = E_All;
+ } else if (op->sel_p) {
+ val = *op->sel_p;
+ } else {
+ val = *op->optp;
+ }
+ if (val) {
+ /*
+ * Do expansion:
+ * ${/var} means take just the last part
+ * ${var/} means take all but the last part
+ * ${.var} means take all but first part
+ * ${var.} means take just the first part
+ * ${var} means take the whole lot
+ */
+ int vlen = strlen(val);
+ char *vptr = val;
+ switch (todo) {
+ case E_Dir:
+ vptr = strrchr(val, '/');
+ if (vptr)
+ vlen = vptr - val;
+ vptr = val;
+ break;
+ case E_File:
+ vptr = strrchr(val, '/');
+ if (vptr) {
+ vptr++;
+ vlen = strlen(vptr);
+ } else
+ vptr = val;
+ break;
+ case E_Domain:
+ vptr = strchr(val, '.');
+ if (vptr) {
+ vptr++;
+ vlen = strlen(vptr);
+ } else {
+ vptr = "";
+ vlen = 0;
+ }
+ break;
+ case E_Host:
+ vptr = strchr(val, '.');
+ if (vptr)
+ vlen = vptr - val;
+ vptr = val;
+ break;
+ case E_All:
+ break;
+ }
+#ifdef DEBUG
+ /*dlog("Expanding \"%s\" to \"%s\"", nbuf, val);*/
+#endif /* DEBUG */
+ if (BUFSPACE(ep, vlen)) {
+ strcpy(ep, vptr);
+ ep += vlen;
+ } else {
+ plog(XLOG_ERROR, expand_error, *p->opt);
+ goto out;
+ }
+ }
+ /*
+ * Done with this variable
+ */
+ break;
+ }
+ }
+ /*
+ * Check that the search was succesful
+ */
+ if (!op->name) {
+ /*
+ * If it wasn't then scan the
+ * environment for that name
+ * and use any value found
+ */
+ char *env = getenv(nbuf);
+ if (env) {
+ int vlen = strlen(env);
+
+ if (BUFSPACE(ep, vlen)) {
+ strcpy(ep, env);
+ ep += vlen;
+ } else {
+ plog(XLOG_ERROR, expand_error, *p->opt);
+ goto out;
+ }
+#ifdef DEBUG
+ Debug(D_STR)
+ plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
+#endif /* DEBUG */
+ } else {
+ plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
+ }
+ }
+ } else {
+ /*
+ * Error, error
+ */
+ plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt);
+ }
+ }
+
+out:
+ /*
+ * Handle common case - no expansion
+ */
+ if (cp == *p->opt) {
+ *p->opt = strdup(cp);
+ } else {
+ /*
+ * Finish off the expansion
+ */
+ if (BUFSPACE(ep, strlen(cp))) {
+ strcpy(ep, cp);
+ /*ep += strlen(ep);*/
+ } else {
+ plog(XLOG_ERROR, expand_error, *p->opt);
+ }
+
+ /*
+ * Save the exansion
+ */
+ *p->opt = strdup(expbuf);
+ }
+
+ normalize_slash(*p->opt);
+
+#ifdef DEBUG
+ Debug(D_STR) {
+ plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
+ plog(XLOG_DEBUG, "... is \"%s\"", *p->opt);
+ }
+#endif /* DEBUG */
+}
+
+/*
+ * Wrapper for expand_op
+ */
+static void expand_opts P((opt_apply*, int));
+static void expand_opts(p, sel_p)
+opt_apply *p;
+int sel_p;
+{
+ if (*p->opt) {
+ expand_op(p, sel_p);
+ } else if (p->val) {
+ /*
+ * Do double expansion, remembering
+ * to free the string from the first
+ * expansion...
+ */
+ char *s = *p->opt = expand_key(p->val);
+ expand_op(p, sel_p);
+ free(s);
+ }
+}
+
+/*
+ * Apply a function to a list of options
+ */
+static void apply_opts(op, ppp, b)
+void (*op)();
+opt_apply ppp[];
+int b;
+{
+ opt_apply *pp;
+ for (pp = ppp; pp->opt; pp++)
+ (*op)(pp, b);
+}
+
+/*
+ * Free the option table
+ */
+void free_opts(fo)
+am_opts *fo;
+{
+ /*
+ * Copy in the structure we are playing with
+ */
+ fs_static = *fo;
+
+ /*
+ * Free previously allocated memory
+ */
+ apply_opts(free_op, to_free, FALSE);
+}
+
+/*
+ * Expand lookup key
+ */
+char *expand_key(key)
+char *key;
+{
+ opt_apply oa;
+
+ oa.opt = &key; oa.val = 0;
+ expand_opts(&oa, TRUE);
+
+ return key;
+}
+
+/*
+ * Remove trailing /'s from a string
+ * unless the string is a single / (Steven Glassman)
+ */
+void deslashify P((char *s));
+void deslashify(s)
+char *s;
+{
+ if (s && *s) {
+ char *sl = s + strlen(s);
+ while (*--sl == '/' && sl > s)
+ *sl = '\0';
+ }
+}
+
+int eval_fs_opts(fo, opts, g_opts, path, key, map)
+am_opts *fo;
+char *opts, *g_opts, *path, *key, *map;
+{
+ int ok = TRUE;
+
+ free_opts(fo);
+
+ /*
+ * Clear out the option table
+ */
+ bzero((voidp) &fs_static, sizeof(fs_static));
+ bzero((voidp) vars, sizeof(vars));
+ bzero((voidp) fo, sizeof(*fo));
+
+ /*
+ * Set key, map & path before expansion
+ */
+ opt_key = key;
+ opt_map = map;
+ opt_path = path;
+
+ /*
+ * Expand global options
+ */
+ fs_static.fs_glob = expand_key(g_opts);
+
+ /*
+ * Expand local options
+ */
+ fs_static.fs_local = expand_key(opts);
+
+ /*
+ * Expand default (global) options
+ */
+ if (!eval_opts(fs_static.fs_glob, key))
+ ok = FALSE;
+
+ /*
+ * Expand local options
+ */
+ if (ok && !eval_opts(fs_static.fs_local, key))
+ ok = FALSE;
+
+ /*
+ * Normalise remote host name.
+ * 1. Expand variables
+ * 2. Normalize relative to host tables
+ * 3. Strip local domains from the remote host
+ * name before using it in other expansions.
+ * This makes mount point names and other things
+ * much shorter, while allowing cross domain
+ * sharing of mount maps.
+ */
+ apply_opts(expand_opts, rhost_expansion, FALSE);
+ if (ok && fs_static.opt_rhost && *fs_static.opt_rhost)
+ host_normalize(&fs_static.opt_rhost);
+
+ /*
+ * Macro expand the options.
+ * Do this regardless of whether we are accepting
+ * this mount - otherwise nasty things happen
+ * with memory allocation.
+ */
+ apply_opts(expand_opts, expansions, FALSE);
+
+ /*
+ * Strip trailing slashes from local pathname...
+ */
+ deslashify(fs_static.opt_fs);
+
+ /*
+ * ok... copy the data back out.
+ */
+ *fo = fs_static;
+
+ /*
+ * Clear defined options
+ */
+ opt_key = opt_map = opt_path = nullstr;
+
+ return ok;
+}
diff --git a/usr.sbin/amd/amd/pfs_ops.c b/usr.sbin/amd/amd/pfs_ops.c
new file mode 100644
index 0000000..314f62b
--- /dev/null
+++ b/usr.sbin/amd/amd/pfs_ops.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)pfs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: pfs_ops.c,v 5.2.2.1 1992/02/09 15:08:56 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_PFS
+
+/*
+ * Program file system
+ */
+
+/*
+ * Execute needs a mount and unmount command.
+ */
+static char *pfs_match(fo)
+am_opts *fo;
+{
+ char *prog;
+ if (!fo->opt_mount || !fo->opt_unmount) {
+ plog(XLOG_USER, "program: no mount/unmount specified");
+ return 0;
+ }
+ prog = strchr(fo->opt_mount, ' ');
+ return strdup(prog ? prog+1 : fo->opt_mount);
+}
+
+static int pfs_init(mf)
+mntfs *mf;
+{
+ /*
+ * Save unmount command
+ */
+ if (mf->mf_refc == 1) {
+ mf->mf_private = (voidp) strdup(mf->mf_fo->opt_unmount);
+ mf->mf_prfree = (void (*) ()) free;
+ }
+ return 0;
+}
+
+static int pfs_exec(info)
+char *info;
+{
+ char **xivec;
+ int error;
+ /*
+ * Split copy of command info string
+ */
+ info = strdup(info);
+ if (info == 0)
+ return ENOBUFS;
+ xivec = strsplit(info, ' ', '\'');
+ /*
+ * Put stdout to stderr
+ */
+ (void) fclose(stdout);
+ (void) dup(fileno(logfp));
+ if (fileno(logfp) != fileno(stderr)) {
+ (void) fclose(stderr);
+ (void) dup(fileno(logfp));
+ }
+ /*
+ * Try the exec
+ */
+#ifdef DEBUG
+ Debug(D_FULL) {
+ char **cp = xivec;
+ plog(XLOG_DEBUG, "executing (un)mount command...");
+ while (*cp) {
+ plog(XLOG_DEBUG, "arg[%d] = '%s'", cp-xivec, *cp);
+ cp++;
+ }
+ }
+#endif /* DEBUG */
+ if (xivec[0] == 0 || xivec[1] == 0) {
+ errno = EINVAL;
+ plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
+ } else {
+ (void) execv(xivec[0], xivec+1);
+ }
+ /*
+ * Save error number
+ */
+ error = errno;
+ plog(XLOG_ERROR, "exec failed: %m");
+
+ /*
+ * Free allocate memory
+ */
+ free((voidp) info);
+ free((voidp) xivec);
+ /*
+ * Return error
+ */
+ return error;
+}
+
+static int pfs_fmount(mf)
+mntfs *mf;
+{
+ return pfs_exec(mf->mf_fo->opt_mount);
+}
+
+static int pfs_fumount(mf)
+mntfs *mf;
+{
+ return pfs_exec((char *) mf->mf_private);
+}
+
+/*
+ * Ops structure
+ */
+am_ops pfs_ops = {
+ "program",
+ pfs_match,
+ pfs_init,
+ auto_fmount,
+ pfs_fmount,
+ auto_fumount,
+ pfs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* pfs_readlink */
+ 0, /* pfs_mounted */
+ 0, /* pfs_umounted */
+ find_afs_srvr,
+ FS_BACKGROUND|FS_AMQINFO
+};
+
+#endif /* HAS_PFS */
diff --git a/usr.sbin/amd/amd/restart.c b/usr.sbin/amd/amd/restart.c
new file mode 100644
index 0000000..52a9c87
--- /dev/null
+++ b/usr.sbin/amd/amd/restart.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * $Id: restart.c,v 5.2.2.1 1992/02/09 15:08:59 jsp beta $
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)restart.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "am.h"
+
+/*
+ * Handle an amd restart.
+ *
+ * Scan through the mount list finding all "interesting" mount points.
+ * Next hack up partial data structures and add the mounted file
+ * system to the list of known filesystems. This will leave a
+ * dangling reference to that filesystems, so when the filesystem is
+ * finally inherited, an extra "free" must be done on it.
+ *
+ * This module relies on internal details of other components. If
+ * you change something else make *sure* restart() still works.
+ */
+void restart()
+{
+ /*
+ * Read the existing mount table
+ */
+ mntlist *ml, *mlp;
+
+ /*
+ * For each entry, find nfs, ufs or auto mounts
+ * and create a partial am_node to represent it.
+ */
+ for (mlp = ml = read_mtab("restart"); mlp; mlp = mlp->mnext) {
+ struct mntent *me = mlp->mnt;
+ am_ops *fs_ops = 0;
+ if (STREQ(me->mnt_type, MTAB_TYPE_UFS)) {
+ /*
+ * UFS entry
+ */
+ fs_ops = &ufs_ops;
+ } else if (STREQ(me->mnt_type, MTAB_TYPE_NFS)) {
+ /*
+ * NFS entry, or possibly an Amd entry...
+ */
+ int au_pid;
+ char *colon = strchr(me->mnt_fsname, ':');
+ if (colon && sscanf(colon, ":(pid%d)", &au_pid) == 1) {
+ plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
+ fs_ops = &sfs_ops;
+ } else {
+ fs_ops = &nfs_ops;
+ }
+#ifdef MTAB_TYPE_MFS
+ } else if (STREQ(me->mnt_type, MTAB_TYPE_MFS)) {
+ /*
+ * MFS entry. Fake with a symlink.
+ */
+ fs_ops = &sfs_ops;
+#endif /* MTAB_TYPE_MFS */
+ } else {
+ /*
+ * Catch everything else with symlinks to
+ * avoid recursive mounts. This is debatable...
+ */
+ fs_ops = &sfs_ops;
+ }
+
+ /*
+ * If we found something to do
+ */
+ if (fs_ops) {
+ mntfs *mf;
+ am_opts mo;
+ char *cp;
+ cp = strchr(me->mnt_fsname, ':');
+ /*
+ * Partially fake up an opts structure
+ */
+ mo.opt_rhost = 0;
+ mo.opt_rfs = 0;
+ if (cp) {
+ *cp = '\0';
+ mo.opt_rhost = strdup(me->mnt_fsname);
+ mo.opt_rfs = strdup(cp+1);
+ *cp = ':';
+ } else if (fs_ops->ffserver == find_nfs_srvr) {
+ /*
+ * Prototype 4.4 BSD used to end up here -
+ * might as well keep the workaround for now
+ */
+ plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
+ mo.opt_rhost = strdup(me->mnt_fsname);
+ mo.opt_rfs = strdup("/");
+ me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
+ }
+ mo.opt_fs = me->mnt_dir;
+ mo.opt_opts = me->mnt_opts;
+
+ /*
+ * Make a new mounted filesystem
+ */
+ mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
+ me->mnt_fsname, "", me->mnt_opts, "");
+ if (mf->mf_refc == 1) {
+ mf->mf_flags |= MFF_RESTART|MFF_MOUNTED;
+ mf->mf_error = 0; /* Already mounted correctly */
+ mf->mf_fo = 0;
+ /*
+ * If the restarted type is a link then
+ * don't time out.
+ */
+ if (fs_ops == &sfs_ops || fs_ops == &ufs_ops)
+ mf->mf_flags |= MFF_RSTKEEP;
+ if (fs_ops->fs_init) {
+ /*
+ * Don't care whether this worked since
+ * it is checked again when the fs is
+ * inherited.
+ */
+ (void) (*fs_ops->fs_init)(mf);
+ }
+
+ plog(XLOG_INFO, "%s restarted fstype %s on %s",
+ me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
+ } else {
+ /* Something strange happened - two mounts at the same place! */
+ free_mntfs(mf);
+ }
+ /*
+ * Clean up mo
+ */
+ if (mo.opt_rhost)
+ free(mo.opt_rhost);
+ if (mo.opt_rfs)
+ free(mo.opt_rfs);
+ }
+ }
+
+ /*
+ * Free the mount list
+ */
+ free_mntlist(ml);
+}
diff --git a/usr.sbin/amd/amd/rpc_fwd.c b/usr.sbin/amd/amd/rpc_fwd.c
new file mode 100644
index 0000000..aaf1e0a
--- /dev/null
+++ b/usr.sbin/amd/amd/rpc_fwd.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)rpc_fwd.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: rpc_fwd.c,v 5.2.2.1 1992/02/09 15:09:01 jsp beta $
+ *
+ */
+
+/*
+ * RPC packet forwarding
+ */
+
+#include "am.h"
+#include <sys/ioctl.h>
+#ifndef F_SETFL
+#include <fcntl.h>
+#endif /* F_SETFL */
+#ifndef FNDELAY
+#include <sys/file.h>
+#endif /* FNDELAY */
+
+/*
+ * Note that the ID field in the external packet is only
+ * ever treated as a 32 bit opaque data object, so there
+ * is no need to convert to and from network byte ordering.
+ */
+
+/*
+ * Each pending reply has an rpc_forward structure
+ * associated with it. These have a 15 second lifespan.
+ * If a new structure is required, then an expired
+ * one will be re-allocated if available, otherwise a fresh
+ * one is allocated. Whenever a reply is received the
+ * structure is discarded.
+ */
+typedef struct rpc_forward rpc_forward;
+struct rpc_forward {
+ qelem rf_q; /* Linked list */
+ time_t rf_ttl; /* Time to live */
+ u_int rf_xid; /* Packet id */
+ u_int rf_oldid; /* Original packet id */
+ fwd_fun rf_fwd; /* Forwarding function */
+ voidp rf_ptr;
+ struct sockaddr_in rf_sin;
+};
+
+/*
+ * Head of list of pending replies
+ */
+extern qelem rpc_head;
+qelem rpc_head = { &rpc_head, &rpc_head };
+
+static u_int xid;
+#define XID_ALLOC() (xid++)
+
+#define MAX_PACKET_SIZE 8192 /* Maximum UDP packet size */
+
+int fwd_sock;
+
+/*
+ * Allocate a rely structure
+ */
+static rpc_forward *fwd_alloc()
+{
+ time_t now = clocktime();
+ rpc_forward *p = 0, *p2;
+
+#ifdef DEBUG
+ /*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
+#endif /* DEBUG */
+ /*
+ * First search for an existing expired one.
+ */
+ ITER(p2, rpc_forward, &rpc_head) {
+ if (p2->rf_ttl <= now) {
+ p = p2;
+ break;
+ }
+ }
+
+ /*
+ * If one couldn't be found then allocate
+ * a new structure and link it at the
+ * head of the list.
+ */
+ if (p) {
+ /*
+ * Call forwarding function to say that
+ * this message was junked.
+ */
+#ifdef DEBUG
+ dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
+#endif /* DEBUG */
+ if (p->rf_fwd)
+ (*p->rf_fwd)(0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
+ rem_que(&p->rf_q);
+ } else {
+ p = ALLOC(rpc_forward);
+ }
+ ins_que(&p->rf_q, &rpc_head);
+
+ /*
+ * Set the time to live field
+ * Timeout in 43 seconds
+ */
+ p->rf_ttl = now + 43;
+
+#ifdef DEBUG
+ /*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
+#endif /* DEBUG */
+ return p;
+}
+
+/*
+ * Free an allocated reply structure.
+ * First unlink it from the list, then
+ * discard it.
+ */
+static void fwd_free(p)
+rpc_forward *p;
+{
+#ifdef DEBUG
+ /*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
+#endif /* DEBUG */
+ rem_que(&p->rf_q);
+#ifdef DEBUG
+ /*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
+#endif /* DEBUG */
+ free((voidp) p);
+}
+
+/*
+ * Initialise the RPC forwarder
+ */
+int fwd_init()
+{
+ int on = 1;
+
+ /*
+ * Create ping socket
+ */
+ fwd_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fwd_sock < 0) {
+ plog(XLOG_ERROR, "Unable to create RPC forwarding socket: %m");
+ return errno;
+ }
+
+ /*
+ * Some things we talk to require a priv port - so make one here
+ */
+ if (bind_resv_port(fwd_sock, (unsigned short *) 0) < 0)
+ plog(XLOG_ERROR, "can't bind privileged port");
+
+ if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0 &&
+ ioctl(fwd_sock, FIONBIO, &on) < 0) {
+ plog(XLOG_ERROR, "Can't set non-block on forwarding socket: %m");
+ return errno;
+ }
+
+ return 0;
+}
+
+/*
+ * Locate a packet in the forwarding list
+ */
+static rpc_forward *fwd_locate(id)
+u_int id;
+{
+ rpc_forward *p;
+
+ ITER(p, rpc_forward, &rpc_head) {
+ if (p->rf_xid == id)
+ return p;
+ }
+
+ return 0;
+}
+
+/*
+ * This is called to forward a packet to another
+ * RPC server. The message id is changed and noted
+ * so that when a reply appears we can tie it up
+ * correctly. Just matching the reply's source address
+ * would not work because it might come from a
+ * different address.
+ */
+int fwd_packet(type_id, pkt, len, fwdto, replyto, i, cb)
+int type_id;
+voidp pkt;
+int len;
+struct sockaddr_in *fwdto, *replyto;
+voidp i;
+fwd_fun cb;
+{
+ rpc_forward *p;
+ u_int *pkt_int;
+ int error;
+
+ if ((int)amd_state >= (int)Finishing)
+ return ENOENT;
+
+ /*
+ * See if the type_id is fully specified.
+ * If so, then discard any old entries
+ * for this id.
+ * Otherwise make sure the type_id is
+ * fully qualified by allocating an id here.
+ */
+#ifdef DEBUG
+ switch (type_id & RPC_XID_MASK) {
+ case RPC_XID_PORTMAP: dlog("Sending PORTMAP request"); break;
+ case RPC_XID_MOUNTD: dlog("Sending MOUNTD request %#x", type_id); break;
+ case RPC_XID_NFSPING: dlog("Sending NFS ping"); break;
+ default: dlog("UNKNOWN RPC XID"); break;
+ }
+#endif /* DEBUG */
+
+ if (type_id & ~RPC_XID_MASK) {
+#ifdef DEBUG
+ /*dlog("Fully qualified rpc type provided");*/
+#endif /* DEBUG */
+ p = fwd_locate(type_id);
+ if (p) {
+#ifdef DEBUG
+ dlog("Discarding earlier rpc fwd handle");
+#endif /* DEBUG */
+ fwd_free(p);
+ }
+ } else {
+#ifdef DEBUG
+ dlog("Allocating a new xid...");
+#endif /* DEBUG */
+ type_id = MK_RPC_XID(type_id, XID_ALLOC());
+ }
+
+ p = fwd_alloc();
+ if (!p)
+ return ENOBUFS;
+
+ error = 0;
+
+ pkt_int = (u_int *) pkt;
+
+ /*
+ * Get the original packet id
+ */
+ p->rf_oldid = *pkt_int;
+
+ /*
+ * Replace with newly allocated id
+ */
+ p->rf_xid = *pkt_int = type_id;
+
+ /*
+ * The sendto may fail if, for example, the route
+ * to a remote host is lost because an intermediate
+ * gateway has gone down. Important to fill in the
+ * rest of "p" otherwise nasty things happen later...
+ */
+#ifdef DEBUG
+ { char dq[20];
+ dlog("Sending packet id %#x to %s.%d", p->rf_xid, inet_dquad(dq, fwdto->sin_addr.s_addr), ntohs(fwdto->sin_port));
+ }
+#endif /* DEBUG */
+ if (sendto(fwd_sock, (char *) pkt, len, 0,
+ (struct sockaddr *) fwdto, sizeof(*fwdto)) < 0)
+ error = errno;
+
+ /*
+ * Save callback function and return address
+ */
+ p->rf_fwd = cb;
+ if (replyto)
+ p->rf_sin = *replyto;
+ else
+ bzero((voidp) &p->rf_sin, sizeof(p->rf_sin));
+ p->rf_ptr = i;
+
+ return error;
+}
+
+/*
+ * Called when some data arrives on the forwarding socket
+ */
+void fwd_reply()
+{
+ int len;
+#ifdef DYNAMIC_BUFFERS
+ voidp pkt;
+#else
+ u_int pkt[MAX_PACKET_SIZE/sizeof(u_int)+1];
+#endif /* DYNAMIC_BUFFERS */
+ u_int *pkt_int;
+ int rc;
+ rpc_forward *p;
+ struct sockaddr_in src_addr;
+ int src_addr_len;
+
+ /*
+ * Determine the length of the packet
+ */
+#ifdef DYNAMIC_BUFFERS
+ if (ioctl(fwd_sock, FIONREAD, &len) < 0) {
+ plog(XLOG_ERROR, "Error reading packet size: %m");
+ return;
+ }
+
+ /*
+ * Allocate a buffer
+ */
+ pkt = (voidp) malloc((unsigned) len);
+ if (!pkt) {
+ plog(XLOG_ERROR, "Out of buffers in fwd_reply");
+ return;
+ }
+#else
+ len = MAX_PACKET_SIZE;
+#endif /* DYNAMIC_BUFFERS */
+
+ /*
+ * Read the packet and check for validity
+ */
+again:
+ src_addr_len = sizeof(src_addr);
+ rc = recvfrom(fwd_sock, (char *) pkt, len, 0,
+ (struct sockaddr *) &src_addr, &src_addr_len);
+ if (rc < 0 || src_addr_len != sizeof(src_addr) ||
+ src_addr.sin_family != AF_INET) {
+ if (rc < 0 && errno == EINTR)
+ goto again;
+ plog(XLOG_ERROR, "Error reading RPC reply: %m");
+ goto out;
+ }
+
+#ifdef DYNAMIC_BUFFERS
+ if (rc != len) {
+ plog(XLOG_ERROR, "Short read in fwd_reply");
+ goto out;
+ }
+#endif /* DYNAMIC_BUFFERS */
+
+ /*
+ * Do no more work if finishing soon
+ */
+ if ((int)amd_state >= (int)Finishing)
+ goto out;
+
+ /*
+ * Find packet reference
+ */
+ pkt_int = (u_int *) pkt;
+
+#ifdef DEBUG
+ switch (*pkt_int & RPC_XID_MASK) {
+ case RPC_XID_PORTMAP: dlog("Receiving PORTMAP reply"); break;
+ case RPC_XID_MOUNTD: dlog("Receiving MOUNTD reply %#x", *pkt_int); break;
+ case RPC_XID_NFSPING: dlog("Receiving NFS ping %#x", *pkt_int); break;
+ default: dlog("UNKNOWN RPC XID"); break;
+ }
+#endif /* DEBUG */
+
+ p = fwd_locate(*pkt_int);
+ if (!p) {
+#ifdef DEBUG
+ dlog("Can't forward reply id %#x", *pkt_int);
+#endif /* DEBUG */
+ goto out;
+ }
+
+ if (p->rf_fwd) {
+ /*
+ * Put the original message id back
+ * into the packet.
+ */
+ *pkt_int = p->rf_oldid;
+
+ /*
+ * Call forwarding function
+ */
+ (*p->rf_fwd)((voidp) pkt, rc, &src_addr, &p->rf_sin, p->rf_ptr, TRUE);
+ }
+
+ /*
+ * Free forwarding info
+ */
+ fwd_free(p);
+
+out:;
+#ifdef DYNAMIC_BUFFERS
+ /*
+ * Free the packet
+ */
+ free((voidp) pkt);
+#endif /* DYNAMIC_BUFFERS */
+}
diff --git a/usr.sbin/amd/amd/sched.c b/usr.sbin/amd/amd/sched.c
new file mode 100644
index 0000000..cd12e3b
--- /dev/null
+++ b/usr.sbin/amd/amd/sched.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)sched.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: sched.c,v 5.2.2.1 1992/02/09 15:09:02 jsp beta $
+ *
+ */
+
+/*
+ * Process scheduler
+ */
+
+#include "am.h"
+#include <sys/signal.h>
+#include WAIT
+#include <setjmp.h>
+extern jmp_buf select_intr;
+extern int select_intr_valid;
+
+typedef struct pjob pjob;
+struct pjob {
+ qelem hdr; /* Linked list */
+ int pid; /* Process ID of job */
+ cb_fun cb_fun; /* Callback function */
+ voidp cb_closure; /* Closure for callback */
+ union wait w; /* Status filled in by sigchld */
+ voidp wchan; /* Wait channel */
+};
+
+extern qelem proc_list_head;
+qelem proc_list_head = { &proc_list_head, &proc_list_head };
+extern qelem proc_wait_list;
+qelem proc_wait_list = { &proc_wait_list, &proc_wait_list };
+
+int task_notify_todo;
+
+void ins_que(elem, pred)
+qelem *elem, *pred;
+{
+ qelem *p = pred->q_forw;
+ elem->q_back = pred;
+ elem->q_forw = p;
+ pred->q_forw = elem;
+ p->q_back = elem;
+}
+
+void rem_que(elem)
+qelem *elem;
+{
+ qelem *p = elem->q_forw;
+ qelem *p2 = elem->q_back;
+ p2->q_forw = p;
+ p->q_back = p2;
+}
+
+static pjob *sched_job(cf, ca)
+cb_fun cf;
+voidp ca;
+{
+ pjob *p = ALLOC(pjob);
+
+ p->cb_fun = cf;
+ p->cb_closure = ca;
+
+ /*
+ * Now place on wait queue
+ */
+ ins_que(&p->hdr, &proc_wait_list);
+
+ return p;
+}
+
+void run_task(tf, ta, cf, ca)
+task_fun tf;
+voidp ta;
+cb_fun cf;
+voidp ca;
+{
+ pjob *p = sched_job(cf, ca);
+ int mask;
+
+ p->wchan = (voidp) p;
+
+ mask = sigblock(sigmask(SIGCHLD));
+
+ if (p->pid = background()) {
+ sigsetmask(mask);
+ return;
+ }
+
+ exit((*tf)(ta));
+ /* firewall... */
+ abort();
+}
+
+/*
+ * Schedule a task to be run when woken up
+ */
+void sched_task(cf, ca, wchan)
+cb_fun cf;
+voidp ca;
+voidp wchan;
+{
+ /*
+ * Allocate a new task
+ */
+ pjob *p = sched_job(cf, ca);
+#ifdef DEBUG_SLEEP
+ dlog("SLEEP on %#x", wchan);
+#endif
+ p->wchan = wchan;
+ p->pid = 0;
+ bzero((voidp) &p->w, sizeof(p->w));
+}
+
+static void wakeupjob(p)
+pjob *p;
+{
+ rem_que(&p->hdr);
+ ins_que(&p->hdr, &proc_list_head);
+ task_notify_todo++;
+}
+
+void wakeup(wchan)
+voidp wchan;
+{
+ pjob *p, *p2;
+#ifdef DEBUG_SLEEP
+ int done = 0;
+#endif
+ if (!foreground)
+ return;
+
+#ifdef DEBUG_SLEEP
+ /*dlog("wakeup(%#x)", wchan);*/
+#endif
+ /*
+ * Can't user ITER() here because
+ * wakeupjob() juggles the list.
+ */
+ for (p = FIRST(pjob, &proc_wait_list);
+ p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
+ p = p2) {
+ if (p->wchan == wchan) {
+#ifdef DEBUG_SLEEP
+ done = 1;
+#endif
+ wakeupjob(p);
+ }
+ }
+
+#ifdef DEBUG_SLEEP
+ if (!done)
+ dlog("Nothing SLEEPing on %#x", wchan);
+#endif
+}
+
+void wakeup_task(rc, term, cl)
+int rc;
+int term;
+voidp cl;
+{
+ wakeup(cl);
+}
+
+/*ARGSUSED*/
+
+void sigchld(sig)
+int sig;
+{
+ union wait w;
+ int pid;
+
+#ifdef SYS5_SIGNALS
+ if ((pid = wait(&w)) > 0) {
+#else
+ while ((pid = wait3((int *) &w, WNOHANG, (struct rusage *) 0)) > 0) {
+#endif /* SYS5_SIGNALS */
+ pjob *p, *p2;
+
+ if (WIFSIGNALED(w))
+ plog(XLOG_ERROR, "Process %d exited with signal %d",
+ pid, w.w_termsig);
+#ifdef DEBUG
+ else
+ dlog("Process %d exited with status %d",
+ pid, w.w_retcode);
+#endif /* DEBUG */
+
+ for (p = FIRST(pjob, &proc_wait_list);
+ p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
+ p = p2) {
+ if (p->pid == pid) {
+ p->w = w;
+ wakeupjob(p);
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ if (p) ; else dlog("can't locate task block for pid %d", pid);
+#endif /* DEBUG */
+ }
+
+#ifdef SYS5_SIGNALS
+ signal(sig, sigchld);
+#endif /* SYS5_SIGNALS */
+ if (select_intr_valid)
+ longjmp(select_intr, sig);
+}
+
+/*
+ * Run any pending tasks.
+ * This must be called with SIGCHLD disabled
+ */
+void do_task_notify(P_void)
+{
+ /*
+ * Keep taking the first item off the list and processing it.
+ *
+ * Done this way because the the callback can, quite reasonably,
+ * queue a new task, so no local reference into the list can be
+ * held here.
+ */
+ while (FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
+ pjob *p = FIRST(pjob, &proc_list_head);
+ rem_que(&p->hdr);
+ /*
+ * This job has completed
+ */
+ --task_notify_todo;
+
+ /*
+ * Do callback if it exists
+ */
+ if (p->cb_fun)
+ (*p->cb_fun)(p->w.w_retcode,
+ p->w.w_termsig, p->cb_closure);
+
+ free((voidp) p);
+ }
+}
+
+#ifdef HAS_SVR3_SIGNALS
+/*
+ * 4.2 signal library based on svr3 (4.1+ bsd) interface
+ * From Stephen C. Pope <scp@acl.lanl.gov).
+ */
+
+static int current_mask = 0;
+
+int sigblock(mask)
+int mask;
+{
+ int sig;
+ int m;
+ int oldmask;
+
+ oldmask = current_mask;
+ for ( sig = 1, m = 1; sig <= MAXSIG; sig++, m <<= 1 ) {
+ if (mask & m) {
+ sighold(sig);
+ current_mask |= m;
+ }
+ }
+ return oldmask;
+}
+
+int sigsetmask(mask)
+int mask;
+{
+ int sig;
+ int m;
+ int oldmask;
+
+ oldmask = current_mask;
+ for ( sig = 1, m = 1; sig <= MAXSIG; sig++, m <<= 1 ) {
+ if (mask & m) {
+ sighold(sig);
+ current_mask |= m;
+ }
+ else {
+ sigrelse(sig);
+ current_mask &= ~m;
+ }
+ }
+ return oldmask;
+}
+
+#endif /* HAS_SVR3_SIGNALS */
diff --git a/usr.sbin/amd/amd/sfs_ops.c b/usr.sbin/amd/amd/sfs_ops.c
new file mode 100644
index 0000000..c1b1eba
--- /dev/null
+++ b/usr.sbin/amd/amd/sfs_ops.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)sfs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: sfs_ops.c,v 5.2.2.1 1992/02/09 15:09:04 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#if defined(HAS_SFS) || defined(HAS_SFSX)
+#define NEED_SFS_MATCH
+#define NEED_SFS_UMOUNT
+#endif
+
+/*
+ * Symbol-link file system
+ */
+
+#ifdef HAS_SFSX
+#include <sys/stat.h>
+#endif
+
+#ifdef NEED_SFS_MATCH
+/*
+ * SFS needs a link.
+ */
+static char *sfs_match(fo)
+am_opts *fo;
+{
+ if (!fo->opt_fs) {
+ plog(XLOG_USER, "link: no fs specified");
+ return 0;
+ }
+
+ /*
+ * Bug report (14/12/89) from Jay Plett <jay@princeton.edu>
+ * If an automount point has the same name as an existing
+ * link type mount Amd hits a race condition and either hangs
+ * or causes a symlink loop.
+ *
+ * If fs begins with a '/' change the opt_fs & opt_sublink
+ * fields so that the fs option doesn't end up pointing at
+ * an existing symlink.
+ *
+ * If sublink is nil then set sublink to fs
+ * else set sublink to fs / sublink
+ *
+ * Finally set fs to ".".
+ */
+ if (*fo->opt_fs == '/') {
+ char *fullpath;
+ char *link = fo->opt_sublink;
+ if (link) {
+ if (*link == '/')
+ fullpath = strdup(link);
+ else
+ fullpath = str3cat((char *)0, fo->opt_fs, "/", link);
+ } else {
+ fullpath = strdup(fo->opt_fs);
+ }
+
+ if (fo->opt_sublink)
+ free(fo->opt_sublink);
+ fo->opt_sublink = fullpath;
+ fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, "");
+ }
+
+ return strdup(fo->opt_fs);
+}
+#endif
+
+#ifdef HAS_SFSX
+/*ARGUSED*/
+static int sfsx_mount P((am_node *mp));
+static int sfsx_mount(mp)
+am_node *mp;
+{
+ /*
+ * Check for existence of target.
+ */
+ struct stat stb;
+ char *ln;
+
+ if (mp->am_link)
+ ln = mp->am_link;
+ else /* should never occur */
+ ln = mp->am_mnt->mf_mount;
+
+ /*
+ * Use lstat, not stat, since we don't
+ * want to know if the ultimate target of
+ * a symlink chain exists, just the first.
+ */
+ if (lstat(ln, &stb) < 0)
+ return errno;
+
+ return 0;
+}
+#endif
+
+#ifdef HAS_SFS
+/*ARGUSED*/
+static int sfs_fmount(mf)
+mntfs *mf;
+{
+ /*
+ * Wow - this is hard to implement!
+ */
+
+ return 0;
+}
+#endif
+
+#ifdef NEED_SFS_UMOUNT
+/*ARGUSED*/
+static int sfs_fumount(mf)
+mntfs *mf;
+{
+ return 0;
+}
+#endif
+
+/*
+ * Ops structures
+ */
+#ifdef HAS_SFS
+am_ops sfs_ops = {
+ "link",
+ sfs_match,
+ 0, /* sfs_init */
+ auto_fmount,
+ sfs_fmount,
+ auto_fumount,
+ sfs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* sfs_readlink */
+ 0, /* sfs_mounted */
+ 0, /* sfs_umounted */
+ find_afs_srvr,
+#ifdef FLUSH_KERNEL_NAME_CACHE
+ FS_UBACKGROUND
+#else /* FLUSH_KERNEL_NAME_CACHE */
+ 0
+#endif /* FLUSH_KERNEL_NAME_CACHE */
+};
+
+#endif /* HAS_SFS */
+
+#ifdef HAS_SFSX
+struct am_ops sfsx_ops = {
+ "linkx",
+ sfs_match,
+ 0, /* sfsx_init */
+ sfsx_mount,
+ 0,
+ auto_fumount,
+ sfs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* sfsx_readlink */
+ 0, /* sfsx_mounted */
+ 0, /* sfsx_umounted */
+ find_afs_srvr,
+#ifdef FLUSH_KERNEL_NAME_CACHE
+ FS_BACKGROUND
+#else /* FLUSH_KERNEL_NAME_CACHE */
+ FS_MBACKGROUND
+#endif /* FLUSH_KERNEL_NAME_CACHE */
+};
+
+#endif /* HAS_SFSX */
diff --git a/usr.sbin/amd/amd/srvr_afs.c b/usr.sbin/amd/amd/srvr_afs.c
new file mode 100644
index 0000000..0440777
--- /dev/null
+++ b/usr.sbin/amd/amd/srvr_afs.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)srvr_afs.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: srvr_afs.c,v 5.2.2.1 1992/02/09 15:09:05 jsp beta $
+ *
+ */
+
+/*
+ * Automount FS server ("localhost") modeling
+ */
+
+#include "am.h"
+
+extern qelem afs_srvr_list;
+qelem afs_srvr_list = { &afs_srvr_list, &afs_srvr_list };
+
+static fserver *localhost;
+
+/*
+ * Find an nfs server for the local host
+ */
+fserver *find_afs_srvr P((mntfs *));
+fserver *find_afs_srvr(mf)
+mntfs *mf;
+{
+ fserver *fs = localhost;
+
+ if (!fs) {
+ fs = ALLOC(fserver);
+ fs->fs_refc = 0;
+ fs->fs_host = strdup("localhost");
+ fs->fs_ip = 0;
+ fs->fs_cid = 0;
+ fs->fs_pinger = 0;
+ fs->fs_flags = FSF_VALID;
+ fs->fs_type = "local";
+ fs->fs_private = 0;
+ fs->fs_prfree = 0;
+
+ ins_que(&fs->fs_q, &afs_srvr_list);
+
+ srvrlog(fs, "starts up");
+
+ localhost = fs;
+ }
+
+ fs->fs_refc++;
+
+ return fs;
+}
+
+/*------------------------------------------------------------------*/
+ /* Generic routines follow */
+
+/*
+ * Wakeup anything waiting for this server
+ */
+void wakeup_srvr P((fserver *fs));
+void wakeup_srvr(fs)
+fserver *fs;
+{
+ fs->fs_flags &= ~FSF_WANT;
+ wakeup((voidp) fs);
+}
+
+/*
+ * Called when final ttl of server has expired
+ */
+static void timeout_srvr P((fserver *fs));
+static void timeout_srvr(fs)
+fserver *fs;
+{
+ /*
+ * If the reference count is still zero then
+ * we are free to remove this node
+ */
+ if (fs->fs_refc == 0) {
+#ifdef DEBUG
+ dlog("Deleting file server %s", fs->fs_host);
+#endif /* DEBUG */
+ if (fs->fs_flags & FSF_WANT)
+ wakeup_srvr(fs);
+
+ /*
+ * Remove from queue.
+ */
+ rem_que(&fs->fs_q);
+ /*
+ * (Possibly) call the private free routine.
+ */
+ if (fs->fs_private && fs->fs_prfree)
+ (*fs->fs_prfree)(fs->fs_private);
+
+ /*
+ * Free the net address
+ */
+ if (fs->fs_ip)
+ free((voidp) fs->fs_ip);
+
+ /*
+ * Free the host name.
+ */
+ free((voidp) fs->fs_host);
+
+ /*
+ * Discard the fserver object.
+ */
+ free((voidp) fs);
+ }
+}
+
+/*
+ * Free a file server
+ */
+void free_srvr P((fserver *fs));
+void free_srvr(fs)
+fserver *fs;
+{
+ if (--fs->fs_refc == 0) {
+ /*
+ * The reference count is now zero,
+ * so arrange for this node to be
+ * removed in AM_TTL seconds if no
+ * other mntfs is referencing it.
+ */
+ int ttl = (fs->fs_flags & (FSF_DOWN|FSF_ERROR)) ? 19 : AM_TTL;
+#ifdef DEBUG
+ dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
+#endif /* DEBUG */
+ if (fs->fs_cid) {
+ untimeout(fs->fs_cid);
+ /*
+ * Turn off pinging - XXX
+ */
+ fs->fs_flags &= ~FSF_PINGING;
+ }
+ /*
+ * Keep structure lying around for a while
+ */
+ fs->fs_cid = timeout(ttl, timeout_srvr, (voidp) fs);
+ /*
+ * Mark the fileserver down and invalid again
+ */
+ fs->fs_flags &= ~FSF_VALID;
+ fs->fs_flags |= FSF_DOWN;
+ }
+}
+
+/*
+ * Make a duplicate fserver reference
+ */
+fserver *dup_srvr P((fserver *fs));
+fserver *dup_srvr(fs)
+fserver *fs;
+{
+ fs->fs_refc++;
+ return fs;
+}
+
+/*
+ * Log state change
+ */
+void srvrlog P((fserver *fs, char *state));
+void srvrlog(fs, state)
+fserver *fs;
+char *state;
+{
+ plog(XLOG_INFO, "file server %s type %s %s", fs->fs_host, fs->fs_type, state);
+}
diff --git a/usr.sbin/amd/amd/srvr_nfs.c b/usr.sbin/amd/amd/srvr_nfs.c
new file mode 100644
index 0000000..4987c95
--- /dev/null
+++ b/usr.sbin/amd/amd/srvr_nfs.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)srvr_nfs.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: srvr_nfs.c,v 5.2.2.1 1992/02/09 15:09:06 jsp beta $
+ *
+ */
+
+/*
+ * NFS server modeling
+ */
+
+#include "am.h"
+#include <netdb.h>
+#include <rpc/pmap_prot.h>
+#include "mount.h"
+
+extern qelem nfs_srvr_list;
+qelem nfs_srvr_list = { &nfs_srvr_list, &nfs_srvr_list };
+
+typedef struct nfs_private {
+ u_short np_mountd; /* Mount daemon port number */
+ char np_mountd_inval; /* Port *may* be invalid */
+ int np_ping; /* Number of failed ping attempts */
+ time_t np_ttl; /* Time when server is thought dead */
+ int np_xid; /* RPC transaction id for pings */
+ int np_error; /* Error during portmap request */
+} nfs_private;
+
+static int np_xid; /* For NFS pings */
+#define NPXID_ALLOC() (++np_xid)
+/*#define NPXID_ALLOC() ((++np_xid&0x0fffffff) == 0 ? npxid_gc() : np_xid)*/
+
+/*
+ * Number of pings allowed to fail before host is declared down
+ * - three-fifths of the allowed mount time...
+#define MAX_ALLOWED_PINGS ((((ALLOWED_MOUNT_TIME + 5 * AM_PINGER - 1) * 3) / 5) / AM_PINGER)
+ */
+#define MAX_ALLOWED_PINGS (3 + /* for luck ... */ 1)
+
+/*
+ * How often to ping when starting a new server
+ */
+#define FAST_NFS_PING 3
+
+#if (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME
+ #error: sanity check failed
+/*
+ you cannot do things this way...
+ sufficient fast pings must be given the chance to fail
+ within the allowed mount time
+ */
+#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */
+
+static int ping_len;
+static char ping_buf[sizeof(struct rpc_msg) + 32];
+
+/*
+ * Flush any cached data
+ */
+void flush_srvr_nfs_cache P((void));
+void flush_srvr_nfs_cache()
+{
+ fserver *fs = 0;
+
+ ITER(fs, fserver, &nfs_srvr_list) {
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ if (np) {
+ np->np_mountd_inval = TRUE;
+ np->np_error = -1;
+ }
+ }
+}
+
+/*
+ * Startup the NFS ping
+ */
+static void start_ping(P_void);
+static void start_ping()
+{
+ XDR ping_xdr;
+ struct rpc_msg ping_msg;
+
+ rpc_msg_init(&ping_msg, NFS_PROGRAM, NFS_VERSION, NFSPROC_NULL);
+
+ /*
+ * Create an XDR endpoint
+ */
+ xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
+
+ /*
+ * Create the NFS ping message
+ */
+ if (!xdr_callmsg(&ping_xdr, &ping_msg)) {
+ plog(XLOG_ERROR, "Couldn't create ping RPC message");
+ going_down(3);
+ }
+
+ /*
+ * Find out how long it is
+ */
+ ping_len = xdr_getpos(&ping_xdr);
+
+ /*
+ * Destroy the XDR endpoint - we don't need it anymore
+ */
+ xdr_destroy(&ping_xdr);
+}
+
+
+/*
+ * Called when a portmap reply arrives
+ */
+/*ARGSUSED*/
+static void got_portmap P((voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done));
+static void got_portmap(pkt, len, sa, ia, idv, done)
+voidp pkt;
+int len;
+struct sockaddr_in *sa;
+struct sockaddr_in *ia;
+voidp idv;
+int done;
+{
+ fserver *fs2 = (fserver *) idv;
+ fserver *fs = 0;
+
+ /*
+ * Find which fileserver we are talking about
+ */
+ ITER(fs, fserver, &nfs_srvr_list)
+ if (fs == fs2)
+ break;
+
+ if (fs == fs2) {
+ u_long port = 0; /* XXX - should be short but protocol is naff */
+ int error = done ? pickup_rpc_reply(pkt, len, (voidp) &port, xdr_u_long) : -1;
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ if (!error && port) {
+#ifdef DEBUG
+ dlog("got port (%d) for mountd on %s", port, fs->fs_host);
+#endif /* DEBUG */
+ /*
+ * Grab the port number. Portmap sends back
+ * an unsigned long in native ordering, so it
+ * needs converting to a unsigned short in
+ * network ordering.
+ */
+ np->np_mountd = htons((u_short) port);
+ np->np_mountd_inval = FALSE;
+ np->np_error = 0;
+ } else {
+#ifdef DEBUG
+ dlog("Error fetching port for mountd on %s", fs->fs_host);
+#endif /* DEBUG */
+ /*
+ * Almost certainly no mountd running on remote host
+ */
+ np->np_error = error ? error : ETIMEDOUT;
+ }
+ if (fs->fs_flags & FSF_WANT)
+ wakeup_srvr(fs);
+ } else if (done) {
+#ifdef DEBUG
+ dlog("Got portmap for old port request");
+#endif /* DEBUG */
+ } else {
+#ifdef DEBUG
+ dlog("portmap request timed out");
+#endif /* DEBUG */
+ }
+}
+
+/*
+ * Obtain portmap information
+ */
+static int call_portmap P((fserver *fs, AUTH *auth, unsigned long prog, unsigned long vers, unsigned long prot));
+static int call_portmap(fs, auth, prog, vers, prot)
+fserver *fs;
+AUTH *auth;
+unsigned long prog, vers, prot;
+{
+ struct rpc_msg pmap_msg;
+ int len;
+ char iobuf[UDPMSGSIZE];
+ int error;
+ struct pmap pmap;
+
+ rpc_msg_init(&pmap_msg, PMAPPROG, PMAPVERS, (unsigned long) 0);
+ pmap.pm_prog = prog;
+ pmap.pm_vers = vers;
+ pmap.pm_prot = prot;
+ pmap.pm_port = 0;
+ len = make_rpc_packet(iobuf, sizeof(iobuf), PMAPPROC_GETPORT,
+ &pmap_msg, (voidp) &pmap, xdr_pmap, auth);
+ if (len > 0) {
+ struct sockaddr_in sin;
+ bzero((voidp) &sin, sizeof(sin));
+ sin = *fs->fs_ip;
+ sin.sin_port = htons(PMAPPORT);
+ error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
+ &sin, &sin, (voidp) fs, got_portmap);
+ } else {
+ error = -len;
+ }
+ return error;
+}
+
+static void nfs_keepalive P((fserver*));
+
+static void recompute_portmap P((fserver *fs));
+static void recompute_portmap(fs)
+fserver *fs;
+{
+ int error;
+
+ if (nfs_auth)
+ error = 0;
+ else
+ error = make_nfs_auth();
+
+ if (error) {
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ np->np_error = error;
+ } else {
+ call_portmap(fs, nfs_auth, MOUNTPROG,
+ MOUNTVERS, (unsigned long) IPPROTO_UDP);
+ }
+}
+
+/*
+ * This is called when we get a reply to an RPC ping.
+ * The value of id was taken from the nfs_private
+ * structure when the ping was transmitted.
+ */
+/*ARGSUSED*/
+static void nfs_pinged P((voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done));
+static void nfs_pinged(pkt, len, sp, tsp, idv, done)
+voidp pkt;
+int len;
+struct sockaddr_in *sp;
+struct sockaddr_in *tsp;
+voidp idv;
+int done;
+{
+ int xid = (int) idv;
+ fserver *fs;
+#ifdef DEBUG
+ int found_map = 0;
+#endif /* DEBUG */
+
+ if (!done)
+ return;
+
+ /*
+ * For each node...
+ */
+ ITER(fs, fserver, &nfs_srvr_list) {
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ if (np->np_xid == xid) {
+ /*
+ * Reset the ping counter.
+ * Update the keepalive timer.
+ * Log what happened.
+ */
+ if (fs->fs_flags & FSF_DOWN) {
+ fs->fs_flags &= ~FSF_DOWN;
+ if (fs->fs_flags & FSF_VALID) {
+ srvrlog(fs, "is up");
+ } else {
+ if (np->np_ping > 1)
+ srvrlog(fs, "ok");
+#ifdef DEBUG
+ else
+ srvrlog(fs, "starts up");
+#endif
+ fs->fs_flags |= FSF_VALID;
+ }
+
+#ifdef notdef
+ /* why ??? */
+ if (fs->fs_flags & FSF_WANT)
+ wakeup_srvr(fs);
+#endif /* notdef */
+ map_flush_srvr(fs);
+ } else {
+ if (fs->fs_flags & FSF_VALID) {
+#ifdef DEBUG
+ dlog("file server %s type nfs is still up", fs->fs_host);
+#endif /* DEBUG */
+ } else {
+ if (np->np_ping > 1)
+ srvrlog(fs, "ok");
+ fs->fs_flags |= FSF_VALID;
+ }
+ }
+
+ /*
+ * Adjust ping interval
+ */
+ untimeout(fs->fs_cid);
+ fs->fs_cid = timeout(fs->fs_pinger, nfs_keepalive, (voidp) fs);
+
+ /*
+ * Update ttl for this server
+ */
+ np->np_ttl = clocktime() +
+ (MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
+
+ /*
+ * New RPC xid...
+ */
+ np->np_xid = NPXID_ALLOC();
+
+ /*
+ * Failed pings is zero...
+ */
+ np->np_ping = 0;
+
+ /*
+ * Recompute portmap information if not known
+ */
+ if (np->np_mountd_inval)
+ recompute_portmap(fs);
+
+#ifdef DEBUG
+ found_map++;
+#endif /* DEBUG */
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ if (found_map == 0)
+ dlog("Spurious ping packet");
+#endif /* DEBUG */
+}
+
+/*
+ * Called when no ping-reply received
+ */
+static void nfs_timed_out P((fserver *fs));
+static void nfs_timed_out(fs)
+fserver *fs;
+{
+ nfs_private *np = (nfs_private *) fs->fs_private;
+
+ /*
+ * Another ping has failed
+ */
+ np->np_ping++;
+
+ /*
+ * Not known to be up any longer
+ */
+ if (FSRV_ISUP(fs)) {
+ fs->fs_flags &= ~FSF_VALID;
+ if (np->np_ping > 1)
+ srvrlog(fs, "not responding");
+ }
+
+ /*
+ * If ttl has expired then guess that it is dead
+ */
+ if (np->np_ttl < clocktime()) {
+ int oflags = fs->fs_flags;
+ if ((fs->fs_flags & FSF_DOWN) == 0) {
+ /*
+ * Server was up, but is now down.
+ */
+ srvrlog(fs, "is down");
+ fs->fs_flags |= FSF_DOWN|FSF_VALID;
+ /*
+ * Since the server is down, the portmap
+ * information may now be wrong, so it
+ * must be flushed from the local cache
+ */
+ flush_nfs_fhandle_cache(fs);
+ np->np_error = -1;
+#ifdef notdef
+ /*
+ * Pretend just one ping has failed now
+ */
+ np->np_ping = 1;
+#endif
+ } else {
+ /*
+ * Known to be down
+ */
+#ifdef DEBUG
+ if ((fs->fs_flags & FSF_VALID) == 0)
+ srvrlog(fs, "starts down");
+#endif
+ fs->fs_flags |= FSF_VALID;
+ }
+ if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT))
+ wakeup_srvr(fs);
+ } else {
+#ifdef DEBUG
+ if (np->np_ping > 1)
+ dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
+#endif /* DEBUG */
+ }
+
+ /*
+ * Run keepalive again
+ */
+ nfs_keepalive(fs);
+}
+
+/*
+ * Keep track of whether a server is alive
+ */
+static void nfs_keepalive P((fserver *fs));
+static void nfs_keepalive(fs)
+fserver *fs;
+{
+ int error;
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ int fstimeo = -1;
+
+ /*
+ * Send an NFS ping to this node
+ */
+
+ if (ping_len == 0)
+ start_ping();
+
+ /*
+ * Queue the packet...
+ */
+ error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid), (voidp) ping_buf,
+ ping_len, fs->fs_ip, (struct sockaddr_in *) 0, (voidp) np->np_xid, nfs_pinged);
+
+ /*
+ * See if a hard error occured
+ */
+ switch (error) {
+ case ENETDOWN:
+ case ENETUNREACH:
+ case EHOSTDOWN:
+ case EHOSTUNREACH:
+ np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
+ np->np_ttl = (time_t) 0;
+ /*
+ * This causes an immediate call to nfs_timed_out
+ * whenever the server was thought to be up.
+ * See +++ below.
+ */
+ fstimeo = 0;
+ break;
+
+ case 0:
+#ifdef DEBUG
+ dlog("Sent NFS ping to %s", fs->fs_host);
+#endif /* DEBUG */
+ break;
+ }
+
+#ifdef DEBUG
+ /*dlog("keepalive, ping = %d", np->np_ping);*/
+#endif /* DEBUG */
+
+ /*
+ * Back off the ping interval if we are not getting replies and
+ * the remote system is know to be down.
+ */
+ switch (fs->fs_flags & (FSF_DOWN|FSF_VALID)) {
+ case FSF_VALID: /* Up */
+ if (fstimeo < 0) /* +++ see above */
+ fstimeo = FAST_NFS_PING;
+ break;
+
+ case FSF_VALID|FSF_DOWN: /* Down */
+ fstimeo = fs->fs_pinger;
+ break;
+
+ default: /* Unknown */
+ fstimeo = FAST_NFS_PING;
+ break;
+ }
+
+#ifdef DEBUG
+ dlog("NFS timeout in %d seconds", fstimeo);
+#endif /* DEBUG */
+
+ fs->fs_cid = timeout(fstimeo, nfs_timed_out, (voidp) fs);
+}
+
+int nfs_srvr_port P((fserver *fs, u_short *port, voidp wchan));
+int nfs_srvr_port(fs, port, wchan)
+fserver *fs;
+u_short *port;
+voidp wchan;
+{
+ int error = -1;
+ if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
+ if ((fs->fs_flags & FSF_DOWN) == 0) {
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ if (np->np_error == 0) {
+ *port = np->np_mountd;
+ error = 0;
+ } else {
+ error = np->np_error;
+ }
+ /*
+ * Now go get the port mapping again in case it changed.
+ * Note that it is used even if (np_mountd_inval)
+ * is True. The flag is used simply as an
+ * indication that the mountd may be invalid, not
+ * that it is known to be invalid.
+ */
+ if (np->np_mountd_inval)
+ recompute_portmap(fs);
+ else
+ np->np_mountd_inval = TRUE;
+ } else {
+ error = EWOULDBLOCK;
+ }
+ }
+ if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
+ /*
+ * If a wait channel is supplied, and no
+ * error has yet occured, then arrange
+ * that a wakeup is done on the wait channel,
+ * whenever a wakeup is done on this fs node.
+ * Wakeup's are done on the fs node whenever
+ * it changes state - thus causing control to
+ * come back here and new, better things to happen.
+ */
+ fs->fs_flags |= FSF_WANT;
+ sched_task(wakeup_task, wchan, (voidp) fs);
+ }
+ return error;
+}
+
+static void start_nfs_pings P((fserver *fs, int pingval));
+static void start_nfs_pings(fs, pingval)
+fserver *fs;
+int pingval;
+{
+ if (!(fs->fs_flags & FSF_PINGING)) {
+ fs->fs_flags |= FSF_PINGING;
+ if (fs->fs_cid)
+ untimeout(fs->fs_cid);
+ if (pingval < 0) {
+ srvrlog(fs, "wired up");
+ fs->fs_flags |= FSF_VALID;
+ fs->fs_flags &= ~FSF_DOWN;
+ } else {
+ nfs_keepalive(fs);
+ }
+ } else {
+#ifdef DEBUG
+ dlog("Already running pings to %s", fs->fs_host);
+#endif /* DEBUG */
+ }
+}
+
+/*
+ * Find an nfs server for a host.
+ */
+fserver *find_nfs_srvr P((mntfs *mf));
+fserver *find_nfs_srvr(mf)
+mntfs *mf;
+{
+ fserver *fs;
+ struct hostent *hp = 0;
+ char *host = mf->mf_fo->opt_rhost;
+ struct sockaddr_in *ip;
+ nfs_private *np;
+ int pingval;
+
+ /*
+ * Get ping interval from mount options.
+ * Current only used to decide whether pings
+ * are required or not. < 0 = no pings.
+ */
+ { struct mntent mnt;
+ mnt.mnt_opts = mf->mf_mopts;
+ pingval = hasmntval(&mnt, "ping");
+#ifdef HAS_TCP_NFS
+ /*
+ * Over TCP mount, don't bother to do pings.
+ * This is experimental - maybe you want to
+ * do pings anyway...
+ */
+ if (pingval == 0 && hasmntopt(&mnt, "tcp"))
+ pingval = -1;
+#endif /* HAS_TCP_NFS */
+ }
+
+
+ /*
+ * lookup host address and canonical name
+ */
+ hp = gethostbyname(host);
+
+ /*
+ * New code from Bob Harris <harris@basil-rathbone.mit.edu>
+ * Use canonical name to keep track of file server
+ * information. This way aliases do not generate
+ * multiple NFS pingers. (Except when we're normalizing
+ * hosts.)
+ */
+ if (hp && !normalize_hosts) host = hp->h_name;
+
+ ITER(fs, fserver, &nfs_srvr_list) {
+ if (STREQ(host, fs->fs_host)) {
+ start_nfs_pings(fs, pingval);
+ fs->fs_refc++;
+ return fs;
+ }
+ }
+
+
+
+ /*
+ * Get here if we can't find an entry
+ */
+ if (hp) {
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ ip = ALLOC(sockaddr_in);
+ bzero((voidp) ip, sizeof(*ip));
+ ip->sin_family = AF_INET;
+ bcopy((voidp) hp->h_addr, (voidp) &ip->sin_addr, sizeof(ip->sin_addr));
+
+ ip->sin_port = htons(NFS_PORT);
+ break;
+
+ default:
+ ip = 0;
+ break;
+ }
+ } else {
+ plog(XLOG_USER, "Unknown host: %s", host);
+ ip = 0;
+ }
+
+ /*
+ * Allocate a new server
+ */
+ fs = ALLOC(fserver);
+ fs->fs_refc = 1;
+ fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname");
+ if (normalize_hosts) host_normalize(&fs->fs_host);
+ fs->fs_ip = ip;
+ fs->fs_cid = 0;
+ if (ip) {
+ fs->fs_flags = FSF_DOWN; /* Starts off down */
+ } else {
+ fs->fs_flags = FSF_ERROR|FSF_VALID;
+ mf->mf_flags |= MFF_ERROR;
+ mf->mf_error = ENOENT;
+ }
+ fs->fs_type = "nfs";
+ fs->fs_pinger = AM_PINGER;
+ np = ALLOC(nfs_private);
+ bzero((voidp) np, sizeof(*np));
+ np->np_mountd_inval = TRUE;
+ np->np_xid = NPXID_ALLOC();
+ np->np_error = -1;
+ /*
+ * Initially the server will be deemed dead after
+ * MAX_ALLOWED_PINGS of the fast variety have failed.
+ */
+ np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
+ fs->fs_private = (voidp) np;
+ fs->fs_prfree = (void (*)()) free;
+
+ if (!(fs->fs_flags & FSF_ERROR)) {
+ /*
+ * Start of keepalive timer
+ */
+ start_nfs_pings(fs, pingval);
+ }
+
+ /*
+ * Add to list of servers
+ */
+ ins_que(&fs->fs_q, &nfs_srvr_list);
+
+ return fs;
+}
diff --git a/usr.sbin/amd/amd/ufs_ops.c b/usr.sbin/amd/amd/ufs_ops.c
new file mode 100644
index 0000000..fd81c37
--- /dev/null
+++ b/usr.sbin/amd/amd/ufs_ops.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)ufs_ops.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: ufs_ops.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef HAS_UFS
+
+#include <sys/stat.h>
+#ifdef NFS_3
+typedef nfs_fh fhandle_t;
+#endif /* NFS_3 */
+
+#ifdef UFS_HDR
+#include UFS_HDR
+#endif /* UFS_HDR */
+
+#include <sys/mount.h>
+
+/*
+ * UN*X file system
+ */
+
+/*
+ * UFS needs local filesystem and device.
+ */
+static char *ufs_match P((am_opts *fo));
+static char *ufs_match(fo)
+am_opts *fo;
+{
+ if (!fo->opt_dev) {
+ plog(XLOG_USER, "ufs: no device specified");
+ return 0;
+ }
+
+#ifdef DEBUG
+ dlog("UFS: mounting device \"%s\" on \"%s\"",
+ fo->opt_dev, fo->opt_fs);
+#endif /* DEBUG */
+
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ return strdup(fo->opt_dev);
+}
+
+static mount_ufs(dir, fs_name, opts)
+char *dir;
+char *fs_name;
+char *opts;
+{
+ struct ufs_args ufs_args;
+ struct mntent mnt;
+ int flags;
+
+ /*
+ * Figure out the name of the file system type.
+ */
+#ifdef M_NEWTYPE
+ char *type = MOUNT_TYPE_UFS;
+#else
+ int type = MOUNT_TYPE_UFS;
+#endif /* M_NEWTYPE */
+
+ bzero((voidp) &ufs_args, sizeof(ufs_args)); /* Paranoid */
+
+ /*
+ * Fill in the mount structure
+ */
+ mnt.mnt_dir = dir;
+ mnt.mnt_fsname = fs_name;
+ mnt.mnt_type = MTAB_TYPE_UFS;
+ mnt.mnt_opts = opts;
+ mnt.mnt_freq = 1;
+ mnt.mnt_passno = 2;
+
+ flags = compute_mount_flags(&mnt);
+
+#ifdef ULTRIX_HACK
+ ufs_args.ufs_flags = flags;
+ ufs_args.ufs_pgthresh = 64; /* 64K - XXX */
+ flags &= M_RDONLY;
+#else
+ ufs_args.fspec = fs_name;
+#endif /* ULTRIX_HACK */
+
+ /*
+ * Call generic mount routine
+ */
+ return mount_fs(&mnt, flags, (caddr_t) &ufs_args, 0, type);
+}
+
+/*ARGSUSED*/
+static int ufs_fmount(mf)
+mntfs *mf;
+{
+ int error;
+
+ error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+ if (error) {
+ errno = error;
+ plog(XLOG_ERROR, "mount_ufs: %m");
+ return error;
+ }
+
+ return 0;
+}
+
+static int ufs_fumount(mf)
+mntfs *mf;
+{
+ return UMOUNT_FS(mf->mf_mount);
+}
+
+/*
+ * Ops structure
+ */
+am_ops ufs_ops = {
+ "ufs",
+ ufs_match,
+ 0, /* ufs_init */
+ auto_fmount,
+ ufs_fmount,
+ auto_fumount,
+ ufs_fumount,
+ efs_lookuppn,
+ efs_readdir,
+ 0, /* ufs_readlink */
+ 0, /* ufs_mounted */
+ 0, /* ufs_umounted */
+ find_afs_srvr,
+#ifdef FLUSH_KERNEL_NAME_CACHE
+ FS_MKMNT|FS_NOTIMEOUT|FS_UBACKGROUND|FS_AMQINFO
+#else /* FLUSH_KERNEL_NAME_CACHE */
+ FS_MKMNT|FS_NOTIMEOUT|FS_UBACKGROUND|FS_AMQINFO
+#endif /* FLUSH_KERNEL_NAME_CACHE */
+};
+
+#endif /* HAS_UFS */
diff --git a/usr.sbin/amd/amd/umount_fs.c b/usr.sbin/amd/amd/umount_fs.c
new file mode 100644
index 0000000..2c3e73d
--- /dev/null
+++ b/usr.sbin/amd/amd/umount_fs.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)umount_fs.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: umount_fs.c,v 5.2.2.1 1992/02/09 15:09:10 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef NEED_UMOUNT_BSD
+
+int umount_fs P((char *fs_name));
+int umount_fs(fs_name)
+char *fs_name;
+{
+ int error;
+
+eintr:
+ error = unmount(fs_name, 0);
+ if (error < 0)
+ error = errno;
+
+ switch (error) {
+ case EINVAL:
+ case ENOTBLK:
+ case ENOENT:
+ plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
+ error = 0; /* Not really an error */
+ break;
+
+ case EINTR:
+#ifdef DEBUG
+ /* not sure why this happens, but it does. ask kirk one day... */
+ dlog("%s: unmount: %m", fs_name);
+#endif /* DEBUG */
+ goto eintr;
+
+#ifdef DEBUG
+ default:
+ dlog("%s: unmount: %m", fs_name);
+ break;
+#endif /* DEBUG */
+ }
+
+ return error;
+}
+
+#endif /* NEED_UMOUNT_BSD */
+
+#ifdef NEED_UMOUNT_OSF
+
+#include <sys/mount.h> /* For MNT_NOFORCE */
+
+int umount_fs(fs_name)
+char *fs_name;
+{
+ int error;
+
+eintr:
+ error = umount(fs_name, MNT_NOFORCE);
+ if (error < 0)
+ error = errno;
+
+ switch (error) {
+ case EINVAL:
+ case ENOTBLK:
+ plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
+ error = 0; /* Not really an error */
+ break;
+
+ case ENOENT:
+ plog(XLOG_ERROR, "mount point %s: %m", fs_name);
+ break;
+
+ case EINTR:
+#ifdef DEBUG
+ /* not sure why this happens, but it does. ask kirk one day... */
+ dlog("%s: unmount: %m", fs_name);
+#endif /* DEBUG */
+ goto eintr;
+
+#ifdef DEBUG
+ default:
+ dlog("%s: unmount: %m", fs_name);
+ break;
+#endif /* DEBUG */
+ }
+
+ return error;
+}
+
+#endif /* NEED_UMOUNT_OSF */
+
+#ifdef NEED_UMOUNT_FS
+
+int umount_fs(fs_name)
+char *fs_name;
+{
+ mntlist *mlist, *mp, *mp_save = 0;
+ int error = 0;
+
+ mp = mlist = read_mtab(fs_name);
+
+ /*
+ * Search the mount table looking for
+ * the correct (ie last) matching entry
+ */
+ while (mp) {
+ if (strcmp(mp->mnt->mnt_fsname, fs_name) == 0 ||
+ strcmp(mp->mnt->mnt_dir, fs_name) == 0)
+ mp_save = mp;
+ mp = mp->mnext;
+ }
+
+ if (mp_save) {
+#ifdef DEBUG
+ dlog("Trying unmount(%s)", mp_save->mnt->mnt_dir);
+#endif /* DEBUG */
+ /*
+ * This unmount may hang leaving this
+ * process with an exlusive lock on
+ * /etc/mtab. Therefore it is necessary
+ * to unlock mtab, do the unmount, then
+ * lock mtab (again) and reread it and
+ * finally update it.
+ */
+ unlock_mntlist();
+ if (UNMOUNT_TRAP(mp_save->mnt) < 0) {
+ switch (error = errno) {
+ case EINVAL:
+ case ENOTBLK:
+ plog(XLOG_WARNING, "unmount: %s is not mounted", mp_save->mnt->mnt_dir);
+ error = 0; /* Not really an error */
+ break;
+
+ case ENOENT:
+ plog(XLOG_ERROR, "mount point %s: %m", mp_save->mnt->mnt_dir);
+ break;
+
+ default:
+#ifdef DEBUG
+ dlog("%s: unmount: %m", mp_save->mnt->mnt_dir);
+#endif /* DEBUG */
+ break;
+ }
+ }
+#ifdef DEBUG
+ dlog("Finished unmount(%s)", mp_save->mnt->mnt_dir);
+#endif
+
+
+#ifdef UPDATE_MTAB
+ if (!error) {
+ free_mntlist(mlist);
+ mp = mlist = read_mtab(fs_name);
+
+ /*
+ * Search the mount table looking for
+ * the correct (ie last) matching entry
+ */
+ mp_save = 0;
+ while (mp) {
+ if (strcmp(mp->mnt->mnt_fsname, fs_name) == 0 ||
+ strcmp(mp->mnt->mnt_dir, fs_name) == 0)
+ mp_save = mp;
+ mp = mp->mnext;
+ }
+
+ if (mp_save) {
+ mnt_free(mp_save->mnt);
+ mp_save->mnt = 0;
+ rewrite_mtab(mlist);
+ }
+ }
+#endif /* UPDATE_MTAB */
+ } else {
+ plog(XLOG_ERROR, "Couldn't find how to unmount %s", fs_name);
+ /*
+ * Assume it is already unmounted
+ */
+ error = 0;
+ }
+
+ free_mntlist(mlist);
+
+ return error;
+}
+
+#endif /* NEED_UMOUNT_FS */
diff --git a/usr.sbin/amd/amd/util.c b/usr.sbin/amd/amd/util.c
new file mode 100644
index 0000000..8503cc8
--- /dev/null
+++ b/usr.sbin/amd/amd/util.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)util.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: util.c,v 5.2.2.2 1992/03/07 17:52:06 jsp Exp $
+ *
+ */
+
+/*
+ * Utils
+ */
+
+#include "am.h"
+#include <ctype.h>
+#include <sys/stat.h>
+#include <netdb.h>
+
+
+char *strnsave(str, len)
+Const char *str;
+int len;
+{
+ char *sp = (char *) xmalloc(len+1);
+
+ bcopy(str, sp, len);
+ sp[len] = 0;
+
+ return sp;
+}
+
+char *strdup(s)
+Const char *s;
+{
+ return strnsave(s, strlen(s));
+}
+
+/*
+ * Concatenate three strings and store in buffer pointed to
+ * by p, making p large enough to hold the strings
+ */
+char *str3cat(p, s1, s2, s3)
+char *p;
+char *s1;
+char *s2;
+char *s3;
+{
+ int l1 = strlen(s1);
+ int l2 = strlen(s2);
+ int l3 = strlen(s3);
+ p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
+ bcopy(s1, p, l1);
+ bcopy(s2, p + l1, l2);
+ bcopy(s3, p + l1 + l2, l3 + 1);
+ return p;
+}
+
+char *strealloc(p, s)
+char *p;
+char *s;
+{
+ int len = strlen(s) + 1;
+
+ p = (char *) xrealloc((voidp) p, len);
+
+ strcpy(p, s);
+#ifdef DEBUG_MEM
+ malloc_verify();
+#endif /* DEBUG_MEM */
+ return p;
+}
+
+char **strsplit P((char *s, int ch, int qc));
+char **strsplit(s, ch, qc)
+char *s;
+int ch;
+int qc;
+{
+ char **ivec;
+ int ic = 0;
+ int done = 0;
+
+ ivec = (char **) xmalloc((ic+1)*sizeof(char *));
+
+ while (!done) {
+ char *v;
+ /*
+ * skip to split char
+ */
+ while (*s && (ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch))
+ *s++ = '\0';
+
+ /*
+ * End of string?
+ */
+ if (!*s)
+ break;
+
+ /*
+ * remember start of string
+ */
+ v = s;
+
+ /*
+ * skip to split char
+ */
+ while (*s && !(ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch)) {
+ if (*s++ == qc) {
+ /*
+ * Skip past string.
+ */
+ s++;
+ while (*s && *s != qc)
+ s++;
+ if (*s == qc)
+ s++;
+ }
+ }
+
+ if (!*s)
+ done = 1;
+ *s++ = '\0';
+
+ /*
+ * save string in new ivec slot
+ */
+ ivec[ic++] = v;
+ ivec = (char **) xrealloc((voidp) ivec, (ic+1)*sizeof(char *));
+#ifdef DEBUG
+ Debug(D_STR)
+ plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
+#endif /* DEBUG */
+ }
+
+#ifdef DEBUG
+ Debug(D_STR)
+ plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
+#endif /* DEBUG */
+
+ ivec[ic] = 0;
+
+ return ivec;
+}
+
+/*
+ * Strip off the trailing part of a domain
+ * to produce a short-form domain relative
+ * to the local host domain.
+ * Note that this has no effect if the domain
+ * names do not have the same number of
+ * components. If that restriction proves
+ * to be a problem then the loop needs recoding
+ * to skip from right to left and do partial
+ * matches along the way -- ie more expensive.
+ */
+static void domain_strip P((char *otherdom, char *localdom));
+static void domain_strip(otherdom, localdom)
+char *otherdom, *localdom;
+{
+#ifdef PARTIAL_DOMAINS
+ char *p1 = otherdom-1;
+ char *p2 = localdom-1;
+
+ do {
+ if (p1 = strchr(p1+1, '.'))
+ if (p2 = strchr(p2+1, '.'))
+ if (strcmp(p1+1, p2+1) == 0) {
+ *p1 = '\0';
+ break;
+ }
+ } while (p1 && p2);
+#else
+ char *p1, *p2;
+
+ if ((p1 = strchr(otherdom, '.')) &&
+ (p2 = strchr(localdom, '.')) &&
+ (strcmp(p1+1, p2+1) == 0))
+ *p1 = '\0';
+#endif /* PARTIAL_DOMAINS */
+}
+
+/*
+ * Normalize a host name
+ */
+void host_normalize P((char **chp));
+void host_normalize(chp)
+char **chp;
+{
+ /*
+ * Normalize hosts is used to resolve host name aliases
+ * and replace them with the standard-form name.
+ * Invoked with "-n" command line option.
+ */
+ if (normalize_hosts) {
+ struct hostent *hp;
+ clock_valid = 0;
+ hp = gethostbyname(*chp);
+ if (hp && hp->h_addrtype == AF_INET) {
+#ifdef DEBUG
+ dlog("Hostname %s normalized to %s", *chp, hp->h_name);
+#endif /* DEBUG */
+ *chp = strealloc(*chp, hp->h_name);
+ }
+ }
+ domain_strip(*chp, hostd);
+}
+
+/*
+ * Make a dotted quad from a 32bit IP address
+ * addr is in network byte order.
+ * sizeof(buf) needs to be at least 16.
+ */
+char *inet_dquad P((char *buf, unsigned long addr));
+char *inet_dquad(buf, addr)
+char *buf;
+unsigned long addr;
+{
+ addr = ntohl(addr);
+ sprintf(buf, "%d.%d.%d.%d",
+ ((addr >> 24) & 0xff),
+ ((addr >> 16) & 0xff),
+ ((addr >> 8) & 0xff),
+ ((addr >> 0) & 0xff));
+ return buf;
+}
+
+/*
+ * Keys are not allowed to contain " ' ! or ; to avoid
+ * problems with macro expansions.
+ */
+static char invalid_keys[] = "\"'!;@ \t\n";
+int valid_key P((char *key));
+int valid_key(key)
+char *key;
+{
+ while (*key)
+ if (strchr(invalid_keys, *key++))
+ return FALSE;
+ return TRUE;
+}
+
+void going_down P((int rc));
+void going_down(rc)
+int rc;
+{
+ if (foreground) {
+ if (amd_state != Start) {
+ if (amd_state != Done)
+ return;
+ unregister_amq();
+ }
+ }
+ if (foreground) {
+ plog(XLOG_INFO, "Finishing with status %d", rc);
+ } else {
+#ifdef DEBUG
+ dlog("background process exiting with status %d", rc);
+#endif /* DEBUG */
+ }
+
+ exit(rc);
+}
+
+
+int bind_resv_port P((int so, u_short *pp));
+int bind_resv_port(so, pp)
+int so;
+u_short *pp;
+{
+ struct sockaddr_in sin;
+ int rc;
+ unsigned short port;
+
+ bzero((voidp) &sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+
+ port = IPPORT_RESERVED;
+
+ do {
+ --port;
+ sin.sin_port = htons(port);
+ rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
+ } while (rc < 0 && port > IPPORT_RESERVED/2);
+
+ if (pp && rc == 0)
+ *pp = port;
+ return rc;
+}
+
+void forcibly_timeout_mp P((am_node *mp));
+void forcibly_timeout_mp(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ /*
+ * Arrange to timeout this node
+ */
+ if (mf && ((mp->am_flags & AMF_ROOT) ||
+ (mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)))) {
+ if (!(mf->mf_flags & MFF_UNMOUNTING))
+ plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
+ } else {
+ plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
+ mp->am_flags &= ~AMF_NOTIMEOUT;
+ mp->am_ttl = clocktime();
+ reschedule_timeout_mp();
+ }
+}
+
+void mf_mounted P((mntfs *mf));
+void mf_mounted(mf)
+mntfs *mf;
+{
+ int quoted;
+ int wasmounted = mf->mf_flags & MFF_MOUNTED;
+
+ if (!wasmounted) {
+ /*
+ * If this is a freshly mounted
+ * filesystem then update the
+ * mntfs structure...
+ */
+ mf->mf_flags |= MFF_MOUNTED;
+ mf->mf_error = 0;
+
+ /*
+ * Do mounted callback
+ */
+ if (mf->mf_ops->mounted)
+ (*mf->mf_ops->mounted)(mf);
+
+ mf->mf_fo = 0;
+ }
+
+ /*
+ * Log message
+ */
+ quoted = strchr(mf->mf_info, ' ') != 0;
+ plog(XLOG_INFO, "%s%s%s %s fstype %s on %s",
+ quoted ? "\"" : "",
+ mf->mf_info,
+ quoted ? "\"" : "",
+ wasmounted ? "referenced" : "mounted",
+ mf->mf_ops->fs_type, mf->mf_mount);
+}
+
+void am_mounted P((am_node *mp));
+void am_mounted(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ mf_mounted(mf);
+
+ /*
+ * Patch up path for direct mounts
+ */
+ if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &dfs_ops)
+ mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
+
+ /*
+ * Check whether this mount should be cached permanently
+ */
+ if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
+ mp->am_flags |= AMF_NOTIMEOUT;
+ } else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
+ mp->am_flags |= AMF_NOTIMEOUT;
+ } else {
+ struct mntent mnt;
+ if (mf->mf_mopts) {
+ mnt.mnt_opts = mf->mf_mopts;
+ if (hasmntopt(&mnt, "nounmount"))
+ mp->am_flags |= AMF_NOTIMEOUT;
+ if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
+ mp->am_timeo = am_timeo;
+ }
+ }
+
+ /*
+ * If this node is a symlink then
+ * compute the length of the returned string.
+ */
+ if (mp->am_fattr.type == NFLNK)
+ mp->am_fattr.size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+
+ /*
+ * Record mount time
+ */
+ mp->am_fattr.mtime.seconds = mp->am_stats.s_mtime = clocktime();
+ new_ttl(mp);
+ /*
+ * Update mtime of parent node
+ */
+ if (mp->am_parent && mp->am_parent->am_mnt)
+ mp->am_parent->am_fattr.mtime.seconds = mp->am_stats.s_mtime;
+
+
+ /*
+ * Update stats
+ */
+ amd_stats.d_mok++;
+}
+
+int mount_node P((am_node *mp));
+int mount_node(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ int error;
+
+ mf->mf_flags |= MFF_MOUNTING;
+ error = (*mf->mf_ops->mount_fs)(mp);
+ mf = mp->am_mnt;
+ if (error >= 0)
+ mf->mf_flags &= ~MFF_MOUNTING;
+ if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
+ /* ...but see ifs_mount */
+ am_mounted(mp);
+ }
+
+ return error;
+}
+
+void am_unmounted P((am_node *mp));
+void am_unmounted(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+
+ if (!foreground) /* firewall - should never happen */
+ return;
+
+#ifdef DEBUG
+ /*dlog("in am_unmounted(), foreground = %d", foreground);*/
+#endif /* DEBUG */
+
+ /*
+ * Do unmounted callback
+ */
+ if (mf->mf_ops->umounted)
+ (*mf->mf_ops->umounted)(mp);
+
+ /*
+ * Update mtime of parent node
+ */
+ if (mp->am_parent && mp->am_parent->am_mnt)
+ mp->am_parent->am_fattr.mtime.seconds = clocktime();
+
+ free_map(mp);
+}
+
+int auto_fmount P((am_node *mp));
+int auto_fmount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ return (*mf->mf_ops->fmount_fs)(mf);
+}
+
+int auto_fumount P((am_node *mp));
+int auto_fumount(mp)
+am_node *mp;
+{
+ mntfs *mf = mp->am_mnt;
+ return (*mf->mf_ops->fumount_fs)(mf);
+}
+
+/*
+ * Fork the automounter
+ *
+ * TODO: Need a better strategy for handling errors
+ */
+static int dofork(P_void);
+static int dofork()
+{
+ int pid;
+top:
+ pid = fork();
+
+ if (pid < 0) {
+ sleep(1);
+ goto top;
+ }
+
+ if (pid == 0) {
+ mypid = getpid();
+ foreground = 0;
+ }
+
+ return pid;
+}
+
+int background(P_void);
+int background()
+{
+ int pid = dofork();
+ if (pid == 0) {
+#ifdef DEBUG
+ dlog("backgrounded");
+#endif
+ foreground = 0;
+ }
+
+ return pid;
+}
+
+/*
+ * Make all the directories in the path.
+ */
+int mkdirs P((char *path, int mode));
+int mkdirs(path, mode)
+char *path;
+int mode;
+{
+ /*
+ * take a copy in case path is in readonly store
+ */
+ char *p2 = strdup(path);
+ char *sp = p2;
+ struct stat stb;
+ int error_so_far = 0;
+
+ /*
+ * Skip through the string make the directories.
+ * Mostly ignore errors - the result is tested at the end.
+ *
+ * This assumes we are root so that we can do mkdir in a
+ * mode 555 directory...
+ */
+ while (sp = strchr(sp+1, '/')) {
+ *sp = '\0';
+ if (mkdir(p2, mode) < 0) {
+ error_so_far = errno;
+ } else {
+#ifdef DEBUG
+ dlog("mkdir(%s)", p2);
+#endif
+ }
+ *sp = '/';
+ }
+
+ if (mkdir(p2, mode) < 0) {
+ error_so_far = errno;
+ } else {
+#ifdef DEBUG
+ dlog("mkdir(%s)", p2);
+#endif
+ }
+
+#ifdef SUNOS4_WORKAROUND
+ /*
+ * Do a sync - if we do rmdirs() immediately
+ * and then the system crashes it leaves
+ * the filesystem in a state that fsck -p
+ * can't fix. (Observed more than once on
+ * SunOS 4 ...)
+ *
+ * The problem was caused by a bug somewhere
+ * in the UFS code which has since been fixed
+ * (at least at Berkeley).
+ *
+ * Attempted workaround - XXX.
+ */
+ sync();
+#endif /* SUNOS4_WORKAROUND */
+
+ free(p2);
+
+ return stat(path, &stb) == 0 &&
+ (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
+}
+
+/*
+ * Remove as many directories in the path as possible.
+ * Give up if the directory doesn't appear to have
+ * been created by Amd (not mode dr-x) or an rmdir
+ * fails for any reason.
+ */
+void rmdirs P((char *dir));
+void rmdirs(dir)
+char *dir;
+{
+ char *xdp = strdup(dir);
+ char *dp;
+
+ do {
+ struct stat stb;
+ /*
+ * Try to find out whether this was
+ * created by amd. Do this by checking
+ * for owner write permission.
+ */
+ if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
+ if (rmdir(xdp) < 0) {
+ if (errno != ENOTEMPTY &&
+ errno != EBUSY &&
+ errno != EEXIST &&
+ errno != EINVAL)
+ plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
+ break;
+ } else {
+#ifdef DEBUG
+ dlog("rmdir(%s)", xdp);
+#endif
+ }
+ } else {
+ break;
+ }
+ dp = strrchr(xdp, '/');
+ if (dp)
+ *dp = '\0';
+ } while (dp && dp > xdp);
+ free(xdp);
+}
diff --git a/usr.sbin/amd/amd/wire.c b/usr.sbin/amd/amd/wire.c
new file mode 100644
index 0000000..ea6d3da
--- /dev/null
+++ b/usr.sbin/amd/amd/wire.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wire.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wire.c,v 5.2.2.1 1992/02/09 15:09:15 jsp beta $
+ *
+ */
+
+/*
+ * This function returns the subnet (address&netmask) for the primary network
+ * interface. If the resulting address has an entry in the hosts file, the
+ * corresponding name is retuned, otherwise the address is returned in
+ * standard internet format.
+ * As a side-effect, a list of local IP/net address is recorded for use
+ * by the islocalnet() function.
+ *
+ * Derived from original by Paul Anderson (23/4/90)
+ * Updates from Dirk Grunwald (11/11/91)
+ */
+
+#include "am.h"
+
+#include <sys/ioctl.h>
+
+#define NO_SUBNET "notknown"
+
+/*
+ * List of locally connected networks
+ */
+typedef struct addrlist addrlist;
+struct addrlist {
+ addrlist *ip_next;
+ unsigned long ip_addr;
+ unsigned long ip_mask;
+};
+static addrlist *localnets = 0;
+
+#ifdef SIOCGIFFLAGS
+#ifdef STELLIX
+#include <sys/sema.h>
+#endif /* STELLIX */
+#include <net/if.h>
+#include <netdb.h>
+
+#if defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK)
+#define IFF_LOOPBACK IFF_LOCAL_LOOPBACK
+#endif
+
+#define GFBUFLEN 1024
+#define clist (ifc.ifc_ifcu.ifcu_req)
+#define count (ifc.ifc_len/sizeof(struct ifreq))
+
+char *getwire P((void));
+char *getwire()
+{
+ struct hostent *hp;
+ struct netent *np;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ caddr_t cp, cplim;
+ unsigned long address, netmask, subnet;
+ char buf[GFBUFLEN], *s;
+ int sk = -1;
+ char *netname = 0;
+
+ /*
+ * Get suitable socket
+ */
+ if ((sk = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ goto out;
+
+ /*
+ * Fill in ifconf details
+ */
+ ifc.ifc_len = sizeof buf;
+ ifc.ifc_buf = buf;
+
+ /*
+ * Get network interface configurations
+ */
+ if (ioctl(sk, SIOCGIFCONF, (caddr_t) &ifc) < 0)
+ goto out;
+
+ /*
+ * Upper bound on array
+ */
+ cplim = buf + ifc.ifc_len;
+
+ /*
+ * This is some magic to cope with both "traditional" and the
+ * new 4.4BSD-style struct sockaddrs. The new structure has
+ * variable length and a size field to support longer addresses.
+ * AF_LINK is a new definition for 4.4BSD.
+ */
+#ifdef AF_LINK
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define size(ifr) (max((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof(ifr->ifr_name))
+#else
+#define size(ifr) sizeof(*ifr)
+#endif
+ /*
+ * Scan the list looking for a suitable interface
+ */
+ for (cp = buf; cp < cplim; cp += size(ifr)) {
+ addrlist *al;
+ ifr = (struct ifreq *) cp;
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ else
+ address = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+
+ /*
+ * Get interface flags
+ */
+ if (ioctl(sk, SIOCGIFFLAGS, (caddr_t) ifr) < 0)
+ continue;
+
+ /*
+ * If the interface is a loopback, or its not running
+ * then ignore it.
+ */
+ if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
+ continue;
+ if ((ifr->ifr_flags & IFF_RUNNING) == 0)
+ continue;
+
+ /*
+ * Get the netmask of this interface
+ */
+ if (ioctl(sk, SIOCGIFNETMASK, (caddr_t) ifr) < 0)
+ continue;
+
+ netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+
+ /*
+ * Add interface to local network list
+ */
+ al = ALLOC(addrlist);
+ al->ip_addr = address;
+ al->ip_mask = netmask;
+ al->ip_next = localnets;
+ localnets = al;
+
+ if (netname == 0) {
+ unsigned long net;
+ unsigned long mask;
+ unsigned long subnetshift;
+ /*
+ * Figure out the subnet's network address
+ */
+ subnet = address & netmask;
+
+#ifdef IN_CLASSA
+ subnet = ntohl(subnet);
+
+ if (IN_CLASSA(subnet)) {
+ mask = IN_CLASSA_NET;
+ subnetshift = 8;
+ } else if (IN_CLASSB(subnet)) {
+ mask = IN_CLASSB_NET;
+ subnetshift = 8;
+ } else {
+ mask = IN_CLASSC_NET;
+ subnetshift = 4;
+ }
+
+ /*
+ * If there are more bits than the standard mask
+ * would suggest, subnets must be in use.
+ * Guess at the subnet mask, assuming reasonable
+ * width subnet fields.
+ * XXX: Or-in at least 1 byte's worth of 1s to make
+ * sure the top bits remain set.
+ */
+ while (subnet &~ mask)
+ mask = (mask >> subnetshift) | 0xff000000;
+
+ net = subnet & mask;
+ while ((mask & 1) == 0)
+ mask >>= 1, net >>= 1;
+
+ /*
+ * Now get a usable name.
+ * First use the network database,
+ * then the host database,
+ * and finally just make a dotted quad.
+ */
+
+ np = getnetbyaddr(net, AF_INET);
+#else
+ /* This is probably very wrong. */
+ np = getnetbyaddr(subnet, AF_INET);
+#endif /* IN_CLASSA */
+ if (np)
+ s = np->n_name;
+ else {
+ subnet = address & netmask;
+ hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
+ if (hp)
+ s = hp->h_name;
+ else
+ s = inet_dquad(buf, subnet);
+ }
+ netname = strdup(s);
+ }
+ }
+
+out:
+ if (sk >= 0)
+ (void) close(sk);
+ if (netname)
+ return netname;
+ return strdup(NO_SUBNET);
+}
+
+#else
+
+char *getwire P((void));
+char *getwire()
+{
+ return strdup(NO_SUBNET);
+}
+#endif /* SIOCGIFFLAGS */
+
+/*
+ * Determine whether a network is on a local network
+ * (addr) is in network byte order.
+ */
+int islocalnet P((unsigned long addr));
+int islocalnet(addr)
+unsigned long addr;
+{
+ addrlist *al;
+
+ for (al = localnets; al; al = al->ip_next)
+ if (((addr ^ al->ip_addr) & al->ip_mask) == 0)
+ return TRUE;
+
+#ifdef DEBUG
+ { char buf[16];
+ plog(XLOG_INFO, "%s is on a remote network", inet_dquad(buf, addr));
+ }
+#endif
+ return FALSE;
+}
diff --git a/usr.sbin/amd/amd/xutil.c b/usr.sbin/amd/amd/xutil.c
new file mode 100644
index 0000000..8af6951
--- /dev/null
+++ b/usr.sbin/amd/amd/xutil.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)xutil.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: xutil.c,v 5.2.2.3 1992/03/07 10:36:09 jsp Exp $
+ *
+ */
+
+#include "config.h"
+#ifdef HAS_SYSLOG
+#include <syslog.h>
+#endif /* HAS_SYSLOG */
+#ifdef HAS_STRERROR
+#include <string.h>
+#endif
+
+FILE *logfp = stderr; /* Log errors to stderr initially */
+#ifdef HAS_SYSLOG
+int syslogging;
+#endif /* HAS_SYSLOG */
+int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
+int xlog_level_init = ~0;
+
+/*
+ * List of log options
+ */
+struct opt_tab xlog_opt[] = {
+ { "all", XLOG_ALL }, /* All messages */
+#ifdef DEBUG
+ { "debug", XLOG_DEBUG }, /* Debug messages */
+#endif /* DEBUG */
+ { "error", XLOG_ERROR }, /* Non-fatal system errors */
+ { "fatal", XLOG_FATAL }, /* Fatal errors */
+ { "info", XLOG_INFO }, /* Information */
+ { "map", XLOG_MAP }, /* Map errors */
+ { "stats", XLOG_STATS }, /* Additional statistical information */
+ { "user", XLOG_USER }, /* Non-fatal user errors */
+ { "warn", XLOG_WARNING }, /* Warnings */
+ { "warning", XLOG_WARNING }, /* Warnings */
+ { 0, 0 }
+};
+
+voidp xmalloc(len)
+int len;
+{
+ voidp p;
+ int retries = 600;
+
+ /*
+ * Avoid malloc's which return NULL for malloc(0)
+ */
+ if (len == 0)
+ len = 1;
+
+ do {
+ p = (voidp) malloc((unsigned) len);
+ if (p) {
+#if defined(DEBUG) && defined(DEBUG_MEM)
+ Debug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+ return p;
+ }
+ if (retries > 0) {
+ plog(XLOG_ERROR, "Retrying memory allocation");
+ sleep(1);
+ }
+ } while (--retries);
+
+ plog(XLOG_FATAL, "Out of memory");
+ going_down(1);
+
+ abort();
+
+ return 0;
+}
+
+voidp xrealloc(ptr, len)
+voidp ptr;
+int len;
+{
+#if defined(DEBUG) && defined(DEBUG_MEM)
+ Debug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+
+ if (len == 0)
+ len = 1;
+
+ if (ptr)
+ ptr = (voidp) realloc(ptr, (unsigned) len);
+ else
+ ptr = (voidp) xmalloc((unsigned) len);
+
+ if (!ptr) {
+ plog(XLOG_FATAL, "Out of memory in realloc");
+ going_down(1);
+ abort();
+ }
+ return ptr;
+}
+
+#if defined(DEBUG) && defined(DEBUG_MEM)
+xfree(f, l, p)
+char *f;
+int l;
+voidp p;
+{
+ Debug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
+#undef free
+ free(p);
+}
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+#ifdef DEBUG_MEM
+static int mem_bytes;
+static int orig_mem_bytes;
+static void checkup_mem(P_void)
+{
+extern struct mallinfo __mallinfo;
+ if (mem_bytes != __mallinfo.uordbytes) {
+ if (orig_mem_bytes == 0)
+ mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
+ else {
+ fprintf(logfp, "%s[%d]: ", progname, mypid);
+ if (mem_bytes < __mallinfo.uordbytes) {
+ fprintf(logfp, "ALLOC: %d bytes",
+ __mallinfo.uordbytes - mem_bytes);
+ } else {
+ fprintf(logfp, "FREE: %d bytes",
+ mem_bytes - __mallinfo.uordbytes);
+ }
+ mem_bytes = __mallinfo.uordbytes;
+ fprintf(logfp, ", making %d missing\n",
+ mem_bytes - orig_mem_bytes);
+ }
+ }
+ malloc_verify();
+}
+#endif /* DEBUG_MEM */
+
+/*
+ * Take a log format string and expand occurences of %m
+ * with the current error code take from errno.
+ */
+INLINE
+static void expand_error(f, e)
+char *f;
+char *e;
+{
+#ifndef HAS_STRERROR
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+#endif
+ char *p;
+ int error = errno;
+
+ for (p = f; *e = *p; e++, p++) {
+ if (p[0] == '%' && p[1] == 'm') {
+ char *errstr;
+#ifdef HAS_STRERROR
+ errstr = strerror(error);
+#else
+ if (error < 0 || error >= sys_nerr)
+ errstr = 0;
+ else
+ errstr = sys_errlist[error];
+#endif
+ if (errstr)
+ strcpy(e, errstr);
+ else
+ sprintf(e, "Error %d", error);
+ e += strlen(e) - 1;
+ p++;
+ }
+ }
+}
+
+/*
+ * Output the time of day and hostname to the logfile
+ */
+static void show_time_host_and_name(lvl)
+int lvl;
+{
+static time_t last_t = 0;
+static char *last_ctime = 0;
+ time_t t = clocktime();
+ char *sev;
+ extern char *ctime();
+
+#if defined(DEBUG) && defined(PARANOID)
+extern char **gargv;
+#endif /* defined(DEBUG) && defined(PARANOID) */
+
+ if (t != last_t) {
+ last_ctime = ctime(&t);
+ last_t = t;
+ }
+
+ switch (lvl) {
+ case XLOG_FATAL: sev = "fatal:"; break;
+ case XLOG_ERROR: sev = "error:"; break;
+ case XLOG_USER: sev = "user: "; break;
+ case XLOG_WARNING: sev = "warn: "; break;
+ case XLOG_INFO: sev = "info: "; break;
+ case XLOG_DEBUG: sev = "debug:"; break;
+ case XLOG_MAP: sev = "map: "; break;
+ case XLOG_STATS: sev = "stats:"; break;
+ default: sev = "hmm: "; break;
+ }
+ fprintf(logfp, "%15.15s %s %s[%d]/%s ",
+ last_ctime+4, hostname,
+#if defined(DEBUG) && defined(PARANOID)
+ gargv[0],
+#else
+ progname,
+#endif /* defined(DEBUG) && defined(PARANOID) */
+ mypid,
+ sev);
+}
+
+#ifdef DEBUG
+/*VARARGS1*/
+void dplog(fmt, j,s,_,p,e,n,d,r,y)
+char *fmt;
+char *j, *s, *_, *p, *e, *n, *d, *r, *y;
+{
+ plog(XLOG_DEBUG, fmt, j,s,_,p,e,n,d,r,y);
+}
+
+#endif /* DEBUG */
+/*VARARGS1*/
+void plog(lvl, fmt, j,s,_,p,e,n,d,r,y)
+int lvl;
+char *fmt;
+char *j, *s, *_, *p, *e, *n, *d, *r, *y;
+{
+ char msg[1024];
+ char efmt[1024];
+ char *ptr = msg;
+
+ if (!(xlog_level & lvl))
+ return;
+
+#ifdef DEBUG_MEM
+ checkup_mem();
+#endif /* DEBUG_MEM */
+
+ expand_error(fmt, efmt);
+ sprintf(ptr, efmt, j,s,_,p,e,n,d,r,y);
+ ptr += strlen(ptr);
+ if (ptr[-1] == '\n')
+ *--ptr = '\0';
+#ifdef HAS_SYSLOG
+ if (syslogging) {
+ switch(lvl) { /* from mike <mcooper@usc.edu> */
+ case XLOG_FATAL: lvl = LOG_CRIT; break;
+ case XLOG_ERROR: lvl = LOG_ERR; break;
+ case XLOG_USER: lvl = LOG_WARNING; break;
+ case XLOG_WARNING: lvl = LOG_WARNING; break;
+ case XLOG_INFO: lvl = LOG_INFO; break;
+ case XLOG_DEBUG: lvl = LOG_DEBUG; break;
+ case XLOG_MAP: lvl = LOG_DEBUG; break;
+ case XLOG_STATS: lvl = LOG_INFO; break;
+ default: lvl = LOG_ERR; break;
+ }
+ syslog(lvl, "%s", msg);
+ return;
+ }
+#endif /* HAS_SYSLOG */
+
+ *ptr++ = '\n';
+ *ptr = '\0';
+
+ /*
+ * Mimic syslog header
+ */
+ show_time_host_and_name(lvl);
+ fwrite(msg, ptr - msg, 1, logfp);
+ fflush(logfp);
+}
+
+void show_opts P((int ch, struct opt_tab *opts));
+void show_opts(ch, opts)
+int ch;
+struct opt_tab *opts;
+{
+ /*
+ * Display current debug options
+ */
+ int i;
+ int s = '{';
+ fprintf(stderr, "\t[-%c {no}", ch);
+ for (i = 0; opts[i].opt; i++) {
+ fprintf(stderr, "%c%s", s, opts[i].opt);
+ s = ',';
+ }
+ fputs("}]\n", stderr);
+}
+
+int cmdoption P((char *s, struct opt_tab *optb, int *flags));
+int cmdoption(s, optb, flags)
+char *s;
+struct opt_tab *optb;
+int *flags;
+{
+ char *p = s;
+ int errs = 0;
+
+ while (p && *p) {
+ int neg;
+ char *opt;
+ struct opt_tab *dp, *dpn = 0;
+
+ s = p;
+ p = strchr(p, ',');
+ if (p)
+ *p = '\0';
+
+ if (s[0] == 'n' && s[1] == 'o') {
+ opt = s + 2;
+ neg = 1;
+ } else {
+ opt = s;
+ neg = 0;
+ }
+
+ /*
+ * Scan the array of debug options to find the
+ * corresponding flag value. If it is found
+ * then set (or clear) the flag (depending on
+ * whether the option was prefixed with "no").
+ */
+ for (dp = optb; dp->opt; dp++) {
+ if (strcmp(opt, dp->opt) == 0)
+ break;
+ if (opt != s && !dpn && strcmp(s, dp->opt) == 0)
+ dpn = dp;
+ }
+
+ if (dp->opt || dpn) {
+ if (!dp->opt) {
+ dp = dpn;
+ neg = !neg;
+ }
+ if (neg)
+ *flags &= ~dp->flag;
+ else
+ *flags |= dp->flag;
+ } else {
+ /*
+ * This will log to stderr when parsing the command line
+ * since any -l option will not yet have taken effect.
+ */
+ plog(XLOG_USER, "option \"%s\" not recognised", s);
+ errs++;
+ }
+ /*
+ * Put the comma back
+ */
+ if (p)
+ *p++ = ',';
+ }
+
+ return errs;
+}
+
+/*
+ * Switch on/off logging options
+ */
+int switch_option(opt)
+char *opt;
+{
+ int xl = xlog_level;
+ int rc = cmdoption(opt, xlog_opt, &xl);
+ if (rc) {
+ rc = EINVAL;
+ } else {
+ /*
+ * Keep track of initial log level, and
+ * don't allow options to be turned off.
+ */
+ if (xlog_level_init == ~0)
+ xlog_level_init = xl;
+ else
+ xl |= xlog_level_init;
+ xlog_level = xl;
+ }
+ return rc;
+}
+
+/*
+ * Change current logfile
+ */
+int switch_to_logfile P((char *logfile));
+int switch_to_logfile(logfile)
+char *logfile;
+{
+ FILE *new_logfp = stderr;
+
+ if (logfile) {
+#ifdef HAS_SYSLOG
+ syslogging = 0;
+#endif /* HAS_SYSLOG */
+ if (strcmp(logfile, "/dev/stderr") == 0)
+ new_logfp = stderr;
+ else if (strcmp(logfile, "syslog") == 0) {
+#ifdef HAS_SYSLOG
+ syslogging = 1;
+ new_logfp = stderr;
+#if defined(LOG_CONS) && defined(LOG_NOWAIT)
+ openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
+ LOG_DAEMON);
+#else
+ /* 4.2 compat mode - XXX */
+ openlog(progname, LOG_PID);
+#endif /* LOG_CONS && LOG_NOWAIT */
+#else
+ plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
+#endif /* HAS_SYSLOG */
+ } else {
+ (void) umask(orig_umask);
+ new_logfp = fopen(logfile, "a");
+ umask(0);
+ }
+ }
+
+ /*
+ * If we couldn't open a new file, then continue using the old.
+ */
+ if (!new_logfp && logfile) {
+ plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
+ return 1;
+ }
+ /*
+ * Close the previous file
+ */
+ if (logfp && logfp != stderr)
+ (void) fclose(logfp);
+ logfp = new_logfp;
+ return 0;
+}
+
+time_t clock_valid = 0;
+time_t xclock_valid = 0;
+#ifndef clocktime
+time_t clocktime(P_void)
+{
+ time_t now = time(&clock_valid);
+ if (xclock_valid > now) {
+ /*
+ * Someone set the clock back!
+ */
+ plog(XLOG_WARNING, "system clock reset");
+ reschedule_timeouts(now, xclock_valid);
+ }
+ return xclock_valid = now;
+}
+#endif /* clocktime */
diff --git a/usr.sbin/amd/amq/Makefile b/usr.sbin/amd/amq/Makefile
new file mode 100644
index 0000000..adbd5f4
--- /dev/null
+++ b/usr.sbin/amd/amq/Makefile
@@ -0,0 +1,15 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG = amq
+SRCS = amq.c amq_clnt.c amq_xdr.c misc_rpc.c
+LDADD+=-lrpc
+CFLAGS+=-I${.CURDIR}/../include
+CFLAGS+=-I${.CURDIR}/../rpcx
+CFLAGS+=-I${.CURDIR}/../config
+CFLAGS+=-DARCH_REP=\"${MACHINE}\"
+CFLAGS+=-DOS_REP=\"bsd44\"
+CFLAGS+=-DOS_HDR=\"os-bsd44.h\"
+.PATH: ${.CURDIR}/../rpcx ${.CURDIR}/../amd
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/amd/amq/amq.8 b/usr.sbin/amd/amq/amq.8
new file mode 100644
index 0000000..5485925
--- /dev/null
+++ b/usr.sbin/amd/amq/amq.8
@@ -0,0 +1,130 @@
+.\"
+.\" Copyright (c) 1990 Jan-Simon Pendry
+.\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jan-Simon Pendry at Imperial College, London.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)amq.8 8.3 (Berkeley) 4/18/94
+.\"
+.\" $Id: amq.8,v 5.2.2.1 1992/02/09 15:11:41 jsp beta $
+.\"
+.Dd March 16, 1991
+.Dt AMQ 8
+.Os
+.Sh NAME
+.Nm amq
+.Nd automounter query tool
+.Sh SYNOPSIS
+.Nm amq
+.Op Fl f
+.Op Fl h Ar hostname
+.Op Fl M Ar mountmap_entry
+.Op Fl m
+.Op Fl s
+.Op Fl u
+.Op Fl v
+.Op Ar directory
+.Ar ...
+.Sh DESCRIPTION
+.Nm Amq
+provides a simple way of determining the current state of the
+.Xr amd 8
+program.
+Communication is by
+.Tn RPC .
+Three modes of operation are supported by the current protocol.
+By default a list of mount points and auto-mounted filesystems
+is output.
+An alternative host can be specified using the
+.Fl h
+option.
+.Pp
+If directory names are given, as output by default,
+then per-filesystem information is displayed.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl f
+Request automounter to flush the internal caches.
+.It Fl h Ar hostname
+Query alternate host
+.Ar hostname .
+By default the local host is used. In an
+.Tn HP-UX
+cluster, the root server is queried by default, since
+that is the system on which the automounter is normally run.
+.It Fl m
+Request the automounter to provide a list of mounted filesystems,
+including the number of references to each filesystem and any error
+which occurred while mounting.
+.It Fl s
+Request the automounter to provide system-wide mount statistics.
+.It Fl u
+Request the automounter to unmount the named filesystems
+instead of providing information about them. Unmounts are requested,
+not forced. They merely cause the mounted filesystem to timeout,
+which will be picked up by
+.Xr amd Ns \'s
+main scheduler thus causing the normal timeout action to be taken.
+.It Fl v
+Request the automounter to provide version information. This is a subset
+of the information provided by
+.Xr amd Ns \'s Fl v
+option.
+.It Fl M
+Request automounter to add the given map entry to the root map and then
+trigger a mount request for it.
+.El
+.Sh FILES
+.Bl -tag -width amq.xxxxx -compact
+.Bl -tag -width Ds
+.It Pa amq.x
+.Tn RPC
+protocol description.
+.El
+.Sh CAVEATS
+.Nm Amq
+uses a Sun registered
+.Tn RPC
+program number (300019 decimal) which may not
+be in the
+.Pa /etc/rpc
+database.
+.Sh SEE ALSO
+.Xr amd 8
+.Sh AUTHOR
+.An Jan-Simon Pendry
+<jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
+.Sh HISTORY
+.Nm Amq
+.At
diff --git a/usr.sbin/amd/amq/amq.c b/usr.sbin/amd/amq/amq.c
new file mode 100644
index 0000000..d3749bc
--- /dev/null
+++ b/usr.sbin/amd/amq/amq.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq.c 8.1 (Berkeley) 6/7/93
+ *
+ * $Id: amq.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
+ *
+ */
+
+/*
+ * Automounter query tool
+ */
+
+#ifndef lint
+char copyright[] = "\
+@(#)Copyright (c) 1990 Jan-Simon Pendry\n\
+@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
+@(#)Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char rcsid[] = "$Id: amq.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $";
+static char sccsid[] = "@(#)amq.c 8.1 (Berkeley) 6/7/93";
+#endif /* not lint */
+
+#include "am.h"
+#include "amq.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <netdb.h>
+
+static int privsock();
+
+char *progname;
+static int flush_flag;
+static int minfo_flag;
+static int unmount_flag;
+static int stats_flag;
+static int getvers_flag;
+static char *debug_opts;
+static char *logfile;
+static char *mount_map;
+static char *xlog_optstr;
+static char localhost[] = "localhost";
+static char *def_server = localhost;
+
+extern int optind;
+extern char *optarg;
+
+static struct timeval tmo = { 10, 0 };
+#define TIMEOUT tmo
+
+enum show_opt { Full, Stats, Calc, Short, ShowDone };
+
+/*
+ * If (e) is Calc then just calculate the sizes
+ * Otherwise display the mount node on stdout
+ */
+static void show_mti(mt, e, mwid, dwid, twid)
+amq_mount_tree *mt;
+enum show_opt e;
+int *mwid;
+int *dwid;
+int *twid;
+{
+ switch (e) {
+ case Calc: {
+ int mw = strlen(mt->mt_mountinfo);
+ int dw = strlen(mt->mt_directory);
+ int tw = strlen(mt->mt_type);
+ if (mw > *mwid) *mwid = mw;
+ if (dw > *dwid) *dwid = dw;
+ if (tw > *twid) *twid = tw;
+ } break;
+
+ case Full: {
+ struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
+printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
+ *twid, *twid,
+ mt->mt_type,
+ *mwid, *mwid,
+ mt->mt_mountinfo,
+ mt->mt_mountpoint,
+
+ mt->mt_mountuid,
+ mt->mt_getattr,
+ mt->mt_lookup,
+ mt->mt_readdir,
+ mt->mt_readlink,
+ mt->mt_statfs,
+
+ tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
+ tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ } break;
+
+ case Stats: {
+ struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
+printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
+
+ mt->mt_mountuid,
+ mt->mt_getattr,
+ mt->mt_lookup,
+ mt->mt_readdir,
+ mt->mt_readlink,
+ mt->mt_statfs,
+
+ tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
+ tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ } break;
+
+ case Short: {
+ printf("%-*.*s %-*.*s %-*.*s %s\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/",
+ *twid, *twid,
+ mt->mt_type,
+ *mwid, *mwid,
+ mt->mt_mountinfo,
+ mt->mt_mountpoint);
+ } break;
+ }
+}
+
+/*
+ * Display a mount tree.
+ */
+static void show_mt(mt, e, mwid, dwid, pwid)
+amq_mount_tree *mt;
+enum show_opt e;
+int *mwid;
+int *dwid;
+int *pwid;
+{
+ while (mt) {
+ show_mti(mt, e, mwid, dwid, pwid);
+ show_mt(mt->mt_next, e, mwid, dwid, pwid);
+ mt = mt->mt_child;
+ }
+}
+
+static void show_mi(ml, e, mwid, dwid, twid)
+amq_mount_info_list *ml;
+enum show_opt e;
+int *mwid;
+int *dwid;
+int *twid;
+{
+ int i;
+ switch (e) {
+ case Calc: {
+ for (i = 0; i < ml->amq_mount_info_list_len; i++) {
+ amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
+ int mw = strlen(mi->mi_mountinfo);
+ int dw = strlen(mi->mi_mountpt);
+ int tw = strlen(mi->mi_type);
+ if (mw > *mwid) *mwid = mw;
+ if (dw > *dwid) *dwid = dw;
+ if (tw > *twid) *twid = tw;
+ }
+ } break;
+
+ case Full: {
+ for (i = 0; i < ml->amq_mount_info_list_len; i++) {
+ amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
+ printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
+ *mwid, *mwid, mi->mi_mountinfo,
+ *dwid, *dwid, mi->mi_mountpt,
+ *twid, *twid, mi->mi_type,
+ mi->mi_refc, mi->mi_fserver,
+ mi->mi_up > 0 ? "up" :
+ mi->mi_up < 0 ? "starting" : "down");
+ if (mi->mi_error > 0) {
+#ifdef HAS_STRERROR
+ printf(" (%s)", strerror(mi->mi_error));
+#else
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+ if (mi->mi_error < sys_nerr)
+ printf(" (%s)", sys_errlist[mi->mi_error]);
+ else
+ printf(" (Error %d)", mi->mi_error);
+#endif
+ } else if (mi->mi_error < 0) {
+ fputs(" (in progress)", stdout);
+ }
+ fputc('\n', stdout);
+ }
+ } break;
+ }
+}
+
+/*
+ * Display general mount statistics
+ */
+static void show_ms(ms)
+amq_mount_stats *ms;
+{
+ printf("\
+requests stale mount mount unmount\n\
+deferred fhandles ok failed failed\n\
+%-9d %-9d %-9d %-9d %-9d\n",
+ ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
+}
+
+static bool_t
+xdr_pri_free(xdr_args, args_ptr)
+xdrproc_t xdr_args;
+caddr_t args_ptr;
+{
+ XDR xdr;
+ xdr.x_op = XDR_FREE;
+ return ((*xdr_args)(&xdr, args_ptr));
+}
+
+#ifdef hpux
+#include <cluster.h>
+static char *cluster_server()
+{
+ struct cct_entry *cp;
+
+ if (cnodeid() == 0) {
+ /*
+ * Not clustered
+ */
+ return def_server;
+ }
+
+ while (cp = getccent())
+ if (cp->cnode_type == 'r')
+ return cp->cnode_name;
+
+
+ return def_server;
+}
+#endif /* hpux */
+
+/*
+ * MAIN
+ */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int opt_ch;
+ int errs = 0;
+ char *server;
+ struct sockaddr_in server_addr;
+
+ /* In order to pass the Amd security check, we must use a priv port. */
+ int s;
+
+ CLIENT *clnt;
+ struct hostent *hp;
+ int nodefault = 0;
+
+ /*
+ * Compute program name
+ */
+ if (argv[0]) {
+ progname = strrchr(argv[0], '/');
+ if (progname && progname[1])
+ progname++;
+ else
+ progname = argv[0];
+ }
+ if (!progname)
+ progname = "amq";
+
+ /*
+ * Parse arguments
+ */
+ while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:M:")) != EOF)
+ switch (opt_ch) {
+ case 'f':
+ flush_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'h':
+ def_server = optarg;
+ break;
+
+ case 'l':
+ logfile = optarg;
+ nodefault = 1;
+ break;
+
+ case 'm':
+ minfo_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 's':
+ stats_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'u':
+ unmount_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'v':
+ getvers_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'x':
+ xlog_optstr = optarg;
+ nodefault = 1;
+ break;
+
+ case 'D':
+ debug_opts = optarg;
+ nodefault = 1;
+ break;
+
+ case 'M':
+ mount_map = optarg;
+ nodefault = 1;
+ break;
+
+ default:
+ errs = 1;
+ break;
+ }
+
+ if (optind == argc) {
+ if (unmount_flag)
+ errs = 1;
+ }
+
+ if (errs) {
+show_usage:
+ fprintf(stderr, "\
+Usage: %s [-h host] [[-f] [-m] [-v] [-s]] | [[-u] directory ...]] |\n\
+\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts] [-M mapent]\n", progname);
+ exit(1);
+ }
+
+#ifdef hpux
+ /*
+ * Figure out root server of cluster
+ */
+ if (def_server == localhost)
+ server = cluster_server();
+ else
+#endif /* hpux */
+ server = def_server;
+
+ /*
+ * Get address of server
+ */
+ if ((hp = gethostbyname(server)) == 0 && strcmp(server, localhost) != 0) {
+ fprintf(stderr, "%s: Can't get address of %s\n", progname, server);
+ exit(1);
+ }
+ bzero(&server_addr, sizeof server_addr);
+ server_addr.sin_family = AF_INET;
+ if (hp) {
+ bcopy((voidp) hp->h_addr, (voidp) &server_addr.sin_addr,
+ sizeof(server_addr.sin_addr));
+ } else {
+ /* fake "localhost" */
+ server_addr.sin_addr.s_addr = htonl(0x7f000001);
+ }
+
+ /*
+ * Create RPC endpoint
+ */
+ s = privsock(SOCK_STREAM);
+ clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
+ if (clnt == 0) {
+ close(s);
+ s = privsock(SOCK_DGRAM);
+ clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, TIMEOUT, &s);
+ }
+ if (clnt == 0) {
+ fprintf(stderr, "%s: ", progname);
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+ /*
+ * Control debugging
+ */
+ if (debug_opts) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_DEBUG;
+ opt.as_str = debug_opts;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (rc && *rc < 0) {
+ fprintf(stderr, "%s: daemon not compiled for debug", progname);
+ errs = 1;
+ } else if (!rc || *rc > 0) {
+ fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Control logging
+ */
+ if (xlog_optstr) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_XLOG;
+ opt.as_str = xlog_optstr;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_optstr);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Control log file
+ */
+ if (logfile) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_LOGFILE;
+ opt.as_str = logfile;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, logfile);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Flush map cache
+ */
+ if (flush_flag) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_FLUSHMAPC;
+ opt.as_str = "";
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Mount info
+ */
+ if (minfo_flag) {
+ int dummy;
+ amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
+ if (ml) {
+ int mwid = 0, dwid = 0, twid = 0;
+ show_mi(ml, Calc, &mwid, &dwid, &twid);
+ mwid++; dwid++; twid++;
+ show_mi(ml, Full, &mwid, &dwid, &twid);
+
+ } else {
+ fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server);
+ }
+ }
+
+ /*
+ * Mount map
+ */
+ if (mount_map) {
+ int *rc;
+ do {
+ rc = amqproc_mount_1(&mount_map, clnt);
+ } while (rc && *rc < 0);
+ if (!rc || *rc > 0) {
+ if (rc)
+ errno = *rc;
+ else
+ errno = ETIMEDOUT;
+ fprintf(stderr, "%s: could not start new ", progname);
+ perror("autmount point");
+ }
+ }
+
+ /*
+ * Get Version
+ */
+ if (getvers_flag) {
+ amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
+ if (spp && *spp) {
+ printf("%s.\n", *spp);
+ free(*spp);
+ } else {
+ fprintf(stderr, "%s: failed to get version information\n", progname);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Apply required operation to all remaining arguments
+ */
+ if (optind < argc) {
+ do {
+ char *fs = argv[optind++];
+ if (unmount_flag) {
+ /*
+ * Unmount request
+ */
+ amqproc_umnt_1(&fs, clnt);
+ } else {
+ /*
+ * Stats request
+ */
+ amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
+ if (mtp) {
+ amq_mount_tree *mt = *mtp;
+ if (mt) {
+ int mwid = 0, dwid = 0, twid = 0;
+ show_mt(mt, Calc, &mwid, &dwid, &twid);
+ mwid++; dwid++, twid++;
+ printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n",
+ dwid, dwid, "What");
+ show_mt(mt, Stats, &mwid, &dwid, &twid);
+ } else {
+ fprintf(stderr, "%s: %s not automounted\n", progname, fs);
+ }
+ xdr_pri_free(xdr_amq_mount_tree_p, (caddr_t) mtp);
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+ }
+ } while (optind < argc);
+ } else if (unmount_flag) {
+ goto show_usage;
+ } else if (stats_flag) {
+ amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
+ if (ms) {
+ show_ms(ms);
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+ } else if (!nodefault) {
+ amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
+ if (mlp) {
+ enum show_opt e = Calc;
+ int mwid = 0, dwid = 0, pwid = 0;
+ while (e != ShowDone) {
+ int i;
+ for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
+ show_mt(mlp->amq_mount_tree_list_val[i],
+ e, &mwid, &dwid, &pwid);
+ }
+ mwid++; dwid++, pwid++;
+ if (e == Calc) e = Short;
+ else if (e == Short) e = ShowDone;
+ }
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+ }
+
+ exit(errs);
+}
+
+/*
+ * udpresport creates a datagram socket and attempts to bind it to a
+ * secure port.
+ * returns: The bound socket, or -1 to indicate an error.
+ */
+static int inetresport(ty)
+int ty;
+{
+ int alport;
+ struct sockaddr_in addr;
+ int sock;
+
+ /* Use internet address family */
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ if ((sock = socket(AF_INET, ty, 0)) < 0)
+ return -1;
+ for (alport = IPPORT_RESERVED-1; alport > IPPORT_RESERVED/2 + 1; alport--) {
+ addr.sin_port = htons((u_short)alport);
+ if (bind(sock, (struct sockaddr *)&addr, sizeof (addr)) >= 0)
+ return sock;
+ if (errno != EADDRINUSE) {
+ close(sock);
+ return -1;
+ }
+ }
+ close(sock);
+ errno = EAGAIN;
+ return -1;
+}
+
+/*
+ * Privsock() calls inetresport() to attempt to bind a socket to a secure
+ * port. If inetresport() fails, privsock returns a magic socket number which
+ * indicates to RPC that it should make its own socket.
+ * returns: A privileged socket # or RPC_ANYSOCK.
+ */
+static int privsock(ty)
+int ty;
+{
+ int sock = inetresport(ty);
+
+ if (sock < 0) {
+ errno = 0;
+ /* Couldn't get a secure port, let RPC make an insecure one */
+ sock = RPC_ANYSOCK;
+ }
+ return sock;
+}
+
+#ifdef DEBUG
+xfree(f, l, p)
+char *f, *l;
+voidp p;
+{
+ free(p);
+}
+#endif /* DEBUG */
diff --git a/usr.sbin/amd/config/Configure b/usr.sbin/amd/config/Configure
new file mode 100644
index 0000000..2851786
--- /dev/null
+++ b/usr.sbin/amd/config/Configure
@@ -0,0 +1,60 @@
+#!/bin/sh -
+#
+# Copyright (c) 1989 Jan-Simon Pendry
+# Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the 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.
+#
+# @(#)Configure 8.1 (Berkeley) 6/6/93
+#
+# $Id: Configure,v 5.2.1.2 91/05/07 22:20:26 jsp Alpha $
+#
+echo "Making ./arch and ./os-type executable ..."
+until chmod +x ./arch ./os-type; do echo "Error: chmod command failed" >&2; exit 1; done
+echo "Checking ./arch and ./os-type ..."
+echo ""
+arch="`sh ./arch 2>/dev/null`"
+os="`sh ./os-type 2>/dev/null`"
+case "$arch" in
+"") echo "./arch doesn't produce an answer - please check it" >&2; exit 1;;
+esac
+case "$os" in
+"") echo "./os-type doesn't produce an answer - please check it" >&2; exit 1;;
+esac
+cat << %
+This machine appears to be a "$arch" running "$os".
+If that is correct just run make.
+If those are incorrect please edit ./arch and ./os-type
+%
+exit 0
diff --git a/usr.sbin/amd/config/Makefile.aix3 b/usr.sbin/amd/config/Makefile.aix3
new file mode 100644
index 0000000..c4bdd3a
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.aix3
@@ -0,0 +1,5 @@
+# @(#)Makefile.aix3 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.aix3,v 5.2.2.1 1992/02/09 15:10:06 jsp beta $
+#
+SYSLIB = -lbsd
diff --git a/usr.sbin/amd/config/Makefile.bsd44 b/usr.sbin/amd/config/Makefile.bsd44
new file mode 100644
index 0000000..a41ff2d
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.bsd44
@@ -0,0 +1,8 @@
+# @(#)Makefile.bsd44 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.bsd44,v 5.2.2.1 1992/02/09 15:10:12 jsp beta $
+#
+# Extra Makefile definitions for 4.4 BSD
+#
+
+RPCLIB = -lrpc
diff --git a/usr.sbin/amd/config/Makefile.config b/usr.sbin/amd/config/Makefile.config
new file mode 100644
index 0000000..0c4d7be
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.config
@@ -0,0 +1,91 @@
+# @(#)Makefile.config 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.config,v 5.2.2.1 1992/02/09 15:11:17 jsp beta $
+#
+
+#
+# Comment/uncomment the following lines as required
+#
+
+#
+# Where local include files are stored
+#
+#XINCLUDE = -I/usr/local/athena/include
+
+#
+# Define RESOLV if your C library does not include support
+# for Hesiod and/or Named.
+#
+#RESOLV = -lhesiod -lresolv
+
+#
+# Define XLIBDIR if you have libraries not on the standard
+# search path.
+#
+#XLIBDIR = -L/usr/local/athena/lib
+
+#
+# Define DBM if your C library does not include
+# support for gdbm and/or ndbm.
+#
+#DBM = -lgdbm #-lndbm
+
+#
+# Define RPCLIB if your C library does not include
+# support for RPC
+#
+#RPCLIB = -lrpc
+
+#
+# Include support for Network Information Service (NIS)
+# Also define HAS_NIS_RELOAD to include map
+# enumeration code implementing "cache:=all"
+#
+#HAS_NIS_MAPS = -DHAS_NIS_MAPS -DHAS_NIS_RELOAD
+
+#
+# Include support for file maps
+#
+HAS_FILE_MAPS = -DHAS_FILE_MAPS
+
+#
+# Include support for Hesiod
+# Also define HAS_HESIOD_RELOAD to include zone
+# transfer code implementing "cache:=all"
+#
+#HAS_HESIOD_MAPS = -DHAS_HESIOD_MAPS -DHAS_HESIOD_RELOAD
+
+#
+# Include support for /etc/passwd
+#
+HAS_PASSWD_MAPS = -DHAS_PASSWD_MAPS
+
+#
+# Include support for union maps
+#
+HAS_UNION_MAPS = -DHAS_UNION_MAPS
+
+#
+# Include support for ndbm.
+# This removes support for gdbm and is only supported
+# if your operating system supports ndbm
+#
+#HAS_NDBM_MAPS = -DHAS_NDBM_MAPS
+
+#
+# Include support for "regexp" maps
+#
+HAS_REGEXP = -DHAS_REGEXP
+
+#
+# Make sure that the hostname passed in RPC authentication packets
+# contains a fully qualified domain name. See nfs_ops.c
+#
+#HAS_NFS_QUALIFIED_NAMES = -DHAS_NFS_QUALIFIED_NAMES
+
+##############################################################
+# Do NOT edit the following lines
+#
+CONFIG = ${XINCLUDE} ${HAS_NIS_MAPS} ${HAS_FILE_MAPS} ${HAS_HESIOD_MAPS} \
+ ${HAS_NDBM_MAPS} ${HAS_MOUNTD_MAPS} ${HAS_PASSWD_MAPS} ${HAS_UNION_MAPS} \
+ ${HAS_REGEXP} ${HAS_NFS_QUALIFIED_NAMES}
diff --git a/usr.sbin/amd/config/Makefile.hpux b/usr.sbin/amd/config/Makefile.hpux
new file mode 100644
index 0000000..dd92f9e
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.hpux
@@ -0,0 +1,13 @@
+# @(#)Makefile.hpux 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.hpux,v 5.2.2.1 1992/02/09 15:10:26 jsp beta $
+#
+# Extra Makefile definitions for HP-UX
+#
+
+#CC = gcc ${GCCOPTS}
+# Works only on HP300
+CC = cc -Wc,-Nd2000
+SYSCC = $(CC)
+# Works only Hp800
+# CC = cc
diff --git a/usr.sbin/amd/config/Makefile.irix b/usr.sbin/amd/config/Makefile.irix
new file mode 100644
index 0000000..e936b45
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.irix
@@ -0,0 +1,10 @@
+# @(#)Makefile.irix 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.irix,v 5.2.2.1 1992/02/09 15:10:31 jsp beta $
+#
+# Extra Makefile definitions for IRIX
+#
+
+DEBUG = #-g -DDEBUG
+CCOPTS = -I/usr/include/sun -I/usr/include/bsd -DIRIX
+RESOLV = -lrpcsvc -lsun -lbsd
diff --git a/usr.sbin/amd/config/Makefile.irix3 b/usr.sbin/amd/config/Makefile.irix3
new file mode 100644
index 0000000..165e0e4
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.irix3
@@ -0,0 +1,13 @@
+# @(#)Makefile.irix3 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.irix3,v 5.2 1992/05/31 16:40:22 jsp Exp $
+#
+# Extra Makefile definitions for IRIX
+#
+
+# For 3.3.x and earlier we might need to indicate the Sun and BSD include
+# paths.
+
+DEBUG = #-g -DDEBUG
+CCOPTS = -I/usr/include/sun -I/usr/include/bsd
+RESOLV = -lrpcsvc -lsun -lbsd
diff --git a/usr.sbin/amd/config/Makefile.irix4 b/usr.sbin/amd/config/Makefile.irix4
new file mode 100644
index 0000000..4480e93
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.irix4
@@ -0,0 +1,14 @@
+# @(#)Makefile.irix4 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.irix4,v 5.2 1992/05/31 16:40:22 jsp Exp $
+#
+# Extra Makefile definitions for IRIX
+#
+
+# For 4.0.X and later we need to specify the -cckr option - although amd
+# has prototypes - some of the rpc prototypes clash. The special include
+# paths are not required. -lsun always comes before -lbsd.
+
+DEBUG = -g
+CCOPTS = -cckr
+RESOLV = -lrpcsvc -lsun -lbsd
diff --git a/usr.sbin/amd/config/Makefile.stellix b/usr.sbin/amd/config/Makefile.stellix
new file mode 100644
index 0000000..0bcfff6
--- /dev/null
+++ b/usr.sbin/amd/config/Makefile.stellix
@@ -0,0 +1,10 @@
+# @(#)Makefile.stellix 8.1 (Berkeley) 6/6/93
+#
+# $Id: Makefile.stellix,v 5.2.2.1 1992/02/09 15:10:45 jsp beta $
+#
+# Extra Makefile definitions for STELLIX
+#
+
+DEBUG = #-g -DDEBUG
+CCOPTS = -DSTELLIX
+RESOLV = -lrpcsvc
diff --git a/usr.sbin/amd/config/RELEASE b/usr.sbin/amd/config/RELEASE
new file mode 100644
index 0000000..36f8f1f
--- /dev/null
+++ b/usr.sbin/amd/config/RELEASE
@@ -0,0 +1 @@
+$Revision: 5.2.3.1 $ of $Date: 1993/06/01 11:43:31 $ bsd44
diff --git a/usr.sbin/amd/config/arch b/usr.sbin/amd/config/arch
new file mode 100644
index 0000000..71c9224
--- /dev/null
+++ b/usr.sbin/amd/config/arch
@@ -0,0 +1,126 @@
+#! /bin/sh
+#
+# Copyright (c) 1989 Jan-Simon Pendry
+# Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the 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.
+#
+# @(#)arch 8.1 (Berkeley) 6/6/93
+#
+# $Id: arch,v 5.2.2.2 1992/05/31 16:45:35 jsp Exp $
+#
+# Figure out machine architecture
+#
+
+PATH=/bin:/usr/bin:/usr/ucb:/etc:/usr/local/bin:${PATH} export PATH
+
+#
+# First try to find a standard command
+#
+a=arch # Sun compat
+m=machine # BSD compat
+u=uname # Sys5 compat
+
+if [ -f /etc/$a -o -f /bin/$a -o -f /usr/bin/$a -o -f /usr/local/bin/$a ]
+then
+ exec $a
+elif [ -f /etc/$m -o -f /bin/$m -o -f /usr/bin/$m -o -f /usr/ucb/$m -o -f /usr/local/bin/$m ]
+then
+ exec $m
+elif [ -f /etc/$u -o -f /bin/$u -o -f /usr/bin/$u -o -f /usr/local/bin/$u ]
+then
+ ARCH="`uname`"
+ case "$ARCH" in
+ "HP-UX") echo hp9000; exit 0;;
+ AIX*) MACH="`uname -m`"
+ case "$MACH" in
+ 00*) echo ibm6000; exit 0;;
+ 10*) echo ibm032; exit 0;;
+ 20*) echo ibm032; exit 0;;
+ esac
+ ;;
+ A/UX) echo macII ; exit 0 ;;
+ dgux) MACH="`uname -m`"
+ case "$MACH" in
+ AViiON) echo aviion; exit 0;;
+ esac
+ ;;
+ *) MACH="`uname -m`"
+ case "$MACH" in
+ IP6) echo mips; exit 0;;
+ IP7) echo mips; exit 0;;
+ *) ;;
+ esac
+ ;;
+ esac
+fi
+
+#
+# Take a pot-shot at your machine architecture
+#
+echo "# ... No ARCH= option specified; dynamically determining architecture" >&2
+
+case "`exec 2>/dev/null; head -2 /etc/motd`" in
+*"HP-UX"*) ARCH=hp9000;;
+*"Iris"*) ARCH=iris4d;;
+*"Ultrix"*) ARCH=vax;;
+*"RISC iX"*) ARCH=arm;;
+*"Umax 4.2"*) ARCH=encore;;
+*"Alliant Concentrix"*) ARCH=alliant;;
+*"FPS Model 500"*) ARCH=fps500;;
+*"HCX/UX"*) ARCH=harris;;
+*) ARCH=unknown;
+ if [ -d /usr/include/caif ]; then
+ ARCH=ibm032
+ elif [ -f /bin/pyr ]; then
+ if /bin/pyr; then
+ ARCH=pyr
+ fi
+ elif [ -d /NextApps ]; then
+ ARCH=next
+ elif [ -f /etc/comply ]; then
+ # Tex 4300 is essentially a sun 3.
+ ARCH=sun3
+ fi
+ ;;
+esac
+
+echo "# ... architecture appears to be \"${ARCH}\"" >&2
+echo $ARCH
+
+case "$ARCH" in
+unknown) exit 1
+esac
+
+exit 0
diff --git a/usr.sbin/amd/config/misc-aix3.h b/usr.sbin/amd/config/misc-aix3.h
new file mode 100644
index 0000000..2c97d81
--- /dev/null
+++ b/usr.sbin/amd/config/misc-aix3.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-aix3.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc-aix3.h,v 5.2.2.1 1992/02/09 15:10:05 jsp beta $
+ *
+ */
+
+struct ufs_args {
+ char *fspec; /* Block device */
+};
+
+struct nfs_args {
+ struct sockaddr_in addr; /* file server address */
+ fhandle_t fh; /* File handle to be mounted */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ char *hostname; /* server's hostname */
+ int acregmin; /* attr cache file min secs */
+ int acregmax; /* attr cache file max secs */
+ int acdirmin; /* attr cache dir min secs */
+ int acdirmax; /* attr cache dir max secs */
+ char *netname; /* server's netname */
+ int biods; /* number of BIODS */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define MNTOPT_RO "ro" /* read only */
+#define MNTOPT_RW "rw" /* read/write */
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_HARD "hard" /* hard mount */
+#define MNTOPT_NOSUID "nosuid"/* no set uid allowed */
+#define MNTOPT_NOAUTO "noauto"/* hide entry from mount -a */
+#define MNTOPT_INTR "intr" /* allow interrupts on hard mount */
+#define MNTOPT_SECURE "secure"/* use secure RPC for NFS */
+#define MNTOPT_GRPID "grpid" /* SysV-compatible group-id on create */
+#define MNTOPT_NOSUB "nosub" /* disallow mounts beneath this one */
+#define MNTOPT_MULTI "multi" /* Do multi-component lookup */
+#define MNTOPT_NOAC "noac" /* don't cache attributes */
+
+#define NFSMNT_SOFT 0x001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x002 /* set write size */
+#define NFSMNT_RSIZE 0x004 /* set read size */
+#define NFSMNT_TIMEO 0x008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x010 /* set number of request retrys */
+#define NFSMNT_HOSTNAME 0x020 /* set hostname for error printf */
+#define NFSMNT_INT 0x040 /* allow interrupts on hard mount */
+#define NFSMNT_NOAC 0x080 /* don't cache attributes */
+#define NFSMNT_ACREGMIN 0x0100 /* set min secs for file attr cache */
+#define NFSMNT_ACREGMAX 0x0200 /* set max secs for file attr cache */
+#define NFSMNT_ACDIRMIN 0x0400 /* set min secs for dir attr cache */
+#define NFSMNT_ACDIRMAX 0x0800 /* set max secs for dir attr cache */
+#define NFSMNT_SECURE 0x1000 /* secure mount */
+#define NFSMNT_BIODS 0x10000 /* Number of biods for the file system */
+
+#define DEF_BIODS 6
diff --git a/usr.sbin/amd/config/misc-hpux.h b/usr.sbin/amd/config/misc-hpux.h
new file mode 100644
index 0000000..d808627
--- /dev/null
+++ b/usr.sbin/amd/config/misc-hpux.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-hpux.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc-hpux.h,v 5.2.2.1 1992/02/09 15:10:24 jsp beta $
+ *
+ */
+
+/*
+ * These definitions are from <nfs/nfs.h>
+ * Unfortunately, that file cannot be included
+ * because it contains lots of structure definitions
+ * that are not wanted (they produce name clashes).
+ * Isn't HP-UX wonderful!
+ */
+
+/*
+ * HP-UX specific definitions
+ */
+struct nfs_args {
+ struct sockaddr_in *addr; /* file server address */
+ fhandle_t *fh; /* File handle to be mounted */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ char *hostname; /* server's name */
+#ifdef __hp9000s700 /* XXX for HPUX 8.0 */
+ char *fsname; /* server's filesystem name */
+#endif
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x002 /* set write size */
+#define NFSMNT_RSIZE 0x004 /* set read size */
+#define NFSMNT_TIMEO 0x008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x010 /* set number of request retrys */
+#define NFSMNT_HOSTNAME 0x020 /* set hostname for error printf */
+#define NFSMNT_INT 0x040 /* set option to have interruptable mounts */
+#define NFSMNT_NODEVS 0x080 /* turn off device file access (default on) */
diff --git a/usr.sbin/amd/config/misc-irix.h b/usr.sbin/amd/config/misc-irix.h
new file mode 100644
index 0000000..f7d6682
--- /dev/null
+++ b/usr.sbin/amd/config/misc-irix.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-irix.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc-irix.h,v 5.2.2.1 1992/02/09 15:10:30 jsp beta $
+ *
+ */
+
+#include <sys/fs/nfs_clnt.h>
+#include <sys/fsid.h>
+#include <sys/fstyp.h>
+
+struct ufs_args {
+ char *fspec;
+};
diff --git a/usr.sbin/amd/config/misc-next.h b/usr.sbin/amd/config/misc-next.h
new file mode 100644
index 0000000..46a498e
--- /dev/null
+++ b/usr.sbin/amd/config/misc-next.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-next.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc-next.h,v 5.2.2.1 1992/02/09 15:10:34 jsp beta $
+ *
+ */
+
+#include <nfs/nfs_mount.h>
diff --git a/usr.sbin/amd/config/misc-stellix.h b/usr.sbin/amd/config/misc-stellix.h
new file mode 100644
index 0000000..275a853
--- /dev/null
+++ b/usr.sbin/amd/config/misc-stellix.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-stellix.h 8.1 (Berkeley) 6/6/93
+ *
+ */
+
+#include <sys/fstyp.h>
+
+struct ufs_args {
+ char *fspec;
+};
+
+struct nfs_args {
+ struct sockaddr_in *addr; /* file server address */
+ fhandle_t *fh; /* File handle to be mounted */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int timeo; /* initial timeout in .1 secs *
+/
+ int retrans; /* times to retry send */
+ char *hostname; /* server's name */
+};
+#define NFSMNT_SOFT 0x001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x002 /* set write size */
+#define NFSMNT_RSIZE 0x004 /* set read size */
+#define NFSMNT_TIMEO 0x008 /* set initial timeout (= 1.6 sec) */
+#define NFSMNT_RETRANS 0x010 /* set number of request retrys */
+#define NFSMNT_HOSTNAME 0x020 /* set hostname for error printf */
+#define NFSMNT_INT 0x040 /* allow interrupts on hard mount */
diff --git a/usr.sbin/amd/config/misc-ultrix.h b/usr.sbin/amd/config/misc-ultrix.h
new file mode 100644
index 0000000..640c5a7
--- /dev/null
+++ b/usr.sbin/amd/config/misc-ultrix.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)misc-ultrix.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: misc-ultrix.h,v 5.2.2.1 1992/02/09 15:10:49 jsp beta $
+ *
+ */
+
+#include <nfs/nfs_gfs.h>
+#define KERNEL
+#include <sys/fs_types.h>
+#undef KERNEL
+
+#ifndef HOSTNAMESZ
+#include <nfs/nfs_clnt.h>
+#endif
+
+#include <ufs/ufs_mount.h>
+
+#define ufs_args ufs_specific
diff --git a/usr.sbin/amd/config/mount_aix.c b/usr.sbin/amd/config/mount_aix.c
new file mode 100644
index 0000000..07d9e80
--- /dev/null
+++ b/usr.sbin/amd/config/mount_aix.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount_aix.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mount_aix.c,v 5.2.2.1 1992/02/09 15:10:08 jsp beta $
+ *
+ */
+
+
+/*
+ * AIX 3 Mount helper
+ */
+
+#include "misc-aix3.h"
+
+static int aix3_mkvp(p, gfstype, flags, object, stub, host, info, info_size, args)
+char *p;
+int gfstype;
+int flags;
+char *object;
+char *stub;
+char *host;
+char *info;
+int info_size;
+char *args;
+{
+ struct vmount *vp = (struct vmount *) p;
+ bzero((voidp) vp, sizeof(*vp));
+ /*
+ * Fill in standard fields
+ */
+ vp->vmt_revision = VMT_REVISION;
+ vp->vmt_flags = flags;
+ vp->vmt_gfstype = gfstype;
+
+#define VMT_ROUNDUP(len) (4 * ((len + 3) / 4))
+#define VMT_ASSIGN(vp, idx, data, size) \
+ vp->vmt_data[idx].vmt_off = p - (char *) vp; \
+ vp->vmt_data[idx].vmt_size = size; \
+ bcopy(data, p, size); \
+ p += VMT_ROUNDUP(size);
+
+ /*
+ * Fill in all variable length data
+ */
+ p += sizeof(*vp);
+
+ VMT_ASSIGN(vp, VMT_OBJECT, object, strlen(object) + 1);
+ VMT_ASSIGN(vp, VMT_STUB, stub, strlen(stub) + 1);
+ VMT_ASSIGN(vp, VMT_HOST, host, strlen(host) + 1);
+ VMT_ASSIGN(vp, VMT_HOSTNAME, host, strlen(host) + 1);
+ VMT_ASSIGN(vp, VMT_INFO, info, info_size);
+ VMT_ASSIGN(vp, VMT_ARGS, args, strlen(args) + 1);
+
+#undef VMT_ASSIGN
+#undef VMT_ROUNDUP
+
+ /*
+ * Return length
+ */
+ return vp->vmt_length = p - (char *) vp;
+}
+
+/*
+ * Map from conventional mount arguments
+ * to AIX 3-style arguments.
+ */
+aix3_mount(fsname, dir, flags, type, data, args)
+char *fsname;
+char *dir;
+int flags;
+int type;
+void *data;
+char *args;
+{
+ char buf[4096];
+ int size;
+
+#ifdef DEBUG
+ dlog("aix3_mount: fsname %s, dir %s, type %d", fsname, dir, type);
+#endif /* DEBUG */
+
+/* aix3_mkvp(p, gfstype, flags, object, stub, host, info, info_size, args) */
+
+ switch (type) {
+
+ case MOUNT_TYPE_NFS: {
+ char *host = strdup(fsname);
+ char *rfs = strchr(host, ':');
+ int free_rfs = 0;
+ if (rfs) {
+ *rfs++ = '\0';
+ } else {
+ rfs = host;
+ free_rfs = 1;
+ host = strdup(hostname);
+ }
+
+ size = aix3_mkvp(buf, type, flags, rfs, dir, host, data, sizeof(struct nfs_args), args);
+ if (free_rfs)
+ free((voidp) rfs);
+ free(host);
+
+ } break;
+
+ case MOUNT_TYPE_UFS:
+ /* Need to open block device and extract log device info from sblk. */
+ return EINVAL;
+
+ default:
+ return EINVAL;
+ }
+#ifdef DEBUG
+ /*dlog("aix3_mkvp: flags %#x, size %d, args %s", flags, size, args);*/
+#endif /* DEBUG */
+
+ return vmount(buf, size);
+}
diff --git a/usr.sbin/amd/config/mount_irix.c b/usr.sbin/amd/config/mount_irix.c
new file mode 100644
index 0000000..9926960
--- /dev/null
+++ b/usr.sbin/amd/config/mount_irix.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount_irix.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mount_irix.c,v 5.2.2.1 1992/02/09 15:10:32 jsp beta $
+ *
+ */
+
+
+/*
+ * IRIX Mount helper
+ */
+
+#include "misc-irix.h"
+
+/*
+ * Map from conventional mount arguments
+ * to IRIX style arguments.
+ */
+irix_mount(fsname, dir, flags, type, data)
+char *fsname;
+char *dir;
+int flags;
+int type;
+void *data;
+{
+ int size;
+
+#ifdef DEBUG
+ dlog("irix_mount: fsname %s, dir %s, type %d", fsname, dir, type);
+#endif /* DEBUG */
+
+ if (type == MOUNT_TYPE_NFS) {
+
+ size = sizeof (struct nfs_args);
+
+ return mount(dir, dir, (MS_FSS|MS_DATA|flags),
+ type, (struct nfs_args *) data, size);
+
+ } else if (type == MOUNT_TYPE_UFS) {
+
+ return mount(fsname, dir, (MS_FSS|flags), type);
+
+ } else {
+ return EINVAL;
+ }
+
+}
diff --git a/usr.sbin/amd/config/mount_stellix.c b/usr.sbin/amd/config/mount_stellix.c
new file mode 100644
index 0000000..45703db
--- /dev/null
+++ b/usr.sbin/amd/config/mount_stellix.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount_stellix.c 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * IRIX Mount helper
+ */
+
+#include "misc-stellix.h"
+
+/*
+ * Map from conventional mount arguments
+ * to IRIX style arguments.
+ */
+stellix_mount(fsname, dir, flags, type, data)
+char *fsname;
+char *dir;
+int flags;
+int type;
+void *data;
+{
+
+#ifdef DEBUG
+ dlog("stellix_mount: fsname %s, dir %s, type %d", fsname, dir, type);
+#endif /* DEBUG */
+
+ if (type == MOUNT_TYPE_NFS) {
+
+ return mount(dir, dir, (MS_FSS|MS_NFS|flags),
+ type, (caddr_t) data );
+
+ } else if (type == MOUNT_TYPE_UFS) {
+
+ return mount(fsname, dir, (MS_FSS|flags), type);
+
+ } else {
+ return EINVAL;
+ }
+
+}
diff --git a/usr.sbin/amd/config/mtab_aix.c b/usr.sbin/amd/config/mtab_aix.c
new file mode 100644
index 0000000..78bf941
--- /dev/null
+++ b/usr.sbin/amd/config/mtab_aix.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mtab_aix.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mtab_aix.c,v 5.2.2.1 1992/02/09 15:10:07 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef READ_MTAB_AIX3_STYLE
+
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+
+static struct mntent *mnt_dup(mp)
+struct vmount *mp;
+{
+ struct mntent *new_mp = ALLOC(mntent);
+
+ char *ty;
+ new_mp->mnt_fsname = strdup(vmt2dataptr(mp, VMT_OBJECT));
+ new_mp->mnt_dir = strdup(vmt2dataptr(mp, VMT_STUB));
+ new_mp->mnt_opts = strdup(vmt2dataptr(mp, VMT_ARGS));
+ switch (mp->vmt_gfstype) {
+ case MNT_JFS: ty = MTAB_TYPE_UFS; break;
+ case MNT_NFS:
+ ty = MTAB_TYPE_NFS;
+ new_mp->mnt_fsname = str3cat(new_mp->mnt_fsname,
+ vmt2dataptr(mp, VMT_HOSTNAME),
+ ":", new_mp->mnt_fsname);
+ break;
+ default: ty = "unknown"; break;
+ }
+ new_mp->mnt_type = strdup(ty);
+ new_mp->mnt_passno = mp->vmt_vfsnumber;
+ new_mp->mnt_freq = 0;
+
+ return new_mp;
+}
+
+/*
+ * Read a mount table into memory
+ */
+mntlist *read_mtab(fs)
+char *fs;
+{
+ mntlist **mpp, *mhp;
+
+ int i;
+ char *mntinfo = 0, *cp;
+ struct vmount *vp;
+ int ret;
+
+ /*
+ * First figure out size of mount table
+ * and allocate space for a copy...
+ * Then get mount table for real.
+ */
+ ret = mntctl(MCTL_QUERY, sizeof(i), &i);
+ if (ret == 0) {
+ mntinfo = xmalloc(i);
+ ret = mntctl(MCTL_QUERY, i, mntinfo);
+ }
+
+ if (ret <= 0) {
+ plog(XLOG_ERROR, "mntctl: %m");
+ goto out;
+ }
+#ifdef DEBUG
+ /*dlog("mntctl returns %d structures", ret);*/
+#endif /* DEBUG */
+
+ mpp = &mhp;
+ for (i = 0, cp = mntinfo; i < ret; i++, cp += vp->vmt_length) {
+ vp = (struct vmount *) cp;
+
+ /*
+ * Allocate a new slot
+ */
+ *mpp = ALLOC(mntlist);
+
+ /*
+ * Copy the data returned by mntctl
+ */
+ (*mpp)->mnt = mnt_dup(vp);
+
+ /*
+ * Move to next pointer
+ */
+ mpp = &(*mpp)->mnext;
+ }
+
+ *mpp = 0;
+
+out:
+ if (mntinfo)
+ free(mntinfo);
+ return mhp;
+}
+
+#endif /* READ_MTAB_AIX3_STYLE */
diff --git a/usr.sbin/amd/config/mtab_bsd.c b/usr.sbin/amd/config/mtab_bsd.c
new file mode 100644
index 0000000..1d81127
--- /dev/null
+++ b/usr.sbin/amd/config/mtab_bsd.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mtab_bsd.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mtab_bsd.c,v 5.2.2.1 1992/02/09 15:10:13 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef READ_MTAB_BSD_STYLE
+
+#include <sys/mount.h>
+
+static struct mntent *mnt_dup(mp)
+struct statfs *mp;
+{
+ struct mntent *new_mp = ALLOC(mntent);
+ char *ty;
+
+ new_mp->mnt_fsname = strdup(mp->f_mntfromname);
+ new_mp->mnt_dir = strdup(mp->f_mntonname);
+ switch (mp->f_type) {
+ case MOUNT_UFS: ty = MTAB_TYPE_UFS; break;
+ case MOUNT_NFS: ty = MTAB_TYPE_NFS; break;
+ case MOUNT_MFS: ty = MTAB_TYPE_MFS; break;
+ default: ty = "unknown"; break;
+ }
+ new_mp->mnt_type = strdup(ty);
+ new_mp->mnt_opts = strdup("unset");
+ new_mp->mnt_freq = 0;
+ new_mp->mnt_passno = 0;
+
+ return new_mp;
+}
+
+/*
+ * Read a mount table into memory
+ */
+mntlist *read_mtab(fs)
+char *fs;
+{
+ mntlist **mpp, *mhp;
+ struct statfs *mntbufp, *mntp;
+
+ int nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
+
+ if (nloc == 0) {
+ plog(XLOG_ERROR, "Can't read mount table");
+ return 0;
+ }
+
+ mpp = &mhp;
+ for (mntp = mntbufp; mntp < mntbufp + nloc; mntp++) {
+ /*
+ * Allocate a new slot
+ */
+ *mpp = ALLOC(mntlist);
+
+ /*
+ * Copy the data returned by getmntent
+ */
+ (*mpp)->mnt = mnt_dup(mntp);
+
+ /*
+ * Move to next pointer
+ */
+ mpp = &(*mpp)->mnext;
+ }
+
+ /*
+ * Terminate the list
+ */
+ *mpp = 0;
+
+ return mhp;
+}
+
+#endif /* READ_MTAB_BSD_STYLE */
diff --git a/usr.sbin/amd/config/mtab_file.c b/usr.sbin/amd/config/mtab_file.c
new file mode 100644
index 0000000..8101f71
--- /dev/null
+++ b/usr.sbin/amd/config/mtab_file.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mtab_file.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mtab_file.c,v 5.2.2.1 1992/02/09 15:10:42 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef READ_MTAB_FROM_FILE
+
+#ifdef USE_FCNTL
+#include <fcntl.h>
+#else
+#include <sys/file.h>
+#endif /* USE_FCNTL */
+
+#ifdef UPDATE_MTAB
+
+/*
+ * Do strict /etc/mtab locking
+ */
+#define MTAB_LOCKING
+
+/*
+ * Firewall mtab entries
+ */
+#define MTAB_STRIPNL
+
+#include <sys/stat.h>
+static FILE *mnt_file;
+
+/*
+ * If the system is being trashed by something, then
+ * opening mtab may fail with ENFILE. So, go to sleep
+ * for a second and try again. (Yes - this has happened to me.)
+ *
+ * Note that this *may* block the automounter, oh well.
+ * If we get to this state then things are badly wrong anyway...
+ *
+ * Give the system 10 seconds to recover but then give up.
+ * Hopefully something else will exit and free up some file
+ * table slots in that time.
+ */
+#define NFILE_RETRIES 10 /* seconds */
+
+#ifdef MTAB_LOCKING
+#ifdef LOCK_FCNTL
+static int lock(fd)
+{
+ int rc;
+ struct flock lk;
+
+ lk.l_type = F_WRLCK;
+ lk.l_whence = 0;
+ lk.l_start = 0;
+ lk.l_len = 0;
+
+again:
+ rc = fcntl(fd, F_SETLKW, (caddr_t) &lk);
+ if (rc < 0 && (errno == EACCES || errno == EAGAIN)) {
+#ifdef DEBUG
+ dlog("Blocked, trying to obtain exclusive mtab lock");
+#endif /* DEBUG */
+ sleep(1);
+ goto again;
+ }
+ return rc;
+}
+#else
+#define lock(fd) (flock((fd), LOCK_EX))
+#endif /* LOCK_FCNTL */
+#endif /* MTAB_LOCKING */
+
+static FILE *open_locked_mtab(mtab_file, mode, fs)
+char *mtab_file;
+char *mode;
+char *fs;
+{
+ FILE *mfp = 0;
+
+#ifdef UPDATE_MTAB
+ /*
+ * There is a possible race condition if two processes enter
+ * this routine at the same time. One will be blocked by the
+ * exclusive lock below (or by the shared lock in setmntent)
+ * and by the time the second process has the exclusive lock
+ * it will be on the wrong underlying object. To check for this
+ * the mtab file is stat'ed before and after all the locking
+ * sequence, and if it is a different file then we assume that
+ * it may be the wrong file (only "may", since there is another
+ * race between the initial stat and the setmntent).
+ *
+ * Simpler solutions to this problem are invited...
+ */
+ int racing = 2;
+#ifdef MTAB_LOCKING
+ int rc;
+ int retries = 0;
+ struct stat st_before, st_after;
+#endif /* MTAB_LOCKING */
+
+ if (mnt_file) {
+#ifdef DEBUG
+ dlog("Forced close on %s in read_mtab", mtab_file);
+#endif /* DEBUG */
+ endmntent(mnt_file);
+ mnt_file = 0;
+ }
+
+#ifdef MTAB_LOCKING
+again:
+ if (mfp) {
+ endmntent(mfp);
+ mfp = 0;
+ }
+
+ clock_valid = 0;
+ if (stat(mtab_file, &st_before) < 0) {
+ plog(XLOG_ERROR, "%s: stat: %m", mtab_file);
+ if (errno == ESTALE) {
+ /* happens occasionally */
+ sleep(1);
+ goto again;
+ }
+ return 0;
+ }
+#endif /* MTAB_LOCKING */
+#endif /* UPDATE_MTAB */
+
+eacces:
+ mfp = setmntent(mtab_file, mode);
+ if (!mfp) {
+ /*
+ * Since setmntent locks the descriptor, it
+ * is possible it can fail... so retry if
+ * needed.
+ */
+ if (errno == EACCES || errno == EAGAIN) {
+#ifdef DEBUG
+ dlog("Blocked, trying to obtain exclusive mtab lock");
+#endif /* DEBUG */
+ goto eacces;
+ } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
+ sleep(1);
+ goto eacces;
+ }
+
+ plog(XLOG_ERROR, "setmntent(\"%s\", \"%s\"): %m", mtab_file, mode);
+ return 0;
+ }
+
+#ifdef MTAB_LOCKING
+#ifdef UPDATE_MTAB
+ /*
+ * At this point we have an exclusive lock on the mount list,
+ * but it may be the wrong one so...
+ */
+
+ /*
+ * Need to get an exclusive lock on the current
+ * mount table until we have a new copy written
+ * out, when the lock is released in free_mntlist.
+ * flock is good enough since the mount table is
+ * not shared between machines.
+ */
+ do
+ rc = lock(fileno(mfp));
+ while (rc < 0 && errno == EINTR);
+ if (rc < 0) {
+ plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab_file);
+ endmntent(mfp);
+ return 0;
+ }
+ /*
+ * Now check whether the mtab file has changed under our feet
+ */
+ if (stat(mtab_file, &st_after) < 0) {
+ plog(XLOG_ERROR, "%s: stat", mtab_file);
+ goto again;
+ }
+
+ if (st_before.st_dev != st_after.st_dev ||
+ st_before.st_ino != st_after.st_ino) {
+ struct timeval tv;
+ if (racing == 0) {
+ /* Sometimes print a warning */
+ plog(XLOG_WARNING,
+ "Possible mount table race - retrying %s", fs);
+ }
+ racing = (racing+1) & 3;
+ /*
+ * Take a nap. From: Doug Kingston <dpk@morgan.com>
+ */
+ tv.tv_sec = 0;
+ tv.tv_usec = (mypid & 0x07) << 17;
+ if (tv.tv_usec)
+ if (select(0, (voidp) 0, (voidp) 0, (voidp) 0, &tv) < 0)
+ plog(XLOG_WARNING, "mtab nap failed: %m");
+
+ goto again;
+ }
+#endif /* UPDATE_MTAB */
+#endif /* MTAB_LOCKING */
+
+ return mfp;
+}
+
+/*
+ * Unlock the mount table
+ */
+void unlock_mntlist P((void));
+void unlock_mntlist()
+{
+ /*
+ * Release file lock, by closing the file
+ */
+ if (mnt_file) {
+ endmntent(mnt_file);
+ mnt_file = 0;
+ }
+}
+
+/*
+ * Write out a mount list
+ */
+void rewrite_mtab(mp)
+mntlist *mp;
+{
+ FILE *mfp;
+ int error = 0;
+
+ /*
+ * Concoct a temporary name in the same
+ * directory as the target mount table
+ * so that rename() will work.
+ */
+ char tmpname[64];
+ int retries;
+ int tmpfd;
+ char *cp;
+ char *mcp = mtab;
+ cp = strrchr(mcp, '/');
+ if (cp) {
+ bcopy(mcp, tmpname, cp - mcp);
+ tmpname[cp-mcp] = '\0';
+ } else {
+ plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mtab);
+ tmpname[0] = '.'; tmpname[1] = '\0';
+ }
+ strcat(tmpname, "/mtabXXXXXX");
+ mktemp(tmpname);
+ retries = 0;
+enfile1:
+ if ((tmpfd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
+ if (errno == ENFILE && retries++ < NFILE_RETRIES) {
+ sleep(1);
+ goto enfile1;
+ }
+ plog(XLOG_ERROR, "%s: open: %m", tmpname);
+ return;
+ }
+ if (close(tmpfd) < 0)
+ plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m");
+
+ retries = 0;
+enfile2:
+ mfp = setmntent(tmpname, "w");
+ if (!mfp) {
+ if (errno == ENFILE && retries++ < NFILE_RETRIES) {
+ sleep(1);
+ goto enfile2;
+ }
+ plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname);
+ error = 1;
+ goto out;
+ }
+
+ while (mp) {
+ if (mp->mnt) {
+ if (addmntent(mfp, mp->mnt)) {
+ plog(XLOG_ERROR, "Can't write entry to %s", tmpname);
+ error = 1;
+ goto out;
+ }
+ }
+ mp = mp->mnext;
+ }
+
+ /*
+ * SunOS 4.1 manuals say that the return code from entmntent()
+ * is always 1 and to treat as a void. That means we need to
+ * call fflush() to make sure the new mtab file got written.
+ */
+ if (fflush(mfp)) {
+ plog(XLOG_ERROR, "flush new mtab file: %m");
+ error = 1;
+ goto out;
+ }
+
+ (void) endmntent(mfp);
+
+ /*
+ * Rename temporary mtab to real mtab
+ */
+ if (rename(tmpname, mtab) < 0) {
+ plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mtab);
+ error = 1;
+ goto out;
+ }
+
+out:
+ if (error)
+ (void) unlink(tmpname);
+}
+
+#ifdef MTAB_STRIPNL
+static void mtab_stripnl(s)
+char *s;
+{
+ do {
+ s = strchr(s, '\n');
+ if (s)
+ *s++ = ' ';
+ } while (s);
+}
+#endif /* MTAB_STRIPNL */
+
+/*
+ * Append a mntent structure to the
+ * current mount table.
+ */
+void write_mntent(mp)
+struct mntent *mp;
+{
+ int retries = 0;
+ FILE *mfp;
+enfile:
+ mfp = open_locked_mtab(mtab, "a", mp->mnt_dir);
+ if (mfp) {
+#ifdef MTAB_STRIPNL
+ mtab_stripnl(mp->mnt_opts);
+#endif /* MTAB_STRIPNL */
+ if (addmntent(mfp, mp))
+ plog(XLOG_ERROR, "Couldn't write %s: %m", mtab);
+ if (fflush(mfp))
+ plog(XLOG_ERROR, "Couldn't flush %s: %m", mtab);
+ (void) endmntent(mfp);
+ } else {
+ if (errno == ENFILE && retries < NFILE_RETRIES) {
+ sleep(1);
+ goto enfile;
+ }
+ plog(XLOG_ERROR, "setmntent(\"%s\", \"a\"): %m", mtab);
+ }
+}
+
+#endif /* UPDATE_MTAB */
+
+static struct mntent *mnt_dup(mp)
+struct mntent *mp;
+{
+ struct mntent *new_mp = ALLOC(mntent);
+
+ new_mp->mnt_fsname = strdup(mp->mnt_fsname);
+ new_mp->mnt_dir = strdup(mp->mnt_dir);
+ new_mp->mnt_type = strdup(mp->mnt_type);
+ new_mp->mnt_opts = strdup(mp->mnt_opts);
+
+ new_mp->mnt_freq = mp->mnt_freq;
+ new_mp->mnt_passno = mp->mnt_passno;
+
+#ifdef FIXUP_MNTENT_DUP
+ /*
+ * Additional fields get dup'ed here
+ */
+ FIXUP_MNTENT_DUP(new_mp, mp);
+#endif
+
+ return new_mp;
+}
+
+/*
+ * Read a mount table into memory
+ */
+mntlist *read_mtab(fs)
+char *fs;
+{
+ mntlist **mpp, *mhp;
+
+ struct mntent *mep;
+ FILE *mfp = open_locked_mtab(mtab, "r+", fs);
+
+ if (!mfp)
+ return 0;
+
+ mpp = &mhp;
+
+/*
+ * XXX - In SunOS 4 there is (yet another) memory leak
+ * which loses 1K the first time getmntent is called.
+ * (jsp)
+ */
+ while (mep = getmntent(mfp)) {
+ /*
+ * Allocate a new slot
+ */
+ *mpp = ALLOC(mntlist);
+
+ /*
+ * Copy the data returned by getmntent
+ */
+ (*mpp)->mnt = mnt_dup(mep);
+
+ /*
+ * Move to next pointer
+ */
+ mpp = &(*mpp)->mnext;
+ }
+ *mpp = 0;
+
+#ifdef UPDATE_MTAB
+ /*
+ * If we are not updating the mount table then we
+ * can free the resources held here, otherwise they
+ * must be held until the mount table update is complete
+ */
+ mnt_file = mfp;
+#else
+ endmntent(mfp);
+#endif /* UPDATE_MTAB */
+
+ return mhp;
+}
+
+#endif /* READ_MTAB_FROM_FILE */
diff --git a/usr.sbin/amd/config/mtab_ultrix.c b/usr.sbin/amd/config/mtab_ultrix.c
new file mode 100644
index 0000000..241ea88
--- /dev/null
+++ b/usr.sbin/amd/config/mtab_ultrix.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mtab_ultrix.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mtab_ultrix.c,v 5.2.2.1 1992/02/09 15:10:50 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+#ifdef READ_MTAB_ULTRIX_STYLE
+
+#include <sys/mount.h>
+#include <sys/fs_types.h>
+
+static struct mntent *mnt_dup(mp)
+struct fs_data *mp;
+{
+ struct mntent *new_mp = ALLOC(mntent);
+
+ new_mp->mnt_fsname = strdup(mp->fd_devname);
+ new_mp->mnt_dir = strdup(mp->fd_path);
+ if (mp->fd_fstype >= GT_NUMTYPES)
+ mp->fd_fstype = GT_UNKWN;
+ else if (gt_names[mp->fd_fstype] == 0)
+ mp->fd_fstype = GT_UNKWN;
+ new_mp->mnt_type = strdup(gt_names[mp->fd_fstype]);
+ new_mp->mnt_opts = strdup("unset");
+
+ new_mp->mnt_freq = 0;
+ new_mp->mnt_passno = mp->fd_dev;
+
+ return new_mp;
+}
+
+/*
+ * Read a mount table into memory
+ */
+mntlist *read_mtab(fs)
+char *fs;
+{
+ mntlist **mpp, *mhp;
+
+/* From: Piete Brooks <pb@cl.cam.ac.uk> */
+
+ int loc=0;
+#undef NMOUNT
+#define NMOUNT 20
+ struct fs_data mountbuffer[NMOUNT], *fs_data;
+ int ret;
+
+ mpp = &mhp;
+ while ((ret = getmountent(&loc, mountbuffer, NMOUNT)) > 0) {
+ for (fs_data = mountbuffer; fs_data < &mountbuffer[ret]; fs_data++) {
+ /*
+ * Allocate a new slot
+ */
+ *mpp = ALLOC(mntlist);
+
+ /*
+ * Copy the data returned by getmntent
+ */
+ (*mpp)->mnt = mnt_dup(fs_data);
+
+ /*
+ * Move to next pointer
+ */
+ mpp = &(*mpp)->mnext;
+ }
+ }
+ if (ret < 0) {
+ plog(XLOG_ERROR, "getmountent: %m");
+ return 0;
+ }
+ *mpp = 0;
+
+ return mhp;
+}
+
+#endif /* READ_MTAB_ULTRIX_STYLE */
diff --git a/usr.sbin/amd/config/newvers.sh b/usr.sbin/amd/config/newvers.sh
new file mode 100644
index 0000000..a510966
--- /dev/null
+++ b/usr.sbin/amd/config/newvers.sh
@@ -0,0 +1,88 @@
+#!/bin/sh -
+#
+# Copyright (c) 1989 Jan-Simon Pendry
+# Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All Rights Reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the 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.
+#
+# @(#)newvers.sh 8.1 (Berkeley) 6/6/93
+#
+# $Id: newvers.sh,v 5.2.2.1 1992/02/09 15:11:19 jsp beta $
+#
+PATH=/usr/ucb:/bin:/usr/bin:$PATH
+if [ $# -ne 3 ]; then echo "Usage: newvers program arch os" >&2; exit 1; fi
+version="version.$1"
+if [ ! -r $version ]; then echo 0 > $version; chmod 444 $version; fi
+v=`cat $version`
+u=${USER-${LOGNAME-root}}
+h=`hostname`
+#h=`expr "$h" : '\([^.]*\)'`
+t=`date`
+if [ ! -s "$d../config/RELEASE" -o ! -s "$d../text/COPYRIGHT" ]; then
+ echo ERROR: config file missing >&2
+ exit 1
+fi
+rm -f vers.$1.c
+(
+cat << %%
+char copyright[] = "\\
+%%
+sed 's/$/\\n\\/' $d../text/COPYRIGHT
+cat << %%
+";
+char version[] = "\\
+%%
+cat << %%
+$1 \\
+%%
+sed \
+ -e 's/\$//g' \
+ -e 's/[A-Z][a-z]*://g' \
+ -e 's/ */ /g' \
+ -e 's/^ //' \
+ -e 's/$/\\/' \
+ $d../config/RELEASE
+cat << %%
+ #${v}: ${t}\\n\\
+Built by ${u}@${h} for \\
+%%
+case "$2" in
+[aeiou]*) echo "an \\" ;;
+*) echo "a \\";;
+esac
+echo "$2 running $3\";"
+) > vers.$1.c
+rm -f $version
+expr ${v} + 1 > $version
+chmod 444 $version
diff --git a/usr.sbin/amd/config/os-acis43.h b/usr.sbin/amd/config/os-acis43.h
new file mode 100644
index 0000000..bcc44d5
--- /dev/null
+++ b/usr.sbin/amd/config/os-acis43.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-acis43.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-acis43.h,v 5.2.2.1 1992/02/09 15:10:02 jsp beta $
+ *
+ * IBM RT ACIS4.3 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Need precise symlink lengths
+#define PRECISE_SYMLINKS
+ */
diff --git a/usr.sbin/amd/config/os-aix3.h b/usr.sbin/amd/config/os-aix3.h
new file mode 100644
index 0000000..c70b159
--- /dev/null
+++ b/usr.sbin/amd/config/os-aix3.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-aix3.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-aix3.h,v 5.2.2.2 1992/05/31 16:38:49 jsp Exp $
+ *
+ * AIX 3.1 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_AIX3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * Pick up BSD bits from include files
+ * Try for 4.4 compatibility if available (AIX 3.2 and later)
+ */
+#define _BSD 44
+
+/*
+ * No mntent info on AIX 3
+ */
+#undef MNTENT_HDR
+#define MNTENT_HDR <sys/mntctl.h>
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MNT_NFS
+#define MOUNT_TYPE_UFS MNT_JFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "jfs"
+
+/*
+ * How to unmount filesystems
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flag, mnt_data) \
+ aix3_mount(mnt->mnt_fsname, mnt->mnt_dir, flag, type, mnt_data, mnt->mnt_opts)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) uvmount(mnt->mnt_passno, 0)
+
+
+/*
+ * Byte ordering
+ */
+#ifndef BYTE_ORDER
+#include <sys/machine.h>
+#endif /* BYTE_ORDER */
+
+#undef ARCH_ENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ARCH_ENDIAN "little"
+#else
+#if BYTE_ORDER == BIG_ENDIAN
+#define ARCH_ENDIAN "big"
+#else
+XXX - Probably no hope of running Amd on this machine!
+#endif /* BIG */
+#endif /* LITTLE */
+
+/*
+ * Miscellaneous AIX 3 bits
+ */
+#define NEED_MNTOPT_PARSER
+#define SHORT_MOUNT_NAME
+
+#define MNTMAXSTR 128
+
+#define MNTTYPE_UFS "jfs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+
+#define NFS_HDR "misc-aix3.h"
+#define UFS_HDR "misc-aix3.h"
+#undef NFS_FH_DREF
+#define NFS_FH_DREF(dst, src) { (dst) = *(src); }
+#undef NFS_SA_DREF
+#define NFS_SA_DREF(dst, src) { (dst).addr = *(src); }
+#define M_RDONLY MNT_READONLY
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_AIX3_STYLE
+
+/*
+ * The data for the mount syscall needs the path in addition to the
+ * host name since that is the only source of information about the
+ * mounted filesystem.
+#define NFS_ARGS_NEEDS_PATH
+ */
+
+#define NFS_LOMAP 34
+#define NFS_HIMAP 99
+#define NFS_ERROR_MAPPING \
+static nfs_errormap[] = { 0,75,77,99,99,99, \
+ 99,99,99,99,99,78,99,99,99,79, \
+ 99,99,70,99,35,36,37,38,39,40, \
+ 41,42,43,44,45,46,47,48,49,50, \
+ 51,52,53,54,55,56,57,58,60,61, \
+ 64,65,99,67,68,62,63,66,69,68, \
+ 99,99,99,71,99,99,99,99,99,99 \
+ };
+
+#define MOUNT_HELPER_SOURCE "mount_aix.c"
+
+/*
+ * Need this too
+ */
+#include <time.h>
diff --git a/usr.sbin/amd/config/os-aux.h b/usr.sbin/amd/config/os-aux.h
new file mode 100644
index 0000000..edd85a4
--- /dev/null
+++ b/usr.sbin/amd/config/os-aux.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-aux.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-aux.h,v 5.2.2.1 1992/02/09 15:10:10 jsp beta $
+ *
+ * A/UX macII definitions for Amd (automounter)
+ * Contributed by Julian Onions <jpo@cs.nott.ac.uk>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * No support for ndbm
+ */
+#undef OS_HAS_NDBM
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
+
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "5.2"
+
+#define SIGCHLD SIGCLD
+#define SYS5_SIGNALS
+
+/*
+ * Use <fcntl.h> rather than <sys/file.h>
+ */
+#define USE_FCNTL
+
+/*
+ * Use fcntl() rather than flock()
+ */
+#define LOCK_FCNTL
+
+#ifdef __GNUC__
+#define alloca(sz) __builtin_alloca(sz)
+#endif
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+#define getpagesize() (2048)
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ fsmount(type, mnt->mnt_dir, flags, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) unmount(mnt->mnt_dir)
+#define NFDS 30 /* conservative */
+
+/* not included in sys/param.h */
+#include <sys/types.h>
+/* not part of sys/time.h */
+#include <time.h>
+/* for NMOUNT */
+#include <sys/config.h>
diff --git a/usr.sbin/amd/config/os-bsd44.h b/usr.sbin/amd/config/os-bsd44.h
new file mode 100644
index 0000000..837d596
--- /dev/null
+++ b/usr.sbin/amd/config/os-bsd44.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-bsd44.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-bsd44.h,v 5.2.2.1 1992/02/09 15:10:11 jsp beta $
+ *
+ * 4.4 BSD definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_44
+#define HAS_TCP_NFS
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * 4.4 doesn't provide NIS.
+ */
+#undef HAS_NIS_MAPS
+
+/*
+ * OS provides strerror()
+ */
+#define HAS_STRERROR
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * No mntent info on 4.4 BSD
+ */
+#undef MNTENT_HDR
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+#define MTAB_TYPE_MFS "mfs"
+
+/*
+ * How to unmount filesystems
+ */
+#undef UNMOUNT_TRAP
+#undef NEED_UMOUNT_FS
+#define NEED_UMOUNT_BSD
+
+/*
+ * How to copy an address into an NFS filehandle
+ */
+#undef NFS_SA_DREF
+#define NFS_SA_DREF(dst, src) { \
+ (dst).addr = (struct sockaddr *) (src); \
+ (dst).addrlen = sizeof(*src); \
+ (dst).sotype = SOCK_DGRAM; \
+ (dst).proto = 0; \
+ }
+
+/*
+ * Byte ordering
+ */
+#ifndef BYTE_ORDER
+#include <machine/endian.h>
+#endif /* BYTE_ORDER */
+
+#undef ARCH_ENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ARCH_ENDIAN "little"
+#else
+#if BYTE_ORDER == BIG_ENDIAN
+#define ARCH_ENDIAN "big"
+#else
+XXX - Probably no hope of running Amd on this machine!
+#endif /* BIG */
+#endif /* LITTLE */
+
+/*
+ * Miscellaneous 4.4 BSD bits
+ */
+#define NEED_MNTOPT_PARSER
+#define SHORT_MOUNT_NAME
+
+#define MNTMAXSTR 128
+
+#define MNTTYPE_UFS "ufs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_MFS "mfs" /* memory file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+#define M_RDONLY MNT_RDONLY
+#define M_SYNC MNT_SYNCHRONOUS
+#define M_NOEXEC MNT_NOEXEC
+#define M_NOSUID MNT_NOSUID
+#define M_NODEV MNT_NODEV
+
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_INTR "intr" /* interrupts allowed */
+
+#define NFSMNT_HOSTNAME 0 /* hostname on 4.4 is not optional */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+
+/*
+ * Type of a file handle
+ */
+#undef NFS_FH_TYPE
+#define NFS_FH_TYPE nfsv2fh_t *
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_BSD_STYLE
+
+/*
+ * The data for the mount syscall needs the path in addition to the
+ * host name since that is the only source of information about the
+ * mounted filesystem.
+ */
+#define NFS_ARGS_NEEDS_PATH
+
+/*
+ * 4.4 has RE support built in
+ */
+#undef RE_HDR
+#define RE_HDR <regexp.h>
diff --git a/usr.sbin/amd/config/os-concentrix.h b/usr.sbin/amd/config/os-concentrix.h
new file mode 100644
index 0000000..4a130e0
--- /dev/null
+++ b/usr.sbin/amd/config/os-concentrix.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-concentrix.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-concentrix.h,v 5.2.2.1 1992/02/09 15:10:14 jsp beta $
+ *
+ * Alliant Concentrix 5.0.0 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#undef VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
diff --git a/usr.sbin/amd/config/os-convex.h b/usr.sbin/amd/config/os-convex.h
new file mode 100644
index 0000000..ade6c4c
--- /dev/null
+++ b/usr.sbin/amd/config/os-convex.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-convex.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-convex.h,v 5.2.2.1 1992/02/09 15:10:16 jsp beta $
+ *
+ * Convex C220, version 7.1 definitions for Amd (automounter)
+ * from Eitan Mizrotsky <eitan@shum.huji.ac.il>
+ */
+
+
+/*
+ * Does the compiler grok void *
+ */
+#undef VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
+
+
+#define strrchr rindex
+#define strchr index
diff --git a/usr.sbin/amd/config/os-defaults.h b/usr.sbin/amd/config/os-defaults.h
new file mode 100644
index 0000000..ce10ae2
--- /dev/null
+++ b/usr.sbin/amd/config/os-defaults.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-defaults.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-defaults.h,v 5.2.2.1 1992/02/09 15:10:17 jsp beta $
+ *
+ * Common OS definitions. These may be overridden in
+ * the OS specific files ("os-foo.h").
+ */
+
+/*
+ * What level of AMD are we backward compatible with?
+ * This only applies to externally visible characteristics.
+ * Rev.Minor.Branch.Patch (2 digits each)
+ */
+#define AMD_COMPAT 5000000 /* 5.0 */
+
+/*
+ * What type is free(void*) returning?
+ */
+#define FREE_RETURN_TYPE void
+
+/*
+ * Is the mount table mirrored in software
+ */
+#define UPDATE_MTAB
+
+/*
+ * Where to get union wait
+ */
+#define WAIT <sys/wait.h>
+
+/*
+ * Where to get mount entry info
+ */
+#define MNTENT_HDR <mntent.h>
+
+/*
+ * Include support for syslog()
+ */
+#define HAS_SYSLOG
+
+/*
+ * Byte ordering
+ */
+#define ARCH_ENDIAN "unknown"
+
+/*
+ * Name of filesystem types
+ */
+#define MTAB_TYPE_NFS "nfs"
+#define MTAB_TYPE_UFS "4.2"
+
+/*
+ * Name of mount & unmount system calls
+ *
+ * NOTE:
+ * UNMOUNT_TRAP takes a struct mntent *
+ */
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ mount(type, mnt->mnt_dir, flags, mnt_data)
+#define UNMOUNT_TRAP(mnt) unmount(mnt->mnt_dir)
+
+/*
+ * How to unmount filesystems.
+ * NEED_UMOUNT_FS includes code to scan the mount table
+ * to find the correct information for the unmount system
+ * call. Some systems, such as 4.4bsd, do not require
+ * this - they can just do an unmount system call directly.
+ */
+#define NEED_UMOUNT_FS
+#define UMOUNT_FS(dir) umount_fs(dir)
+
+/*
+ * Type of a file handle
+ */
+#define NFS_FH_TYPE fhandle_t *
+#define NFS_FH_DREF(dst, src) { (dst) = (src); }
+
+/*
+ * How to copy an address into an NFS filehandle
+ */
+#define NFS_SA_DREF(dst, src) { (dst).addr = (src); }
+
+/*
+ * Type of filesystem type
+ */
+#define MTYPE_TYPE int
+
+/*
+ * How to get a mount list
+ */
+#define READ_MTAB_FROM_FILE
+
+/*
+ * Make Amd automount points appear
+ * to be zero sized. undef this
+ * if the O/S has a divide by zero
+ * problem in df et al.
+ */
+#define HAS_EMPTY_AUTOMOUNTS
+
+/*
+ * For the RE matcher
+ */
+#define CHARBITS 0377
+#define STRCSPN
+#define RE_HDR "re.h"
diff --git a/usr.sbin/amd/config/os-dgux.h b/usr.sbin/amd/config/os-dgux.h
new file mode 100644
index 0000000..98c81bf
--- /dev/null
+++ b/usr.sbin/amd/config/os-dgux.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-dgux.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-dgux.h,v 5.2.2.1 1992/02/09 15:10:18 jsp beta $
+ *
+ * dg/ux definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_4
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS "nfs"
+#define MOUNT_TYPE_UFS "dg/ux"
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "dg/ux"
+
+/*
+ * Need the following in more places than just NFS_HDR
+ */
+#include <sys/dg_mount.h>
+/*
+ * This is braindead
+ * dg/ux has nfs 4.0 but doesn't have the following options
+ */
+#define NFSMNT_HOSTNAME 0x0
+#define NFSMNT_INT 0x0
+#define M_NEWTYPE 0
+
+/*
+ * DG have their own filesystem.
+ */
+#define ufs_args dgux_args
+
+/*
+ * Byte ordering
+ */
+
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+#define _BSD_WAIT_FLAVOR
+#define _BSD_TTY_FLAVOR
+#define _BSD_SIGNAL_FLAVOR
+#define _DGUX_SOURCE
+
+/*
+ * Use fcntl() rather than flock()
+ */
+#define LOCK_FCNTL
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ ((struct nfs_args *)mnt_data)->version = !strcmp(type, MOUNT_TYPE_UFS)?\
+ DG_MOUNT_DGUX_VERSION:DG_MOUNT_NFS_VERSION, \
+ dg_mount(type, mnt->mnt_dir, flags, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
diff --git a/usr.sbin/amd/config/os-fpx4.h b/usr.sbin/amd/config/os-fpx4.h
new file mode 100644
index 0000000..8c69421
--- /dev/null
+++ b/usr.sbin/amd/config/os-fpx4.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-fpx4.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-fpx4.h,v 5.2.2.2 1992/05/31 16:39:34 jsp Exp $
+ *
+ * Celerity FPX 4.1/2 definitions for Amd (automounter)
+ * from Stephen Pope <scp@grizzly.acl.lanl.gov>
+ */
+
+/*
+ * FPX wants to include sys headers multiple times
+ */
+#define INCLUDE_HEADERS
+
+/*
+ * FPX sys/mount.h includes sys/nfs.h; prevent this
+ */
+#define INCLUDED_nfs
+
+/*
+ * FPX doesn't define NMOUNT anywhere
+ */
+#define NMOUNT 40
+
+/*
+ * Does the compiler grok void *
+ */
+/* #define VOIDP */
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+#define svc_fdset svc_fds
+#define svc_getreqset(p) svc_getreq((*p).fds_bits[0])
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
diff --git a/usr.sbin/amd/config/os-hcx.h b/usr.sbin/amd/config/os-hcx.h
new file mode 100644
index 0000000..5b3fb30
--- /dev/null
+++ b/usr.sbin/amd/config/os-hcx.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-hcx.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-hcx.h,v 5.2.2.1 1992/02/09 15:10:20 jsp beta $
+ *
+ * Harris HCX/UX Release 3.0 definitions for Amd (automounter)
+ */
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Deviant call necessary. The mount() routine in libc only works for UFS
+ * (it's a backward-compatible piece of C code which traps to mountsyscall).
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ mountsyscall(type, mnt->mnt_dir, flags, mnt_data)
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#ifdef _hcx
+#define ARCH_ENDIAN "big"
+#else
+XXX - bizarre!
+#endif
diff --git a/usr.sbin/amd/config/os-hlh42.h b/usr.sbin/amd/config/os-hlh42.h
new file mode 100644
index 0000000..43d2d0b
--- /dev/null
+++ b/usr.sbin/amd/config/os-hlh42.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-hlh42.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-hlh42.h,v 5.2.2.1 1992/02/09 15:10:22 jsp beta $
+ *
+ * HLH OTS definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#undef VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(hlh)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+
+/*
+ * Miscellaneous HLH 4.2 incantations
+ */
+#define strchr index
+#define strrchr rindex
+#define sigmask(x) (1 << ((x)-1))
+
+/*
+ * HLH's 4.2 needs the extra RPC definitions.
+ */
+#define NEED_XDR_POINTER
+#define NEED_CLNT_SPERRNO
diff --git a/usr.sbin/amd/config/os-hpux.h b/usr.sbin/amd/config/os-hpux.h
new file mode 100644
index 0000000..42b6b8b
--- /dev/null
+++ b/usr.sbin/amd/config/os-hpux.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-hpux.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-hpux.h,v 5.2.2.1 1992/02/09 15:10:23 jsp beta $
+ *
+ * HP/9000 HP-UX definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#ifdef __GNUC__
+#define VOIDP
+#endif
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(hp9000s200) || defined(hp9000s300) || defined(hp9000s800)
+#define ARCH_ENDIAN "big"
+#endif
+
+#ifndef __hpux
+#define HPUX_VERSION_6
+#endif
+
+/*
+ * No support for syslog() prior to 7.0
+ */
+#ifdef HPUX_VERSION_6
+#undef HAS_SYSLOG
+#endif
+
+/*
+ * No support for ndbm
+ */
+#undef OS_HAS_NDBM
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "hfs"
+
+/*
+ * Where to get NFS definitions
+ */
+#define NFS_HDR "misc-hpux.h"
+
+/*
+ * Where to get union wait
+ */
+#undef WAIT
+#define WAIT "uwait.h"
+#ifdef HPUX_VERSION_6
+#define SIGCHLD SIGCLD
+#endif
+#define SYS5_SIGNALS
+
+/*
+ * Miscellaneous HP-UX definitions
+ */
+
+#define NEED_XDR_POINTER
+#define NEED_CLNT_SPERRNO
+
+/*
+ * Use <fcntl.h> rather than <sys/file.h>
+ */
+#define USE_FCNTL
+
+/*
+ * Use fcntl() rather than flock()
+ */
+#define LOCK_FCNTL
+
+/*
+ * Additional fields in struct mntent
+ * are fixed up here
+ */
+#define FIXUP_MNTENT(mntp) { \
+ (mntp)->mnt_time = clocktime(); \
+}
+#define FIXUP_MNTENT_DUP(mntp, mp) { \
+ (mntp)->mnt_time = (mp)->mnt_time; \
+}
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+#define getpagesize() (2048)
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ vfsmount(type, mnt->mnt_dir, flags, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
+#define NFDS 30 /* conservative */
+#define MOUNTED MNT_MNTTAB
diff --git a/usr.sbin/amd/config/os-irix.h b/usr.sbin/amd/config/os-irix.h
new file mode 100644
index 0000000..1d854f7
--- /dev/null
+++ b/usr.sbin/amd/config/os-irix.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-irix.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-irix.h,v 5.2.2.1 1992/02/09 15:10:28 jsp beta $
+ *
+ * IRIX 3.3 definitions for Amd (automounter)
+ * Contributed by Scott R. Presnell <srp@cgl.ucsf.edu>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Has support for syslog()
+ */
+#define HAS_SYSLOG
+
+#define M_GRPID MS_GRPID
+#define M_RDONLY MS_RDONLY
+/*
+ * Support for ndbm
+ */
+#define OS_HAS_NDBM
+
+#define UPDATE_MTAB
+
+#undef MTAB_TYPE_NFS
+#define MTAB_TYPE_NFS "nfs"
+
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "efs"
+
+#define NMOUNT 40 /* The std sun value */
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS sysfs(GETFSIND, FSID_EFS)
+#define MOUNT_TYPE_NFS sysfs(GETFSIND, FSID_NFS)
+
+#define SYS5_SIGNALS
+
+/*
+ * Use <fcntl.h> rather than <sys/file.h>
+ */
+/*#define USE_FCNTL*/
+
+/*
+ * Use fcntl() rather than flock()
+ */
+/*#define LOCK_FCNTL*/
+
+#ifdef __GNUC__
+#define alloca(sz) __builtin_alloca(sz)
+#endif
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ irix_mount(mnt->mnt_fsname, mnt->mnt_dir,flags, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
+#define NFDS 30 /* conservative */
+
+#define NFS_HDR "misc-irix.h"
+#define UFS_HDR "misc-irix.h"
+
+/* not included in sys/param.h */
+#include <sys/types.h>
+
+#define MOUNT_HELPER_SOURCE "mount_irix.c"
+
+#define MNTINFO_DEV "fsid"
+#define MNTINFO_PREF "0x"
diff --git a/usr.sbin/amd/config/os-irix3.h b/usr.sbin/amd/config/os-irix3.h
new file mode 100644
index 0000000..867097d
--- /dev/null
+++ b/usr.sbin/amd/config/os-irix3.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-irix3.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-irix3.h,v 5.2 1992/05/31 16:40:22 jsp Exp $
+ *
+ * IRIX 3.3 definitions for Amd (automounter)
+ * Contributed by Scott R. Presnell <srp@cgl.ucsf.edu>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Has support for syslog()
+ */
+#define HAS_SYSLOG
+
+#define M_GRPID MS_GRPID
+#define M_RDONLY MS_RDONLY
+/*
+ * Support for ndbm
+ */
+#define OS_HAS_NDBM
+
+#define UPDATE_MTAB
+
+#undef MTAB_TYPE_NFS
+#define MTAB_TYPE_NFS "nfs"
+
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "efs"
+
+#define NMOUNT 40 /* The std sun value */
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS sysfs(GETFSIND, FSID_EFS)
+#define MOUNT_TYPE_NFS sysfs(GETFSIND, FSID_NFS)
+
+#define SYS5_SIGNALS
+
+/*
+ * Use <fcntl.h> rather than <sys/file.h>
+ */
+/*#define USE_FCNTL*/
+
+/*
+ * Use fcntl() rather than flock()
+ */
+/*#define LOCK_FCNTL*/
+
+#ifdef __GNUC__
+#define alloca(sz) __builtin_alloca(sz)
+#endif
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ irix_mount(mnt->mnt_fsname, mnt->mnt_dir,flags, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
+#define NFDS 30 /* conservative */
+
+#define NFS_HDR "misc-irix.h"
+#define UFS_HDR "misc-irix.h"
+
+/* not included in sys/param.h */
+#include <sys/types.h>
+
+#define MOUNT_HELPER_SOURCE "mount_irix.c"
+
+#define MNTINFO_DEV "fsid"
+#define MNTINFO_PREF "0x"
diff --git a/usr.sbin/amd/config/os-irix4.h b/usr.sbin/amd/config/os-irix4.h
new file mode 100644
index 0000000..ee2f8cb
--- /dev/null
+++ b/usr.sbin/amd/config/os-irix4.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-irix4.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-irix4.h,v 5.2 1992/05/31 16:40:22 jsp Exp $
+ *
+ * IRIX 4.0.X definitions for Amd (automounter)
+ * Contributed by Scott R. Presnell <srp@cgl.ucsf.edu>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Has support for syslog()
+ */
+#define HAS_SYSLOG
+
+#define M_RDONLY MS_RDONLY
+#define M_GRPID MS_GRPID
+#define M_NOSUID MS_NOSUID
+#define M_NONDEV MS_NODEV
+
+/*
+ * Support for ndbm
+ */
+#define OS_HAS_NDBM
+
+#define UPDATE_MTAB
+
+#undef MTAB_TYPE_NFS
+#define MTAB_TYPE_NFS "nfs"
+
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "efs"
+
+#define NMOUNT 40 /* The std sun value */
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS sysfs(GETFSIND, FSID_EFS)
+#define MOUNT_TYPE_NFS sysfs(GETFSIND, FSID_NFS)
+
+#define SYS5_SIGNALS
+
+/*
+ * Use <fcntl.h> rather than <sys/file.h>
+ */
+/*#define USE_FCNTL*/
+
+/*
+ * Use fcntl() rather than flock()
+ */
+/*#define LOCK_FCNTL*/
+
+#ifdef __GNUC__
+#define alloca(sz) __builtin_alloca(sz)
+#endif
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
+
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ irix_mount(mnt->mnt_fsname, mnt->mnt_dir,flags, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
+#define NFDS 30 /* conservative */
+
+#define NFS_HDR "misc-irix.h"
+#define UFS_HDR "misc-irix.h"
+
+/* not included in sys/param.h */
+#include <sys/types.h>
+
+#define MOUNT_HELPER_SOURCE "mount_irix.c"
+
+/*
+ * Under 4.0.X this information is in /usr/include/mntent.h
+ * Below is what is used to be for Irix 3.3.X.
+ */
+/*#define MNTINFO_DEV "fsid"*/
+/*#define MNTINFO_PREF "0x"*/
+
+#define MNTINFO_PREF ""
+
+/*
+ * Under Irix, mount type "auto" is probed by statfs() in df. A statfs() of
+ * a direct mount causes that mount to fire. So change the mount type in
+ * /etc/mtab to "ignore" to stop that (this is what SGI does for their
+ * automounter. Use the old FASCIST define for this.
+ */
+#define FASCIST_DF_COMMAND MNTTYPE_IGNORE
diff --git a/usr.sbin/amd/config/os-next.h b/usr.sbin/amd/config/os-next.h
new file mode 100644
index 0000000..c9b1cc2
--- /dev/null
+++ b/usr.sbin/amd/config/os-next.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-next.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-next.h,v 5.2.2.1 1992/02/09 15:10:33 jsp beta $
+ *
+ * NeXT OS definitions for Amd (automounter)
+ * By Bill Trost, Reed College
+ * trost%reed@cse.ogi.edu,
+ *
+ * Derived from the Sun 3.2 definitions for Amd (os-sos3.h).
+ */
+
+/*
+ * Does the compiler grok void * (NeXT uses gcc)
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "4.3"
+
+/*
+ * Where to get NFS definitions
+ */
+#define NFS_HDR "misc-next.h"
diff --git a/usr.sbin/amd/config/os-pyrOSx.h b/usr.sbin/amd/config/os-pyrOSx.h
new file mode 100644
index 0000000..21b5fdd
--- /dev/null
+++ b/usr.sbin/amd/config/os-pyrOSx.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-pyrOSx.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-pyrOSx.h,v 5.2.2.1 1992/02/09 15:10:37 jsp beta $
+ *
+ * Pyramid OSx definitions for Amd (automounter)
+ * from Stefan Petri <petri@tubsibr.UUCP>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
+
+#define strchr index
+#define strrchr rindex
+
+#define hostname mnthostname
diff --git a/usr.sbin/amd/config/os-riscix.h b/usr.sbin/amd/config/os-riscix.h
new file mode 100644
index 0000000..cff7951
--- /dev/null
+++ b/usr.sbin/amd/config/os-riscix.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-riscix.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-riscix.h,v 5.2.2.1 1992/02/09 15:10:38 jsp beta $
+ *
+ * Acorn Archimedes RISC iX definitions for Amd (automounter)
+ * Contributed by Piete Brooks.
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "little"
+
+/*
+ * Is the mount table mirrored in software
+ */
+#define UPDATE_MTAB
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS MNTTYPE_43
diff --git a/usr.sbin/amd/config/os-sos3.h b/usr.sbin/amd/config/os-sos3.h
new file mode 100644
index 0000000..15c632c
--- /dev/null
+++ b/usr.sbin/amd/config/os-sos3.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-sos3.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-sos3.h,v 5.2.2.1 1992/02/09 15:10:39 jsp beta $
+ *
+ * SunOS 3.2 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(mc68010) || defined(mc68020) || defined(sparc)
+#define ARCH_ENDIAN "big"
+#endif
+#if defined(i386)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#define MOUNT_TYPE_NFS MOUNT_NFS
diff --git a/usr.sbin/amd/config/os-sos4.h b/usr.sbin/amd/config/os-sos4.h
new file mode 100644
index 0000000..3853a6c
--- /dev/null
+++ b/usr.sbin/amd/config/os-sos4.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-sos4.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-sos4.h,v 5.2.2.1 1992/02/09 15:10:41 jsp beta $
+ *
+ * SunOS 4.0 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * What type is free(void*) returning?
+ */
+#undef FREE_RETURN_TYPE
+#define FREE_RETURN_TYPE int
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_4
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(mc68010) || defined(mc68020) || defined(sparc)
+#define ARCH_ENDIAN "big"
+#endif
+#if defined(i386)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS "nfs"
+#define MOUNT_TYPE_UFS "4.2"
+
+/*
+ * Type of a file handle
+ */
+#undef NFS_FH_TYPE
+#define NFS_FH_TYPE caddr_t
+
+/*
+ * Type of filesystem type
+ */
+#undef MTYPE_TYPE
+#define MTYPE_TYPE char *
+
+/*
+ * Add support for SunOS 4 automounter files
+ */
+#define SUNOS4_COMPAT
+
+/*
+ * System Vr4 / SunOS 4.1 compatibility
+ * - put dev= in the options list
+ *
+ * From: Brent Callaghan <brent@eng.sun.com>
+ */
+#define MNTINFO_DEV "dev"
+#define MNTINFO_PREF ""
diff --git a/usr.sbin/amd/config/os-stellix.h b/usr.sbin/amd/config/os-stellix.h
new file mode 100644
index 0000000..8c6290a
--- /dev/null
+++ b/usr.sbin/amd/config/os-stellix.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-stellix.h 8.1 (Berkeley) 6/6/93
+ *
+ * Amd (automounter) definitions for Stellix.
+ * From Stephen C. Pope <scp@acl.lanl.gov>
+ *
+ * $Id: os-stellix.h,v 5.2.2.1 1992/02/09 15:10:43 jsp beta $
+ */
+
+#define RPC_3
+
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "big"
+
+#define HAS_SYSLOG
+
+#define OS_HAS_NDBM
+
+#define UPDATE_MTAB
+
+#define USE_FCNTL
+
+#define LOCK_FCNTL
+
+/*
+ * Name of filesystem types
+ */
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "sfs"
+
+#define MOUNT_TYPE_UFS sysfs(GETFSIND, "SFS1")
+#define MOUNT_TYPE_NFS sysfs(GETFSIND, "NFS")
+
+#define SYS5_SIGNALS
+#define HAS_SVR3_SIGNALS
+
+#define MOUNT_HELPER_SOURCE "mount_stellix.c"
+
+/*
+ * Name of mount & unmount system calls
+ *
+ * NOTE:
+ * UNMOUNT_TRAP takes a struct mntent *
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flags, mnt_data) \
+ stellix_mount(mnt->mnt_fsname, mnt->mnt_dir, flags, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_dir)
+
+/*
+ * How to unmount filesystems.
+ * NEED_UMOUNT_FS includes code to scan the mount table
+ * to find the correct information for the unmount system
+ * call. Some systems, such as 4.4bsd, do not require
+ * this - they can just do an unmount system call directly.
+ */
+/* #define NEED_UMOUNT_FS */
+/* #define UMOUNT_FS(dir) umount_fs(dir) */
+
+#define NFS_HDR "misc-stellix.h"
+#define UFS_HDR "misc-stellix.h"
+
+#define M_RDONLY 0x01 /* mount fs read only */
+
+#define bzero(ptr, len) memset(ptr, 0, len)
+#define bcopy(from, to, len) memcpy(to, from, len)
diff --git a/usr.sbin/amd/config/os-type b/usr.sbin/amd/config/os-type
new file mode 100644
index 0000000..4871d79
--- /dev/null
+++ b/usr.sbin/amd/config/os-type
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# Copyright (c) 1989 Jan-Simon Pendry
+# Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the 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.
+#
+# @(#)os-type 8.1 (Berkeley) 6/6/93
+#
+# $Id: os-type,v 5.2.2.2 1992/05/31 16:45:46 jsp Exp $
+#
+
+#
+# Take a pot-shot at your os type
+#
+echo "# ... No OS= option specified; dynamically determining OS type" >&2
+
+#
+# First try poking around in /etc/motd
+#
+
+case "`exec 2>/dev/null; head -2 /etc/motd`" in
+*"Sun UNIX 4.2 Release 3."*) OS=sos3;;
+*"SunOS Release 4."*) OS=sos4;;
+*"HP-UX on the HP"*) OS=hpux;;
+*"Ultrix V2."*) OS=u2_2;;
+*"Ultrix V3."*) OS=u3_0;;
+*"Ultrix-32 V3."*) OS=u3_0;;
+*"Ultrix Worksystem V2."*) OS=u3_0;;
+*"ULTRIX V4.2"*) OS=u4_2;;
+*"ULTRIX V4."*) OS=u4_0;;
+*"HLH OTS Version 1."*) OS=hlh42;;
+*"RISC iX release 1."*) OS=riscix;;
+*"FPX 4."*) OS=fpx4;;
+*"HCX/UX"*) OS=hcx;;
+*"4.4 BSD UNIX"*) OS=bsd44;;
+*"4.3 BSD Reno UNIX"*) OS=bsd44;;
+*"4.3 BSD UNIX"*) if [ -f /etc/minidisk ]; then
+ OS=acis43
+ elif [ -f /sbin/nfsiod ]; then
+ OS=bsd44 # prototype
+ else
+ OS=xinu43
+ fi;;
+*"Alliant Concentrix"*) OS=concentrix;;
+*"Umax 4.3"*) OS=umax43;;
+*)
+#
+# Well, that didn't work so apply some heuristics
+# to the filesystem name space...
+#
+ echo "# ... inspecting File system ..." >&2
+ if [ -f /etc/comply ]; then
+ OS=utek
+ elif [ -d /usr/lib/methods -o -d /etc/methods ]; then
+ OS=aix3
+ elif [ -f /usr/bin/cat ]; then
+ OS=sos4
+ elif [ -f /etc/nd ]; then
+ OS=sos3
+ elif [ -f /etc/elcsd ]; then
+ echo "# ... Ultrix - assuming U4.0 ..." >&2
+ OS=u4_0
+ elif [ -f /hp-ux ]; then
+ OS=hpux
+ elif [ -f /etc/ttylocal ]; then
+ OS=xinu43
+ elif [ -f /etc/minidisk ]; then
+ OS=acis43
+ elif [ -f /etc/toolboxdaemon ]; then
+ OS=aux
+ elif [ -f /sbin/nfsiod ]; then
+ OS=bsd44
+ elif [ -d /vrm ]; then
+ OS=aix2
+ elif [ -f /bin/pyr ] && /bin/pyr; then
+ OS=pyrOSx
+ elif [ -d /NextApps ]; then
+ OS=next
+ elif [ -f /etc/gl/ucode ]; then
+ OS=irix3
+ elif [ -f /usr/gfx/ucode ]; then
+ OS=irix4
+ elif [ -f /stellix ]; then
+ OS=stellix
+ else
+ case "`(sh ../config/arch)2>/dev/null`" in
+ ibm032) OS=acis43;;
+ aviion) OS=dgux;;
+ *) OS=unknown;;
+ esac
+ fi;;
+esac
+
+echo "# ... OS appears to be \"${OS}\"" >&2
+echo "${OS}"
+exit 0
diff --git a/usr.sbin/amd/config/os-u2_2.h b/usr.sbin/amd/config/os-u2_2.h
new file mode 100644
index 0000000..aece171
--- /dev/null
+++ b/usr.sbin/amd/config/os-u2_2.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-u2_2.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-u2_2.h,v 5.2.2.1 1992/02/09 15:10:48 jsp beta $
+ *
+ * Ultrix 2.2 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#undef VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(vax)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * No mntent info on Ultrix
+ */
+#undef MNTENT_HDR
+
+/*
+ * No support for syslog()
+ */
+#undef HAS_SYSLOG
+
+/*
+ * No support for ndbm
+ */
+#undef HAS_NDBM_MAPS
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS GT_NFS
+#define MOUNT_TYPE_UFS GT_ULTRIX
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+/*
+ * Name of mount & unmount system calls
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flag, mnt_data) \
+ mount(mnt->mnt_fsname, mnt->mnt_dir, flag, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_passno)
+
+/*
+ * Miscellaneous Ultrix bits
+ */
+#define M_RDONLY M_RONLY
+
+#ifndef MNTMAXSTR
+#define MNTMAXSTR 128
+#endif
+
+#define MNTTYPE_UFS "ufs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+#define MNTOPT_RO "ro" /* read only */
+#define MNTOPT_RW "rw" /* read/write */
+#define MNTOPT_QUOTA "quota" /* quotas */
+#define MNTOPT_NOQUOTA "noquota" /* no quotas */
+#define MNTOPT_HARD "hard" /* hard mount */
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_INTR "intr" /* interrupts allowed */
+
+#define MNTOPT_NOSUID "nosuid" /* no set uid allowed */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+#define MOUNTED "/etc/mtab"
+
+#define NFS_HDR "misc-ultrix.h"
+#define UFS_HDR "misc-ultrix.h"
+
+#define NEED_XDR_POINTER
+#define NEED_CLNT_SPERRNO
+
+#define nfs_args nfs_gfs_mount
+#define ULTRIX_HACK /* Should be handled better than this !! */
+#define NEED_MNTOPT_PARSER
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_ULTRIX_STYLE
+
+/*
+ * Need precise length links
+ */
+#define PRECISE_SYMLINKS
diff --git a/usr.sbin/amd/config/os-u3_0.h b/usr.sbin/amd/config/os-u3_0.h
new file mode 100644
index 0000000..08a4f36
--- /dev/null
+++ b/usr.sbin/amd/config/os-u3_0.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-u3_0.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-u3_0.h,v 5.2.2.1 1992/02/09 15:10:52 jsp beta $
+ *
+ * Ultrix 3.0 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#undef VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(vax) || defined(mips)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * No mntent info on Ultrix
+ */
+#undef MNTENT_HDR
+
+/*
+ * No support for syslog()
+ */
+#undef HAS_SYSLOG
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS GT_NFS
+#define MOUNT_TYPE_UFS GT_ULTRIX
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+/*
+ * Name of mount & unmount system calls
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flag, mnt_data) \
+ mount(mnt->mnt_fsname, mnt->mnt_dir, flag, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_passno)
+
+/*
+ * Miscellaneous Ultrix bits
+ */
+#define M_RDONLY M_RONLY
+
+#define MNTMAXSTR 128
+
+#define MNTTYPE_UFS "ufs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+#define MNTOPT_RO "ro" /* read only */
+#define MNTOPT_RW "rw" /* read/write */
+#define MNTOPT_QUOTA "quota" /* quotas */
+#define MNTOPT_NOQUOTA "noquota" /* no quotas */
+#define MNTOPT_HARD "hard" /* hard mount */
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_INTR "intr" /* interrupts allowed */
+
+#define MNTOPT_NOSUID "nosuid" /* no set uid allowed */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+#define MOUNTED "/etc/mtab"
+
+#define NFS_HDR "misc-ultrix.h"
+#define UFS_HDR "misc-ultrix.h"
+
+#define NEED_XDR_POINTER
+#define NEED_CLNT_SPERRNO
+
+#define nfs_args nfs_gfs_mount
+#define ULTRIX_HACK /* Should be handled better than this !! */
+#define NEED_MNTOPT_PARSER
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_ULTRIX_STYLE
+
+/*
+ * Need precise length links
+ */
+#define PRECISE_SYMLINKS
diff --git a/usr.sbin/amd/config/os-u4_0.h b/usr.sbin/amd/config/os-u4_0.h
new file mode 100644
index 0000000..07c9833
--- /dev/null
+++ b/usr.sbin/amd/config/os-u4_0.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-u4_0.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-u4_0.h,v 5.2.2.1 1992/02/09 15:10:53 jsp beta $
+ *
+ * Ultrix 4.0 definitions for Amd (automounter)
+ * from Chris Lindblad <cjl@ai.mit.edu>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#ifdef __STDC__
+#define VOIDP
+#else
+#undef VOIDP
+#endif
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(vax) || defined(mips)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * No mntent info on Ultrix
+ */
+#undef MNTENT_HDR
+
+/*
+ * No support for syslog()
+ */
+#define HAS_SYSLOG
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS GT_NFS
+#define MOUNT_TYPE_UFS GT_ULTRIX
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+/*
+ * Name of mount & unmount system calls
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flag, mnt_data) \
+ mount(mnt->mnt_fsname, mnt->mnt_dir, flag, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_passno)
+
+/*
+ * Miscellaneous Ultrix bits
+ */
+#define M_RDONLY M_RONLY
+
+#define MNTMAXSTR 128
+
+#define MNTTYPE_UFS "ufs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+#define MNTOPT_RO "ro" /* read only */
+#define MNTOPT_RW "rw" /* read/write */
+#define MNTOPT_QUOTA "quota" /* quotas */
+#define MNTOPT_NOQUOTA "noquota" /* no quotas */
+#define MNTOPT_HARD "hard" /* hard mount */
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_INTR "intr" /* interrupts allowed */
+
+#define MNTOPT_NOSUID "nosuid" /* no set uid allowed */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+#define MOUNTED "/etc/mtab"
+
+#define NFS_HDR "misc-ultrix.h"
+#define UFS_HDR "misc-ultrix.h"
+
+#define NEED_CLNT_SPERRNO
+
+#define nfs_args nfs_gfs_mount
+#define ULTRIX_HACK /* Should be handled better than this !! */
+#define NEED_MNTOPT_PARSER
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_ULTRIX_STYLE
+
+/*
+ * Need precise length links
+ */
+#define PRECISE_SYMLINKS
diff --git a/usr.sbin/amd/config/os-u4_2.h b/usr.sbin/amd/config/os-u4_2.h
new file mode 100644
index 0000000..f8f039c
--- /dev/null
+++ b/usr.sbin/amd/config/os-u4_2.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-u4_2.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-u4_2.h,v 5.2.2.1 1992/02/09 15:10:54 jsp beta $
+ *
+ * Ultrix 4.2 definitions for Amd (automounter)
+ * from Chris Lindblad <cjl@ai.mit.edu>
+ * and Chris Metcalf <metcalf@lcs.mit.edu>
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(vax) || defined(mips)
+#define ARCH_ENDIAN "little"
+#endif
+
+/*
+ * The mount table is obtained from the kernel
+ */
+#undef UPDATE_MTAB
+
+/*
+ * No mntent info on Ultrix
+ */
+#undef MNTENT_HDR
+
+/*
+ * No support for syslog()
+ */
+#define HAS_SYSLOG
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS GT_NFS
+#define MOUNT_TYPE_UFS GT_ULTRIX
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+/*
+ * Name of mount & unmount system calls
+ */
+#undef MOUNT_TRAP
+#define MOUNT_TRAP(type, mnt, flag, mnt_data) \
+ mount(mnt->mnt_fsname, mnt->mnt_dir, flag, type, mnt_data)
+#undef UNMOUNT_TRAP
+#define UNMOUNT_TRAP(mnt) umount(mnt->mnt_passno)
+
+/*
+ * Miscellaneous Ultrix bits
+ */
+#define M_RDONLY M_RONLY
+
+#define MNTMAXSTR 128
+
+#define MNTTYPE_UFS "ufs" /* Un*x file system */
+#define MNTTYPE_NFS "nfs" /* network file system */
+#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
+
+#define MNTOPT_RO "ro" /* read only */
+#define MNTOPT_RW "rw" /* read/write */
+#define MNTOPT_QUOTA "quota" /* quotas */
+#define MNTOPT_NOQUOTA "noquota" /* no quotas */
+#define MNTOPT_HARD "hard" /* hard mount */
+#define MNTOPT_SOFT "soft" /* soft mount */
+#define MNTOPT_INTR "intr" /* interrupts allowed */
+
+#define MNTOPT_NOSUID "nosuid" /* no set uid allowed */
+
+struct mntent {
+ char *mnt_fsname; /* name of mounted file system */
+ char *mnt_dir; /* file system path prefix */
+ char *mnt_type; /* MNTTYPE_* */
+ char *mnt_opts; /* MNTOPT* */
+ int mnt_freq; /* dump frequency, in days */
+ int mnt_passno; /* pass number on parallel fsck */
+};
+#define MOUNTED "/etc/mtab"
+
+#define NFS_HDR "misc-ultrix.h"
+#define UFS_HDR "misc-ultrix.h"
+
+#define nfs_args nfs_gfs_mount
+#define ULTRIX_HACK /* Should be handled better than this !! */
+#define NEED_MNTOPT_PARSER
+
+/*
+ * How to get a mount list
+ */
+#undef READ_MTAB_FROM_FILE
+#define READ_MTAB_ULTRIX_STYLE
+
+/*
+ * Need precise length links
+ */
+#define PRECISE_SYMLINKS
diff --git a/usr.sbin/amd/config/os-umax43.h b/usr.sbin/amd/config/os-umax43.h
new file mode 100644
index 0000000..3e80872
--- /dev/null
+++ b/usr.sbin/amd/config/os-umax43.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-umax43.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-umax43.h,v 5.2.2.1 1992/02/09 15:10:55 jsp beta $
+ *
+ * UMAX 4.3 definitions for Amd (automounter)
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#define VOIDP
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#define ARCH_ENDIAN "little"
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
diff --git a/usr.sbin/amd/config/os-utek.h b/usr.sbin/amd/config/os-utek.h
new file mode 100644
index 0000000..eb1be04
--- /dev/null
+++ b/usr.sbin/amd/config/os-utek.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-utek.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-utek.h,v 5.2.2.1 1992/02/09 15:10:56 jsp beta $
+ *
+ * Utek 4.0 definitions for Amd (automounter)
+ * from Bill Trost <trost%reed@cse.ogi.edu>
+ */
+
+#define UTEK
+#define __NFS_HEADER__ /* prevent re-inclusion of <sys/nfs.h> */
+/* ... and fake the rest */
+#include "os-sos3.h"
diff --git a/usr.sbin/amd/config/os-utx32.h b/usr.sbin/amd/config/os-utx32.h
new file mode 100644
index 0000000..29612c4
--- /dev/null
+++ b/usr.sbin/amd/config/os-utx32.h
@@ -0,0 +1,85 @@
+/* $Id: os-utx32.h,v 5.2.1.1 90/10/21 22:31:11 jsp Exp $ */
+
+/*
+ * Gould UTX/32 definitions for Amd (automounter)
+ *
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-utx32.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#ifdef __GNUC__
+#define VOIDP
+#endif
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_3
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_3
+
+/*
+ * Does this OS have NDBM support?
+ */
+#define OS_HAS_NDBM
+
+/*
+ * Byte ordering
+ */
+#undef ARCH_ENDIAN
+#if defined(gould) || defined(GOULD_PN)
+#define ARCH_ENDIAN "big"
+#endif
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS MOUNT_NFS
+#define MOUNT_TYPE_UFS MOUNT_UFS
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "4.3"
diff --git a/usr.sbin/amd/config/os-xinu43.h b/usr.sbin/amd/config/os-xinu43.h
new file mode 100644
index 0000000..e85cea2
--- /dev/null
+++ b/usr.sbin/amd/config/os-xinu43.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)os-xinu43.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: os-xinu43.h,v 5.2.2.1 1992/02/09 15:10:58 jsp beta $
+ *
+ * mt Xinu 4.3 (MORE/bsd) definitions for Amd (automounter)
+ * Should work on both Vax and HP ...
+ */
+
+/*
+ * Does the compiler grok void *
+ */
+#ifdef __GNUC__
+#define VOIDP
+#endif
+
+/*
+ * Which version of the Sun RPC library we are using
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define RPC_4
+
+/*
+ * mt Xinu have a compatibility problem
+ * with getreq vs. getreqset. On SunOS
+ * getreqset takes a pointer to an fd_set,
+ * whereas on MORE/bsd, getreq takes a
+ * fd_set directly (cf. an integer on SunOS).
+ */
+#define svc_getreqset(p) svc_getreq(*p)
+
+/*
+ * Which version of the NFS interface are we using.
+ * This is the implementation release number, not
+ * the protocol revision number.
+ */
+#define NFS_4
+
+/*
+ * Name of filesystem types
+ */
+#define MOUNT_TYPE_NFS "nfs"
+#define MOUNT_TYPE_UFS "ufs"
+#undef MTAB_TYPE_UFS
+#define MTAB_TYPE_UFS "ufs"
+
+/*
+ * Byte ordering
+ */
+#ifndef BYTE_ORDER
+#include <machine/endian.h>
+#endif /* BYTE_ORDER */
+
+#undef ARCH_ENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ARCH_ENDIAN "little"
+#else
+#if BYTE_ORDER == BIG_ENDIAN
+#define ARCH_ENDIAN "big"
+#else
+XXX - Probably no hope of running Amd on this machine!
+#endif /* BIG */
+#endif /* LITTLE */
+
+/*
+ * Type of a file handle
+ */
+#undef NFS_FH_TYPE
+#define NFS_FH_TYPE caddr_t
+
+/*
+ * Type of filesystem type
+ */
+#undef MTYPE_TYPE
+#define MTYPE_TYPE char *
diff --git a/usr.sbin/amd/doc/Makefile b/usr.sbin/amd/doc/Makefile
new file mode 100644
index 0000000..297de2b
--- /dev/null
+++ b/usr.sbin/amd/doc/Makefile
@@ -0,0 +1,53 @@
+#
+# $Id: Makefile,v 5.2 90/06/23 22:21:25 jsp Rel $
+#
+# Copyright (c) 1990 Jan-Simon Pendry
+# Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1990 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+#
+
+PROG = amdref
+SRCS = amdref.texinfo
+
+${PROG}: amdref.dvi
+
+amdref.dvi: ${SRCS}
+ -tex amdref; tex amdref
+
+clean:
+ -rm -f amdref.aux amdref.cp amdref.dvi amdref.fn amdref.ky \
+ amdref.log amdref.pg amdref.toc amdref.tp amdref.vr
diff --git a/usr.sbin/amd/doc/amdref.cps b/usr.sbin/amd/doc/amdref.cps
new file mode 100644
index 0000000..a146372
--- /dev/null
+++ b/usr.sbin/amd/doc/amdref.cps
@@ -0,0 +1,381 @@
+\initial {/}
+\entry {/etc/amd.start}{40}
+\entry {/etc/passwd maps}{15}
+\entry {/etc/rc.local additions}{40}
+\entry {/vol}{70}
+\initial {A}
+\entry {Additions to /etc/rc.local}{40}
+\entry {Aliased hostnames}{27}
+\entry {Alternate locations}{7}
+\entry {Amd command line options}{25}
+\entry {Amq command}{40}
+\entry {arch, FSinfo host attribute}{50}
+\entry {arch, mount selector}{20}
+\entry {Architecture dependent volumes}{68}
+\entry {Architecture sharing}{68}
+\entry {Architecture specific mounts}{69}
+\entry {Atomic NFS mounts}{33}
+\entry {auto, filesystem type}{36}
+\entry {autodir, mount selector}{20}
+\entry {Automatic generation of user maps}{15}
+\entry {Automount directory}{25}
+\entry {Automount filesystem}{36}
+\entry {Automounter configuration maps}{12}
+\entry {Automounter fundamentals}{5}
+\initial {B}
+\entry {Background mounts}{7}
+\entry {Binding names to filesystems}{6}
+\entry {bootparams, FSinfo prefix}{59}
+\entry {Bug reports}{3}
+\entry {byte, mount selector}{20}
+\initial {C}
+\entry {Cache interval}{26}
+\entry {cache, mount option}{36}
+\entry {Catch-all mount point}{70}
+\entry {Changing the interval before a filesystem times out}{26}
+\entry {Cluster names}{30}
+\entry {cluster, FSinfo host attribute}{50}
+\entry {cluster, mount selector}{20}
+\entry {Command line options, Amd}{25}
+\entry {Command line options, FSinfo}{58}
+\entry {config, FSinfo host attribute}{49}
+\entry {Configuration map types}{12}
+\entry {Controlling Amd}{41}
+\entry {Creating a pid file}{27}
+\initial {D}
+\entry {Debug options}{30}
+\entry {Defining a host, FSinfo}{48}
+\entry {Defining an Amd mount map, FSinfo}{56}
+\entry {Defining host attributes, FSinfo}{48}
+\entry {delay, mount option}{21}
+\entry {Delaying mounts from specific locations}{21}
+\entry {Determining the map type}{12}
+\entry {dev, mount option}{34}
+\entry {Direct automount filesystem}{37}
+\entry {direct, filesystem type}{37}
+\entry {Discovering version information}{28}
+\entry {Discovering what is going on at run-time}{41}
+\entry {Disk filesystems}{34}
+\entry {Displaying the process id}{27}
+\entry {Domain name}{26}
+\entry {Domain stripping}{18}
+\entry {domain, mount selector}{20}
+\entry {Domainname operators}{18}
+\entry {dumpset, FSinfo filesystems option}{55}
+\entry {dumpset, FSinfo prefix}{59}
+\entry {Duplicated volumes}{6}
+\initial {E}
+\entry {Environment variables}{18}
+\entry {Error filesystem}{38}
+\entry {error, filesystem type}{38}
+\entry {Example of architecture specific mounts}{69}
+\entry {Example of mounting home directories}{66}
+\entry {export, FSinfo special fstype}{52}
+\entry {exportfs, FSinfo mount option}{54}
+\entry {exports, FSinfo prefix}{59}
+\initial {F}
+\entry {File map syntactic conventions}{12}
+\entry {File maps}{12}
+\entry {Fileserver}{5}
+\entry {Filesystem}{5}
+\entry {Filesystem info package}{46}
+\entry {Filesystem type; auto}{36}
+\entry {Filesystem type; direct}{37}
+\entry {Filesystem type; error}{38}
+\entry {Filesystem type; host}{32}
+\entry {Filesystem type; inherit}{39}
+\entry {Filesystem type; link}{35}
+\entry {Filesystem type; nfs}{31}
+\entry {Filesystem type; nfsx}{33}
+\entry {Filesystem type; program}{34}
+\entry {Filesystem type; root}{39}
+\entry {Filesystem type; toplvl}{38}
+\entry {Filesystem type; ufs}{34}
+\entry {Filesystem type; union}{38}
+\entry {Filesystem types}{31}
+\entry {Flat file maps}{12}
+\entry {Flushing the map cache}{43}
+\entry {Forcing filesystem to time out}{45}
+\entry {freq, FSinfo filesystems option}{53}
+\entry {fs, mount option}{21}
+\entry {FSinfo}{46}
+\entry {FSinfo arch host attribute}{50}
+\entry {FSinfo automount definitions}{56}
+\entry {FSinfo cluster host attribute}{50}
+\entry {FSinfo command line options}{58}
+\entry {FSinfo config host attribute}{49}
+\entry {FSinfo dumpset filesystems option}{55}
+\entry {FSinfo error messages}{61}
+\entry {FSinfo filesystems}{51}
+\entry {FSinfo freq filesystems option}{53}
+\entry {FSinfo fstype filesystems option}{52}
+\entry {FSinfo grammar}{47}
+\entry {FSinfo host attributes}{48}
+\entry {FSinfo host definitions}{48}
+\entry {FSinfo log filesystems option}{55}
+\entry {FSinfo mount filesystems option}{54}
+\entry {FSinfo opts filesystems option}{53}
+\entry {FSinfo os host attribute}{50}
+\entry {FSinfo overview}{46}
+\entry {FSinfo passno filesystems option}{53}
+\entry {FSinfo static mounts}{55}
+\entry {fstab, FSinfo prefix}{60}
+\entry {fstype, FSinfo filesystems option}{52}
+\initial {G}
+\entry {Generic volume name}{70}
+\entry {Global statistics}{44}
+\entry {Grammar, FSinfo}{47}
+\initial {H}
+\entry {Hesiod maps}{15}
+\entry {Home directories}{66}
+\entry {host, filesystem type}{32}
+\entry {host, mount selector}{20}
+\entry {hostd, mount selector}{20}
+\entry {Hostname normalisation}{27}
+\entry {hostname, FSinfo command line option}{60}
+\entry {How keys are looked up}{16}
+\entry {How locations are parsed}{17}
+\entry {How to access environment variables in maps}{18}
+\entry {How to discover your version of Amd}{28}
+\entry {How to mount a local disk}{34}
+\entry {How to mount a UFS filesystems}{34}
+\entry {How to mount all NFS exported filesystems}{32}
+\entry {How to mount an atomic group of NFS filesystems}{33}
+\entry {How to mount and NFS filesystem}{31}
+\entry {How to reference part of the local name space}{35}
+\entry {How to select log messages}{29}
+\entry {How to set default map parameters}{18}
+\entry {How to set map cache parameters}{36}
+\entry {How to start a direct automount point}{37}
+\entry {How to start an indirect automount point}{36}
+\entry {How variables are expanded}{18}
+\initial {I}
+\entry {inherit, filesystem type}{39}
+\entry {Inheritance filesystem}{39}
+\entry {Interval before a filesystem times out}{26}
+\entry {Introduction}{4}
+\initial {K}
+\entry {karch, mount selector}{20}
+\entry {Keep-alives}{8}
+\entry {Key lookup}{16}
+\entry {key, mount selector}{20}
+\initial {L}
+\entry {License Information}{2}
+\entry {link, filesystem type}{35}
+\entry {Listing currently mounted filesystems}{41}
+\entry {Location format}{17}
+\entry {Location lists}{7}
+\entry {Log filename}{27}
+\entry {Log message selection}{29}
+\entry {log, FSinfo filesystems option}{55}
+\entry {Looking up keys}{16}
+\initial {M}
+\entry {Machine architecture names}{11}
+\entry {Machine architectures supported by Amd}{11}
+\entry {Mailing list}{3}
+\entry {Map cache options}{36}
+\entry {Map cache synchronising}{36}
+\entry {Map cache types}{36}
+\entry {Map cache, flushing}{43}
+\entry {Map defaults}{18}
+\entry {Map entry format}{17}
+\entry {Map lookup}{16}
+\entry {Map options}{21}
+\entry {Map types}{12}
+\entry {map, mount selector}{20}
+\entry {maps, FSinfo command line option}{60}
+\entry {Mount a filesystem under program control}{34}
+\entry {Mount home directories}{66}
+\entry {Mount information}{12}
+\entry {Mount map types}{12}
+\entry {Mount maps}{12}
+\entry {Mount option; cache}{36}
+\entry {Mount option; delay}{21}
+\entry {Mount option; dev}{34}
+\entry {Mount option; fs}{21}
+\entry {Mount option; mount}{34}
+\entry {Mount option; opts}{22}
+\entry {Mount option; rfs}{31}
+\entry {Mount option; rhost}{31}
+\entry {Mount option; sublink}{23}
+\entry {Mount option; type}{24}
+\entry {Mount option; unmount}{34}
+\entry {Mount retries}{7}
+\entry {Mount selector; arch}{20}
+\entry {Mount selector; autodir}{20}
+\entry {Mount selector; byte}{20}
+\entry {Mount selector; cluster}{20}
+\entry {Mount selector; domain}{20}
+\entry {Mount selector; host}{20}
+\entry {Mount selector; hostd}{20}
+\entry {Mount selector; karch}{20}
+\entry {Mount selector; key}{20}
+\entry {Mount selector; map}{20}
+\entry {Mount selector; os}{20}
+\entry {Mount selector; path}{20}
+\entry {Mount selector; wire}{21}
+\entry {mount system call}{22}
+\entry {mount system call flags}{22}
+\entry {Mount types}{31}
+\entry {mount, FSinfo filesystems option}{54}
+\entry {mount, mount option}{34}
+\entry {Mounting a local disk}{34}
+\entry {Mounting a UFS filesystem}{34}
+\entry {Mounting a volume}{7}
+\entry {Mounting an atomic group of NFS filesystems}{33}
+\entry {Mounting an NFS filesystem}{31}
+\entry {Mounting entire export trees}{32}
+\entry {Mounting part of the local name space}{35}
+\entry {Mounting user filesystems}{65}
+\entry {Multiple-threaded server}{9}
+\initial {N}
+\entry {Namespace}{6}
+\entry {ndbm maps}{13}
+\entry {Network filesystem group}{33}
+\entry {Network host filesystem}{32}
+\entry {Network-wide naming}{6}
+\entry {NFS}{31}
+\entry {NFS ping}{8}
+\entry {nfs, filesystem type}{31}
+\entry {nfsx, filesystem type}{33}
+\entry {NIS (YP) domain name}{30}
+\entry {NIS (YP) maps}{14}
+\entry {Nodes generated on a restart}{39}
+\entry {Non-blocking operation}{9}
+\entry {Normalising hostnames}{27}
+\initial {O}
+\entry {Obtaining the source code}{3}
+\entry {Operating system names}{10}
+\entry {Operating systems supported by Amd}{10}
+\entry {Operational principles}{7}
+\entry {opts, FSinfo filesystems option}{53}
+\entry {opts, mount option}{22}
+\entry {os, FSinfo host attribute}{50}
+\entry {os, mount selector}{20}
+\entry {Overriding defaults on the command line}{25}
+\entry {Overriding the default mount point}{21}
+\entry {Overriding the local domain name}{26}
+\entry {Overriding the NIS (YP) domain name}{30}
+\initial {P}
+\entry {Passing parameters to the mount system call}{22}
+\entry {passno, FSinfo filesystems option}{53}
+\entry {Password file maps}{15}
+\entry {path, mount selector}{20}
+\entry {Pathname operators}{18}
+\entry {Picking up existing mounts}{28}
+\entry {pid file, creating with -p option}{27}
+\entry {Primary server}{21}
+\entry {Process id}{27}
+\entry {process id of Amd daemon}{27}
+\entry {Program filesystem}{34}
+\entry {program, filesystem type}{34}
+\initial {Q}
+\entry {Querying an alternate host}{43}
+\entry {quiet, FSinfo command line option}{61}
+\initial {R}
+\entry {Referencing part of the local name space}{35}
+\entry {Regular expressions in maps}{36}
+\entry {Replacement volumes}{6}
+\entry {Replicated volumes}{6}
+\entry {Resolving aliased hostnames}{27}
+\entry {Restarting existing mounts}{28}
+\entry {rfs, mount option}{31}
+\entry {rhost, mount option}{31}
+\entry {Root filesystem}{39}
+\entry {root, filesystem type}{39}
+\entry {RPC retries}{9}
+\entry {Run-time administration}{40}
+\entry {rwho servers}{69}
+\initial {S}
+\entry {Secondary server}{21}
+\entry {sel, FSinfo mount option}{54}
+\entry {Selecting specific log messages}{29}
+\entry {Selector; arch}{20}
+\entry {Selector; autodir}{20}
+\entry {Selector; byte}{20}
+\entry {Selector; cluster}{20}
+\entry {Selector; domain}{20}
+\entry {Selector; host}{20}
+\entry {Selector; hostd}{20}
+\entry {Selector; karch}{20}
+\entry {Selector; key}{20}
+\entry {Selector; map}{20}
+\entry {Selector; os}{20}
+\entry {Selector; path}{20}
+\entry {Selector; wire}{21}
+\entry {Selectors}{19}
+\entry {Server crashes}{8}
+\entry {Setting a delay on a mount location}{21}
+\entry {Setting Amd's RPC parameters}{28}
+\entry {Setting debug flags}{30}
+\entry {Setting default map parameters}{18}
+\entry {Setting map cache parameters}{36}
+\entry {Setting map options}{21}
+\entry {Setting system mount options}{22}
+\entry {Setting the cluster name}{30}
+\entry {Setting the default mount directory}{25}
+\entry {Setting the filesystem type option}{24}
+\entry {Setting the interval before a filesystem times out}{26}
+\entry {Setting the interval between unmount attempts}{28}
+\entry {Setting the Kernel architecture}{26}
+\entry {Setting the local domain name}{26}
+\entry {Setting the local mount point}{21}
+\entry {Setting the log file}{27}
+\entry {Setting the NIS (YP) domain name}{30}
+\entry {Setting the sublink option}{23}
+\entry {Sharing a fileserver between architectures}{68}
+\entry {SIGHUP signal}{36}
+\entry {SIGINT signal}{41}
+\entry {SIGTERM signal}{41}
+\entry {Source code distribution}{3}
+\entry {Starting Amd}{40}
+\entry {Statically mounts filesystems, FSinfo}{55}
+\entry {Statistics}{44}
+\entry {Stopping Amd}{41}
+\entry {Stripping the local domain name}{18}
+\entry {sublink}{5}
+\entry {sublink, mount option}{23}
+\entry {Supported machine architectures}{11}
+\entry {Supported operating systems}{10}
+\entry {Symbolic link filesystem}{35}
+\entry {symlink, link filesystem type}{35}
+\entry {Synchronising the map cache}{36}
+\entry {syslog}{27}
+\entry {syslog priorities}{29}
+\initial {T}
+\entry {The mount system call}{22}
+\entry {Top level filesystem}{38}
+\entry {toplvl, filesystem type}{38}
+\entry {type, mount option}{24}
+\entry {Types of configuration map}{12}
+\entry {Types of filesystem}{31}
+\entry {Types of mount map}{12}
+\initial {U}
+\entry {UFS}{34}
+\entry {ufs, filesystem type}{34}
+\entry {Union file maps}{16}
+\entry {Union filesystem}{38}
+\entry {union, filesystem type}{38}
+\entry {Unix filesystem}{34}
+\entry {Unix namespace}{6}
+\entry {unmount attempt backoff interval}{28}
+\entry {unmount, mount option}{34}
+\entry {Unmounting a filesystem}{45}
+\entry {User filesystems}{65}
+\entry {User maps, automatic generation}{15}
+\entry {Using FSinfo}{46}
+\entry {Using syslog to log errors}{27}
+\entry {Using the password file as a map}{15}
+\initial {V}
+\entry {Variable expansion}{18}
+\entry {verbose, FSinfo command line option}{61}
+\entry {Version information}{28}
+\entry {volname, FSinfo mount option}{54}
+\entry {Volume}{5}
+\entry {Volume binding}{6}
+\entry {Volume names}{6}
+\initial {W}
+\entry {Wildcards in maps}{16}
+\entry {wire, mount selector}{21}
+\initial {Y}
+\entry {YP domain name}{30}
diff --git a/usr.sbin/amd/doc/amdref.ps b/usr.sbin/amd/doc/amdref.ps
new file mode 100644
index 0000000..17e10f5
--- /dev/null
+++ b/usr.sbin/amd/doc/amdref.ps
@@ -0,0 +1,6429 @@
+%!PS-Adobe-2.0
+%%Creator: dvipsk 5.512a Copyright 1986, 1993 Radical Eye Software
+%%Title: amdref.dvi
+%%Pages: 62
+%%PageOrder: Ascend
+%%BoundingBox: 0 0 612 792
+%%EndComments
+%DVIPSCommandLine: dvips amdref.dvi -o
+%DVIPSSource: TeX output 1993.06.10:1525
+%%BeginProcSet: tex.pro
+/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N}
+B /TR{translate}N /isls false N /vsize 11 72 mul N /@rigin{isls{[0 -1 1 0 0 0]
+concat}if 72 Resolution div 72 VResolution div neg scale isls{Resolution hsize
+-72 div mul 0 TR}if Resolution VResolution vsize -72 div 1 add mul TR matrix
+currentmatrix dup dup 4 get round 4 exch put dup dup 5 get round 5 exch put
+setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed
+true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N
+/IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin /FontType 3 N /FontMatrix
+fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{
+CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn
+put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0
+0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data
+dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{128
+ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127
+sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type
+/stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N
+/cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get
+S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height
+sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0
+-1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}imagemask restore}B /D{/cc X dup
+type /stringtype ne{]}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1
+ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}
+B /I{cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
+0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add
+.99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore showpage userdict
+/eop-hook known{eop-hook}if}N /@start{userdict /start-hook known{start-hook}
+if pop /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255
+{IE S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76
+div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N
+/ruley 0 N /v{/ruley X /rulex X V}B /V{}B /RV statusdict begin /product where{
+pop product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4
+getinterval(NeXT)eq or}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1
+TR 1 1 scale rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1
+-.1 TR rulex ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /QV{
+gsave transform round exch round exch itransform moveto rulex 0 rlineto 0
+ruley neg rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N
+/tail{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}
+B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{4 M}B
+/w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{p 1 w}B /r{
+p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save
+N}B /eos{SS restore}B end
+%%EndProcSet
+TeXDict begin 40258431 52099146 1000 300 300 (amdref.dvi) @start
+/Fa 1 59 df<78FCFCFCFC7806067B8510>58 D E /Fb 1 59 df<60F0F06004047D830B>58
+D E /Fc 68 122 df<00FE7C0381C60603CE0E03841C03801C03801C03801C03801C03801C0380
+FFFFF01C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C0380
+1C03801C0380FF8FF0171A809916>11 D<00FE000381000601800E03801C01001C00001C00001C
+00001C00001C0000FFFF801C03801C03801C03801C03801C03801C03801C03801C03801C03801C
+03801C03801C03801C03801C0380FF8FF0141A809915>I<00FF800383800603800E03801C0380
+1C03801C03801C03801C03801C0380FFFF801C03801C03801C03801C03801C03801C03801C0380
+1C03801C03801C03801C03801C03801C03801C0380FF9FF0141A809915>I<60F0F86808080810
+102040050B7D990B>39 D<00800100020004000C00080018003000300030006000600060006000
+E000E000E000E000E000E000E000E000E000E0006000600060006000300030003000180008000C
+00040002000100008009267D9B0F>I<8000400020001000180008000C00060006000600030003
+000300030003800380038003800380038003800380038003800300030003000300060006000600
+0C0008001800100020004000800009267E9B0F>I<60F0F07010101020204040040B7D830B>44
+D<FFC0FFC00A0280880D>I<60F0F06004047D830B>I<0004000C00180018001800300030003000
+600060006000C000C000C00180018001800300030003000600060006000C000C000C0018001800
+1800300030003000600060006000C000C0000E257E9B13>I<07E01C38381C300C700E60066006
+E007E007E007E007E007E007E007E007E007E00760066006700E300C381C1C3807E010187F9713
+>I<03000700FF0007000700070007000700070007000700070007000700070007000700070007
+0007000700070007007FF80D187D9713>I<0F80106020304038803CC01CE01C401C003C003800
+380070006000C001800100020004040804100430083FF87FF8FFF80E187E9713>I<07E0183820
+1C601E700E201E001E001C001C0038007007E00038001C000E000F000FE00FE00FC00F400E601C
+183807E010187F9713>I<001800180038007800F800B801380238023804380838183810382038
+4038C038FFFF00380038003800380038003803FF10187F9713>I<30183FF03FE03F8020002000
+2000200020002FC03060203000380018001C001C401CE01CE01C80184038403030E00F800E187E
+9713>I<01F807040C06180E300E300070006000E000E3E0E418E80CF00EE006E007E007E00760
+0760077006300E180C0C3807E010187F9713>I<40007FFF7FFE7FFE4004800880108010002000
+400040008001800100030003000700060006000E000E000E000E000E00040010197E9813>I<07
+E01818300C2006600660067006780C3E181F3007C003E00CF8307C601E600FC007C003C003C003
+60022004181807E010187F9713>I<07E01C303018700C600EE006E006E007E007E0076007700F
+3017182707C700070006000E000C700C7018603030600F8010187F9713>I<60F0F06000000000
+0000000060F0F0701010102020404004177D8F0B>59 D<000C0000000C0000000C0000001E0000
+001E0000002F000000270000002700000043800000438000004380000081C0000081C0000181E0
+000100E0000100E00003FFF000020070000200700004003800040038000400380008001C000800
+1C003C001E00FF00FFC01A1A7F991D>65 D<FFFF800E00E00E00700E00380E003C0E003C0E003C
+0E003C0E003C0E00780E00700E01E00FFFC00E00F00E00780E003C0E001C0E001E0E001E0E001E
+0E001E0E001C0E003C0E00780E00F0FFFFC0171A7F991B>I<003F0201C0C603002E0E001E1C00
+0E1C0006380006780002700002700002F00000F00000F00000F00000F00000F000007000027000
+027800023800041C00041C00080E000803003001C0C0003F00171A7E991C>I<FFFF80000E00E0
+000E0070000E0038000E001C000E000E000E000E000E0007000E0007000E0007800E0007800E00
+07800E0007800E0007800E0007800E0007800E0007800E0007000E0007000E000F000E000E000E
+001C000E001C000E0078000E00E000FFFF8000191A7F991D>I<FFFFF80E00380E00180E00080E
+000C0E00040E00040E00040E01000E01000E01000E03000FFF000E03000E01000E01000E01000E
+00020E00020E00020E00060E00040E00040E000C0E003CFFFFFC171A7F991A>I<FFFFF80E0038
+0E00180E00080E000C0E00040E00040E00040E01000E01000E01000E03000FFF000E03000E0100
+0E01000E01000E00000E00000E00000E00000E00000E00000E00000E0000FFE000161A7F9919>
+I<003F020001C0C60003002E000E001E001C000E001C0006003800060078000200700002007000
+0200F0000000F0000000F0000000F0000000F0000000F001FFC070000E0070000E0078000E0038
+000E001C000E001C000E000E000E000300160001C06600003F82001A1A7E991E>I<FFE1FFC00E
+001C000E001C000E001C000E001C000E001C000E001C000E001C000E001C000E001C000E001C00
+0E001C000FFFFC000E001C000E001C000E001C000E001C000E001C000E001C000E001C000E001C
+000E001C000E001C000E001C000E001C00FFE1FFC01A1A7F991D>I<FF801C001C001C001C001C
+001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C00
+FF80091A7E990E>I<FFE01FC00E000F000E000C000E0008000E0010000E0020000E0040000E01
+80000E0200000E0400000E0C00000E1C00000E2E00000E4700000E8380000F0380000E01C0000E
+00E0000E00E0000E0070000E0038000E0038000E001C000E001E000E001F00FFE07FC01A1A7F99
+1E>75 D<FFE0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00
+000E00000E00000E00000E00000E00000E00080E00080E00080E00180E00100E00300E00700E00
+F0FFFFF0151A7F9918>I<FF0000FF0F0000F00F0000F00B8001700B80017009C0027009C00270
+09C0027008E0047008E00470087008700870087008700870083810700838107008381070081C20
+70081C2070080E4070080E4070080E40700807807008078070080300701C030070FF8307FF201A
+7F9923>I<FE007FC00F000E000F0004000B80040009C0040009C0040008E00400087004000870
+040008380400081C0400081C0400080E04000807040008038400080384000801C4000800E40008
+00E4000800740008003C0008003C0008001C0008000C001C000C00FF8004001A1A7F991D>I<00
+7F000001C1C000070070000E0038001C001C003C001E0038000E0078000F0070000700F0000780
+F0000780F0000780F0000780F0000780F0000780F0000780F000078078000F0078000F0038000E
+003C001E001C001C000E0038000700700001C1C000007F0000191A7E991E>I<FFFF800E01E00E
+00700E00780E00380E003C0E003C0E003C0E003C0E00380E00780E00700E01E00FFF800E00000E
+00000E00000E00000E00000E00000E00000E00000E00000E00000E0000FFE000161A7F991A>I<
+007F000001C1C000070070000E0038001C001C003C001E0038000E0078000F0070000700F00007
+80F0000780F0000780F0000780F0000780F0000780F0000780F00007807000070078000F003800
+0E003C1C1E001C221C000E4138000741F00001E1C000007F80800000C0800000C0800000E18000
+007F0000007F0000003E0000001C0019217E991E>I<FFFF00000E01C0000E0070000E0078000E
+003C000E003C000E003C000E003C000E003C000E0078000E0070000E01C0000FFF00000E038000
+0E00C0000E00E0000E0070000E0070000E0070000E0078000E0078000E0078000E0078400E003C
+400E001C80FFE00F001A1A7F991C>I<0FC21836200E6006C006C002C002C002E00070007E003F
+E01FF803FC007E000E00070003800380038003C002C006E004D81887E0101A7E9915>I<7FFFFF
+00701C0700401C0100401C0100C01C0180801C0080801C0080801C0080001C0000001C0000001C
+0000001C0000001C0000001C0000001C0000001C0000001C0000001C0000001C0000001C000000
+1C0000001C0000001C0000001C0000001C000003FFE000191A7F991C>I<FFE07FC00E000E000E
+0004000E0004000E0004000E0004000E0004000E0004000E0004000E0004000E0004000E000400
+0E0004000E0004000E0004000E0004000E0004000E0004000E0004000E00040006000800070008
+00030010000180200000E0C000003F00001A1A7F991D>I<FF801FC01C0007001C0006000E0004
+000E0004000E000400070008000700080003801000038010000380100001C0200001C0200000E0
+400000E0400000E040000070800000708000007980000039000000390000001E0000001E000000
+1E0000000C0000000C00001A1A7F991D>I<FF81FF07F03C007801C01C007800801C007800801C
+007800800E009C01000E009C01000E009C010007010E020007010E020007010E020003830F0400
+038207040003820704000382070C0001C403880001C403880001C403880000E801D00000E801D0
+0000E801D000007000E000007000E000007000E000003000C0000020004000241A7F9927>I<FF
+801FE01E0007001E0006000F00040007000C00078008000380100001C0100001E0200000E06000
+007040000078800000388000001D0000001F0000000E0000000E0000000E0000000E0000000E00
+00000E0000000E0000000E0000000E0000000E000000FFC0001B1A7F991D>89
+D<1FC000387000383800101C00001C00001C0003FC001E1C00381C00701C00E01C00E01C80E01C
+80E03C80705F801F8F0011107F8F13>97 D<FC00001C00001C00001C00001C00001C00001C0000
+1C00001C00001C00001CFC001D07001E03801C01C01C00C01C00E01C00E01C00E01C00E01C00E0
+1C00E01C01C01C01801E030019060010F800131A809915>I<07F81C1C381C70087000E000E000
+E000E000E000E0007000700438081C1807E00E107F8F11>I<003F000007000007000007000007
+0000070000070000070000070000070003E7000C1700180F00300700700700E00700E00700E007
+00E00700E00700E00700600700700700380F001C370007C7E0131A7F9915>I<07C01C30301870
+18600CE00CFFFCE000E000E000E0006000700438081C1807E00E107F8F11>I<01F007180E381C
+101C001C001C001C001C001C00FFC01C001C001C001C001C001C001C001C001C001C001C001C00
+1C001C00FF800D1A80990C>I<0FCF001871803030007038007038007038007038003030001860
+002FC0006000006000007000003FF0003FFC001FFE00600F00C00300C00300C00300C003006006
+00381C0007E00011187F8F13>I<FC00001C00001C00001C00001C00001C00001C00001C00001C
+00001C00001C7C001D87001E03801E03801C03801C03801C03801C03801C03801C03801C03801C
+03801C03801C03801C0380FF9FF0141A809915>I<183C3C18000000000000FC1C1C1C1C1C1C1C
+1C1C1C1C1C1C1CFF081A80990A>I<FC00001C00001C00001C00001C00001C00001C00001C0000
+1C00001C00001C1FC01C0F001C0C001C18001C20001C40001CE0001DE0001E70001C78001C3800
+1C1C001C1E001C0F001C0F80FF9FE0131A809914>107 D<FC001C001C001C001C001C001C001C
+001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80091A
+80990A>I<FC7C1F001D8E63801E0781C01E0781C01C0701C01C0701C01C0701C01C0701C01C07
+01C01C0701C01C0701C01C0701C01C0701C01C0701C01C0701C0FF9FE7F81D107F8F20>I<FC7C
+001D87001E03801E03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03
+801C0380FF9FF01410808F15>I<07E01C38300C700E6006E007E007E007E007E007E007600670
+0E381C1C3807E010107F8F13>I<FCFC001D07001E03801C01C01C01C01C00E01C00E01C00E01C
+00E01C00E01C00E01C01C01C01801E03001D06001CF8001C00001C00001C00001C00001C00001C
+0000FF80001317808F15>I<03E1000C1300180B00300F00700700E00700E00700E00700E00700
+E00700E00700700700700700380F001C370007C700000700000700000700000700000700000700
+003FE013177F8F14>I<FC781D9C1E1C1E081C001C001C001C001C001C001C001C001C001C001C
+00FF800E10808F0F>I<1F2060E04020C020C020F0007F003FC01FE000F080708030C030C020F0
+408F800C107F8F0F>I<0800080008000800180018003800FFC038003800380038003800380038
+003800382038203820382018201C4007800B177F960F>I<FC1F801C03801C03801C03801C0380
+1C03801C03801C03801C03801C03801C03801C03801C07800C07800E0B8003F3F01410808F15>
+I<FF0F803C07001C06001C04001C04000E08000E080007100007100007100003A00003A00001C0
+0001C00001C00000800011107F8F14>I<FE7F1F80381C07003C1C06001C0C04001C0E04000E16
+08000E1708000E170800072310000723900007A3900003C1A00003C1E0000180C0000180C00001
+80C00019107F8F1C>I<FE3F803C1E001C08000E10000F300007600003C00001C00001E00003E0
+00027000043800083800181C00381E00FC3FC012107F8F14>I<FF0F803C07001C06001C04001C
+04000E08000E080007100007100007100003A00003A00001C00001C00001C00000800000800001
+0000010000E10000E20000E4000078000011177F8F14>I E /Fd 13 119
+df<7FFFF0FFFFF8FFFFF87FFFF015047D921C>45 D<FFFF00FFFFC0FFFFE01E03F01E00F01E00
+781E007C1E003C1E003E1E001E1E001E1E001E1E000F1E000F1E000F1E000F1E000F1E000F1E00
+0F1E000F1E000F1E001F1E001E1E001E1E001E1E003C1E007C1E00781E00F81E03F0FFFFE0FFFF
+C0FFFF0018217FA01C>68 D<FFFFC0FFFFC0FFFFC001E00001E00001E00001E00001E00001E000
+01E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E000
+01E00001E00001E00001E00001E00001E00001E00001E000FFFFC0FFFFC0FFFFC012217BA01C>
+73 D<7FE0FFC0FFF1FFE07FE0FFC00F001E000F001E000F001E000F001E000F001E000F001E00
+0F001E000F001E000F001E000F001E000F001E000F001E000F001E000F001E000F001E000F001E
+000F001E000F001E000F001E000F001E000F001E000F001E0007001C0007803C0007803C0003C0
+780001E0F00000FFE000007FC000001F00001B2180A01C>85 D<0FF8001FFE003FFF803C0F8018
+03C00001E00001E00001E0003FE003FFE00FFFE03FC1E07E01E07801E0F001E0F001E0F001E0F0
+01E07803E07C0FE03FFFFF1FFEFF03F03F18177D961C>97 D<FF0000FF0000FF00000F00000F00
+000F00000F00000F00000F00000F00000F1F800F7FE00FFFF00FE0F80FC07C0F803C0F001E0F00
+1E0F000F0F000F0F000F0F000F0F000F0F000F0F000F0F001E0F801E0F803C0FC07C0FE0F80FFF
+F00F7FC0071F0018217FA01C>I<000FF0000FF0000FF00000F00000F00000F00000F00000F000
+00F00000F000F8F003FEF00FFFF01F07F03E03F03C01F07800F07800F0F000F0F000F0F000F0F0
+00F0F000F0F000F0F000F07800F07801F03C01F03E03F01F07F00FFFFF07FEFF01F8FF18217EA0
+1C>100 D<00FC0003FF000FFFC01F03E03E01E03C00F07800F0780070F00078F00078FFFFF8FF
+FFF8FFFFF8F00000F000007800007800783C00783E00F81F81F00FFFE003FFC000FE0015177D96
+1C>I<0003F8001FFC003FFE007C1E00780C00F00000F00000F00000F00000F0007FFFFCFFFFFC
+FFFFFC00F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F000
+00F00000F00000F00000F00000F0007FFFE07FFFE07FFFE017217FA01C>I<FF000000FF000000
+FF0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0F80000F3FE0
+000FFFF0000FF0F0000FC078000F8078000F8078000F0078000F0078000F0078000F0078000F00
+78000F0078000F0078000F0078000F0078000F0078000F0078000F0078000F007800FFF1FF80FF
+F1FF80FFF1FF8019217FA01C>104 D<7E783C00FEFE7F007FFFFF001FCFE7801F0F87801F0F87
+801E0F07801E0F07801E0F07801E0F07801E0F07801E0F07801E0F07801E0F07801E0F07801E0F
+07801E0F07801E0F07801E0F07801E0F07807F8FC7E0FFCFE7F07F8FC7E01C1780961C>109
+D<00FC780003FF78000FFFF8001F03F8003E01F8003C00F8007800F80078007800F0007800F000
+7800F0007800F0007800F0007800F0007800F0007800780078007800F8003C01F8003E01F8001F
+07F8000FFFF80003FE780000F87800000078000000780000007800000078000000780000007800
+0000780000007800000078000007FF800007FF800007FF8019237E961C>113
+D<7FE3FF00FFE3FF807FE3FF000F0078000F0078000F80F8000780F0000780F00007C1F00003C1
+E00003C1E00003C1E00001E3C00001E3C00001E3C00000E3800000F7800000F7800000F7800000
+7F0000007F0000007F0000003E000019177F961C>118 D E /Fe 24 122
+df<FFF8FFF8FFF80D037D8C12>45 D<1FFFFFFFE07FFFFFFFF07FFFFFFFF00000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000FFFF
+FFFFC0FFFFFFFFC07FFFFFFF80240F7B942A>61 D<000001000000000180000000038000000007
+8000000007800000000F800000000FC000000013C000000013C000000023C000000023C0000000
+43E000000041E000000081E000000081E000000101E000000101F000000200F000000200F00000
+0400F000000400F000000800F00000080078000010007800003FFFF800003FFFF8000040007800
+0040007C000080003C000080003C000100003C000100003C000200003E000200001E000600001E
+001F00003E00FFC001FFF0FFC003FFE024267EA528>65 D<007F80007F8000FF0000E00000E000
+00E00000E00000E00001C00001C00001C00001C00001C00001C000038000038000038000038000
+0380000380000700000700000700000700000700000700000E00000E00000E00000E00000E0000
+0E00001C00001C00001C00001C00001C00001C0000380000380000380000380000380000380000
+700000700000700000700000700000700000E00000E00000FF0000FF0000FF000011377DA80F>
+91 D<007F80007F8000FF00000700000700000700000700000700000E00000E00000E00000E00
+000E00000E00001C00001C00001C00001C00001C00001C00003800003800003800003800003800
+00380000700000700000700000700000700000700000E00000E00000E00000E00000E00000E000
+01C00001C00001C00001C00001C00001C000038000038000038000038000038000038000070000
+070000FF0000FF0000FF0000113781A80F>93 D<01FF000701C00780E00F80F00F807807007800
+00780000780000F0003FF001F0F00780F01E00F03C00F07801E07801E1F001E1F001E1F003E1F0
+05E2700DE23C11FC0FE07818177D961B>97 D<03C0003FC0003FC00007C00007C0000780000780
+000780000780000780000780000F00000F00000F00000F00000F0FC00F30701EC0181F001C1E00
+0E1E000E1E000F1E000F3C000F3C000F3C000F3C000F3C000F3C000E78001E78001C78003C7800
+387800707800E0E401C0C3070080FC0018267BA51E>I<007FC001C0700300F00E01F01E01F01C
+00E0380000780000780000F00000F00000F00000F00000F00000F00000F00000F0000070002070
+00403800C01801000E060003F80014177C9618>I<000003C000003FC000003FC0000007C00000
+07C000000780000007800000078000000780000007800000078000000F0000000F0000000F0000
+000F00003F0F0000E0CF0003803E0006003E000E001E001C001E0038001E0078001E0078003C00
+F0003C00F0003C00F0003C00F0003C00F0003C00F0007800F0007800F0007800700078007000F8
+003801F8001802F8000E0CFF0003F0FF001A267CA51E>I<007E0001C1800700E00E00601C0070
+3C0070380070780070780070FFFFF0F00000F00000F00000F00000F00000F00000F00000700020
+7000403800801801000E060003F80014177C9618>I<0000F800038C000E1E001E3E003C3E003C
+3C00780000780000780000780000780000F00000F00000F00000F0001FFF801FFF8001E00001E0
+0001E00001E00001E00001E00003C00003C00003C00003C00003C00003C0000780000780000780
+000780000780000780000F8000FFF800FFF80017267FA510>I<003C000003FC000003FC000000
+7C0000007C000000780000007800000078000000780000007800000078000000F0000000F00000
+00F0000000F0000000F0FE0000F3070001E4038001E803C001F003C001F003C001E003C001E003
+C003C0078003C0078003C0078003C0078003C0078003C0078007800F0007800F0007800F000780
+0F0007800F0007800F000F801F00FFF1FFE0FFF1FFE01B267FA51E>104
+D<0038007C007C0078003000000000000000000000000000000000000000F00FF00FE001E001E0
+01E001E001E003C003C003C003C003C003C00780078007800780078007800F80FFF0FFF00E257F
+A40F>I<00F0FE01FC001FF307060E001FE40388070001E803D0078001F003E0078001F003E007
+8001E003C0078001E003C0078003C007800F0003C007800F0003C007800F0003C007800F0003C0
+07800F0003C007800F0007800F001E0007800F001E0007800F001E0007800F001E0007800F001E
+0007800F001E000F801F003E00FFF1FFE3FFC0FFF1FFE3FFC02A177F962D>109
+D<00F0FE000FF307001FE4038001E803C001F003C001F003C001E003C001E003C003C0078003C0
+078003C0078003C0078003C0078003C0078007800F0007800F0007800F0007800F0007800F0007
+800F000F801F00FFF1FFE0FFF1FFE01B177F961E>I<003F0001C1C00300600E00701C00381C00
+3838003C78003C78003CF0003CF0003CF0003CF0003CF00038F00078F00078F00070F000E07001
+E03801C01807000E0E0003F00016177C961B>I<003C3F0003FCC1C007FB00E0007C0070007800
+78007800380078003C0078003C00F0003C00F0003C00F0003C00F0003C00F0003C00F0007801E0
+007801E0007001E000F001E000E001E001C001E0038003D0070003CC1C0003C3F00003C0000003
+C0000003C0000007800000078000000780000007800000078000000F800000FFF00000FFF00000
+1E2281961E>I<003E0601E18603808C07005C0E007C1C003C3C003C78003C780078F00078F000
+78F00078F00078F00078F000F0F000F0F000F07000F07001F03802F01805E00E19E003E1E00001
+E00001E00001E00003C00003C00003C00003C00003C00007C0007FF8007FF817227C961C>I<00
+F1F00FF2381FE47801E87801F03001F00001E00001E00003E00003C00003C00003C00003C00003
+C0000780000780000780000780000780000780000F8000FFF800FFF80015177F9615>I<00FE20
+0381E00600C00C00401C00401C00401C00401E00001FC0001FFC000FFE0007FF0000FF80000F80
+400780400380600380600380600300600700F00600C81C0087F00013177E9615>I<0040008000
+8000800080018001800300030007000F003FFEFFFE1E001E001E001E001E001E003C003C003C00
+3C003C003C0478087808780878087808781038201C600F800F227BA115>I<07800F7F80FFFF01
+FE0F001E0F001E0F001E0F001E0F001E1E003C1E003C1E003C1E003C1E003C1E003C3C00783C00
+783C00783C00F83C00F83C01781C02F80E0CFF03F0FF18177C961E>I<0FFE1FF01FFC1FF001F8
+0F8000F00C000078080000781000003C2000003E4000001E8000001F0000000F0000000F800000
+0F8000001BC0000013C0000021E0000041E0000080F0000100F800030078001F00FC00FF81FFC0
+FF81FFC01C177F961C>120 D<07FF03FC07FF03FC00F801E000F8008000780180007801000078
+020000780200003C0400003C0400003C0800003C0800003E1000001E2000001E2000001E400000
+1F4000000F8000000F8000000F0000000E00000006000000040000000400000008000000080000
+0010000030200000F8200000F8400000F8C00000F1800000C30000003C0000001E2280961C>I
+E /Ff 28 122 df<FFFEFFFEFFFE0F037D8E14>45 D<387C7EFC7C3807067B8510>I<00000020
+0000000060000000007000000000F000000000F000000001F000000001F000000003F000000003
+F800000004F80000000CF800000008F800000010F800000010FC000000207C000000207C000000
+407C000000407C000000807E000000803E000001003E000001003E000002003E000002003F0000
+04001F000004001F000008001F00000FFFFF00001FFFFF000010001F800020000F800060000F80
+0040000F800080000F800080000FC001000007C001000007C003000007C007000007C01F80000F
+E0FFE000FFFEFFE000FFFE272A7EA92C>65 D<03FFFFFFF803FFFFFFF8001F8001F8001F000078
+001F000038001F000018001F000018001F000018003E000018003E000018003E000008003E0000
+08003E002008003E002008007C004000007C004000007C004000007C00C000007C03C000007FFF
+C00000FFFF800000F803800000F801800000F801800000F800800000F800800001F001000001F0
+01000001F000000001F000000001F000000001F000000003E000000003E000000003E000000003
+E000000003E000000003E000000007E0000000FFFF800000FFFF80000025297DA826>70
+D<03FFFC03FFFC001F80001F00001F00001F00001F00001F00003E00003E00003E00003E00003E
+00003E00007C00007C00007C00007C00007C00007C0000F80000F80000F80000F80000F80000F8
+0001F00001F00001F00001F00001F00001F00003E00003E00003E00003E00003E00003E00007E0
+00FFFF00FFFF0016297DA815>73 D<03FF8000FFF003FFC000FFF0001FC0001F800017C0000600
+0013E00004000013E00004000011F00004000011F00004000020F80008000020F800080000207C
+00080000207C00080000203E00080000203E00080000401F00100000401F00100000401F801000
+00400F80100000400FC01000004007C01000008007E02000008003E02000008003F02000008001
+F02000008001F82000008000F82000010000FC40000100007C40000100007E40000100003E4000
+0100003F40000100001F40000200001F80000200000F80000200000F8000020000078000020000
+0780000600000380001F8000030000FFF000010000FFF0000100002C297DA82C>78
+D<0001FC020007FF06001E038E003800DC0070007C00E0003C01E0001C03C0001C03C0001C0380
+000807800008078000080780000807C0000807C0000007E0000003F0000003FE000001FFE00001
+FFFC0000FFFF00003FFF800007FFC00000FFE000000FE0000003F0000001F0000001F0000001F0
+200000F0200000F0200000F0200000E0600001E0600001E0700001C0700003C0780007807C0007
+00E6001E00E3C07C00C1FFF000803FC0001F2B7DA921>83 D<003F800001C0E000020070000780
+380007C03C000F803C0007803C0002003C0000003C0000003C0000003C00003FF80001F0780007
+C078000F0078001E0078003C0078007C00F040F800F040F800F040F800F040F801F040F802F080
+7C04F0803E187F0007E03C001A1A7D991D>97 D<001FE000701801C00403803C07003E0F007C1E
+003C3E00103C00007C00007C0000F80000F80000F80000F80000F80000F80000F80000F8000078
+00107800103C00201C00400E008007070001F800171A7C991A>99 D<0000007800000FF800000F
+F8000000F0000000F0000000F0000000F0000000F0000000F0000001E0000001E0000001E00000
+01E0000001E0000001E0000003C0000FC3C0007833C001E00BC003800BC0070007C00F0007801E
+0007803E0007803C0007807C0007807C00078078000F00F8000F00F8000F00F8000F00F8000F00
+F8000F00F8001E00F8001E0078001E0078001E0038003E001C005E000E00BE0007073FE001F83F
+E01D2A7CA921>I<003F8000E0E001C0700780700F00780E00381E003C3C003C3C003C7C003C7C
+007CFFFFF8F80000F80000F80000F80000F80000F80000F800007800107800103800201C00400C
+018007060001F800161A7C991A>I<00007C0001C200070F000F1F001E1F001C0F003C04003C00
+003C0000780000780000780000780000780000780000F0001FFFC01FFFC000F00000F00000F000
+01E00001E00001E00001E00001E00001E00003C00003C00003C00003C00003C00003C000078000
+0780000780000780000780000780000F8000FFFC00FFFC00182A7EA912>I<000000780007E084
+003C3B1C00701C1C00E01E0801E01E0003E01F0003C01F0007C01F0007C01F0007C01F0007C01E
+0007C03E0007C03C0003C0780001C0700002E1E000063F000004000000040000000C0000000C00
+00000E00000007FFE00007FFF80003FFFC000E003E0018000F00380007007000070070000700E0
+000700E0000700E0000700E0000E0070001C0030003800180070000F03C00001FE00001E287F9A
+1D>I<001E000003FE000003FE0000003C0000003C0000003C0000003C0000003C0000003C0000
+00780000007800000078000000780000007800000078000000F0000000F07F0000F1838000F201
+C000F401E000F801E001F001E001F001E001E001E001E001E001E001E001E001E003C003C003C0
+03C003C003C003C003C003C003C003C003C0078007800780078007800780078007800780078007
+8007800F800F80FFF8FFF8FFF8FFF81D2A7EA921>I<0038007C00FC00FC007C00780000000000
+0000000000000000000000000000F00FF00FF001F001F001E001E001E001E001E001E003C003C0
+03C003C003C003C00780078007800780078007800F80FFF0FFF00E297EA811>I<001E000003FE
+000003FE0000003C0000003C0000003C0000003C0000003C0000003C0000007800000078000000
+78000000780000007800000078000000F0000000F00FFC00F00FFC00F007C000F0070000F00400
+01E0080001E0100001E0200001E0800001E1800001E3800003C7C00003D3C00003E3E00003C3E0
+0003C1E00003C1F0000780F0000780F8000780780007807C0007803C0007803E000F807F00FFF9
+FFE0FFF9FFE01E2A7EA91F>107 D<001E01FE03FE003C003C003C003C003C003C007800780078
+00780078007800F000F000F000F000F000F001E001E001E001E001E001E003C003C003C003C003
+C003C00780078007800780078007800F80FFF0FFF00F2A7EA911>I<00F07F007F000FF1838183
+801FF201C201C001F401E401E001F801E801E001F001F001E001F001F001E001E001E001E001E0
+01E001E001E001E001E001E001E001E003C003C003C003C003C003C003C003C003C003C003C003
+C003C003C003C003C003C003C00780078007800780078007800780078007800780078007800780
+078007800780078007800F800F800F80FFF8FFF8FFF8FFF8FFF8FFF82D1A7E9931>I<00F07F00
+0FF183801FF201C001F401E001F801E001F001E001F001E001E001E001E001E001E001E001E001
+E003C003C003C003C003C003C003C003C003C003C003C003C00780078007800780078007800780
+078007800780078007800F800F80FFF8FFF8FFF8FFF81D1A7E9921>I<001FC00070F001C03803
+801C07001E0E000E1E000F3C000F3C000F7C000F7C000F78001FF8001FF8001FF8001FF8001FF8
+003EF8003EF8003C78007C7800783800F03C01E01E03C007070001F800181A7C991D>I<003C1F
+8003FC60E007FD8078007E003C003C003C007C001E0078001F0078001F0078001F0078001F0078
+001F00F0001F00F0001F00F0001F00F0001F00F0001E00F0003E01E0003E01E0007C01E0007801
+E000F001E001E001F001C003C8078003C40E0003C3F80003C0000003C0000003C0000007800000
+07800000078000000780000007800000078000000F800000FFF80000FFF800002026809921>I<
+00F0F80FF11C0FF63E01F43E01F83C01F03C01F00001F00001E00001E00001E00003C00003C000
+03C00003C00003C00003C0000780000780000780000780000780000780000F8000FFFC00FFFC00
+171A7E9917>114 D<007F0801C0D80300380600180E00180C00101C00101E00101E00001F8000
+0FFC0007FF0003FF8000FFC0000FE00003E02001E06000E06000E06000E06000E06000C0700180
+E80300C40E0083F800151A7E9917>I<00200000200000200000600000400000C00000C00001C0
+0001C00003C0000780001FFF80FFFF800780000780000780000F00000F00000F00000F00000F00
+000F00001E00001E00001E00001E00001E01001E01003C02003C02003C02003C02003C04001C04
+001C08000E100003E00011257BA417>I<078007807F807F80FF80FF800F800F800F800F800F00
+0F000F000F000F000F000F000F000F000F000F000F001E001E001E001E001E001E001E001E001E
+001E001E001E003C003C003C003C003C003C003C007C003C007C003C00BC001C017C000E067FC0
+03F87FC01A1A7B9921>I<FFF01FF0FFF01FF00F8007800F0007000F8006000780040007800C00
+0780080007C0100003C0100003C0200003C0200003C0400001E0400001E0800001E1000001E100
+0001F2000000F2000000F4000000F4000000F80000007800000070000000600000006000001C1A
+7B991F>I<FFF3FFC3FEFFF3FF83FE1F803C00F80F003C00600F003C00400F003C00400F003C00
+8007805C008007805E010007809E010007809E020007811E060007C10E040003C20E0C0003C20F
+080003C40F100003C40F100003C807200001E807200001F007C00001F007C00001E007800001E0
+07800001C003000000C00300000080020000271A7B992A>I<07FF80FF8007FF80FF80007C003C
+000078003800007C003000003C002000003C006000003C004000003E008000001E008000001E01
+0000001E010000001E020000000F020000000F040000000F080000000F080000000F9000000007
+9000000007A000000007A000000007C000000003C0000000038000000003000000000300000000
+0200000000020000000004000000000C00000000080000007010000000F810000000F820000000
+F040000000F080000000C1000000003E00000000212680991F>121 D E
+/Fg 28 122 df<7FFFFEFFFFFFFFFFFF7FFFFE18047D931F>45 D<00000600000F00000F00001F
+00001E00003E00003C00007C0000780000F80000F00001F00001E00003E00003C00007C0000780
+000780000F80000F00001F00001E00003E00003C00007C0000780000F80000F00001F00001E000
+01E00003E00003C00007C0000780000F80000F00001F00001E00003E00003C00007C0000780000
+F80000F00000F00000600000182F7DA91F>47 D<387CFEFEFE7C38000000000000000000000000
+387CFEFEFE7C38071A74991F>58 D<7FFFFF80FFFFFFC0FFFFFFC07FFFFF800000000000000000
+000000000000000000000000000000007FFFFF80FFFFFFC0FFFFFFC07FFFFF801A0E7E981F>61
+D<001F81C0007FF1C001FFFBC003E07FC007C01FC00F800FC01F0007C01E0007C03C0003C03C00
+03C0780003C0780003C07800000070000000F0000000F0000000F0000000F0000000F0000000F0
+000000F0000000F0000000F0000000700000007800000078000000780003C03C0003C03C0003C0
+1E0003C01F0007800F800F8007C01F0003E07E0001FFFC00007FF000001FC0001A257EA41F>67
+D<7FFF8000FFFFE0007FFFF8000F00FC000F003E000F001E000F001F000F000F800F0007800F00
+07800F0003C00F0003C00F0003C00F0003E00F0001E00F0001E00F0001E00F0001E00F0001E00F
+0001E00F0001E00F0001E00F0001E00F0001E00F0003C00F0003C00F0003C00F0007C00F000780
+0F000F800F000F000F001E000F003E000F00FC007FFFF800FFFFE0007FFF80001B257FA41F>I<
+07FC00001FFF00003FFFC0003E03E0003E01F0001C00F000000078000000780000007800000078
+00003FF80001FFF80007FFF8001FE078003E0078007C00780078007800F0007800F0007800F000
+7800F00078007800F8007E03F8003FFFFFE00FFF3FE003FC0FE01B1A7D991F>97
+D<007FE001FFF807FFFC0FC07C1F007C3E00383C0000780000780000700000F00000F00000F000
+00F00000F00000F000007000007800007800003C003C3E003C1F007C0FC0F807FFF001FFE0007F
+80161A7C991F>99 D<0001FE000003FE000001FE0000001E0000001E0000001E0000001E000000
+1E0000001E0000001E0000001E00007E1E0001FF9E0007FFDE000F81FE001F00FE003E007E003C
+003E0078001E0078001E00F0001E00F0001E00F0001E00F0001E00F0001E00F0001E00F0001E00
+F0001E0078001E0078003E003C003E003C007E001E00FE000F83FE0007FFDFE003FF1FF0007C1F
+E01C257EA41F>I<007F0001FFC007FFE00F81F01F00783E00783C003C78003C78001E70001EF0
+001EFFFFFEFFFFFEFFFFFEF00000F000007800007800007800003C001E1E001E1F003E0FC0FC03
+FFF801FFF0003F80171A7D991F>I<0001FC000007FF00001FFF80003F0F80003C0F8000780700
+00780000007800000078000000780000007800007FFFFE00FFFFFE00FFFFFE0000780000007800
+000078000000780000007800000078000000780000007800000078000000780000007800000078
+000000780000007800000078000000780000007800000078000000780000007800003FFFF0007F
+FFF8003FFFF00019257FA41F>I<007C0F8001FF3FC007FFFFE00F83F1E01F01F1C01E00F0003C
+0078003C0078003C0078003C0078003C0078003C0078001E00F0001F01F0000F83E0001FFFC000
+1DFF00001C7C00003C0000003C0000003C0000001E0000001FFFE0000FFFF8000FFFFE001FFFFF
+003C003F8078000F80780007C0F00003C0F00003C0F00003C0F00003C078000780780007803E00
+1F001F807E000FFFFC0003FFF000007F80001B287E991F>I<7F800000FF8000007F8000000780
+0000078000000780000007800000078000000780000007800000078000000783F000078FFC0007
+BFFE0007FC1F0007F00F0007E0078007C0078007C0078007800780078007800780078007800780
+078007800780078007800780078007800780078007800780078007800780078007800780078007
+80078007807FF87FF8FFFCFFFC7FF87FF81E2580A41F>I<00700000F80000F80000F800007000
+0000000000000000000000000000000000000000007FF800FFF8007FF800007800007800007800
+007800007800007800007800007800007800007800007800007800007800007800007800007800
+007800007800007800007800FFFFF8FFFFF8FFFFF815267BA51F>I<7F800000FF8000007F8000
+0007800000078000000780000007800000078000000780000007800000078000000787FFC00787
+FFE00787FFC007807E000780FC000781F8000783F0000787E000078FC000079F800007BF000007
+FF000007FF800007FFC00007F3C00007E3E00007C1F0000780F0000780F80007807C0007803C00
+07801E0007801F007FF87FE0FFFCFFF07FF87FE01C257FA41F>107 D<FFF800FFF800FFF80000
+780000780000780000780000780000780000780000780000780000780000780000780000780000
+780000780000780000780000780000780000780000780000780000780000780000780000780000
+7800007800007800007800007800FFFFFCFFFFFCFFFFFC16257CA41F>I<FE3C0F00FEFE3F80FF
+FF7FC01FCFF3C01F87E1E01F07C1E01F07C1E01E0781E01E0781E01E0781E01E0781E01E0781E0
+1E0781E01E0781E01E0781E01E0781E01E0781E01E0781E01E0781E01E0781E01E0781E01E0781
+E01E0781E0FFC7F1FCFFCFF3FCFFC7F1FC1E1A80991F>I<7F83F000FF8FFC007FBFFE0007FC1F
+0007F00F0007E0078007C0078007C0078007800780078007800780078007800780078007800780
+07800780078007800780078007800780078007800780078007800780078007800780078007807F
+F87FF8FFFCFFFC7FF87FF81E1A80991F>I<00FC0003FF0007FF801F87E01E01E03C00F07C00F8
+780078780078F0003CF0003CF0003CF0003CF0003CF0003CF0003CF8007C7800787800787C00F8
+3C00F01E01E01F87E007FF8003FF0000FC00161A7C991F>I<7F83E000FF9FFC007FBFFE0007FC
+1F0007F0078007E003C007C003C0078001E0078001E0078000F0078000F0078000F0078000F007
+8000F0078000F0078000F0078000F0078001E007C001E007C003C007E007C007F00F8007F81F00
+07BFFE00079FF8000787E000078000000780000007800000078000000780000007800000078000
+000780000007800000078000007FF80000FFFC00007FF800001C2780991F>I<7FE07E00FFE1FF
+807FE3FFC001EF87C001FF07C001FC038001F8000001F8000001F0000001F0000001F0000001E0
+000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001
+E0000001E000007FFFE000FFFFE0007FFFE0001A1A7E991F>114 D<03FC700FFFF03FFFF07C03
+F07001F0E000F0E000F0E000F0F000F07C00003FE0001FFF0007FFC000FFF00003F80000787000
+3CF0001CF0001CF8001CF8001CFC0038FF00F0FFFFF0E7FFC0E1FE00161A7C991F>I<00700000
+00F0000000F0000000F0000000F0000000F0000000F000007FFFFE00FFFFFE00FFFFFE0000F000
+0000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0
+000000F0000000F0000000F0078000F0078000F0078000F0078000F0078000F00F00007C1F0000
+3FFE00001FFC000007F00019217FA01F>I<7F807F80FF80FF807F807F80078007800780078007
+800780078007800780078007800780078007800780078007800780078007800780078007800780
+078007800780078007800780078007800780078007800F8007801F8003C07F8001FFFFF800FFE7
+FC003F87F81E1A80991F>I<7FF0FFE0FFF0FFF07FF0FFE00F000F0007801E0007801E0007801E
+0003C03C0003C03C0003C03C0003E07C0001E0780001E0780001E0780000F0F00000F0F00000F0
+F0000079E0000079E0000079E0000039C0000039C000003FC000003FC000001F8000001F80001C
+1A7F991F>I<FFE07FF0FFF0FFF0FFE07FF01E0007801E0007801E0007801E0007801E0007800F
+000F000F000F000F0F0F000F0F0F000F1F8F000F1F8F00071B8E00079B9E00079B9E0007BBDE00
+07BBDE0007B1DE0003B1DC0003B1DC0003F1FC0003E0FC0003E0FC0001E078001C1A7F991F>I<
+7FF1FFC07FF1FFE07FF1FFC007C07C0003E0780001E0F80000F1F00000F9E000007FE000003FC0
+00003F8000001F8000000F0000001F0000001F8000003FC0000079E00000F9E00000F0F00001E0
+F80003E07C0003C03C0007803E007FF0FFE0FFF9FFF07FF0FFE01C1A7F991F>I<7FF0FFE0FFF8
+FFF07FF0FFE00F800F0007801E0007801E0003C01E0003C03C0003C03C0001E03C0001E07C0001
+E0780000F0780000F0780000F0F0000078F0000078F0000038E0000039E000003DE000001DC000
+001DC000001FC000000FC000000F8000000F8000000F8000000F0000000F0000001F0000001E00
+00001E0000383E00007C3C00007C7C00007CF800007FF000003FE000000F8000001C277F991F>
+I E /Fh 3 110 df<00000001800000000003C00000000003C00000000007C00000000007C000
+0000000FC0000000000FE0000000001FE0000000001FE00000000037E00000000037E000000000
+67F00000000063F000000000C3F000000000C3F00000000183F00000000183F00000000303F800
+00000301F80000000601F80000000601F80000000C01F80000000C01FC0000001800FC00000018
+00FC0000003000FC0000003000FC0000006000FE000000E0007E000000C0007E000001C0007E00
+000180007E000003FFFFFE000003FFFFFF00000600003F00000600003F00000C00003F00000C00
+003F00001800003F80001800001F80003000001F80003000001F80006000001F80006000001F80
+00C000001FC001C000000FC003E000000FC00FF000003FE0FFFE0003FFFFFFFC0003FFFF30327E
+B135>65 D<00000007C0000000FFC0000000FFC00000000FC00000000FC00000000F800000000F
+800000000F800000000F800000000F800000000F800000001F000000001F000000001F00000000
+1F000000001F000000001F000000003E000000003E000003F83E00001E063E000038013E0000E0
+00BE0001C000FC000380007C000780007C000F00007C001F00007C001E00007C003E0000F8003C
+0000F8007C0000F8007C0000F8007C0000F8007C0000F800F80001F000F80001F000F80001F000
+F80001F000780001F000780001F000780003E000780003E0003C0003E0003C0007E0001C000FE0
+000E001BE000070037F00001C1C7FF00007F07FE0022327BB127>100 D<003E03F8003F800FFE
+0C1E00C1E00FFE300F0300F000FE4007840078007C8007C8007C007D0007D0007C007E0007E000
+7C007E0007E0007C007C0007C0007C007C0007C0007C00FC000FC000F800F8000F8000F800F800
+0F8000F800F8000F8000F800F8000F8000F800F8000F8000F801F0001F0001F001F0001F0001F0
+01F0001F0001F001F0001F0001F001F0001F0001F001F0001F0001F003E0003E0003E003E0003E
+0003E003E0003E0003E003E0003E0003E003E0003E0003E007E0007E0007E007E0007E0007E0FF
+FF0FFFF0FFFFFFFF0FFFF0FFFF381F7E9E3C>109 D E /Fi 49 122 df<0007FC00003FFF0000
+FE078003F007C007E00FC007E00FC00FC00FC00FC00FC00FC00FC00FC003000FC000000FC00000
+0FC000000FC07FE0FFFFFFE0FFFFFFE00FC007E00FC007E00FC007E00FC007E00FC007E00FC007
+E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC0
+07E00FC007E00FC007E00FC007E00FC007E0FFFC7FFEFFFC7FFE1F267FA522>12
+D<FFFEFFFEFFFEFFFEFFFE0F057F8E14>45 D<3C7EFFFFFFFF7E3C08087C8711>I<007F800003
+FFF00007E1F8000F807C001F003E003F003F003E001F007E001F807E001F807E001F807E001F80
+FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001F
+C0FE001FC0FE001FC0FE001FC07E001F807E001F807E001F807E001F803F003F003F003F001F00
+3E000F807C0007E1F80003FFF000007F80001A237EA21F>48 D<001C00003C0000FC00FFFC00FF
+FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000
+FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000
+FC0000FC0000FC007FFFFC7FFFFC16237CA21F>I<01FF0007FFC01E07F03803F86001FC7C00FE
+FE00FEFE00FFFE007FFE007F7C007F3800FF0000FF0000FE0000FE0001FC0001F80003F00007E0
+000780000F00001E00003C0000700000E00301C0030380070700060600060FFFFE1FFFFE3FFFFE
+7FFFFCFFFFFCFFFFFC18237DA21F>I<01FF0007FFE01E03F03801F83C01FC7E00FE7E00FE7E00
+FE3E00FE1C01FE0001FC0001FC0003F80007F0000FC001FF0001FF000007E00001F00001F80000
+FC0000FE0000FF0000FF1000FF7C00FFFE00FFFE00FFFE00FEFE00FE7C01FC7001F83E07F00FFF
+C001FF0018237DA21F>I<0000380000007800000078000000F8000001F8000003F8000007F800
+0006F800000CF800001CF8000038F8000030F8000060F80000E0F80001C0F8000180F8000300F8
+000700F8000E00F8001C00F8001800F8003000F8007000F800E000F800FFFFFFC0FFFFFFC00001
+F8000001F8000001F8000001F8000001F8000001F8000001F800007FFFC0007FFFC01A237EA21F
+>I<18000C1F007C1FFFF81FFFF01FFFE01FFFC01FFF801FFC0018000018000018000018000018
+000018FF001BFFE01F03F01C00F80800FC00007E00007E00007E00007F00007F78007FFC007FFC
+007FFC007FFC007EF8007E6000FC7000FC3801F81E07E007FFC001FE0018237DA21F>I<001FC0
+007FF001F03803E00C07803E0F807E1F007E3F007E3F007E7E003C7E00007E00007E0000FE3FC0
+FE7FF0FE80F8FF80FCFF007CFF007EFE007EFE007FFE007FFE007FFE007F7E007F7E007F7E007F
+7E007F3E007E3F007E1F007C0F80F807C1F003FFC0007F0018237DA21F>I<300000003C000000
+3FFFFFC03FFFFFC03FFFFF807FFFFF007FFFFE007FFFFC006000180060001800E0003000C00060
+00C000C00000018000000180000003000000060000000E0000000E0000001C0000001C0000003C
+0000003C0000007800000078000000F8000000F8000000F8000000F8000001F8000001F8000001
+F8000001F8000001F8000001F8000000F00000006000001A257DA41F>I<00FF8003FFE00F01F8
+1C007C38003C38001E78001E78001E7C001E7E001E7F803C7FE03C3FF8781FFDF01FFFC00FFFC0
+03FFE003FFF80FFFFC1E1FFC3C07FE7803FE7800FFF0003FF0001FF0000FF0000FF0000FF0000E
+78000E78001C3C00381F80F007FFE001FF0018237DA21F>I<00FF0003FFC00F83E01F00F03F00
+F87E007C7E007C7E007EFE007EFE007EFE007EFE007FFE007FFE007FFE007F7E007F7E00FF3E00
+FF3F01FF1F017F0FFE7F03FC7F00007F00007E00007E3C007E7E00FC7E00FC7E00F87E00F07C01
+F03003E01C0F800FFF0003F80018237DA21F>I<FFFFFFE00000FFFFFFFC000003F800FF000003
+F8001FC00003F80007E00003F80003F00003F80001F80003F80001FC0003F80000FC0003F80000
+FE0003F80000FE0003F800007F0003F800007F0003F800007F0003F800007F8003F800007F8003
+F800007F8003F800007F8003F800007F8003F800007F8003F800007F8003F800007F8003F80000
+7F8003F800007F8003F800007F0003F800007F0003F800007F0003F80000FE0003F80000FE0003
+F80001FC0003F80001F80003F80003F00003F80007E00003F8001FC00003F800FF8000FFFFFFFE
+0000FFFFFFE0000029257EA42F>68 D<FFFFFFFF00FFFFFFFF0003F8007F0003F8000F8003F800
+078003F800038003F800038003F800018003F800018003F800018003F80000C003F80600C003F8
+0600C003F806000003F806000003F80E000003F81E000003FFFE000003FFFE000003F81E000003
+F80E000003F806000003F806000003F806006003F806006003F800006003F80000C003F80000C0
+03F80000C003F80000C003F80001C003F80003C003F80003C003F8000F8003F8003F80FFFFFFFF
+80FFFFFFFF8023257EA428>I<FFFFFFFE00FFFFFFFE0003F800FE0003F8001F0003F8000F0003
+F800070003F800070003F800030003F800030003F800030003F800018003F803018003F8030180
+03F803000003F803000003F807000003F80F000003FFFF000003FFFF000003F80F000003F80700
+0003F803000003F803000003F803000003F803000003F800000003F800000003F800000003F800
+000003F800000003F800000003F800000003F800000003F800000003F8000000FFFFF00000FFFF
+F0000021257EA427>I<FFFFE0FFFFE0FFFFE0FFFFE003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003FFFFFFF8
+0003FFFFFFF80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F800FFFFE0FFFFE0FFFFE0FFFFE02B25
+7EA430>72 D<FFFFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800FFFFE0FFFFE0
+13257EA417>I<FFF8000000FFF8FFFC000001FFF803FC000001FE00037E0000037E00037E0000
+037E00037E0000037E00033F0000067E00033F0000067E00031F80000C7E00031F80000C7E0003
+0FC000187E00030FC000187E000307E000307E000307E000307E000307E000307E000303F00060
+7E000303F000607E000301F800C07E000301F800C07E000300FC01807E000300FC01807E000300
+7E03007E0003007E03007E0003007E03007E0003003F06007E0003003F06007E0003001F8C007E
+0003001F8C007E0003000FD8007E0003000FD8007E00030007F0007E00030007F0007E00030007
+F0007E00030003E0007E00078003E0007E00FFFC01C01FFFF8FFFC01C01FFFF835257EA43A>77
+D<FFF80007FFE0FFFC0007FFE003FE00003C0003FF00001800037F00001800033F80001800031F
+C0001800031FE0001800030FF00018000307F80018000303F80018000301FC0018000300FE0018
+000300FF00180003007F80180003003FC0180003001FC0180003000FE0180003000FF018000300
+07F81800030003FC1800030001FC1800030000FE18000300007F18000300007F98000300003FD8
+000300001FF8000300000FF80003000007F80003000003F80003000003F80003000001F8000300
+0000F800030000007800078000003800FFFC00001800FFFC000018002B257EA430>I<0003FF80
+00001FFFF000007F01FC0001FC007F0003F0001F8007E0000FC00FE0000FE01FC00007F01F8000
+03F03F800003F83F800003F87F800003FC7F000001FC7F000001FCFF000001FEFF000001FEFF00
+0001FEFF000001FEFF000001FEFF000001FEFF000001FEFF000001FEFF000001FE7F000001FC7F
+000001FC7F800003FC3F800003F83F800003F81FC00007F01FC00007F00FE0000FE007F0001FC0
+03F8003F8001FC007F00007F01FC00001FFFF0000003FF800027257DA42E>I<FFFFFFE000FFFF
+FFFC0003F800FF0003F8003F8003F8001FC003F8001FE003F8000FE003F8000FF003F8000FF003
+F8000FF003F8000FF003F8000FF003F8000FF003F8000FE003F8001FE003F8001FC003F8003F80
+03F800FF0003FFFFFC0003FFFFE00003F800000003F800000003F800000003F800000003F80000
+0003F800000003F800000003F800000003F800000003F800000003F800000003F800000003F800
+000003F800000003F8000000FFFFE00000FFFFE0000024257EA42A>I<00FF008007FFE3800F80
+F7801E001F803C000F807800078078000380F8000380F8000180F8000180FC000180FC000000FF
+0000007FE000007FFE00003FFFE0003FFFF8001FFFFE0007FFFF0003FFFF80007FFF800003FFC0
+00003FC000000FE0000007E0000007E0C00003E0C00003E0C00003E0C00003C0E00003C0F00007
+C0F8000780FC000F00FFC03E00E3FFF800803FE0001B257DA422>83 D<FFFFE00FFFC0FFFFE00F
+FFC003F80000780003F80000300003F80000300003F80000300003F80000300003F80000300003
+F80000300003F80000300003F80000300003F80000300003F80000300003F80000300003F80000
+300003F80000300003F80000300003F80000300003F80000300003F80000300003F80000300003
+F80000300003F80000300003F80000300003F80000300003F80000300003F80000300003F80000
+300001F80000600001FC0000600000FC0000C000007C0000C000003E00018000001F0007000000
+0FE03E00000003FFF8000000007FC000002A257EA42F>85 D<FFFF8001FFE0FFFF8001FFE007F8
+00001C0003F80000180003F80000180003FC0000380001FC0000300001FE0000700000FE000060
+0000FF00006000007F0000C000007F8000C000003F80018000003F80018000003FC0038000001F
+C0030000001FE0070000000FE0060000000FF00600000007F00C00000007F00C00000003F81800
+000003F81800000003FC3800000001FC3000000001FE7000000000FE6000000000FF6000000000
+7FC0000000007FC0000000003F80000000003F80000000003F80000000001F00000000001F0000
+0000000E00000000000E0000002B257FA42E>I<07FF00001FFFE0003E03F0003F00F8003F00FC
+003F007E001E007E0000007E0000007E0000007E00001FFE0003FE7E000FC07E001F007E003E00
+7E007E007E00FC007E00FC007E00FC007E00FC00BE007E01BE003F073E001FFE1FE007F00FE01B
+187E971E>97 D<FFC00000FFC000000FC000000FC000000FC000000FC000000FC000000FC00000
+0FC000000FC000000FC000000FC000000FC000000FC000000FC1FC000FCFFF000FFC0FC00FF007
+E00FC003F00FC003F00FC001F80FC001F80FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC0
+01FC0FC001FC0FC001FC0FC001F80FC001F80FC003F00FE003F00FF007E00F1C1F800E0FFF000C
+03F8001E267FA522>I<007FE003FFF807C07C1F80FC1F00FC3F00FC7E00787E0000FE0000FE00
+00FE0000FE0000FE0000FE0000FE0000FE00007E00007F00003F000C1F800C1FC01807E07003FF
+E0007F0016187E971B>I<0000FFC00000FFC000000FC000000FC000000FC000000FC000000FC0
+00000FC000000FC000000FC000000FC000000FC000000FC000000FC0007F0FC003FFCFC00FE0FF
+C01F803FC03F000FC03F000FC07E000FC07E000FC0FE000FC0FE000FC0FE000FC0FE000FC0FE00
+0FC0FE000FC0FE000FC0FE000FC07E000FC07E000FC03F000FC03F001FC01F803FC00FC0EFC003
+FFCFFC00FE0FFC1E267EA522>I<007F0003FFC007C1F00F80F81F00F83F007C7E007C7E007EFE
+007EFE007EFFFFFEFFFFFEFE0000FE0000FE00007E00007E00007E00063F00061F000C0F801807
+E07003FFE0007F8017187E971C>I<001FC0007FF001F8F003E1F807E1F807C1F80FC0F00FC000
+0FC0000FC0000FC0000FC0000FC0000FC000FFFF00FFFF000FC0000FC0000FC0000FC0000FC000
+0FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC000
+0FC0000FC000FFFE00FFFE0015267EA513>I<01FF07C007FFDFE00F83F1E01F01F1E03E00F800
+7E00FC007E00FC007E00FC007E00FC007E00FC007E00FC003E00F8001F01F0000F83E0000FFFC0
+0011FF00003000000030000000380000003C0000003FFFE0001FFFFC001FFFFE000FFFFF001FFF
+FF803C003F8078000FC0F80007C0F80007C0F80007C0F80007C07C000F803E001F001F807E0007
+FFF80000FFC0001B247E971F>I<FFC00000FFC000000FC000000FC000000FC000000FC000000F
+C000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0FE000FC3FF80
+0FCE0FC00FD80FC00FD007E00FE007E00FE007E00FC007E00FC007E00FC007E00FC007E00FC007
+E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC0
+07E0FFFC7FFEFFFC7FFE1F267EA522>I<0F001F803FC03FC03FC03FC01F800F00000000000000
+00000000000000007FC07FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC0FFF8FFF80D277EA611>I<FFC00000FFC000000FC000000FC000
+000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0
+00000FC01FF00FC01FF00FC007800FC00E000FC01C000FC030000FC060000FC1C0000FC380000F
+C780000FDF80000FFFC0000FE7E0000FC3F0000F81F0000F81F8000F80FC000F807E000F803F00
+0F803F000F801F800F800FC0FFF83FF8FFF83FF81D267FA520>107 D<FFC0FFC00FC00FC00FC0
+0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFFCFFFC0E267EA511>I<FF80FE007F
+00FF83FF81FFC00F8E0FC707E00F980FCC07E00F9007E803F00FA007F003F00FA007F003F00FC0
+07E003F00FC007E003F00FC007E003F00FC007E003F00FC007E003F00FC007E003F00FC007E003
+F00FC007E003F00FC007E003F00FC007E003F00FC007E003F00FC007E003F00FC007E003F00FC0
+07E003F00FC007E003F0FFFC7FFE3FFFFFFC7FFE3FFF30187E9733>I<FF80FE00FF83FF800F8E
+0FC00F980FC00F9007E00FA007E00FA007E00FC007E00FC007E00FC007E00FC007E00FC007E00F
+C007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E0
+FFFC7FFEFFFC7FFE1F187E9722>I<007F800003FFF00007C0F8001F807E003F003F003F003F00
+7E001F807E001F80FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0FE001F
+C07E001F807E001F803F003F003F003F001F807E000FC0FC0003FFF000007F80001A187E971F>
+I<FFC1FC00FFCFFF000FFC1FC00FF007E00FC007F00FC003F00FC003F80FC001F80FC001FC0FC0
+01FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC003F80FC003F80FC003F00F
+E007F00FF00FE00FDC1F800FCFFF000FC3F8000FC000000FC000000FC000000FC000000FC00000
+0FC000000FC000000FC000000FC00000FFFC0000FFFC00001E237F9722>I<007F00C003FFC1C0
+07E0E3C01FC033C01F801FC03F001FC07F000FC07F000FC0FE000FC0FE000FC0FE000FC0FE000F
+C0FE000FC0FE000FC0FE000FC0FE000FC07E000FC07F000FC03F000FC03F801FC01F803FC00FE0
+EFC003FF8FC000FE0FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000
+000FC000000FC00000FFFC0000FFFC1E237E9720>I<FF83E0FF8FF80F8C7C0F90FC0FB0FC0FA0
+FC0FA0780FE0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0
+000FC0000FC0000FC000FFFE00FFFE0016187F9719>I<07F8C01FFFC03C07C07001C0F000C0F0
+00C0F000C0FC0000FF80007FFC007FFE003FFF800FFFC003FFC0001FE00003E0C001E0C001E0E0
+01E0E001C0F003C0FC0780EFFF00C3FC0013187E9718>I<00C00000C00000C00000C00001C000
+01C00001C00003C00007C0000FC0001FC000FFFFC0FFFFC00FC0000FC0000FC0000FC0000FC000
+0FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0600FC0600FC0600FC0600FC0600FC060
+07E0C007E1C001FF80007E0013237FA218>I<FFC07FE0FFC07FE00FC007E00FC007E00FC007E0
+0FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007
+E00FC007E00FC007E00FC007E00FC00FE00FC00FE007C017E007E067E003FFC7FE007F07FE1F18
+7E9722>I<FFF80FF8FFF80FF80FC001C00FC0018007E0030007E0030007F0070003F0060003F8
+0E0001F80C0001FC0C0000FC180000FE1800007E3000007E3000003F6000003F6000003FE00000
+1FC000001FC000000F8000000F800000070000000700001D187F9720>I<FFF9FFE0FF80FFF9FF
+E0FF801FC03F001C000FC01F0018000FC01F80180007E01F80300007E01F80300007F03FC07000
+03F037C0600003F037E0600001F863E0C00001F863E0C00001FCE3F1C00000FCC1F1800000FCC1
+F98000007F80FB0000007F80FB0000007F80FF0000003F007E0000003F007E0000001E003C0000
+001E003C0000001E003C0000000C0018000029187F972C>I<FFF83FF0FFF83FF00FC00F0007E0
+0E0003F01C0003F8380001FC700000FC6000007EC000003F8000003F8000001F8000000FC00000
+1FE000001FF0000033F8000061F80000E0FC0001C07E0003807F0007003F800F001F80FFC07FF8
+FFC07FF81D187F9720>I<FFF80FF8FFF80FF80FC001C00FC0018007E0030007E0030007F00700
+03F0060003F80E0001F80C0001FC0C0000FC180000FE1800007E3000007E3000003F6000003F60
+00003FE000001FC000001FC000000F8000000F800000070000000700000006000000060000000C
+0000300C0000781C0000FC180000FC300000FC70000068E000007FC000001F0000001D237F9720
+>I E /Fj 1 59 df<70F8F8F87005057C840D>58 D E /Fk 34 122 df<000700000007000000
+070000000F8000000F8000001FC000001FC000001FC000003FE0000037E0000037E0000063F000
+0063F0000063F00000C1F80000C1F80000C1F8000180FC000180FC000180FC0003007E0003FFFE
+0007FFFF0006003F0006003F000E001F800C001F800C001F801C000FC0FF80FFF8FF80FFF81D1F
+7E9E22>65 D<FFFFF000FFFFFC000F807E000F803F000F803F000F803F800F803F800F801F800F
+803F800F803F800F803F800F803F000F807E000F80FE000FFFF8000FFFFE000F803F000F801F80
+0F800FC00F800FC00F800FE00F800FE00F800FE00F800FE00F800FE00F800FC00F801FC00F801F
+800F803F80FFFFFE00FFFFF8001B1F7E9E20>I<000FF010007FFC7001FC0EF003E003F00FC001
+F01F8000F01F8000F03F0000703F0000707E0000307E000030FE000030FE000000FE000000FE00
+0000FE000000FE000000FE000000FE000000FE0000007E0000307E0000303F0000303F0000701F
+8000601F8000E00FC000C003E0038001FC0F00007FFC00000FF0001C1F7E9E21>I<FFFFF000FF
+FFFE000FC07F000FC01F800FC007C00FC007E00FC003F00FC003F00FC001F80FC001F80FC001F8
+0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001FC0FC001
+F80FC001F80FC001F80FC003F00FC003F00FC003E00FC007E00FC00FC00FC03F00FFFFFE00FFFF
+F0001E1F7E9E23>I<FFFFFF00FFFFFF000FC01F000FC00F000FC007000FC003000FC003800FC0
+01800FC001800FC181800FC181800FC180000FC180000FC380000FFF80000FFF80000FC380000F
+C180000FC180000FC180C00FC180C00FC000C00FC001800FC001800FC001800FC003800FC00380
+0FC007800FC03F00FFFFFF00FFFFFF001A1F7E9E1E>I<FFFFFEFFFFFE0FC03E0FC00E0FC00E0F
+C0060FC0070FC0030FC0030FC1830FC1830FC1800FC1800FC3800FFF800FFF800FC3800FC1800F
+C1800FC1800FC1800FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC000FFFE00FFFE0018
+1F7E9E1D>I<FFFCFFFC0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFFCFFFC0E1F7E9E12>73
+D<FFC0000FFCFFE0001FFC0FE0001FC00FE0001FC00DF00037C00DF00037C00DF00037C00CF800
+67C00CF80067C00C7C00C7C00C7C00C7C00C7C00C7C00C3E0187C00C3E0187C00C3E0187C00C1F
+0307C00C1F0307C00C1F0307C00C0F8607C00C0F8607C00C07CC07C00C07CC07C00C07CC07C00C
+03F807C00C03F807C00C03F807C00C01F007C00C01F007C00C00E007C0FFC0E07FFCFFC0E07FFC
+261F7E9E2B>77 D<FFC007FEFFC007FE0FE000600FF000600DF800600DF800600CFC00600C7E00
+600C7E00600C3F00600C1F80600C0FC0600C0FC0600C07E0600C03F0600C03F8600C01F8600C00
+FC600C007E600C007E600C003F600C001FE00C000FE00C000FE00C0007E00C0003E00C0003E00C
+0001E00C0000E0FFC00060FFC000601F1F7E9E24>I<003FE00000FFF80003F07E0007C01F000F
+800F801F800FC03F0007E03F0007E07F0007F07E0003F07E0003F0FE0003F8FE0003F8FE0003F8
+FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F87E0003F07E0003F07F0007F03F0007
+E03F0007E01F800FC00FC01F8007E03F0003F07E0000FFF800003FE0001D1F7E9E22>I<03F040
+0FFDC01C0FC03803C07001C07001C0F000C0F000C0F000C0F80000FC0000FF80007FF8003FFE00
+3FFF801FFFC007FFC000FFE0000FE00003F00001F00000F0C000F0C000F0C000F0E000E0E001E0
+F801C0FE0380EFFF0081FC00141F7E9E19>83 D<FFFC0FFCFFFC0FFC0FC000C00FC000C00FC000
+C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC0
+00C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C00FC000C007
+C0018007E0018003E0030001F0070000F81E00003FF800000FE0001E1F7E9E23>85
+D<FFF803FEFFF803FE0FC000700FC000600FC0006007E000C007E000C007F001C003F0018003F0
+018001F8030001F8030001FC070000FC060000FC0600007E0C00007E0C00007E0C00003F180000
+3F1800003FB800001FB000001FB000000FE000000FE000000FE0000007C0000007C0000007C000
+00038000000380001F1F7F9E22>I<7FFC3FF87FFC3FF807E0070007F0060003F00E0001F80C00
+01FC1C0000FC180000FE3000007E7000003F6000003FC000001FC000001FC000000FC0000007E0
+000007F000000FF000000FF8000019F8000038FC000030FE0000607E0000E07F0000C03F000180
+1F8003801FC003000FC007000FE0FFE07FFEFFE07FFE1F1F7F9E22>88 D<0FF0003FFC007E1E00
+7E1F007E0F807E0F80180F80000F8000FF800FFF801F0F807C0F807C0F80F80F80F80F80F80F80
+F817807C37803FE3F00F81F014147F9316>97 D<03F8000FFE001F3F003E3F007E3F007C3F007C
+0C00FC0000FC0000FC0000FC0000FC0000FC00007C00007C00007E01803E03801F87000FFE0003
+F80011147F9314>99 D<001FE0001FE00003E00003E00003E00003E00003E00003E00003E00003
+E00003E00003E003F3E00FFFE01F0FE03E03E07C03E07C03E07C03E0FC03E0FC03E0FC03E0FC03
+E0FC03E0FC03E0FC03E07C03E07C03E03E07E01F0FE00FFBFC03F3FC16207F9F19>I<03F8000F
+FE001F0F003E07803C07807C07C07C07C0FC07C0FFFFC0FFFFC0FC0000FC0000FC00007C00007C
+00003E00C03E00C01F038007FF0001FC0012147F9315>I<007F0001FF8007C7C00F8FC00F0FC0
+1F0FC01F07801F00001F00001F00001F00001F0000FFF000FFF0001F00001F00001F00001F0000
+1F00001F00001F00001F00001F00001F00001F00001F00001F00001F00001F00001F0000FFF000
+FFF00012207F9F0E>I<03F0E00FFDF01E1EF03C0FF07C0F807C0F807C0F807C0F807C0F803C0F
+001E1E001FFC0033F0003000003000003800003FFE003FFF801FFFC03FFFE07803F07000F0F000
+F0F000F0F000F0F000F07801E03E07C01FFF8003FC00141E7F9317>I<FF0000FF00001F00001F
+00001F00001F00001F00001F00001F00001F00001F00001F00001F1F001F3FC01F63C01F83E01F
+83E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F
+03E0FFE7FCFFE7FC16207E9F19>I<1C003E007F007F007F003E001C0000000000000000000000
+0000FF00FF001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F00FF
+E0FFE00B217FA00C>I<FF0000FF00001F00001F00001F00001F00001F00001F00001F00001F00
+001F00001F00001F0FF01F0FF01F03801F06001F0C001F18001F30001F70001FF0001FF8001F7C
+001E3C001E1E001E1F001E0F001E0F801E07801E03C0FFCFF8FFCFF815207F9F18>107
+D<FF00FF001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F00
+1F001F001F001F001F001F001F001F001F001F001F00FFE0FFE00B207F9F0C>I<FE0F80F800FE
+3FC3FC001E63E63E001EC1FC1F001E81F81F001F01F01F001F01F01F001F01F01F001F01F01F00
+1F01F01F001F01F01F001F01F01F001F01F01F001F01F01F001F01F01F001F01F01F001F01F01F
+001F01F01F00FFE7FE7FE0FFE7FE7FE023147E9326>I<FE1F00FE3FC01E63C01E83E01E83E01F
+03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E0FF
+E7FCFFE7FC16147E9319>I<01F8000FFF001F0F803E07C07C03E07C03E07C03E0FC03F0FC03F0
+FC03F0FC03F0FC03F0FC03F0FC03F07C03E07C03E03E07C01F0F800FFF0003FC0014147F9317>
+I<FE3C00FE7F001EDF801E9F801F9F801F1F801F06001F00001F00001F00001F00001F00001F00
+001F00001F00001F00001F00001F0000FFF000FFF0001114809313>114
+D<0FD83FF87038E018E018E018F800FF807FF03FF81FFC03FE003EC00EC00EE00EE00CF81CFFF8
+C7E00F147F9312>I<0300030003000300070007000F000F003F00FFF8FFF81F001F001F001F00
+1F001F001F001F001F001F001F0C1F0C1F0C1F0C1F0C0F9807F003E00E1D7F9C12>I<FF1FE0FF
+1FE01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F03E01F
+03E01F03E01F07E00F0FE007FBFC03F3FC16147E9319>I<FFCFF1FCFFCFF1FC1F03C0701F03C0
+601F07E0600F87E0C00F87E0C00F8CF0C007CCF18007CCF18007D8798003F87B0003F87B0003F8
+7F0003F03F0001F03E0001F03E0001E01E0000E01C0000C00C001E147F9321>119
+D<FFCFF0FFCFF01F03800F830007860007CE0003FC0001F80001F00000F80000780000FC0001FE
+00039E00031F00060F800E07800C07C0FF1FF8FF1FF815147F9318>I<FFC3F8FFC3F81F00C01F
+00C00F81800F81800F818007C30007C30007E70003E60003E60001FC0001FC0001FC0000F80000
+F80000F80000700000700000600000600078E000FCC000FCC000C18000E380007F00003C000015
+1D7F9318>I E /Fl 92 126 df<70F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F870000000000070F8
+F8F870051C779B18>33 D<4010E038F078E038E038E038E038E038E038E038E038E038E0386030
+0D0E7B9C18>I<030600078F00078F00078F00078F00078F00078F007FFFC0FFFFE0FFFFE07FFF
+C00F1E000F1E000F1E000F1E000F1E000F1E007FFFC0FFFFE0FFFFE07FFFC01E3C001E3C001E3C
+001E3C001E3C001E3C000C1800131C7E9B18>I<00C00001C00001C00001C00003F0000FFC003F
+FE007DCF0071C700E1C380E1C780E1C780E1C780F1C00079C0003FC0001FE0000FF80001FC0001
+DE0001CF0001C70061C380F1C380F1C380E1C380E1C70071C70079DE003FFE001FF80007E00001
+C00001C00001C00000C00011247D9F18>I<3803007C07807C0780EE0F80EE0F00EE0F00EE1F00
+EE1E00EE1E00EE3E007C3C007C3C00387C0000780000780000F80000F00001F00001E00001E000
+03E00003C00003C00007C0000783800787C00F87C00F0EE00F0EE01F0EE01E0EE01E0EE03E0EE0
+3C07C03C07C018038013247E9F18>I<01C00007E0000FF0000E70001C38001C38001C38001C38
+001C73F81CF3F81CE3F80FC1C00FC3800F83800F03801F07003F87007B8E0071CE00E1FC00E0FC
+00E07C00E07870E0787070FE707FFFE03FC7E00F03C0151C7F9B18>I<387C7C7E3E0E0E0E1C1C
+38F8F0C0070E789B18>I<007000F001E003C007800F001E001C00380038007000700070007000
+E000E000E000E000E000E000E000E0007000700070007000380038001C001E000F00078003C001
+F000F000700C24799F18>I<6000F00078003C001E000F000780038001C001C000E000E000E000
+E00070007000700070007000700070007000E000E000E000E001C001C0038007800F001E003C00
+7800F00060000C247C9F18>I<01C00001C00001C00001C00041C100F1C780FDDF807FFF001FFC
+0007F00007F0001FFC007FFF00FDDF80F1C78041C10001C00001C00001C00001C00011147D9718
+>I<00600000F00000F00000F00000F00000F00000F00000F0007FFFC0FFFFE0FFFFE07FFFC000
+F00000F00000F00000F00000F00000F00000F00000600013147E9718>I<1C3E7E7F3F1F070E1E
+7CF860080C788518>I<7FFFC0FFFFE0FFFFE07FFFC013047E8F18>I<3078FCFC78300606778518
+>I<000300000780000780000F80000F00001F00001E00001E00003E00003C00007C0000780000
+780000F80000F00001F00001E00003E00003C00003C00007C0000780000F80000F00000F00001F
+00001E00003E00003C00003C00007C0000780000F80000F00000F0000060000011247D9F18>I<
+01F00007FC000FFE001F1F001C07003803807803C07001C07001C0E000E0E000E0E000E0E000E0
+E000E0E000E0E000E0E000E0E000E0F001E07001C07001C07803C03803801C07001F1F000FFE00
+07FC0001F000131C7E9B18>I<01800380038007800F803F80FF80FB8043800380038003800380
+0380038003800380038003800380038003800380038003807FFCFFFE7FFC0F1C7B9B18>I<03F0
+000FFE003FFF007C0F807003C0E001C0F000E0F000E06000E00000E00000E00001C00001C00003
+C0000780000F00001E00003C0000780000F00001E00007C0000F80001E00E03C00E07FFFE0FFFF
+E07FFFE0131C7E9B18>I<07F8001FFE003FFF007807807803C07801C03001C00001C000038000
+0380000F0003FF0003FE0003FF000007800003C00001C00000E00000E00000E0F000E0F000E0F0
+01C0F003C07C07803FFF001FFE0003F800131C7E9B18>I<001F00003F0000770000770000E700
+01E70001C7000387000787000707000E07001E07003C0700380700780700F00700FFFFF8FFFFF8
+FFFFF8000700000700000700000700000700000700007FF0007FF0007FF0151C7F9B18>I<3FFF
+803FFF803FFF803800003800003800003800003800003800003800003800003BF8003FFE003FFF
+003C07803003C00001C00000E00000E06000E0F000E0F000E0E001C07003C07C0F803FFF001FFC
+0003F000131C7E9B18>I<007E0001FF0007FF800F83C01E03C01C03C038018038000070000070
+0000E1F800E7FE00FFFF00FE0780F803C0F001C0F000E0E000E0F000E07000E07000E07000E038
+01C03C03C01E07800FFF0007FE0001F800131C7E9B18>I<E00000FFFFE0FFFFE0FFFFC0E00380
+E00700000F00001E00001C0000380000380000700000F00000E00000E00001C00001C00001C000
+038000038000038000038000070000070000070000070000070000070000070000131D7E9C18>
+I<03F8000FFE001FFF003E0F803803807001C07001C07001C07001C03803803C07801FFF0007FC
+000FFE001F1F003C07807001C0F001E0E000E0E000E0E000E0E000E07001C07803C03E0F801FFF
+000FFE0003F800131C7E9B18>I<03F0000FFC001FFE003C0F00780780700380E001C0E001C0E0
+01C0E001E0E001E07001E07803E03C0FE01FFFE00FFEE003F0E00000E00001C00001C00001C030
+0380780780780F00783E003FFC001FF00007C000131C7E9B18>I<3078FCFC7830000000000000
+00003078FCFC78300614779318>I<183C7E7E3C180000000000000000183C7E7E3E1E0E1C3C78
+F060071A789318>I<0000C00003E00007E0001FC0003F8000FE0001FC0007F0000FE0003F8000
+7F0000FC0000FC00007F00003F80000FE00007F00001FC0000FE00003F80001FC00007E00003E0
+0000C013187E9918>I<7FFFC0FFFFE0FFFFE0FFFFE0000000000000000000000000FFFFE0FFFF
+E0FFFFE07FFFC0130C7E9318>I<600000F80000FC00007F00003F80000FE00007F00001FC0000
+FE00003F80001FC00007E00007E0001FC0003F8000FE0001FC0007F0000FE0003F80007F0000FC
+0000F8000060000013187E9918>I<007C0001FE0007FF000F87801E03C03C1DC0387FC070FFE0
+71E3E071C1E0E1C1E0E380E0E380E0E380E0E380E0E380E0E380E0E1C1C071C1C071E3C070FF80
+387F003C1C001E00E00F83E007FFC001FF80007E00131C7E9B18>64 D<00700000F80000F80000
+D80000D80001DC0001DC0001DC00018C00038E00038E00038E00038E0007070007070007070007
+07000707000FFF800FFF800FFF800E03801C01C01C01C01C01C07F07F0FF07F87F07F0151C7F9B
+18>I<7FFC00FFFF007FFF801C03C01C01C01C00E01C00E01C00E01C00E01C01E01C01C01C07C0
+1FFF801FFF001FFFC01C03C01C00E01C00F01C00701C00701C00701C00701C00F01C00E01C03E0
+7FFFC0FFFF807FFE00141C7F9B18>I<00F8E003FEE007FFE00F07E01E03E03C01E03800E07000
+E07000E0700000E00000E00000E00000E00000E00000E00000E00000E000007000007000E07000
+E03800E03C00E01E01C00F07C007FF8003FE0000F800131C7E9B18>I<7FF800FFFE007FFF001C
+0F801C03C01C03C01C01E01C00E01C00E01C00F01C00701C00701C00701C00701C00701C00701C
+00701C00701C00F01C00E01C00E01C01E01C01C01C03C01C0F807FFF00FFFE007FF800141C7F9B
+18>I<FFFFF0FFFFF0FFFFF01C00701C00701C00701C00701C00001C00001C0E001C0E001C0E00
+1FFE001FFE001FFE001C0E001C0E001C0E001C00001C00001C00381C00381C00381C00381C0038
+FFFFF8FFFFF8FFFFF8151C7F9B18>I<FFFFF8FFFFF8FFFFF81C00381C00381C00381C00381C00
+001C00001C07001C07001C07001FFF001FFF001FFF001C07001C07001C07001C00001C00001C00
+001C00001C00001C00001C0000FFC000FFC000FFC000151C7F9B18>I<01F1C003FDC00FFFC01F
+0FC01C03C03803C03801C07001C07001C0700000E00000E00000E00000E00000E00000E00FF0E0
+1FF0E00FF07001C07001C07003C03803C03803C01C07C01F0FC00FFFC003FDC001F1C0141C7E9B
+18>I<7F07F0FF8FF87F07F01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C0
+1FFFC01FFFC01FFFC01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C0
+7F07F0FF8FF87F07F0151C7F9B18>I<7FFF00FFFF807FFF0001C00001C00001C00001C00001C0
+0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0
+0001C00001C00001C00001C0007FFF00FFFF807FFF00111C7D9B18>I<01FFC001FFC001FFC000
+0E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0000
+0E00000E00000E00000E00000E00000E00F00E00F00E00F03C007FFC003FF0000FC000121C7D9B
+18>I<7F07F0FF87F87F07F01C03C01C07801C07001C0E001C1E001C3C001C38001C70001CF000
+1DF0001DF0001FB8001FB8001F1C001E1C001C0E001C0E001C07001C07001C03801C03801C01C0
+7F03F0FF87F87F03F0151C7F9B18>I<FFC000FFC000FFC0001C00001C00001C00001C00001C00
+001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00
+E01C00E01C00E01C00E01C00E0FFFFE0FFFFE0FFFFE0131C7E9B18>I<FC01F8FE03F8FE03F83B
+06E03B06E03B06E03B06E03B8EE03B8EE0398CE0398CE039DCE039DCE039DCE038D8E038D8E038
+F8E03870E03870E03800E03800E03800E03800E03800E03800E0FE03F8FE03F8FE03F8151C7F9B
+18>I<7E07F0FF0FF87F07F01D81C01D81C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01CE1C0
+1C61C01C71C01C71C01C31C01C39C01C39C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0DC0
+7F07C0FF87C07F03C0151C7F9B18>I<0FFE003FFF807FFFC07803C07001C0F001E0E000E0E000
+E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000
+E0E000E0F001E07001C07C07C07FFFC03FFF800FFE00131C7E9B18>I<FFFE00FFFF80FFFFC01C
+03C01C01E01C00E01C00701C00701C00701C00701C00701C00E01C01E01C03C01FFFC01FFF801F
+FE001C00001C00001C00001C00001C00001C00001C00001C0000FF8000FF8000FF8000141C7F9B
+18>I<0FFE003FFF807FFFC07803C07001C0F001E0E000E0E000E0E000E0E000E0E000E0E000E0
+E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E070E0E070E0F079E07039C0783FC0
+7FFFC03FFF800FFE00000F000007800007800003C00001C00001C013227E9B18>I<7FF800FFFE
+007FFF001C0F801C03801C03C01C01C01C01C01C01C01C03C01C03801C0F801FFF001FFE001FFE
+001C0F001C07001C03801C03801C03801C03801C03801C039C1C039C1C039C7F01F8FF81F87F00
+F0161C7F9B18>I<03F1C01FFFC03FFFC07C0FC07003C0E001C0E001C0E001C0E0000070000078
+00003F00001FF00007FE0000FF00000F800003C00001C00000E00000E06000E0E000E0E001E0F0
+01C0F80780FFFF80FFFE00E7F800131C7E9B18>I<7FFFF8FFFFF8FFFFF8E07038E07038E07038
+E07038007000007000007000007000007000007000007000007000007000007000007000007000
+00700000700000700000700000700000700007FF0007FF0007FF00151C7F9B18>I<FF83FEFF83
+FEFF83FE1C00701C00701C00701C00701C00701C00701C00701C00701C00701C00701C00701C00
+701C00701C00701C00701C00701C00701C00701C00700E00E00F01E00783C003FF8001FF00007C
+00171C809B18>I<FE03F8FF07F8FE03F83C01E01C01C01C01C01C01C01E03C00E03800E03800E
+03800E0380070700070700070700070700038E00038E00038E00038E00018C0001DC0001DC0001
+DC0000D80000F80000F800007000151C7F9B18>I<FE03F8FE03F8FE03F8700070700070700070
+3800E03800E03800E03800E03800E038F8E039FCE039DCE039DCE019DCC019DCC019DCC0198CC0
+198CC01D8DC01D8DC01D8DC01D05C00D05800F07800F07800E0380151C7F9B18>I<7F0FE07F9F
+E07F0FE00E07000F0700070E00078E00039C0003DC0001F80001F80000F80000F00000700000F0
+0000F80001FC0001DC00039E00038E00070F000707000E07800E03801E03C07F07F0FF07F87F07
+F0151C7F9B18>I<FE03F8FF07F8FE03F81C01C01E03C00E03800F0780070700070700038E0003
+8E0001DC0001DC0001DC0000F80000F80000700000700000700000700000700000700000700000
+700000700001FC0003FE0001FC00151C7F9B18>I<3FFFE07FFFE07FFFE07001C07003C0700780
+700700000F00001E00001C00003C0000780000700000F00001E00001C00003C000078000070000
+0F00001E00E01C00E03C00E07800E07000E0FFFFE0FFFFE0FFFFE0131C7E9B18>I<FFF8FFF8FF
+F8E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000
+E000E000E000E000E000E000E000E000E000E000E000FFF8FFF8FFF80D24779F18>I<600000F0
+0000F00000F800007800007C00003C00003C00003E00001E00001F00000F00000F00000F800007
+800007C00003C00003C00003E00001E00001F00000F00000F800007800007800007C00003C0000
+3E00001E00001E00001F00000F00000F8000078000078000030011247D9F18>I<FFF8FFF8FFF8
+003800380038003800380038003800380038003800380038003800380038003800380038003800
+380038003800380038003800380038003800380038FFF8FFF8FFF80D247F9F18>I<018007C01F
+F07EFCF83EE00E0F067C9B18>I<7FFFC0FFFFE0FFFFE07FFFC013047E7F18>I<061E3E387070E0
+E0E0F8FC7C7C38070E789E18>I<0FF0001FFC003FFE003C0F0018070000038000038000FF8007
+FF801FFF807F0380780380E00380E00380E00380F00780780F803FFFF81FFDF807F0F815147E93
+18>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF800FFFC00FC1E0
+0F80E00F00700E00700E00380E00380E00380E00380E00380E00380F00700F00700F80E00FC1E0
+0FFFC00EFF80063E00151C809B18>I<01FE0007FF001FFF803E0780380300700000700000E000
+00E00000E00000E00000E00000E000007000007001C03801C03E03C01FFF8007FF0001FC001214
+7D9318>I<001F80003F80001F8000038000038000038000038000038003E3800FFB801FFF803C
+1F80380F80700780700380E00380E00380E00380E00380E00380E00380700780700780380F803C
+1F801FFFF00FFBF803E3F0151C7E9B18>I<01F00007FC001FFE003E0F00380780700380700380
+E001C0E001C0FFFFC0FFFFC0FFFFC0E000007000007001C03801C03E07C01FFF8007FF0001F800
+12147D9318>I<001F80007FC000FFE000E1E001C0C001C00001C00001C0007FFFC0FFFFC0FFFF
+C001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0
+0001C0007FFF007FFF007FFF00131C7F9B18>I<01E1F007FFF80FFFF81E1E301C0E0038070038
+07003807003807003807001C0E001E1E001FFC001FF80039E0003800001C00001FFE001FFFC03F
+FFE07801F0700070E00038E00038E00038E000387800F07E03F01FFFC00FFF8001FC00151F7F93
+18>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF800FFFC00FC1C0
+0F80E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E0
+7FC7FCFFE7FE7FC7FC171C809B18>I<038007C007C007C0038000000000000000007FC0FFC07F
+C001C001C001C001C001C001C001C001C001C001C001C001C001C001C0FFFFFFFFFFFF101D7C9C
+18>I<0038007C007C007C003800000000000000000FFC0FFC0FFC001C001C001C001C001C001C
+001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C6038F078FFF07F
+E03F800E277E9C18>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3FF00E3F
+F00E3FF00E07800E0F000E1E000E3C000E78000EF0000FF8000FFC000F9C000F0E000E0F000E07
+000E03800E03C07FC7F8FFC7F87FC7F8151C7F9B18>I<FFC000FFC000FFC00001C00001C00001
+C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001
+C00001C00001C00001C00001C00001C00001C000FFFF80FFFF80FFFF80111C7D9B18>I<F9C1C0
+FFF7F0FFFFF03E3E383C3C383C3C38383838383838383838383838383838383838383838383838
+383838383838383838FE3E3EFE7E7EFE3E3E1714809318>I<7E3E00FEFF807FFFC00FC1C00F80
+E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC7
+FCFFE7FE7FC7FC1714809318>I<01F0000FFE001FFF003E0F803803807001C07001C0E000E0E0
+00E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE0001F00013147E93
+18>I<7E3E00FEFF807FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E0038
+0E00380F00700F00700F80E00FC1E00FFFC00EFF800E3E000E00000E00000E00000E00000E0000
+0E00000E00007FC000FFE0007FC000151E809318>I<01F38007FB801FFF803E1F80380F807007
+80700780E00380E00380E00380E00380E00380E00380700780700780380F803C1F801FFF800FFB
+8003E380000380000380000380000380000380000380000380001FF0003FF8001FF0151E7E9318
+>I<FF0FC0FF3FE0FF7FF007F0F007E06007C00007800007800007000007000007000007000007
+0000070000070000070000070000FFFC00FFFE00FFFC0014147E9318>I<07F7003FFF007FFF00
+780F00E00700E00700E007007C00007FE0001FFC0003FE00001F00600780E00380E00380F00380
+F80F00FFFF00FFFC00E7F00011147D9318>I<0180000380000380000380000380007FFFC0FFFF
+C0FFFFC00380000380000380000380000380000380000380000380000380000380400380E00380
+E00380E001C1C001FFC000FF80003E0013197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E
+00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E01E00F03E007FFFC03
+FFFE01FCFC1714809318>I<7F8FF0FF8FF87F8FF01C01C00E03800E03800E0380070700070700
+070700078F00038E00038E00038E0001DC0001DC0001DC0000F80000F80000700015147F9318>
+I<FF07F8FF8FF8FF07F83800E03800E03800E03800E01C01C01C71C01CF9C01CF9C01CD9C01DDD
+C00DDD800DDD800DDD800D8D800F8F800F8F8007070015147F9318>I<7F8FF07F9FF07F8FF00F
+0700078E00039E0001DC0001F80000F80000700000F00000F80001DC00039E00038E000707000E
+07807F8FF0FF8FF87F8FF015147F9318>I<7F8FF0FF8FF87F8FF00E01C00E03800E0380070380
+070700070700038700038700038E0001CE0001CE0001CC0000CC0000DC00007800007800007800
+00700000700000700000F00000E00079E0007BC0007F80003F00001E0000151E7F9318>I<3FFF
+F07FFFF07FFFF07001E07003C0700780000F00001E00003C0000F80001F00003C0000780000F00
+701E00703C0070780070FFFFF0FFFFF0FFFFF014147F9318>I<0007E0001FE0007FE000780000
+E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00001E0007FC000FF
+8000FF80007FC00001E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000
+E00000E000007800007FE0001FE00007E013247E9F18>I<60F0F0F0F0F0F0F0F0F0F0F0F0F0F0
+F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0600424769F18>I<7C0000FF0000FFC00003C0
+0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000F000007F
+C0003FE0003FE0007FC000F00000E00000E00000E00000E00000E00000E00000E00000E00000E0
+0000E00000E00003C000FFC000FF00007C000013247E9F18>I E /Fm 46
+122 df<00003F000000000000FF800000000003E0C00000000007C060000000000F8070000000
+001F8030000000003F0038000000003F0038000000003F0038000000007F0038000000007F0038
+000000007F0070000000007F0060000000007F80E0000000007F80C0000000007F818000000000
+7F8300000000003F8600000000003FCC0000FFFE003FD80000FFFE003FF00000FFFE001FE00000
+0780001FE000000700001FF000000E00000FF000001C00000FF800001C00000FF800003800001F
+FC000038000033FE000070000063FE0000E00001C1FF0000E00003C1FF8001C00007C0FF800380
+000F807FC00700001F807FE00700003F803FF00E00007F801FF81C00007F800FFC380000FF8007
+FC700000FF8003FEE00000FF8001FFC00000FFC000FF800000FFC0007FC0000E7FC0003FF0000E
+7FE0007FF8001C3FF001F7FE003C1FF80FE1FF81F807FFFF807FFFF001FFFE001FFFC0003FE000
+01FE0037327DB13F>38 D<FFFFF8FFFFF8FFFFF8FFFFF8FFFFF8FFFFF8FFFFF815077F921B>45
+D<0001C0000003C000000FC000007FC0001FFFC000FFFFC000FFBFC000E03FC000003FC000003F
+C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00000
+3FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000
+003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0
+00003FC000003FC000003FC000003FC0007FFFFFF07FFFFFF07FFFFFF01C2E7AAD28>49
+D<003FE00001FFFE0007FFFF800F80FFC01E003FE038001FF07C000FF87E0007FCFF0007FCFF80
+07FEFF8007FEFF8003FEFF8003FE7F0003FE3E0007FE000007FE000007FC000007FC00000FF800
+000FF800000FF000001FE000001FC000003F8000007F0000007E000000F8000001F0000003E000
+0007C000000F0000001E000E003C000E0038000E0070001E00E0001C01C0001C0300003C07FFFF
+FC0FFFFFFC1FFFFFFC3FFFFFFC7FFFFFF8FFFFFFF8FFFFFFF8FFFFFFF81F2E7CAD28>I<001FF8
+000000FFFF000003FFFFC00007E01FF0000F0007F8001F8007FC003FC007FC003FC003FE003FC0
+03FE003FC003FE003FC003FE001F8003FE000F0007FE00000007FC00000007FC00000007F80000
+000FF00000001FE00000003F80000000FF0000003FF80000003FFF800000001FE00000000FF000
+000007F800000003FC00000003FE00000001FF00000001FF00000001FF80000001FF80000001FF
+801C0001FF803E0001FF807F0001FF80FF8001FF80FF8001FF00FF8001FF00FF8003FE007F0003
+FE007E0007FC003C0007F8001FC01FF0000FFFFFC00003FFFF0000003FF80000212E7DAD28>I<
+0000007000000000F000000001F000000003F000000007F00000000FF00000000FF00000001FF0
+0000003FF000000077F0000000F7F0000000E7F0000001C7F000000387F000000707F000000F07
+F000000E07F000001C07F000003807F000007007F00000F007F00000E007F00001C007F0000380
+07F000070007F0000F0007F0000E0007F0001C0007F000380007F000700007F000E00007F000FF
+FFFFFFE0FFFFFFFFE0FFFFFFFFE000000FF00000000FF00000000FF00000000FF00000000FF000
+00000FF00000000FF00000000FF00000000FF000000FFFFFE0000FFFFFE0000FFFFFE0232E7EAD
+28>I<0C0000300FC007F00FFFFFE00FFFFFC00FFFFF800FFFFF000FFFFE000FFFF8000FFFF000
+0FFF80000E0000000E0000000E0000000E0000000E0000000E0000000E0000000E0000000E1FF0
+000EFFFE000FE03F800F000FC00E0007E00C0007F0000007F8000003F8000003FC000003FC0000
+03FE000003FE180003FE3E0003FE7F0003FEFF0003FEFF0003FEFF0003FCFF0003FCFE0003FC78
+0007F8780007F03C000FE01E001FC00FC07F8007FFFF0001FFFC00003FE0001F2E7CAD28>I<00
+00FF00000007FFE000001FFFF000007F80F80000FE003C0001F8007C0003F000FE0007F001FE00
+0FE001FE000FE001FE001FC001FE003FC000FC003FC00078003FC00000007F800000007F800000
+007F80000000FF83FC0000FF8FFF8000FF9C0FC000FFB003F000FFB001F800FFE001FC00FFC001
+FE00FFC000FE00FFC000FF00FFC000FF00FF8000FF80FF8000FF80FF8000FF80FF8000FF807F80
+00FF807F8000FF807F8000FF807F8000FF803F8000FF003FC000FF001FC000FF001FC000FE000F
+C001FC0007E001FC0003F003F80001FC0FE00000FFFFC000003FFF0000000FFC0000212E7DAD28
+>I<38000000003E000000003FFFFFFFC03FFFFFFFC03FFFFFFFC03FFFFFFF807FFFFFFF007FFF
+FFFE007FFFFFFC007FFFFFF80078000038007000007000700000E000F00001C000E000038000E0
+00070000E00007000000000E000000001C00000000380000000078000000007000000000F00000
+0001E000000001E000000003E000000003C000000007C000000007C00000000FC00000000FC000
+00001FC00000001F800000001F800000003F800000003F800000003F800000003F800000007F80
+0000007F800000007F800000007F800000007F800000007F800000007F800000007F800000003F
+000000001E00000022307CAF28>I<000FFC0000007FFF800001FFFFE00003F00FF00007C003F8
+000F8000FC001F0000FC001F00007E003F00007E003F00007E003F00007E003F80007E003FC000
+7E003FF000FC003FFC00F8001FFE01F8001FFF81F0000FFFE3C00007FFFF800003FFFE000001FF
+FF000000FFFFC000003FFFE00000FFFFF00003E3FFF80007C1FFFC000F807FFE001F001FFF003E
+000FFF007E0003FF807E0000FF80FC00007F80FC00003F80FC00001F80FC00001F80FC00001F80
+FC00001F00FE00001F007E00001F007E00003E003F00007C001FC000F8000FF007F00003FFFFE0
+0000FFFF8000001FF80000212E7DAD28>I<000FF80000007FFF000001FFFF800003F80FC00007
+E007E0000FC003F0001FC001F8003FC001FC007F8001FC007F8001FE007F8000FE00FF8000FF00
+FF8000FF00FF8000FF00FF8000FF00FF8000FF80FF8000FF80FF8000FF80FF8000FF807F8001FF
+807F8001FF803F8001FF803FC001FF801FC003FF800FC006FF8007E006FF8001F81CFF8000FFF8
+FF80001FE0FF80000000FF00000000FF00000000FF00000000FF000F0001FE001F8001FE003FC0
+01FC003FC001FC003FC003F8003FC003F0003F8007E0001F000FC0001E001F80000F807F000007
+FFFE000001FFF80000007FC00000212E7DAD28>I<0000007800000000000078000000000000FC
+000000000000FC000000000000FC000000000001FE000000000001FE000000000003FF00000000
+0003FF000000000007FF800000000007FF800000000007FF80000000000FFFC0000000000E7FC0
+000000001E7FE0000000001C3FE0000000001C3FE000000000383FF000000000381FF000000000
+781FF800000000700FF800000000700FF800000000E00FFC00000000E007FC00000001E007FE00
+000001C003FE00000001C003FE000000038001FF000000038001FF000000078001FF8000000700
+00FF8000000F0000FFC000000FFFFFFFC000000FFFFFFFC000001FFFFFFFE000001C00003FE000
+003C00003FF000003800001FF000003800001FF000007000001FF800007000000FF80000F00000
+0FFC0000E0000007FC0000E0000007FC0001C0000007FE0003E0000003FE00FFFF0001FFFFFCFF
+FF0001FFFFFCFFFF0001FFFFFC36317DB03D>65 D<000003FF80018000003FFFF003800001FFFF
+FC07800007FF003F0F80001FF800079F80003FC00001FF8000FF800000FF8001FE0000007F8003
+FC0000003F8007FC0000001F8007F80000000F800FF00000000F801FF000000007801FF0000000
+07803FE000000007803FE000000003807FE000000003807FE000000003807FC000000000007FC0
+0000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC000000000
+00FFC00000000000FFC00000000000FFC00000000000FFC000000000007FC000000000007FC000
+000000007FE000000000007FE000000003803FE000000003803FE000000003801FF00000000380
+1FF000000007800FF0000000070007F8000000070007FC0000000E0003FC0000001E0001FE0000
+001C0000FF8000007800003FC00000F000001FF80003E0000007FF003F80000001FFFFFE000000
+003FFFF80000000003FF80000031317CB03A>67 D<FFFFFFFFF00000FFFFFFFFFF0000FFFFFFFF
+FFC00000FF8000FFF00000FF80000FF80000FF800003FE0000FF800001FF0000FF800000FF8000
+FF8000007FC000FF8000003FC000FF8000001FE000FF8000001FF000FF8000000FF000FF800000
+0FF800FF8000000FF800FF80000007FC00FF80000007FC00FF80000007FC00FF80000007FC00FF
+80000007FE00FF80000007FE00FF80000007FE00FF80000007FE00FF80000007FE00FF80000007
+FE00FF80000007FE00FF80000007FE00FF80000007FE00FF80000007FE00FF80000007FE00FF80
+000007FC00FF80000007FC00FF80000007FC00FF80000007FC00FF8000000FF800FF8000000FF8
+00FF8000000FF000FF8000001FF000FF8000001FE000FF8000003FE000FF8000007FC000FF8000
+007F8000FF800001FF0000FF800003FE0000FF80000FFC0000FF80007FF000FFFFFFFFFFC000FF
+FFFFFFFF0000FFFFFFFFF0000037317EB03E>I<FFFFFFFFFFF0FFFFFFFFFFF0FFFFFFFFFFF000
+FF80003FF000FF800007F800FF800003F800FF800000F800FF800000F800FF8000007800FF8000
+007800FF8000003800FF8000003800FF8000003800FF8000001C00FF8007001C00FF8007001C00
+FF8007001C00FF8007000000FF8007000000FF800F000000FF801F000000FF803F000000FFFFFF
+000000FFFFFF000000FFFFFF000000FF803F000000FF801F000000FF800F000000FF8007000000
+FF8007000000FF8007000700FF8007000700FF8007000700FF8000000E00FF8000000E00FF8000
+000E00FF8000000E00FF8000001E00FF8000001E00FF8000003C00FF8000003C00FF8000007C00
+FF800000FC00FF800001FC00FF800007FC00FF80003FFCFFFFFFFFFFF8FFFFFFFFFFF8FFFFFFFF
+FFF830317EB035>I<FFFFFFFFFFE0FFFFFFFFFFE0FFFFFFFFFFE000FF80007FE000FF80000FF0
+00FF800003F000FF800001F000FF800001F000FF800000F000FF800000F000FF8000007000FF80
+00007000FF8000007000FF8000003800FF8000003800FF8007003800FF8007003800FF80070000
+00FF8007000000FF8007000000FF800F000000FF801F000000FF803F000000FFFFFF000000FFFF
+FF000000FFFFFF000000FF803F000000FF801F000000FF800F000000FF8007000000FF80070000
+00FF8007000000FF8007000000FF8007000000FF8000000000FF8000000000FF8000000000FF80
+00000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80000000
+00FF8000000000FF80000000FFFFFFC00000FFFFFFC00000FFFFFFC000002D317EB033>I<FFFF
+FF80FFFFFF80FFFFFF8000FF800000FF800000FF800000FF800000FF800000FF800000FF800000
+FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF8000
+00FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF80
+0000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF
+800000FF800000FF800000FF800000FF800000FF800000FF8000FFFFFF80FFFFFF80FFFFFF8019
+317EB01E>73 D<FFFFFF800000FFFFFF800000FFFFFF80000001FF0000000001FF0000000001FF
+0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF000000
+0001FF0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF
+0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF000000
+0001FF0000000001FF0000000001FF0000000001FF0000000001FF0000000001FF0000038001FF
+0000038001FF0000038001FF0000038001FF0000078001FF0000070001FF0000070001FF00000F
+0001FF00000F0001FF00000F0001FF00001F0001FF00003F0001FF00007F0001FF0000FF0001FF
+0001FE0001FF000FFE00FFFFFFFFFE00FFFFFFFFFE00FFFFFFFFFE0029317DB030>76
+D<FFFFC000000003FFFFFFFFC000000003FFFFFFFFE000000007FFFF00FFE000000007FF0000EF
+F00000000EFF0000EFF00000000EFF0000EFF00000000EFF0000E7F80000001CFF0000E7F80000
+001CFF0000E3FC00000038FF0000E3FC00000038FF0000E1FE00000070FF0000E1FE00000070FF
+0000E0FF000000E0FF0000E0FF000000E0FF0000E07F800001C0FF0000E07F800001C0FF0000E0
+3FC0000380FF0000E03FC0000380FF0000E03FC0000380FF0000E01FE0000700FF0000E01FE000
+0700FF0000E00FF0000E00FF0000E00FF0000E00FF0000E007F8001C00FF0000E007F8001C00FF
+0000E003FC003800FF0000E003FC003800FF0000E001FE007000FF0000E001FE007000FF0000E0
+00FF00E000FF0000E000FF00E000FF0000E000FF00E000FF0000E0007F81C000FF0000E0007F81
+C000FF0000E0003FC38000FF0000E0003FC38000FF0000E0001FE70000FF0000E0001FE70000FF
+0000E0000FFE0000FF0000E0000FFE0000FF0000E00007FC0000FF0000E00007FC0000FF0000E0
+0007FC0000FF0000E00003F80000FF0001F00003F80000FF00FFFFE001F000FFFFFFFFFFE001F0
+00FFFFFFFFFFE000E000FFFFFF48317EB04D>I<00000FFF0000000000FFFFF000000007FC03FE
+0000001FE0007F8000003F80001FC000007F00000FE00001FE000007F80003FC000003FC0007F8
+000001FE0007F8000001FE000FF0000000FF001FF0000000FF801FE00000007F803FE00000007F
+C03FE00000007FC03FE00000007FC07FC00000003FE07FC00000003FE07FC00000003FE0FFC000
+00003FF0FFC00000003FF0FFC00000003FF0FFC00000003FF0FFC00000003FF0FFC00000003FF0
+FFC00000003FF0FFC00000003FF0FFC00000003FF0FFC00000003FF0FFC00000003FF07FC00000
+003FE07FE00000007FE07FE00000007FE07FE00000007FE03FE00000007FC03FE00000007FC01F
+F0000000FF801FF0000000FF800FF8000001FF0007F8000001FE0007FC000003FE0003FC000003
+FC0001FE000007F80000FF00000FF000003FC0003FC000001FE0007F80000007FC03FE00000000
+FFFFF0000000000FFF00000034317CB03D>79 D<FFFFFFFFE000FFFFFFFFFE00FFFFFFFFFF8000
+FF8000FFE000FF80003FF000FF80000FF800FF800007FC00FF800007FC00FF800003FE00FF8000
+03FE00FF800003FF00FF800003FF00FF800003FF00FF800003FF00FF800003FF00FF800003FF00
+FF800003FF00FF800003FE00FF800003FE00FF800007FC00FF800007F800FF80000FF800FF8000
+3FE000FF8000FFC000FFFFFFFF0000FFFFFFF80000FF8000000000FF8000000000FF8000000000
+FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000
+000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000
+FF8000000000FF8000000000FF8000000000FF80000000FFFFFF800000FFFFFF800000FFFFFF80
+000030317EB037>I<FFFFFFFF80000000FFFFFFFFF8000000FFFFFFFFFE00000000FF8003FF80
+000000FF80007FE0000000FF80001FF0000000FF80000FF8000000FF80000FF8000000FF80000F
+FC000000FF800007FC000000FF800007FE000000FF800007FE000000FF800007FE000000FF8000
+07FE000000FF800007FE000000FF800007FE000000FF800007FC000000FF80000FFC000000FF80
+000FF8000000FF80001FF0000000FF80003FE0000000FF80007FC0000000FF8003FF00000000FF
+FFFFF800000000FFFFFFE000000000FF8007F800000000FF8001FC00000000FF8000FE00000000
+FF80007F00000000FF80007F80000000FF80003FC0000000FF80003FC0000000FF80003FE00000
+00FF80003FE0000000FF80003FE0000000FF80003FE0000000FF80003FE0000000FF80003FF000
+0000FF80003FF0000000FF80003FF0000000FF80003FF0000000FF80003FF0038000FF80003FF8
+038000FF80001FF8038000FF80001FF8030000FF80000FFC0700FFFFFF8003FE0E00FFFFFF8001
+FFFC00FFFFFF80001FF00039317EB03C>82 D<001FF8018000FFFF038003FFFFC78007F007EF80
+0F8000FF801F00007F803E00001F803E00000F807C00000F807C00000780FC00000780FC000007
+80FC00000380FE00000380FE00000380FF00000000FFC00000007FF00000007FFF8000003FFFF8
+00003FFFFF80001FFFFFF0000FFFFFF80007FFFFFC0003FFFFFF0000FFFFFF00003FFFFF800001
+FFFFC000001FFFE0000001FFE00000003FE00000001FF00000000FF000000007F060000007F0E0
+000003F0E0000003F0E0000003F0E0000003E0F0000003E0F0000003E0F8000007C0FC000007C0
+FF00000F80FFC0001F00FBFC00FE00F1FFFFF800E03FFFF000C003FF800024317CB02D>I<7FFF
+FFFFFFFF007FFFFFFFFFFF007FFFFFFFFFFF007FC00FF801FF007E000FF8003F007C000FF8001F
+0078000FF8000F0078000FF8000F0070000FF8000700F0000FF8000780F0000FF8000780F0000F
+F8000780E0000FF8000380E0000FF8000380E0000FF8000380E0000FF8000380E0000FF8000380
+00000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8
+00000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000
+000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800
+000000000FF800000000000FF800000000000FF800000000000FF800000000000FF80000000000
+0FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF80000
+00007FFFFFFF0000007FFFFFFF0000007FFFFFFF000031307DAF38>I<00FFF0000003FFFF0000
+0F803F80000FC00FE0001FE007F0001FE007F0001FE003F8000FC003FC00078003FC00000003FC
+00000003FC00000003FC00000003FC000000FFFC00001FFFFC0000FFE3FC0003FC03FC000FF003
+FC001FC003FC003FC003FC007F8003FC007F8003FC00FF0003FC00FF0003FC00FF0003FC00FF00
+07FC00FF0007FC007F800DFC003FC01DFE001FE078FFF007FFE07FF000FF803FF024207E9F27>
+97 D<01F8000000FFF8000000FFF8000000FFF80000000FF800000007F800000007F800000007
+F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8000000
+07F800000007F800000007F800000007F83FE00007F8FFFC0007FBE07F0007FF001F8007FE000F
+C007FC000FE007F80007F007F80007F807F80007F807F80003FC07F80003FC07F80003FC07F800
+03FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F8
+0003FC07F80003FC07F80003FC07F80007F807F80007F807F80007F007FC000FE007FE000FC007
+E7003F8007C3C0FE000780FFF80007003FC00027327EB12D>I<000FFF00007FFFC001FC01F003
+F003F007E007F80FE007F81FC007F83FC003F03FC001E07F8000007F8000007F800000FF800000
+FF800000FF800000FF800000FF800000FF800000FF800000FF8000007F8000007F8000007F8000
+003FC0001C3FC0001C1FC000380FE0003807E0007003F001E001FC07C0007FFF00000FF8001E20
+7D9F24>I<0000000FC0000007FFC0000007FFC0000007FFC00000007FC00000003FC00000003F
+C00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0000000
+3FC00000003FC00000003FC00000003FC00007F83FC0003FFF3FC000FE07BFC003F801FFC007E0
+007FC00FE0007FC01FC0003FC03FC0003FC03FC0003FC07F80003FC07F80003FC07F80003FC0FF
+80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0
+7F80003FC07F80003FC07F80003FC03FC0003FC03FC0003FC01FC0003FC00FE0007FC007E000FF
+C003F003FFE001FC0F3FFE007FFE3FFE000FF03FFE27327DB12D>I<000FFC00007FFF8001FC0F
+C003F003E007E001F00FE001F81FC000FC3FC000FE3FC000FE7F80007E7F80007F7F80007FFF80
+007FFF80007FFFFFFFFFFFFFFFFFFF800000FF800000FF800000FF8000007F8000007F8000007F
+8000003FC000071FC000071FC0000E0FE0000E07F0001C03F8007800FE03E0003FFFC00007FE00
+20207E9F25>I<0001FE00000FFF80001FC3C0007F07E000FE0FF001FE0FF001FC0FF003FC0FF0
+03FC07E003FC018003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00
+00FFFFFC00FFFFFC00FFFFFC0003FC000003FC000003FC000003FC000003FC000003FC000003FC
+000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003
+FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0000
+7FFFF0007FFFF0007FFFF0001C327EB119>I<001FF007C000FFFE3FE001F83F79F007E00FC3F0
+0FE00FE1F00FC007E0E01FC007F0001FC007F0003FC007F8003FC007F8003FC007F8003FC007F8
+003FC007F8001FC007F0001FC007F0000FC007E0000FE00FE00007E00FC00003F83F000006FFFE
+00000E1FF000000E000000001E000000001E000000001F000000001F800000001FFFFF80000FFF
+FFF0000FFFFFFC0007FFFFFE0003FFFFFF0003FFFFFF800FFFFFFFC03F00007FC07E00001FE07C
+00000FE0FC000007E0FC000007E0FC000007E0FC000007E07E00000FC03E00000F803F00001F80
+0FC0007E0007F803FC0001FFFFF000001FFF0000242F7E9F28>I<03C00007E0000FF0001FF800
+1FF8001FF8001FF8000FF00007E00003C000000000000000000000000000000000000000000000
+00000000000001F8007FF8007FF8007FF80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB217>105
+D<01F8000000FFF8000000FFF8000000FFF80000000FF800000007F800000007F800000007F800
+000007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8
+00000007F800000007F800000007F800FFF807F800FFF807F800FFF807F8003F0007F8003C0007
+F800780007F800F00007F803C00007F807800007F80F000007F81E000007F878000007F8FC0000
+07F9FE000007FBFE000007FFFF000007FE7F800007FC7FC00007F83FC00007F01FE00007F00FF0
+0007F00FF80007F007FC0007F003FC0007F001FE0007F000FF0007F000FF8007F0007F8007F000
+7FC0FFFF81FFFEFFFF81FFFEFFFF81FFFE27327EB12B>107 D<01F800FFF800FFF800FFF8000F
+F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007
+F80007F80007F80007F800FFFFC0FFFFC0FFFFC012327DB117>I<03F007F8001FE000FFF03FFE
+00FFF800FFF0783F01E0FC00FFF0C03F8300FE000FF1801FC6007F0007F3001FCC007F0007F600
+1FF8007F8007FC001FF0007F8007FC001FF0007F8007FC001FF0007F8007F8001FE0007F8007F8
+001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007
+F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F80
+07F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F
+8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F80FFFFC3FFFF0FFFFCFFFFC3FFFF0F
+FFFCFFFFC3FFFF0FFFFC3E207D9F43>I<03F007F800FFF03FFE00FFF0783F00FFF0C03F800FF1
+801FC007F3001FC007F6001FE007FC001FE007FC001FE007FC001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F
+E007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28207D9F2D>I<0007FC0000007FFFC00001
+FC07F00003F001F80007E000FC000FC0007E001FC0007F003FC0007F803F80003F807F80003FC0
+7F80003FC07F80003FC0FF80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003F
+E0FF80003FE0FF80003FE07F80003FC07F80003FC07F80003FC03FC0007F803FC0007F801FC000
+7F000FE000FE0007E000FC0003F803F80001FE0FF000007FFFC0000007FC000023207E9F28>I<
+01F83FE000FFF8FFFC00FFFBE07F00FFFF003F8007FE001FC007FC000FE007F8000FF007F80007
+F807F80007F807F80007FC07F80003FC07F80003FC07F80003FE07F80003FE07F80003FE07F800
+03FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FC07F80007FC07F80007FC07F8
+0007F807F80007F807F8000FF007FC000FE007FE001FC007FF003F8007FBC0FE0007F8FFF80007
+F83FC00007F800000007F800000007F800000007F800000007F800000007F800000007F8000000
+07F800000007F800000007F800000007F8000000FFFFC00000FFFFC00000FFFFC00000272E7E9F
+2D>I<03F03F00FFF07FC0FFF1C3E0FFF187E00FF30FF007F60FF007F60FF007FC07E007FC03C0
+07FC000007FC000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F800
+0007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8
+0000FFFFE000FFFFE000FFFFE0001C207E9F21>114 D<01FF860007FFFE001F00FE003C003E00
+78001E0078000E00F8000E00F8000E00F8000E00FC000000FF800000FFFC00007FFFC0003FFFF0
+003FFFF8001FFFFC0007FFFE0001FFFF00003FFF000000FF8000003F8060001F80E0000F80E000
+0F80F0000F80F0000F00F8000F00FC001E00FE001C00FF807800F3FFF000C07F800019207D9F20
+>I<001C0000001C0000001C0000001C0000001C0000003C0000003C0000003C0000007C000000
+7C000000FC000001FC000003FC000007FC00001FFFFE00FFFFFE00FFFFFE0003FC000003FC0000
+03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00
+0003FC000003FC000003FC000003FC000003FC038003FC038003FC038003FC038003FC038003FC
+038003FC038001FC038001FC070000FE0700007F0E00003FFC000007F000192E7FAD1F>I<01F8
+0007E0FFF803FFE0FFF803FFE0FFF803FFE00FF8003FE007F8001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F
+E007F8003FE007F8003FE003F8007FE003F8007FE001FC00DFF000FE039FFF007FFF1FFF000FFC
+1FFF28207D9F2D>I<FFFF001FFCFFFF001FFCFFFF001FFC0FF80003C007F800038007FC000780
+03FC00070003FE00070001FE000E0001FF000E0000FF001C0000FF001C0000FF803C00007F8038
+00007FC07800003FC07000003FE0F000001FE0E000001FF1E000000FF1C000000FF9C0000007FB
+80000007FB80000007FF80000003FF00000003FF00000001FE00000001FE00000000FC00000000
+FC00000000780000000078000026207E9F2B>I<FFFF1FFFE03FF8FFFF1FFFE03FF8FFFF1FFFE0
+3FF80FF000FE0007800FF800FE00038007F800FF00070007F8007F00070007FC007F000F0003FC
+00FF800E0003FC00FF800E0001FE01FFC01C0001FE01DFC01C0001FF01DFC03C0000FF038FE038
+0000FF038FE03800007F878FF07000007F8707F07000007FC707F0F000003FCF07F8E000003FCE
+03F8E000001FFE03F9C000001FFC01FDC000001FFC01FFC000000FFC01FF8000000FF800FF8000
+000FF800FF80000007F0007F00000007F0007F00000003F0007E00000003E0003E00000003E000
+3E00000001C0001C000035207E9F3A>I<7FFF807FFC7FFF807FFC7FFF807FFC03FC000F0001FE
+001E0000FF003C0000FF803800007FC07800003FC0F000001FE1E000000FF3C000000FFF800000
+07FF00000003FE00000001FE00000000FF00000000FF80000000FFC0000001FFC0000003DFE000
+00078FF00000078FF800000F07FC00001E03FE00003C01FE00007800FF0000F000FF8001E0007F
+C003E0003FE0FFFC01FFFFFFFC01FFFFFFFC01FFFF28207F9F2B>I<FFFF001FFCFFFF001FFCFF
+FF001FFC0FF80003C007F800038007FC00078003FC00070003FE00070001FE000E0001FF000E00
+00FF001C0000FF001C0000FF803C00007F803800007FC07800003FC07000003FE0F000001FE0E0
+00001FF1E000000FF1C000000FF9C0000007FB80000007FB80000007FF80000003FF00000003FF
+00000001FE00000001FE00000000FC00000000FC00000000780000000078000000007000000000
+7000000000F000000000E000000001E000007C01C00000FE03C00000FE03800000FE07000000FE
+0F000000FC1E000000787C0000003FF00000000FC0000000262E7E9F2B>I
+E /Fn 2 16 df<0000FF00000007FFE000001F00F8000078001E0000E000070001800001800300
+0000C006000000600C000000300C000000301800000018300000000C300000000C600000000660
+0000000660000000066000000006C000000003C000000003C000000003C000000003C000000003
+C000000003C000000003C000000003C00000000360000000066000000006600000000660000000
+06300000000C300000000C18000000180C000000300C00000030060000006003000000C0018000
+018000E00007000078001E00001F00F8000007FFE0000000FF0000282B7EA02D>13
+D<03F0000FFC001FFE003FFF007FFF807FFF80FFFFC0FFFFC0FFFFC0FFFFC0FFFFC0FFFFC07FFF
+807FFF803FFF001FFE000FFC0003F00012127E9317>15 D E /Fo 82 125
+df<001F83E000F06E3001C078780380F8780300F0300700700007007000070070000700700007
+0070000700700007007000FFFFFF80070070000700700007007000070070000700700007007000
+070070000700700007007000070070000700700007007000070070000700700007007000070070
+0007007000070070003FE3FF001D20809F1B>11 D<003F0000E0C001C0C00381E00701E00701E0
+070000070000070000070000070000070000FFFFE00700E00700E00700E00700E00700E00700E0
+0700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E03FC3FC
+1620809F19>I<003FE000E0E001C1E00381E00700E00700E00700E00700E00700E00700E00700
+E00700E0FFFFE00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700
+E00700E00700E00700E00700E00700E00700E00700E03FE7FC1620809F19>I<001F81F80000F0
+4F040001C07C06000380F80F000300F00F000700F00F0007007000000700700000070070000007
+0070000007007000000700700000FFFFFFFF000700700700070070070007007007000700700700
+070070070007007007000700700700070070070007007007000700700700070070070007007007
+000700700700070070070007007007000700700700070070070007007007003FE3FE3FE0232080
+9F26>I<7038F87CFC7EFC7E743A0402040204020804080410081008201040200F0E7F9F17>34
+D<0078000000840000018400000302000007020000070200000702000007020000070400000704
+000007080000070800000390000003A00FFC03C001E003C000C001C0008001C0010002E0010004
+E00200087002001878040030380800703C0800701C1000F00E1000F00F2000F007C000F0038004
+7001C0047802E008380470181C183C3007E00FC01E227EA023>38 D<70F8FCFC74040404080810
+102040060E7C9F0D>I<0040008001000300060004000C00180018003800300030007000600060
+0060006000E000E000E000E000E000E000E000E000E000E000E000E00060006000600060007000
+300030003800180018000C000400060003000100008000400A2E7BA112>I<8000400020003000
+180008000C00060006000700030003000380018001800180018001C001C001C001C001C001C001
+C001C001C001C001C001C001800180018001800380030003000700060006000C00080018003000
+2000400080000A2E7EA112>I<70F0F8F878080808101010202040050E7C840D>44
+D<FFF0FFF00C02808A0F>I<70F8F8F87005057C840D>I<0000400000C000018000018000018000
+0300000300000300000600000600000C00000C00000C0000180000180000180000300000300000
+600000600000600000C00000C00000C00001800001800001800003000003000006000006000006
+00000C00000C00000C0000180000180000300000300000300000600000600000600000C00000C0
+0000122D7EA117>I<03F0000E1C001C0E00180600380700700380700380700380700380F003C0
+F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0700380
+7003807003807807803807001806001C0E000E1C0003F000121F7E9D17>I<008003800F80F380
+038003800380038003800380038003800380038003800380038003800380038003800380038003
+80038003800380038007C0FFFE0F1E7C9D17>I<03F0000C1C00100E00200700400780800780F0
+07C0F803C0F803C0F803C02007C00007C0000780000780000F00000E00001C0000380000700000
+600000C0000180000300000600400C00401800401000803FFF807FFF80FFFF80121E7E9D17>I<
+03F0000C1C00100E00200F00780F80780780780780380F80000F80000F00000F00001E00001C00
+00700007F000003C00000E00000F000007800007800007C02007C0F807C0F807C0F807C0F00780
+400780400F00200E00183C0007F000121F7E9D17>I<000600000600000E00000E00001E00002E
+00002E00004E00008E00008E00010E00020E00020E00040E00080E00080E00100E00200E00200E
+00400E00C00E00FFFFF0000E00000E00000E00000E00000E00000E00000E0000FFE0141E7F9D17
+>I<1803001FFE001FFC001FF8001FE00010000010000010000010000010000010000011F00016
+1C00180E001007001007800003800003800003C00003C00003C07003C0F003C0F003C0E0038040
+0380400700200600100C0008380007E000121F7E9D17>I<007C000182000701000E03800C0780
+180780380300380000780000700000700000F1F000F21C00F40600F80700F80380F80380F003C0
+F003C0F003C0F003C0F003C07003C07003C07003803803803807001807000C0E00061C0001F000
+121F7E9D17>I<4000007FFFE07FFFC07FFFC04000808001008001008002000004000004000008
+0000100000100000200000200000600000600000E00000C00001C00001C00001C00001C00003C0
+0003C00003C00003C00003C00003C00003C000018000131F7E9D17>I<03F0000C0C0010060030
+03002001806001806001806001807001807803003E03003F06001FC8000FF00003F80007FC000C
+7E00103F00300F806007806001C0C001C0C000C0C000C0C000C0C000806001802001001002000C
+0C0003F000121F7E9D17>I<03F0000E18001C0C00380600380700700700700380F00380F00380
+F003C0F003C0F003C0F003C0F003C07007C07007C03807C0180BC00E13C003E3C0000380000380
+000380000700300700780600780E00700C002018001070000FC000121F7E9D17>I<70F8F8F870
+0000000000000000000070F8F8F87005147C930D>I<70F8F8F8700000000000000000000070F0
+F8F878080808101010202040051D7C930D>I<000100000003800000038000000380000007C000
+0007C0000007C0000009E0000009E0000009E0000010F0000010F0000010F00000207800002078
+000020780000403C0000403C0000C03E0000801E0000801E0001FFFF0001000F0001000F000200
+07800200078002000780040003C0040003C00C0003C01E0003E0FF801FFE1F207F9F22>65
+D<FFFFE0000F0078000F001E000F001E000F000F000F000F800F000F800F000F800F000F800F00
+0F800F000F000F001F000F001E000F007C000FFFF0000F007C000F001F000F000F800F0007C00F
+0003C00F0003E00F0003E00F0003E00F0003E00F0003E00F0003C00F0007C00F0007800F000F00
+0F003E00FFFFF0001B1F7E9E20>I<000FE01000381C3000E0027003C00170078000F00F000070
+1E0000701E0000303C0000303C0000107C00001078000010F8000000F8000000F8000000F80000
+00F8000000F8000000F8000000F8000000F8000000780000007C0000103C0000103C0000101E00
+00201E0000200F0000200780004003C0008000E0030000380C00000FF0001C217E9F21>I<FFFF
+F80007801E0007800780078003C0078001E0078000F00780007007800078078000780780003C07
+80003C0780003C0780003E0780003E0780003E0780003E0780003E0780003E0780003E0780003E
+0780003C0780003C0780007C0780007807800078078000F0078001E0078003C00780078007801E
+00FFFFF8001F1F7F9E23>I<FFFFFF800F000F800F0003800F0001800F0000800F0000C00F0000
+400F0000400F0000400F0040400F0040000F0040000F00C0000F01C0000FFFC0000F01C0000F00
+C0000F0040000F0040000F0040000F0000200F0000200F0000200F0000400F0000400F0000400F
+0000C00F0001C00F0003800F000F80FFFFFF801B1F7E9E1F>I<FFFFFF80078007800780018007
+80018007800080078000C007800040078000400780004007800040078020000780200007802000
+078060000780E00007FFE0000780E0000780600007802000078020000780200007800000078000
+0007800000078000000780000007800000078000000780000007C00000FFFE00001A1F7F9E1E>
+I<000FE01000381C3000E0027003C00170078000F00F0000701E0000701E0000303C0000303C00
+00107C00001078000010F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8
+003FFEF80001F0780000F07C0000F03C0000F03C0000F01E0000F01E0000F00F0000F0078000F0
+03C0017000E0023000380C10000FF0001F217E9F24>I<FFF07FF80F0007800F0007800F000780
+0F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007
+800FFFFF800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F00
+07800F0007800F0007800F0007800F0007800F0007800F000780FFF07FF81D1F7E9E22>I<FFF0
+0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F
+000F000F000F000F000F000F000F000F000F00FFF00C1F7E9E10>I<07FFC0003E00001E00001E
+00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E
+00001E00001E00001E00001E00001E00001E00201E00F81E00F81E00F81E00F01C00403C006038
+001070000FC00012207F9E17>I<FFF007FC0F0003E00F0001800F0001000F0002000F0004000F
+0008000F0010000F0020000F0040000F0080000F0100000F0300000F0780000F0F80000F13C000
+0F21E0000F41E0000F80F0000F0078000F0078000F003C000F001E000F001E000F000F000F0007
+800F0007800F0003C00F0003E00F0003F0FFF01FFE1F1F7E9E23>I<FFF8000F80000F00000F00
+000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00
+000F00000F00000F00000F00020F00020F00020F00020F00060F00040F00040F000C0F001C0F00
+7CFFFFFC171F7E9E1C>I<FF800007FE07800007C007800007C005C0000BC005C0000BC004E000
+13C004E00013C004E00013C004700023C004700023C004380043C004380043C004380043C0041C
+0083C0041C0083C0040E0103C0040E0103C0040E0103C004070203C004070203C004070203C004
+038403C004038403C00401C803C00401C803C00401C803C00400F003C00400F003C004006003C0
+1F006003C0FFE0607FFE271F7F9E2A>I<FF000FF80F8003E00F8000800BC0008009E0008009E0
+008008F000800878008008780080083C0080081E0080081E0080080F0080080780800807808008
+03C0800801E0800801E0800800F080080078800800788008003C8008001E8008001E8008000F80
+080007800800078008000380080001803E000180FF8000801D1F7E9E22>I<001FE00000703800
+01C00E0003800700070003800F0003C01E0001E03C0000F03C0000F07C0000F87C0000F8780000
+78F800007CF800007CF800007CF800007CF800007CF800007CF800007CF800007CF800007C7800
+00787C0000F87C0000F83C0000F03E0001F01E0001E00F0003C0070003800380070001E01E0000
+703800001FE0001E217E9F23>I<FFFFE0000F007C000F001E000F000F000F0007800F0007800F
+0007C00F0007C00F0007C00F0007C00F0007800F0007800F000F000F001E000F007C000FFFE000
+0F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000
+000F0000000F0000000F0000000F000000FFF000001A1F7E9E1F>I<001FE0000070380001C00E
+0003800700070003800F0003C01E0001E03E0001F03C0000F07C0000F87C0000F878000078F800
+007CF800007CF800007CF800007CF800007CF800007CF800007CF800007CF800007C780000787C
+0000F87C0000F83C0000F03E0781F01E0841E00F1023C0071023800390170001D01E0000783804
+001FF80400001C0400000C0C00000E1C00000FF800000FF8000007F8000007F0000001E01E297E
+9F23>I<FFFF80000F00F0000F003C000F001E000F000F000F000F000F000F800F000F800F000F
+800F000F800F000F000F000F000F001E000F003C000F00F0000FFF80000F01C0000F0070000F00
+70000F0038000F003C000F003C000F003C000F003E000F003E000F003E000F003E040F003F040F
+001F040F000F08FFF00788000001F01E207E9E21>I<03F0400C0CC01803C03001C06000C06000
+C0E000C0E00040E00040E00040F00000F800007C00007F80003FF8001FFF0007FF8000FFC0001F
+E00003E00001E00000F0000070800070800070800070800070C00060C000E0E000C0F80180C603
+0081FC0014217E9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010
+800F0010800F0010800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F00
+00000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F
+0000000F0000000F0000001F800003FFFC001C1F7E9E21>I<FFF00FF80F0003E00F0000800F00
+00800F0000800F0000800F0000800F0000800F0000800F0000800F0000800F0000800F0000800F
+0000800F0000800F0000800F0000800F0000800F0000800F0000800F0000800F0000800F000080
+0F0000800700010007800100038001000380020001C0040000E0080000383000000FC0001D207E
+9E22>I<FFF003FE1F8000F80F0000600F00002007800040078000400780004003C0008003C000
+8003E0018001E0010001E0010000F0020000F0020000F802000078040000780400003C0800003C
+0800003C0800001E1000001E1000001F1000000F2000000F20000007C0000007C0000007C00000
+0380000003800000038000000100001F207F9E22>I<FFF07FF81FF01F000FC007C00F00078001
+800F00078001000F0007C001000F8007C00300078007C00200078009E0020007C009E0020003C0
+09E0040003C019F0040003C010F0040001E010F0080001E010F0080001E02078080000F0207810
+0000F02078100000F0403C10000078403C20000078403C20000078801E2000007C801E6000003C
+801E4000003D000F4000003F000F4000001F000F8000001F000F8000001E00078000000E000700
+00000E00070000000C000300000004000200002C207F9E2F>I<7FF81FF80FE007C007C0030003
+C0020003E0060001F0040000F0080000F8180000781000003C2000003E6000001E4000000F8000
+000F8000000780000003C0000007E0000005E0000008F0000018F8000010780000207C0000603E
+0000401E0000801F0001000F8001000780020007C0060003C01F0007E0FFC01FFE1F1F7F9E22>
+I<FFF001FF1F8000780F8000600780006007C0004003C0008003E0008001F0010000F0010000F8
+0200007C0600003C0400003E0800001E0800001F1000000FB0000007A0000007E0000003C00000
+03C0000003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C000
+0003C000003FFC00201F7F9E22>I<FFFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0FFFF082D7CA10D>91 D<08041008201020104020
+4020804080408040B85CFC7EFC7E7C3E381C0F0E7A9F17>I<FFFF030303030303030303030303
+0303030303030303030303030303030303030303030303030303030303FFFF082D80A10D>I<08
+1020204040808080B8FCFC7C38060E7D9F0D>96 D<1FE000303000781800781C00300E00000E00
+000E00000E0000FE00078E001E0E00380E00780E00F00E10F00E10F00E10F01E10781E10386720
+0F83C014147E9317>I<1C0000FC00001C00001C00001C00001C00001C00001C00001C00001C00
+001C00001C00001C7C001D87001E01801E00C01C00E01C00701C00701C00781C00781C00781C00
+781C00781C00781C00701C00F01C00E01E00C01A0180198700107C0015207E9F19>I<01FC0007
+06001C0F00380F00380600780000700000F00000F00000F00000F00000F00000F0000070000078
+00003800803800801C010007060001F80011147F9314>I<0001C0000FC00001C00001C00001C0
+0001C00001C00001C00001C00001C00001C00001C001F1C0070DC00C03C01801C03801C07801C0
+7001C0F001C0F001C0F001C0F001C0F001C0F001C07001C07001C03801C01803C00C03C0070DC0
+01F1F815207F9F19>I<03F0000E1C001C0E00380700380700700700700380F00380F00380FFFF
+80F00000F00000F000007000007000003800803800801C010007060001F80011147F9314>I<00
+7C01C6030F070F0E060E000E000E000E000E000E000E00FFF00E000E000E000E000E000E000E00
+0E000E000E000E000E000E000E000E000E000E000E007FE01020809F0E>I<0000E003E3300E3C
+301C1C30380E00780F00780F00780F00780F00780F00380E001C1C001E380033E0002000002000
+003000003000003FFE001FFF801FFFC03001E0600070C00030C00030C00030C000306000603000
+C01C038003FC00141F7F9417>I<1C0000FC00001C00001C00001C00001C00001C00001C00001C
+00001C00001C00001C00001C7C001C86001D03001E03801E03801C03801C03801C03801C03801C
+03801C03801C03801C03801C03801C03801C03801C03801C03801C0380FF8FF014207E9F19>I<
+38007C007C007C0038000000000000000000000000001C00FC001C001C001C001C001C001C001C
+001C001C001C001C001C001C001C001C001C001C00FF80091F7F9E0C>I<00E001F001F001F000
+E0000000000000000000000000007007F000F00070007000700070007000700070007000700070
+007000700070007000700070007000700070007000706070F060F0C061803F000C28829E0E>I<
+1C0000FC00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C1FE0
+1C07801C06001C04001C08001C10001C20001C60001CE0001DF0001E70001C38001C3C001C1C00
+1C0E001C0F001C07001C07801C07C0FF9FF014207E9F18>I<1C00FC001C001C001C001C001C00
+1C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C
+001C001C001C001C00FF8009207F9F0C>I<1C3E03E000FCC30C30001D039038001E01E01C001E
+01E01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C00
+1C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C00FF8FF8FF
+8021147E9326>I<1C7C00FC86001D03001E03801E03801C03801C03801C03801C03801C03801C
+03801C03801C03801C03801C03801C03801C03801C03801C0380FF8FF014147E9319>I<01F800
+070E001C03803801C03801C07000E07000E0F000F0F000F0F000F0F000F0F000F0F000F07000E0
+7000E03801C03801C01C0380070E0001F80014147F9317>I<1C7C00FD87001E01801E01C01C00
+E01C00F01C00701C00781C00781C00781C00781C00781C00781C00701C00F01C00E01E01C01E03
+801D87001C7C001C00001C00001C00001C00001C00001C00001C00001C0000FF8000151D7E9319
+>I<01F040070CC00E02C01C03C03801C07801C07001C0F001C0F001C0F001C0F001C0F001C0F0
+01C07001C07801C03801C01C03C00C05C00709C001F1C00001C00001C00001C00001C00001C000
+01C00001C00001C0000FF8151D7F9318>I<1CF0FD181E3C1E3C1E181C001C001C001C001C001C
+001C001C001C001C001C001C001C001C00FFC00E147E9312>I<0FC830386018C008C008C008E0
+007C003FE01FF007F8003C800E8006C006C006C004E00CD81887E00F147F9312>I<0200020002
+00060006000E000E003E00FFF80E000E000E000E000E000E000E000E000E000E000E000E040E04
+0E040E040E040708030801F00E1C7F9B12>I<1C0380FC1F801C03801C03801C03801C03801C03
+801C03801C03801C03801C03801C03801C03801C03801C03801C03801C07800C0780061B8003E3
+F014147E9319>I<FF83F83E00E01C00C00E00800E00800E008007010007010007830003820003
+820001C40001C40001E40000E80000E80000700000700000700000200015147F9318>I<FF9FE1
+FC3C0780701C0300601C0380200E0380400E0380400E03C0400704C0800704E0800704E0800388
+6100038871000388710001D0320001D03A0001D03E0000E01C0000E01C0000601800004008001E
+147F9321>I<FF87F81E03C00E01800E030007020003840001C80001D80000F000007000007800
+00F800009C00010E00020E000607000403800C03C03C03E0FE07FC16147F9318>I<FF83F83E00
+E01C00C00E00800E00800E008007010007010007830003820003820001C40001C40001E40000E8
+0000E800007000007000007000002000002000004000004000004000F08000F08000F100006200
+003C0000151D7F9318>I<7FFF700E600E401C40384078407000E001E001C00380078007010E01
+1E011C0338027006700EFFFE10147F9314>I<FFFFFC1601808C17>I<FFFFFFFFFFF02C01808C2D
+>I E /Fp 41 123 df<0003F07C001E0DC600380F0F00701E0F00E01E0E00E00C0001C01C0001
+C01C0001C01C0001C01C0001C01C00038038007FFFFFC003803800038038000380380003803800
+0700700007007000070070000700700007007000070070000E00E0000E00E0000E00E0000E00E0
+000E00E0000E00E0001C01C0001E01E000FF8FFC0020207E9F1B>11 D<0003E0001C1800381800
+703C00E03C00E03801C00001C00001C00001C00001C0000380007FFFF003807003807003807003
+80700700E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C
+03801E03C0FF0FF016207E9F19>I<0006000C00100030006000C0008001800300030006000E00
+0C000C0018001800380038003000300070007000600060006000E000E000E000E000E000E000E0
+00E00060006000600060006000300030001000180008000C00040002000F2E7AA112>40
+D<008000C00040002000300030001800180018000C000C000C000C000C000C000C000C000C000C
+000C000C000C001C001C001C0018001800380038003000300070006000E000C000C00180010003
+0006000400080018003000400080000E2E80A112>I<FFF0FFF00C027E8A0F>45
+D<3078F8787005057C840D>I<0018003801F80E700070007000700070007000E000E000E000E0
+00E000E001C001C001C001C001C001C003800380038003800380038007000780FFFC0E1E7B9D17
+>49 D<1FFFFFFE3FFFFFFF00000000000000000000000000000000000000000000000000000000
+00000000FFFFFFFC7FFFFFF8200C7D9023>61 D<0000080000000C0000001C0000003C0000003C
+0000007C0000007E0000009E0000009E0000011E0000011E0000021E0000020F0000040F000004
+0F0000080F0000080F0000100F80001007800020078000200780007FFF80004007C0008003C000
+8003C0010003C0010003C0020003C0020001E0060001E01F0003E0FF801FFE1F207F9F22>65
+D<07FFFFF800F80078007800380078001800F0001800F0000800F0000800F0000800F0000800F0
+000801E0080001E0080001E0080001E0180001E0380001FFF80003C0300003C0100003C0100003
+C0100003C0100003C000000780000007800000078000000780000007800000078000000F000000
+0F800000FFFC00001D1F7E9E1E>70 D<07FF83FFC000F8007C000078003C000078003C0000F000
+780000F000780000F000780000F000780000F000780000F000780001E000F00001E000F00001E0
+00F00001E000F00001FFFFF00001E000F00003C001E00003C001E00003C001E00003C001E00003
+C001E00003C001E000078003C000078003C000078003C000078003C000078003C000078003C000
+0F000780000F8007C000FFF07FF800221F7E9E22>72 D<07FF8000F80000780000780000F00000
+F00000F00000F00000F00000F00001E00001E00001E00001E00001E00001E00003C00003C00003
+C00003C00003C00003C0000780000780000780000780000780000780000F00000F8000FFF00011
+1F7E9E10>I<07F8007FC0007C001F00007C000C00005E000400009E000800008F000800008F00
+0800008780080000878008000083C008000103C010000101E010000101E010000100F010000100
+F010000100781000020078200002003C200002003C200002001E200002001E200002000F200004
+000F4000040007C000040007C000040003C000040003C000040001C0000C000180001E00008000
+FF80008000221F7E9E22>78 D<001F8200706600C01E01800E03000E07000C0600040E00040E00
+040E00040F00000F00000F800007F00007FF0003FFC001FFE0003FF00003F80000F80000780000
+3C00003C400038400038400038400030600070600060F000C0E80180C6030081FC0017217E9F19
+>83 D<00FF01FE0180018001800180018003000300030003000300030006000600060006000600
+06000C000C000C000C000C000C0018001800180018001800180030003000300030003000300060
+0060006000600060006000FF00FF00102D7EA10D>91 D<00FF01FE00060006000600060006000C
+000C000C000C000C000C0018001800180018001800180030003000300030003000300060006000
+6000600060006000C000C000C000C000C000C0018001800180018001800180FF00FF00102D82A1
+0D>93 D<07F8000C0C001E06001E07001C070000070000070000070000FF0007C7001E07003C0E
+00780E00F00E10F00E10F00E10F01E10F02E20784F401F878014147D9317>97
+D<0700003F00000F00000700000700000E00000E00000E00000E00000E00000E00001C00001C7C
+001D83001E01801C01C01C00E03800E03800F03800F03800F03800F03800F07001E07001E07001
+C07003C0700380700700E80E00CC380083E00014207B9F19>I<00FE000383000E07801C078038
+0700380000780000F00000F00000F00000F00000E00000E00000E00000F00000F0010070020038
+04001C180007E00011147D9314>I<0000380001F8000078000038000038000070000070000070
+0000700000700000700000E000FCE00382E00601E01C01E03C00E03801C07801C0F001C0F001C0
+F001C0F001C0E00380E00380E00380E00380F00380700780380F001C378007C7E015207D9F19>
+I<00F800070E000E07001C0700380380780380700380F00380F00380FFFF80F00000E00000E000
+00E00000E00000F001007002003004001C180007E00011147D9314>I<0007C0001C600030F000
+60F000E0E000C00001C00001C00001C00001C00001C0000380003FFC0003800003800003800003
+80000700000700000700000700000700000700000E00000E00000E00000E00000E00000E00001C
+00001E0000FFC00014207F9F0E>I<00000E003E1100E1A301C1C20381E00780E00701E00F01E0
+0F01E00F01E00703C007038007870004FC000800000800001800001C00000FFF000FFFC00FFFE0
+1800F0300030600030C00030C00030C000306000603000C01C070007FC00181F809417>I<00E0
+0007E00001E00000E00000E00001C00001C00001C00001C00001C00001C000038000038F800390
+E003A0E003C0600380600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01
+C00E01C00E01C01C03801E03C0FF8FF014207E9F19>I<01C003E003E003C00180000000000000
+00000000000003801F800780038003800700070007000700070007000E000E000E000E000E000E
+001C001E00FF800B1F7F9E0C>I<00E00007E00001E00000E00000E00001C00001C00001C00001
+C00001C00001C0000380000381FC0380F00380C003818003810007040007080007180007380007
+7C00071C000E1C000E0E000E0E000E0F000E07000E07801C03801E07C0FF8FF016207E9F18>
+107 D<00E007E001E000E000E001C001C001C001C001C001C00380038003800380038003800700
+070007000700070007000E000E000E000E000E000E001C001E00FF800B207F9F0C>I<0387C07C
+001F9861860007A072070003C03403000380380300078078070007007007000700700700070070
+0700070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00
+E00E001C01C01C001E01E01E00FFCFFCFFC022147E9326>I<038F801F90E007A0E003C0600380
+600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C03
+801E03C0FF8FF014147E9319>I<00FC000387000E01801C00C03800E03800E07000F0F000F0F0
+00F0F000F0F000F0E001E0E001E0E001C0E003C0F00380700700380E001C1C0007E00014147D93
+17>I<00E3E00007EC380000F01C0000E00E0000E00F0001C0070001C0078001C0078001C00780
+01C0078001C0078003800F0003800F0003800E0003801E0003801C0003803800074070000761C0
+00071F00000700000007000000070000000E0000000E0000000E0000000E0000001E000000FFC0
+0000191D809319>I<00FC200382600702601E01E03C01E03801C07801C0F001C0F001C0F001C0
+F001C0E00380E00380F00380F00380F00780700780380F001C370007C700000700000700000700
+000E00000E00000E00000E00001E0000FFC0131D7D9318>I<038E001FB38007C78003C7800383
+000780000700000700000700000700000700000E00000E00000E00000E00000E00000E00001C00
+001E0000FFC00011147E9312>I<01F9060708031803180138023C001F001FF007FC01FE001F40
+074003400360036006F004C81887E010147F9312>I<0080010001000100030007000F001E00FF
+F80E000E000E000E001C001C001C001C001C001C00380038103810381038103820382018400F80
+0D1C7C9B12>I<1C0380FC1F803C07801C03801C03803807003807003807003807003807003807
+00700E00700E00700E00700E00701E00701E00703C00305E001F9F8011147B9319>I<FF83F81E
+00E01C00C01C00801E00800E01000E03000E02000E040007040007080007080007100003900003
+A00003E00003C00003800001800001000015147C9318>I<FF9FE1FC3C0780701C0300601C0380
+601C0380401C0380800E0780800E0D81000E0981000E19C2000E11C2000F21C4000720C4000740
+C8000740E8000780F0000780F0000300E00003006000020040001E147C9321>I<1FF0FF03C078
+01C07001C04000E0C000E180007300007600003C00003C00001C00002E00004E00008700010700
+0203800403800C01C03C03E0FE07FC18147F9318>I<0FF83F8001E00E0001C00C0001C0080001
+E0080000E0100000E0300000E0200000E040000070400000708000007080000071000000390000
+003A0000003E0000003C0000003800000018000000100000001000000020000000200000004000
+0070C00000F0800000F1000000E600000078000000191D809318>I<0FFFE00E01E00C01C00803
+80080700100E00101C0000380000700000700000E00001C0000380800700800E00801C01001C01
+00380300700E00FFFE0013147F9314>I E /Fq 63 122 df<0001FF0000001FFFC000007F81E0
+0000FC01E00001F807F00003F807F00007F007F00007F007F00007F007F00007F007F00007F001
+C00007F000000007F000000007F000000007F03FF800FFFFFFF800FFFFFFF800FFFFFFF80007F0
+03F80007F003F80007F003F80007F003F80007F003F80007F003F80007F003F80007F003F80007
+F003F80007F003F80007F003F80007F003F80007F003F80007F003F80007F003F80007F003F800
+07F003F80007F003F80007F003F80007F003F80007F003F8007FFF3FFF807FFF3FFF807FFF3FFF
+80212A7FA925>12 D<0003F0000000000FF8000000001F1C000000003C0E000000007C06000000
+00FC0700000000F80700000001F80700000001F80700000001F80600000001F80E00000001FC0C
+00000001FC1800000001FC3800000001FC3000000000FE6000FFF800FEC000FFF800FF8000FFF8
+00FF00000E00007F00000E00007F00001C00007F80003800007FC000380000FFC0007000019FE0
+00E000038FE000E000070FF001C0000F07F80380001E07FC0380003E03FE0700007E01FE0E0000
+FE00FF1C0000FE007FB80000FE003FF00000FE001FE00000FF000FF000707F0007F800707F801F
+FE00E03FC0FEFF83E01FFFF87FFFC007FFE00FFF8000FF0001FE002D2A7DA934>38
+D<3C007F00FF80FF80FFC0FFC0FFC07FC03EC000C000C00180018001800300030006000E001C00
+380010000A157BA913>I<0006000C00180038007000E001E003C003C0078007800F800F001F00
+1F003E003E003E007E007E007E007C007C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC
+00FC00FC00FC007C007C007E007E007E003E003E003E001F001F000F000F800780078003C003C0
+01E000E0007000380018000C00060F3C7AAC1A>I<C0006000300038001C000E000F0007800780
+03C003C003E001E001F001F000F800F800F800FC00FC00FC007C007C007E007E007E007E007E00
+7E007E007E007E007E007E007E007E007E007C007C00FC00FC00FC00F800F800F801F001F001E0
+03E003C003C0078007800F000E001C00380030006000C0000F3C7CAC1A>I<FFFF80FFFF80FFFF
+80FFFF80FFFF80FFFF8011067F9016>45 D<1C007F007F00FF80FF80FF807F007F001C0009097B
+8813>I<003F800001FFF00007E0FC000FC07E001F803F001F001F003F001F803E000F807E000F
+C07E000FC07E000FC07E000FC0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE00
+0FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE07E000FC07E
+000FC07E000FC07E000FC03F001F803F001F801F001F001F803F000FC07E0007E0FC0001FFF000
+003F80001B277DA622>48 D<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000FE0000FE00
+00FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE00
+00FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE00
+00FE00FFFFFEFFFFFEFFFFFE17277BA622>I<00FF800007FFF0000FFFFC001E03FE003800FF80
+7C003F80FE003FC0FF001FC0FF001FE0FF000FE0FF000FE07E000FE03C001FE000001FE000001F
+C000001FC000003F8000003F0000007E000000FC000000F8000001F0000003E00000078000000F
+0000001E0000003C00E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFFC03F
+FFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF00007FFFC000F
+81FE001F007F003F807F003F803F803F803F803F803F801F803F801F003F8000007F0000007F00
+00007E000000FC000001F8000007F00000FFC00000FFC0000001F80000007E0000003F0000003F
+8000001FC000001FC000001FE000001FE03C001FE07E001FE0FF001FE0FF001FE0FF001FC0FF00
+3FC0FE003F807C007F003F01FE001FFFFC0007FFF00000FF80001B277DA622>I<00000F000000
+0F0000001F0000003F0000007F000000FF000001FF000001FF000003BF0000073F00000E3F0000
+1C3F00003C3F0000383F0000703F0000E03F0001C03F0003803F0007803F0007003F000E003F00
+1C003F0038003F0070003F00F0003F00FFFFFFF8FFFFFFF8FFFFFFF800007F0000007F0000007F
+0000007F0000007F0000007F0000007F0000007F00001FFFF8001FFFF8001FFFF81D277EA622>
+I<180003001F801F001FFFFE001FFFFC001FFFF8001FFFF0001FFFC0001FFF00001C0000001C00
+00001C0000001C0000001C0000001C0000001C0000001C7FC0001DFFF8001F80FC001E003F0008
+003F0000001F8000001FC000001FC000001FE000001FE018001FE07C001FE0FE001FE0FE001FE0
+FE001FE0FE001FC0FC001FC078003F8078003F803C007F001F01FE000FFFFC0003FFF00000FF80
+001B277DA622>I<0007F800003FFE0000FFFF0001FC078003F00FC007C01FC00F801FC01F801F
+C01F001FC03F000F803F0000007E0000007E0000007E000000FE020000FE1FF000FE3FFC00FE60
+3E00FE801F00FF801F80FF000FC0FF000FC0FE000FE0FE000FE0FE000FE0FE000FE07E000FE07E
+000FE07E000FE07E000FE03E000FE03F000FC01F000FC01F001F800F801F0007E07E0003FFFC00
+01FFF800003FC0001B277DA622>I<380000003E0000003FFFFFF03FFFFFF03FFFFFF07FFFFFE0
+7FFFFFC07FFFFF807FFFFF0070000E0070000E0070001C00E0003800E0007000E000E0000001C0
+000001C000000380000007800000070000000F0000001F0000001E0000003E0000003E0000007E
+0000007C0000007C000000FC000000FC000000FC000000FC000001FC000001FC000001FC000001
+FC000001FC000001FC000001FC000000F80000007000001C297CA822>I<003FC00001FFF00003
+FFFC0007C07E000F003F001E001F001E000F803E000F803E000F803F000F803F800F803FC00F00
+3FF01F001FFC1E001FFE3C000FFFF80007FFE00003FFF00001FFFC0001FFFE0007FFFF000F0FFF
+801E07FFC03E01FFC07C007FE07C001FE0F8000FE0F80007E0F80003E0F80003E0F80003E0F800
+03C07C0003C07E0007803F000F001FC03F000FFFFC0003FFF800007FC0001B277DA622>I<007F
+800001FFF00007FFF8000FC0FC001F803E003F001F007E001F807E001F807E000F80FE000FC0FE
+000FC0FE000FC0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE07E001FE07E001FE03F003FE0
+1F002FE00F80CFE007FF8FE001FF0FE000080FE000000FC000000FC000000FC000001F803E001F
+807F001F807F003F007F003E007F007E007E00FC003E03F8001FFFE0000FFF800001FE00001B27
+7DA622>I<00000780000000000780000000000FC0000000000FC0000000000FC0000000001FE0
+000000001FE0000000003FF0000000003FF0000000003FF00000000077F80000000077F8000000
+00F7FC00000000E3FC00000000E3FC00000001C1FE00000001C1FE00000003C1FF0000000380FF
+0000000380FF00000007007F80000007007F8000000F007FC000000E003FC000000E003FC00000
+1C001FE000001C001FE000003FFFFFF000003FFFFFF000003FFFFFF00000700007F80000700007
+F80000F00007FC0000E00003FC0001E00003FE0001C00001FE0001C00001FE0003C00001FF00FF
+FE003FFFFCFFFE003FFFFCFFFE003FFFFC2E297EA833>65 D<FFFFFFF800FFFFFFFF00FFFFFFFF
+C003F8001FE003F8000FF003F80007F803F80003F803F80003FC03F80003FC03F80001FC03F800
+01FC03F80001FC03F80003FC03F80003F803F80003F803F80007F003F8000FF003F8001FC003F8
+00FF8003FFFFFE0003FFFFFFC003F8000FF003F80003F803F80001FC03F80001FE03F80000FE03
+F80000FE03F80000FF03F80000FF03F80000FF03F80000FF03F80000FF03F80000FF03F80000FE
+03F80001FE03F80003FC03F80007FC03F8001FF8FFFFFFFFE0FFFFFFFFC0FFFFFFFE0028297DA8
+30>I<00007FE0030007FFFC07001FFFFF0F007FF00F9F00FF0001FF01FC0000FF03F800007F07
+F000003F0FE000001F1FC000001F1FC000000F3F8000000F3F800000077F800000077F80000007
+7F00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF000000
+00FF00000000FF000000007F000000007F800000007F800000073F800000073F800000071FC000
+00071FC000000E0FE000000E07F000001C03F800003C01FC00007800FF0001F0007FF007C0001F
+FFFF800007FFFE0000007FF00028297CA831>I<FFFFFFFC0000FFFFFFFF8000FFFFFFFFE00003
+FC001FF80003FC0003FC0003FC0000FE0003FC00007F0003FC00003F8003FC00001FC003FC0000
+1FC003FC00000FE003FC00000FE003FC000007F003FC000007F003FC000007F003FC000007F003
+FC000007F803FC000007F803FC000007F803FC000007F803FC000007F803FC000007F803FC0000
+07F803FC000007F803FC000007F803FC000007F803FC000007F003FC000007F003FC000007F003
+FC00000FE003FC00000FE003FC00000FC003FC00001FC003FC00003F8003FC00007F0003FC0000
+FF0003FC0003FC0003FC001FF800FFFFFFFFF000FFFFFFFF8000FFFFFFFC00002D297EA834>I<
+FFFFFFFFE0FFFFFFFFE0FFFFFFFFE003FC001FE003FC0007F003FC0001F003FC0001F003FC0000
+F003FC00007003FC00007003FC00007003FC01C07803FC01C03803FC01C03803FC01C03803FC03
+C00003FC03C00003FC0FC00003FFFFC00003FFFFC00003FFFFC00003FC0FC00003FC03C00003FC
+03C00003FC01C00E03FC01C00E03FC01C00E03FC01C01C03FC00001C03FC00001C03FC00001C03
+FC00003C03FC00003803FC00007803FC0000F803FC0001F803FC0003F803FC001FF8FFFFFFFFF0
+FFFFFFFFF0FFFFFFFFF027297EA82C>I<FFFFFFFFC0FFFFFFFFC0FFFFFFFFC003FC003FC003FC
+000FE003FC0003E003FC0001E003FC0001E003FC0000E003FC0000E003FC0000E003FC0000F003
+FC01C07003FC01C07003FC01C07003FC01C00003FC03C00003FC03C00003FC0FC00003FFFFC000
+03FFFFC00003FFFFC00003FC0FC00003FC03C00003FC03C00003FC01C00003FC01C00003FC01C0
+0003FC01C00003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00
+000003FC00000003FC000000FFFFFC0000FFFFFC0000FFFFFC000024297EA82A>I<00007FE003
+000007FFFC0700001FFFFF0F00007FF00F9F0000FF0001FF0001FC0000FF0003F800007F0007F0
+00003F000FE000001F001FC000001F001FC000000F003F8000000F003F80000007007F80000007
+007F80000007007F0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00
+00000000FF0000000000FF0000000000FF0000000000FF0000FFFFF87F0000FFFFF87F8000FFFF
+F87F800000FF003F800000FF003F800000FF001FC00000FF001FC00000FF000FE00000FF0007F0
+0000FF0003F80000FF0001FC0000FF0000FF0001FF00007FF007FF00001FFFFF9F000007FFFE0F
+0000007FF003002D297CA835>I<FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF03FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FFFFFFFFC003FFFFFFFFC003FFFFFFFFC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC0FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF30297EA835>I<FFFFF0FFFFF0
+FFFFF003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC00
+03FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC00
+03FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC0003FC00FFFFF0FFFFF0FFFFF0
+14297EA819>I<00FFFFF800FFFFF800FFFFF80000FF000000FF000000FF000000FF000000FF00
+0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF
+000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+FF000000FF000000FF001800FF007E00FF00FF00FF00FF00FF00FF00FF00FF00FE007E01FC007C
+01F8003E07F0000FFFE00003FF00001D297EA823>I<FFFFF000FFFEFFFFF000FFFEFFFFF000FF
+FE03FC00000F0003FC00001E0003FC00003C0003FC0000780003FC0000E00003FC0003C00003FC
+0007800003FC000F000003FC001E000003FC003C000003FC00F0000003FC01E0000003FC03C000
+0003FC07C0000003FC0FC0000003FC1FE0000003FC7FF0000003FCFFF8000003FDE7F8000003FF
+C3FC000003FF83FE000003FE01FF000003FC00FF000003FC007F800003FC007FC00003FC003FE0
+0003FC001FE00003FC000FF00003FC000FF80003FC0007F80003FC0003FC0003FC0001FE0003FC
+0001FF0003FC0000FF0003FC00007F80FFFFF00FFFFEFFFFF00FFFFEFFFFF00FFFFE2F297EA835
+>I<FFFFFC0000FFFFFC0000FFFFFC000003FC00000003FC00000003FC00000003FC00000003FC
+00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003
+FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000
+03FC00000003FC0001C003FC0001C003FC0001C003FC0001C003FC0003C003FC00038003FC0003
+8003FC00078003FC00078003FC000F8003FC000F8003FC001F8003FC007F8003FC01FF00FFFFFF
+FF00FFFFFFFF00FFFFFFFF0022297EA828>I<FFFE0000003FFF80FFFE0000003FFF80FFFF0000
+007FFF8003FF0000007FE00003FF0000007FE00003BF800000EFE00003BF800000EFE000039FC0
+0001CFE000039FC00001CFE000038FE000038FE000038FE000038FE000038FE000038FE0000387
+F000070FE0000387F000070FE0000383F8000E0FE0000383F8000E0FE0000381FC001C0FE00003
+81FC001C0FE0000381FC001C0FE0000380FE00380FE0000380FE00380FE00003807F00700FE000
+03807F00700FE00003803F80E00FE00003803F80E00FE00003803F80E00FE00003801FC1C00FE0
+0003801FC1C00FE00003800FE3800FE00003800FE3800FE000038007F7000FE000038007F7000F
+E000038007F7000FE000038003FE000FE000038003FE000FE000038001FC000FE000038001FC00
+0FE000038000F8000FE000FFFE00F803FFFF80FFFE00F803FFFF80FFFE007003FFFF8039297DA8
+40>I<FFFC00007FFFFFFE00007FFFFFFF00007FFF03FF800001C003FFC00001C003BFE00001C0
+039FE00001C0039FF00001C0038FF80001C00387FC0001C00383FE0001C00381FF0001C00380FF
+8001C003807F8001C003807FC001C003803FE001C003801FF001C003800FF801C0038007FC01C0
+038003FC01C0038003FE01C0038001FF01C0038000FF81C00380007FC1C00380003FE1C0038000
+1FF1C00380000FF1C00380000FF9C003800007FDC003800003FFC003800001FFC003800000FFC0
+038000007FC0038000007FC0038000003FC0038000001FC0038000000FC00380000007C0FFFE00
+0003C0FFFE000001C0FFFE000001C030297EA835>I<0000FFC00000000FFFFC0000003F807F00
+0000FE001FC00001F80007E00003F00003F00007E00001F8000FE00001FC001FC00000FE001FC0
+0000FE003F8000007F003F8000007F007F8000007F807F0000003F807F0000003F807F0000003F
+80FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF00
+00003FC0FF0000003FC0FF0000003FC0FF0000003FC07F0000003F807F8000007F807F8000007F
+803F8000007F003F8000007F001FC00000FE001FC00000FE000FE00001FC0007F00003F80003F8
+0007F00001FC000FE00000FE001FC000003FC0FF0000000FFFFC00000000FFC000002A297CA833
+>I<FFFFFFF800FFFFFFFF00FFFFFFFFC003FC003FE003FC0007F003FC0003F803FC0003FC03FC
+0001FC03FC0001FE03FC0001FE03FC0001FE03FC0001FE03FC0001FE03FC0001FE03FC0001FE03
+FC0001FC03FC0003FC03FC0003F803FC0007F003FC003FE003FFFFFF8003FFFFFE0003FC000000
+03FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0000
+0003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000FFFFF0
+0000FFFFF00000FFFFF0000027297EA82E>I<FFFFFFE00000FFFFFFFE0000FFFFFFFF800003FC
+003FE00003FC000FF00003FC0007F80003FC0003FC0003FC0001FC0003FC0001FE0003FC0001FE
+0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FC0003FC0003F80003FC
+0007F80003FC000FE00003FC003FC00003FFFFFE000003FFFFFE000003FC00FF800003FC003FC0
+0003FC001FE00003FC000FF00003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC
+0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80E03FC0007F8
+0E03FC0003F80E03FC0001FC1CFFFFF000FE1CFFFFF0007FF8FFFFF0000FE02F297EA832>82
+D<00FF806003FFF0E00FFFF8E01F80FDE03F001FE03E0007E07C0003E07C0003E0FC0001E0FC00
+01E0FC0000E0FE0000E0FE0000E0FF000000FFC000007FFC00007FFFE0003FFFF8001FFFFE001F
+FFFF0007FFFF8003FFFFC000FFFFC0000FFFE000007FE000001FF000000FF0000007F0E00003F0
+E00003F0E00003F0E00003F0F00003E0F00003E0F80007E0FC0007C0FF000F80FFE03F80E3FFFE
+00E1FFFC00C01FF0001C297CA825>I<7FFFFFFFFF807FFFFFFFFF807FFFFFFFFF807F807F807F
+807C007F800F8078007F80078078007F80078070007F800380F0007F8003C0F0007F8003C0E000
+7F8001C0E0007F8001C0E0007F8001C0E0007F8001C0E0007F8001C000007F80000000007F8000
+0000007F80000000007F80000000007F80000000007F80000000007F80000000007F8000000000
+7F80000000007F80000000007F80000000007F80000000007F80000000007F80000000007F8000
+0000007F80000000007F80000000007F80000000007F80000000007F80000000007F8000000000
+7F80000000FFFFFFC00000FFFFFFC00000FFFFFFC0002A287EA72F>I<FFFFF000FFFEFFFFF000
+FFFEFFFFF000FFFE03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003
+FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000
+038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003
+FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000
+038003FC0000038003FC0000038003FC0000038001FC0000070001FE0000070000FE00000E0000
+7F00000E00003F00003C00001FC0007800000FF003F0000007FFFFE0000000FFFF800000001FFC
+00002F297EA834>I<FFFFF0007FFFFFFFF0007FFFFFFFF0007FFF03FE000001C001FE00000380
+01FE0000038001FF0000078000FF0000070000FF80000F00007F80000E00007FC0000E00003FC0
+001C00003FC0001C00003FE0003C00001FE0003800001FF0007800000FF0007000000FF8007000
+0007F800E0000007F800E0000003FC01C0000003FC01C0000003FE03C0000001FE0380000001FF
+0780000000FF0700000000FF87000000007F8E000000007F8E000000007FDE000000003FDC0000
+00003FFC000000001FF8000000001FF8000000000FF0000000000FF0000000000FF00000000007
+E00000000007E00000000003C00000000003C0000030297FA833>I<FFFFE07FFFE01FFFC0FFFF
+E07FFFE01FFFC0FFFFE07FFFE01FFFC003FC0003FC0000700003FC0003FC0000700003FE0001FE
+0000700001FE0001FE0000E00001FE0001FE0000E00001FF0001FF0001E00000FF0001FF0001C0
+0000FF0003FF8001C00000FF8003FF8003C000007F8003FF80038000007F8007FFC0038000003F
+C0073FC0070000003FC0073FC0070000003FE00E1FE00F0000001FE00E1FE00E0000001FE00E1F
+F00E0000001FF01C0FF01E0000000FF01C0FF01C0000000FF03C0FF81C00000007F83807F83800
+000007F83807F83800000007F87807FC3800000003FC7003FC7000000003FC7003FC7000000003
+FEE001FEF000000001FEE001FEE000000001FFE001FFE000000001FFC000FFE000000000FFC000
+FFC000000000FFC000FFC0000000007F80007F80000000007F80007F80000000007F80007F8000
+0000003F00003F00000000003F00003F00000000003E00001F00000000001E00001E0000000000
+1E00001E00000042297FA845>I<020007000E001C00180030003000600060006000C000C000DF
+00FF80FFC0FFC0FFC07FC07FC03F800F000A157CA913>96 D<03FF80000FFFF0001F01FC003F80
+FE003F807F003F803F003F803F801F003F8000003F8000003F8000003F8000003F80003FFF8001
+FC3F800FE03F801F803F803F003F807E003F80FC003F80FC003F80FC003F80FC003F80FC005F80
+7E00DF803F839FFC1FFE0FFC03FC03FC1E1B7E9A21>I<FFE00000FFE00000FFE000000FE00000
+0FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000
+000FE000000FE1FE000FEFFF800FFE07E00FF803F00FF001F80FE000FC0FE000FC0FE0007E0FE0
+007E0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007E0F
+E0007E0FE0007E0FE000FC0FE000FC0FF001F80FF803F00F9C0FE00F0FFF800E01FC00202A7EA9
+25>I<003FF00001FFFC0003F03E000FC07F001F807F003F007F003F007F007F003E007E000000
+7E000000FE000000FE000000FE000000FE000000FE000000FE000000FE0000007E0000007E0000
+007F0000003F0003803F8003801F8007000FE00E0003F83C0001FFF800003FC000191B7E9A1E>
+I<00007FF000007FF000007FF0000007F0000007F0000007F0000007F0000007F0000007F00000
+07F0000007F0000007F0000007F0000007F0000007F0003F87F001FFF7F007F03FF00FC00FF01F
+8007F03F0007F03F0007F07E0007F07E0007F07E0007F0FE0007F0FE0007F0FE0007F0FE0007F0
+FE0007F0FE0007F0FE0007F0FE0007F07E0007F07E0007F03F0007F03F0007F01F800FF00FC01F
+F007E07FFF01FFE7FF007F87FF202A7EA925>I<003FC00001FFF00003E07C000F803E001F801F
+001F001F003F000F807E000F807E000FC07E000FC0FE0007C0FE0007C0FFFFFFC0FFFFFFC0FE00
+0000FE000000FE0000007E0000007E0000007F0000003F0001C01F0001C00F80038007C0070003
+F01E0000FFFC00003FE0001A1B7E9A1F>I<0007F8003FFC007E3E01FC7F03F87F03F07F07F07F
+07F03E07F00007F00007F00007F00007F00007F00007F000FFFFC0FFFFC0FFFFC007F00007F000
+07F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F000
+07F00007F00007F00007F00007F00007F0007FFF807FFF807FFF80182A7EA915>I<00FF80F003
+FFE3F80FC1FE1C1F007C7C3F007E7C3E003E107E003F007E003F007E003F007E003F007E003F00
+7E003F003E003E003F007E001F007C000FC1F8000BFFE00018FF80001800000038000000380000
+003C0000003FFFF8003FFFFF001FFFFFC00FFFFFE007FFFFF01FFFFFF03C0007F07C0001F8F800
+00F8F80000F8F80000F8F80000F87C0001F07C0001F03F0007E00FC01F8007FFFF00007FF0001E
+287E9A22>I<FFE00000FFE00000FFE000000FE000000FE000000FE000000FE000000FE000000F
+E000000FE000000FE000000FE000000FE000000FE000000FE000000FE07E000FE1FF800FE30FC0
+0FE40FE00FE807E00FF807F00FF007F00FF007F00FE007F00FE007F00FE007F00FE007F00FE007
+F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE0
+07F00FE007F0FFFE3FFFFFFE3FFFFFFE3FFF202A7DA925>I<07000F801FC03FE03FE03FE01FC0
+0F8007000000000000000000000000000000FFE0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00F
+E00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2B7EAA12>
+I<FFE00000FFE00000FFE000000FE000000FE000000FE000000FE000000FE000000FE000000FE0
+00000FE000000FE000000FE000000FE000000FE000000FE01FFC0FE01FFC0FE01FFC0FE007800F
+E00F000FE01E000FE03C000FE078000FE0E0000FE3C0000FE7C0000FEFE0000FFFF0000FFFF800
+0FF3F8000FE1FC000FC0FE000FC07F000FC07F000FC03F800FC01FC00FC00FE00FC00FE00FC007
+F0FFFC1FFFFFFC1FFFFFFC1FFF202A7FA923>107 D<FFE0FFE0FFE00FE00FE00FE00FE00FE00F
+E00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0
+0FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2A7EA912>I<FFC07F00
+1FC000FFC1FFC07FF000FFC307E0C1F8000FC407F101FC000FC803F200FC000FD803FE00FE000F
+D003FC00FE000FD003FC00FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800
+FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE0
+03F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE
+000FE003F800FE00FFFE3FFF8FFFE0FFFE3FFF8FFFE0FFFE3FFF8FFFE0331B7D9A38>I<FFC07E
+00FFC1FF80FFC30FC00FC40FE00FC807E00FD807F00FD007F00FD007F00FE007F00FE007F00FE0
+07F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00F
+E007F00FE007F00FE007F00FE007F0FFFE3FFFFFFE3FFFFFFE3FFF201B7D9A25>I<003FE00001
+FFFC0003F07E000FC01F801F800FC03F0007E03F0007E07E0003F07E0003F07E0003F0FE0003F8
+FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F87E0003F07E0003F03F0007
+E03F0007E01F800FC00FC01F8007F07F0001FFFC00003FE0001D1B7E9A22>I<FFE1FE00FFEFFF
+80FFFE0FE00FF803F00FF001F80FE001FC0FE000FC0FE000FE0FE000FE0FE0007F0FE0007F0FE0
+007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007E0FE000FE0FE000FE0FE000FC0F
+E001FC0FF001F80FF807F00FFC0FE00FEFFF800FE1FC000FE000000FE000000FE000000FE00000
+0FE000000FE000000FE000000FE000000FE00000FFFE0000FFFE0000FFFE000020277E9A25>I<
+FFC1F0FFC7FCFFC63E0FCC7F0FD87F0FD07F0FD07F0FF03E0FE0000FE0000FE0000FE0000FE000
+0FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE000FFFF00FFFF00
+FFFF00181B7F9A1B>114 D<03FE300FFFF03E03F07800F07000F0F00070F00070F80070FE0000
+FFE0007FFF007FFFC03FFFE01FFFF007FFF800FFF80007FC0000FCE0007CE0003CF0003CF00038
+F80038FC0070FF01E0E7FFC0C1FF00161B7E9A1B>I<00E00000E00000E00000E00001E00001E0
+0001E00003E00003E00007E0000FE0001FFFE0FFFFE0FFFFE00FE0000FE0000FE0000FE0000FE0
+000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0700FE0700FE0700FE0700FE0
+700FE0700FE07007F0E003F0C001FF80007F0014267FA51A>I<FFE07FF0FFE07FF0FFE07FF00F
+E007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F0
+0FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE00FF00FE00F
+F007E017F003F067FF01FFC7FF007F87FF201B7D9A25>I<FFFC03FFFFFC03FFFFFC03FF0FF000
+F007F000E007F800E003F801C003F801C003FC03C001FC038001FE078000FE070000FF0700007F
+0E00007F0E00007F9E00003F9C00003FFC00001FF800001FF800000FF000000FF000000FF00000
+07E0000007E0000003C0000003C000201B7F9A23>I<FFFC7FFC1FFCFFFC7FFC1FFCFFFC7FFC1F
+FC0FE00FE001C007F007E0038007F007E0038007F807F0078003F807F0070003F80FF8070003FC
+0FF80F0001FC0FF80E0001FC1FFC0E0000FE1CFC1C0000FE1CFE1C0000FF387E3C00007F387E38
+00007F787F3800003FF03F7000003FF03FF000003FE01FF000001FE01FE000001FE01FE000000F
+C00FC000000FC00FC000000F8007C0000007800780000007800780002E1B7F9A31>I<FFFC1FFE
+FFFC1FFEFFFC1FFE07F0038003F8078003FC0F0001FE1E0000FE3C00007F3800007FF800003FF0
+00001FE000000FE000000FF0000007F800000FF800001FFC00003CFE000038FF0000787F0000F0
+3F8001E01FC003C01FE003800FE0FFF03FFFFFF03FFFFFF03FFF201B7F9A23>I<FFFC03FFFFFC
+03FFFFFC03FF0FF000F007F000E007F800E003F801C003F801C003FC03C001FC038001FE078000
+FE070000FF0700007F0E00007F0E00007F9E00003F9C00003FFC00001FF800001FF800000FF000
+000FF000000FF0000007E0000007E0000003C0000003C000000380000003800000078000380700
+007C0F0000FE0E0000FE1E0000FE1C0000FE38000074F000003FE000000F80000020277F9A23>
+I E /Fr 22 118 df<0F003FC07FE07FE0FFF0FFF0FFF0FFF07FE07FE03FC00F000C0C798B1B>
+46 D<0000000F80000000000F80000000001F80000000003F80000000007F8000000000FF8000
+000000FF8000000001FF8000000003FF8000000007FF8000000007FF800000000FFF800000001E
+FF800000003EFF800000007CFF8000000078FF80000000F0FF80000001E0FF80000003E0FF8000
+0003C0FF8000000780FF8000000F00FF8000001F00FF8000003E00FF8000003C00FF8000007800
+FF800000F000FF800001F000FF800001E000FF800003C000FF8000078000FF80000F8000FF8000
+1F0000FF80001E0000FF80003C0000FF8000780000FF8000F80000FF8000FFFFFFFFFF80FFFFFF
+FFFF80FFFFFFFFFF80FFFFFFFFFF80000001FF8000000001FF8000000001FF8000000001FF8000
+000001FF8000000001FF8000000001FF8000000001FF8000000001FF8000000001FF80000003FF
+FFFF800003FFFFFF800003FFFFFF800003FFFFFF8029377DB630>52 D<00000001E00000000000
+000003F00000000000000003F00000000000000007F80000000000000007F80000000000000007
+F8000000000000000FFC000000000000000FFC000000000000001FFE000000000000001FFE0000
+00000000001FFE000000000000003FFF000000000000003FFF000000000000007FFF8000000000
+00007BFF800000000000007BFF80000000000000F3FFC0000000000000F1FFC0000000000001F1
+FFE0000000000001E0FFE0000000000003E0FFF0000000000003C0FFF0000000000003C07FF000
+0000000007C07FF8000000000007803FF800000000000F803FFC00000000000F001FFC00000000
+000F001FFC00000000001F001FFE00000000001E000FFE00000000003E000FFF00000000003C00
+07FF00000000003C0007FF0000000000780007FF8000000000780003FF8000000000F80003FFC0
+00000000F00001FFC000000000F00001FFC000000001FFFFFFFFE000000001FFFFFFFFE0000000
+03FFFFFFFFF000000003FFFFFFFFF000000007C000007FF8000000078000007FF8000000078000
+003FF80000000F8000003FFC0000000F0000001FFC0000001F0000001FFE0000001E0000000FFE
+0000001E0000000FFE0000003E0000000FFF0000003C00000007FF0000007C00000007FF800000
+7800000003FF800000FC00000003FF8000FFFFF00003FFFFFFC0FFFFF00003FFFFFFC0FFFFF000
+03FFFFFFC0FFFFF00003FFFFFFC0423B7DBA49>65 D<FFFFFFFFFF800000FFFFFFFFFFF80000FF
+FFFFFFFFFF0000FFFFFFFFFFFF8000007FE00003FFE000007FE00000FFF000007FE000003FF800
+007FE000001FFC00007FE000001FFC00007FE000000FFE00007FE000000FFE00007FE000000FFF
+00007FE0000007FF00007FE0000007FF00007FE0000007FF00007FE0000007FF00007FE0000007
+FF00007FE0000007FF00007FE000000FFE00007FE000000FFE00007FE000000FFE00007FE00000
+1FFC00007FE000003FF800007FE000003FF000007FE00000FFE000007FE00001FFC000007FE000
+0FFF0000007FFFFFFFFC0000007FFFFFFFFC0000007FFFFFFFFF8000007FE00000FFE000007FE0
+00003FF800007FE000000FFC00007FE000000FFE00007FE0000007FF00007FE0000003FF80007F
+E0000003FF80007FE0000001FFC0007FE0000001FFC0007FE0000001FFE0007FE0000001FFE000
+7FE0000001FFE0007FE0000001FFE0007FE0000001FFE0007FE0000001FFE0007FE0000001FFE0
+007FE0000001FFE0007FE0000001FFC0007FE0000003FFC0007FE0000003FF80007FE0000007FF
+80007FE000000FFF00007FE000001FFE00007FE000003FFC00007FE00001FFF800FFFFFFFFFFFF
+F000FFFFFFFFFFFFC000FFFFFFFFFFFF0000FFFFFFFFFFF000003B3B7CBA45>I<FFFFFFFFFF80
+0000FFFFFFFFFFF80000FFFFFFFFFFFF0000FFFFFFFFFFFFC000007FF00007FFE000007FF00000
+7FF800007FF000001FFC00007FF000000FFE00007FF0000003FF00007FF0000001FF80007FF000
+0000FFC0007FF00000007FE0007FF00000007FE0007FF00000003FF0007FF00000003FF8007FF0
+0000001FF8007FF00000001FF8007FF00000001FFC007FF00000001FFC007FF00000000FFE007F
+F00000000FFE007FF00000000FFE007FF00000000FFE007FF00000000FFE007FF00000000FFF00
+7FF00000000FFF007FF00000000FFF007FF00000000FFF007FF00000000FFF007FF00000000FFF
+007FF00000000FFF007FF00000000FFF007FF00000000FFF007FF00000000FFF007FF00000000F
+FF007FF00000000FFF007FF00000000FFE007FF00000000FFE007FF00000000FFE007FF0000000
+0FFE007FF00000000FFC007FF00000001FFC007FF00000001FFC007FF00000001FF8007FF00000
+003FF8007FF00000003FF0007FF00000007FF0007FF00000007FE0007FF0000000FFC0007FF000
+0001FFC0007FF0000003FF80007FF0000007FF00007FF000001FFE00007FF000007FF800007FF0
+0007FFF000FFFFFFFFFFFFC000FFFFFFFFFFFF0000FFFFFFFFFFF80000FFFFFFFFFF800000403B
+7CBA4A>68 D<FFFFF00000000003FFFFE0FFFFF80000000007FFFFE0FFFFF80000000007FFFFE0
+FFFFFC000000000FFFFFE0007FFC000000000FFFC000007FFC000000000FFFC000007BFE000000
+001EFFC000007BFE000000001EFFC0000079FF000000003CFFC0000079FF000000003CFFC00000
+78FF8000000078FFC0000078FF8000000078FFC0000078FF8000000078FFC00000787FC0000000
+F0FFC00000787FC0000000F0FFC00000783FE0000001E0FFC00000783FE0000001E0FFC0000078
+1FF0000003C0FFC00000781FF0000003C0FFC00000781FF0000003C0FFC00000780FF800000780
+FFC00000780FF800000780FFC000007807FC00000F00FFC000007807FC00000F00FFC000007803
+FE00001E00FFC000007803FE00001E00FFC000007803FE00001E00FFC000007801FF00003C00FF
+C000007801FF00003C00FFC000007800FF80007800FFC000007800FF80007800FFC0000078007F
+C000F000FFC0000078007FC000F000FFC0000078007FC000F000FFC0000078003FE001E000FFC0
+000078003FE001E000FFC0000078001FF003C000FFC0000078001FF003C000FFC0000078000FF8
+078000FFC0000078000FF8078000FFC00000780007FC0F0000FFC00000780007FC0F0000FFC000
+00780007FC0F0000FFC00000780003FE1E0000FFC00000780003FE1E0000FFC00000780001FF3C
+0000FFC00000780001FF3C0000FFC00000780000FFF80000FFC00000780000FFF80000FFC00000
+780000FFF80000FFC000007800007FF00000FFC000007800007FF00000FFC000007800003FE000
+00FFC000007800003FE00000FFC00000FC00001FC00000FFC000FFFFFC001FC001FFFFFFE0FFFF
+FC001FC001FFFFFFE0FFFFFC000F8001FFFFFFE0FFFFFC00070001FFFFFFE0533B7CBA5C>77
+D<FFFFFFFFF800000000FFFFFFFFFFC0000000FFFFFFFFFFF8000000FFFFFFFFFFFE000000007F
+F0001FFF000000007FF00003FFC00000007FF00000FFE00000007FF000007FF00000007FF00000
+3FF80000007FF000003FF80000007FF000003FFC0000007FF000001FFC0000007FF000001FFC00
+00007FF000001FFE0000007FF000001FFE0000007FF000001FFE0000007FF000001FFE0000007F
+F000001FFE0000007FF000001FFE0000007FF000001FFC0000007FF000001FFC0000007FF00000
+3FFC0000007FF000003FF80000007FF000007FF00000007FF000007FE00000007FF00001FFC000
+00007FF00003FF800000007FF0001FFE000000007FFFFFFFF8000000007FFFFFFFC0000000007F
+FFFFFFC0000000007FF0007FF0000000007FF0001FF8000000007FF0000FFC000000007FF00007
+FE000000007FF00003FF000000007FF00003FF800000007FF00001FF800000007FF00001FF8000
+00007FF00001FFC00000007FF00001FFC00000007FF00001FFC00000007FF00001FFC00000007F
+F00001FFC00000007FF00001FFE00000007FF00001FFE00000007FF00001FFE00000007FF00001
+FFE00000007FF00001FFE00000007FF00001FFE001E0007FF00001FFE001E0007FF00000FFF001
+E0007FF00000FFF001E0007FF00000FFF003C0007FF000007FF803C0FFFFFFF8003FFC0780FFFF
+FFF8001FFE0F80FFFFFFF80007FFFF00FFFFFFF80001FFFC000000000000001FF000433C7CBA48
+>82 D<0003FF000300001FFFE0070000FFFFFC0F0001FFFFFE1F0003FE00FF3F0007F0001FFF00
+0FE00007FF001FC00001FF003F800000FF003F800000FF007F0000007F007F0000003F007F0000
+003F00FF0000001F00FF0000001F00FF0000001F00FF8000000F00FF8000000F00FFC000000F00
+FFC000000F00FFF0000000007FFC000000007FFF800000003FFFF80000003FFFFFC000001FFFFF
+FC00001FFFFFFF00000FFFFFFFC00007FFFFFFF00003FFFFFFF80000FFFFFFFC00007FFFFFFE00
+001FFFFFFE000003FFFFFF0000001FFFFF80000001FFFF800000000FFFC000000003FFC0000000
+00FFC0000000007FE0000000007FE0700000003FE0F00000003FE0F00000001FE0F00000001FE0
+F00000001FE0F80000001FE0F80000001FC0F80000001FC0FC0000001FC0FC0000003F80FE0000
+003F80FF0000003F00FFC000007F00FFE00000FE00FFFC0001FC00FDFFC00FF800F87FFFFFF000
+F01FFFFFC000E003FFFF0000C0003FF800002B3D7BBB36>I<3FFFFFFFFFFFFFC03FFFFFFFFFFF
+FFC03FFFFFFFFFFFFFC03FFFFFFFFFFFFFC03FF8007FF001FFC07FC0007FF0003FE07F80007FF0
+001FE07F00007FF0000FE07E00007FF00007E07C00007FF00003E07C00007FF00003E07C00007F
+F00003E07800007FF00001E07800007FF00001E07800007FF00001E07800007FF00001E0F00000
+7FF00000F0F000007FF00000F0F000007FF00000F0F000007FF00000F0F000007FF00000F00000
+007FF00000000000007FF00000000000007FF00000000000007FF00000000000007FF000000000
+00007FF00000000000007FF00000000000007FF00000000000007FF00000000000007FF0000000
+0000007FF00000000000007FF00000000000007FF00000000000007FF00000000000007FF00000
+000000007FF00000000000007FF00000000000007FF00000000000007FF00000000000007FF000
+00000000007FF00000000000007FF00000000000007FF00000000000007FF00000000000007FF0
+0000000000007FF00000000000007FF00000000000007FF00000000000007FF00000000000007F
+F00000000000007FF00000000000007FF00000000000007FF0000000000FFFFFFFFF8000000FFF
+FFFFFF8000000FFFFFFFFF8000000FFFFFFFFF80003C3A7DB943>I<003FFE00000001FFFFE000
+0007FFFFF800000FE007FC00000FF001FE00001FF800FF00001FF8007F80001FF8007FC0001FF8
+003FC0000FF0003FE00007E0003FE00003C0003FE0000000003FE0000000003FE0000000003FE0
+000000003FE0000000FFFFE000001FFFFFE000007FF83FE00003FF803FE00007FC003FE0000FF0
+003FE0001FE0003FE0003FE0003FE0007FC0003FE0007FC0003FE000FF80003FE000FF80003FE0
+00FF80003FE000FF80003FE000FF80007FE0007FC0007FE0007FC000DFE0003FE0039FF0001FF8
+0F0FFFE007FFFE0FFFE001FFFC07FFE0003FE000FFE02B267DA52F>97 D<0001FFF000000FFFFE
+00003FFFFF8000FF801FC001FE003FC003FC007FE007F8007FE00FF0007FE01FF0007FE03FE000
+3FC03FE0001F807FE0000F007FC00000007FC0000000FFC0000000FFC0000000FFC0000000FFC0
+000000FFC0000000FFC0000000FFC0000000FFC0000000FFC0000000FFC00000007FC00000007F
+E00000007FE00000003FE00000003FF00000F01FF00000F00FF80001E007F80001E003FC0003C0
+01FF000F8000FFC03F00003FFFFE00000FFFF8000001FFC00024267DA52B>99
+D<000000003F800000003FFF800000003FFF800000003FFF800000003FFF8000000001FF800000
+0000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF
+8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF800000
+0000FF8000000000FF8000000000FF800000FF80FF80000FFFF0FF80003FFFFCFF8000FFC03FFF
+8001FE000FFF8003FC0003FF8007F80001FF800FF00000FF801FF00000FF803FE00000FF803FE0
+0000FF807FE00000FF807FC00000FF807FC00000FF807FC00000FF80FFC00000FF80FFC00000FF
+80FFC00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FFC0
+0000FF807FC00000FF807FC00000FF807FC00000FF803FE00000FF803FE00000FF801FE00000FF
+800FF00001FF8007F80003FF8003F80007FF8001FE001FFFC000FF807EFFFE007FFFF8FFFE000F
+FFE0FFFE0001FF00FFFE2F3C7DBB36>I<0001FF8000000FFFF000007FFFFC0000FF81FE0003FE
+007F8007F8003F800FF0001FC00FF0000FE01FE0000FE03FE0000FF03FE00007F07FC00007F07F
+C00007F87FC00007F8FFC00007F8FFC00007F8FFFFFFFFF8FFFFFFFFF8FFFFFFFFF8FFC0000000
+FFC0000000FFC0000000FFC00000007FC00000007FC00000007FC00000003FE00000003FE00000
+781FE00000781FF00000780FF00000F007F80001F003FC0003E001FE000FC000FFC07F80003FFF
+FE00000FFFF8000000FFC00025267DA52C>I<00001FF0000000FFFC000003FFFF00000FF83F80
+001FE07F80003FC0FFC0007F80FFC000FF80FFC000FF80FFC001FF007F8001FF003F0001FF001E
+0001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00
+000001FF00000001FF000000FFFFFF8000FFFFFF8000FFFFFF8000FFFFFF800001FF00000001FF
+00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001
+FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF000000
+01FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF00000001FF0000
+0001FF00000001FF00000001FF00000001FF00000001FF0000007FFFFE00007FFFFE00007FFFFE
+00007FFFFE0000223C7DBB1E>I<00FE00000000FFFE00000000FFFE00000000FFFE00000000FF
+FE0000000007FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000
+000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003
+FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE00FF800003FE03FF
+F00003FE0FFFF80003FE1E03FC0003FE3801FE0003FE6001FF0003FEC000FF0003FFC000FF8003
+FF8000FF8003FF0000FF8003FF0000FF8003FF0000FF8003FE0000FF8003FE0000FF8003FE0000
+FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003
+FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000
+FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF80FF
+FFF83FFFFEFFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFE2F3C7CBB36>104
+D<00FE00FFFE00FFFE00FFFE00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE00FFFFF8FFFFF8FFFFF8FFFFF8153C7DBB1A>108
+D<01FC007FC0000FF80000FFFC03FFF8007FFF0000FFFC0FFFFC01FFFF8000FFFC1F03FE03E07F
+C000FFFC3800FF07001FE00007FC7000FF8E001FF00003FCC0007F98000FF00003FDC0007FF800
+0FF80003FD80007FF0000FF80003FF00007FE0000FF80003FF00007FE0000FF80003FF00007FE0
+000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007F
+C0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE0000
+7FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00
+007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE
+00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF80003
+FE00007FC0000FF80003FE00007FC0000FF80003FE00007FC0000FF800FFFFF81FFFFF03FFFFE0
+FFFFF81FFFFF03FFFFE0FFFFF81FFFFF03FFFFE0FFFFF81FFFFF03FFFFE04B267CA552>I<01FC
+00FF8000FFFC03FFF000FFFC0FFFF800FFFC1E03FC00FFFC3801FE0007FC6001FF0003FCC000FF
+0003FDC000FF8003FD8000FF8003FF0000FF8003FF0000FF8003FF0000FF8003FE0000FF8003FE
+0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF
+8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE
+0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF
+8003FE0000FF80FFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFE2F267CA536>I<00
+01FFC00000000FFFF80000007FFFFF000000FF80FF800003FE003FE00007F8000FF0000FF00007
+F8000FF00007F8001FE00003FC003FE00003FE003FE00003FE007FC00001FF007FC00001FF007F
+C00001FF007FC00001FF00FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC00001
+FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF807FC00001FF007FC00001FF007F
+C00001FF003FE00003FE003FE00003FE001FE00003FC001FF00007FC000FF00007F80007F8000F
+F00003FE003FE00000FF80FF8000007FFFFF0000000FFFF800000001FFC0000029267DA530>I<
+01FC03F000FFFC0FFC00FFFC1FFF00FFFC3C3F80FFFC707F8007FCE0FFC003FCC0FFC003FD80FF
+C003FD80FFC003FF807F8003FF003F0003FF001E0003FF00000003FE00000003FE00000003FE00
+000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE
+00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003
+FE00000003FE00000003FE000000FFFFFC0000FFFFFC0000FFFFFC0000FFFFFC000022267DA528
+>114 D<000F0000000F0000000F0000000F0000000F0000001F0000001F0000001F0000001F00
+00003F0000003F0000007F0000007F000000FF000001FF000003FF000007FF00001FFFFFF0FFFF
+FFF0FFFFFFF0FFFFFFF001FF000001FF000001FF000001FF000001FF000001FF000001FF000001
+FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF0000
+01FF000001FF000001FF003C01FF003C01FF003C01FF003C01FF003C01FF003C01FF003C01FF00
+3C00FF007800FF8078007F80F0003FC1E0001FFFC0000FFF800001FE001E377EB626>116
+D<00FE00003F80FFFE003FFF80FFFE003FFF80FFFE003FFF80FFFE003FFF8007FE0001FF8003FE
+0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF
+8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE
+0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF
+8003FE0000FF8003FE0000FF8003FE0001FF8003FE0001FF8003FE0003FF8001FE0003FF8001FE
+0006FF8000FF000CFFC0007F8078FFFE003FFFF0FFFE001FFFE0FFFE0003FF80FFFE2F267CA536
+>I E end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 300dpi
+TeXDict begin
+
+%%EndSetup
+%%Page: 1 1
+1 0 bop 871 1042 a Fr(Amd)399 1229 y(The)33 b(4.4)g(BSD)f(Automoun)m(ter)592
+1415 y(Reference)h(Man)m(ual)702 1602 y Fq(Jan-Simon)24 b(P)n(endry)937
+1727 y Fp(and)767 1851 y Fq(Nic)n(k)f(Williams)719 2163 y Fo(Last)15
+b(up)q(dated)h(Marc)o(h)e(1991)510 2225 y(Do)q(cumen)o(tation)h(for)g(soft)o
+(w)o(are)e(revision)k(5.3)d(Alpha)p eop
+%%Page: 2 2
+2 1 bop 0 295 a Fo(Cop)o(yrigh)o(t)226 294 y(c)214 295 y Fn(\015)15
+b Fo(1989)f(Jan-Simon)j(P)o(endry)0 370 y(Cop)o(yrigh)o(t)226
+369 y(c)214 370 y Fn(\015)e Fo(1989)f(Imp)q(erial)j(College)f(of)f(Science,)i
+(T)l(ec)o(hnology)e(&)h(Medicine)0 445 y(Cop)o(yrigh)o(t)226
+444 y(c)214 445 y Fn(\015)f Fo(1989)f(The)i(Regen)o(ts)f(of)g(the)g(Univ)o
+(ersit)o(y)h(of)f(California.)0 582 y(All)h(Righ)o(ts)g(Reserv)o(ed.)0
+738 y(P)o(ermission)k(to)g(cop)o(y)f(this)i(do)q(cumen)o(t,)g(or)e(an)o(y)g
+(p)q(ortion)i(of)e(it,)i(as)e(necessary)h(for)g(use)g(of)f(this)h(soft)o(w)o
+(are)e(is)0 801 y(gran)o(ted)d(pro)o(vided)h(this)f(cop)o(yrigh)o(t)g(notice)
+h(and)f(statemen)o(t)f(of)h(p)q(ermission)i(are)e(included.)p
+eop
+%%Page: 1 3
+1 2 bop 0 -83 a Fo(Source)16 b(Distribution)1357 b(SMM:13-1)0
+158 y Fm(Preface)62 299 y Fo(This)11 b(man)o(ual)g(do)q(cumen)o(ts)g(the)f
+(use)h(of)f(the)h(4.4)f(BSD)g(automoun)o(ter|)p Fp(Amd)p Fo(.)18
+b(This)11 b(is)g(primarily)h(a)e(reference)0 349 y(man)o(ual.)20
+b(Unfortunately)l(,)15 b(no)g(tutorial)h(exists.)62 419 y(This)22
+b(man)o(ual)f(comes)f(in)i(t)o(w)o(o)e(forms:)30 b(the)21 b(published)i(form)
+d(and)h(the)g(Info)g(form.)36 b(The)21 b(Info)g(form)f(is)0
+469 y(for)f(on-line)i(p)q(erusal)f(with)g(the)g(INF)o(O)f(program)g(whic)o(h)
+h(is)g(distributed)h(along)e(with)h(GNU)f(Emacs.)32 b(Both)0
+519 y(forms)16 b(con)o(tain)h(substan)o(tially)h(the)f(same)f(text)h(and)g
+(are)f(generated)h(from)f(a)h(common)f(source)h(\014le,)h(whic)o(h)f(is)0
+569 y(distributed)g(with)e(the)h Fp(Amd)h Fo(source.)0 783
+y Fm(License)62 924 y Fp(Amd)f Fo(is)f(not)e(in)i(the)f(public)i(domain;)e
+(it)g(is)h(cop)o(yrigh)o(ted)f(and)g(there)g(are)f(restrictions)i(on)f(its)g
+(distribution.)62 994 y(Redistribution)k(and)d(use)g(in)h(source)f(and)g
+(binary)h(forms)e(are)g(p)q(ermitted)i(pro)o(vided)g(that:)j(\(1\))14
+b(source)h(dis-)0 1044 y(tributions)f(retain)g(this)g(en)o(tire)h(cop)o
+(yrigh)o(t)e(notice)h(and)g(commen)o(t,)f(and)h(\(2\))f(distributions)i
+(including)i(binaries)0 1094 y(displa)o(y)e(the)e(follo)o(wing)h(ac)o(kno)o
+(wledgemen)o(t:)19 b(\\This)14 b(pro)q(duct)g(includes)h(soft)o(w)o(are)d
+(dev)o(elop)q(ed)j(b)o(y)e(The)h(Univ)o(er-)0 1144 y(sit)o(y)f(of)g
+(California,)h(Berk)o(eley)g(and)f(its)h(Con)o(tributors")e(in)i(the)f(do)q
+(cumen)o(tation)g(or)g(other)g(materials)g(pro)o(vided)0 1193
+y(with)18 b(the)f(distribution)i(and)e(in)h(all)g(adv)o(ertising)g(materials)
+f(men)o(tioning)i(features)d(or)h(use)h(of)e(this)i(soft)o(w)o(are.)0
+1243 y(neither)h(the)e(name)h(of)f(the)g(Univ)o(ersit)o(y)i(nor)e(the)g
+(names)h(of)f(its)h(Con)o(tributors)f(ma)o(y)f(b)q(e)j(used)f(to)f(endorse)g
+(or)0 1293 y(promote)d(pro)q(ducts)i(deriv)o(ed)g(from)f(this)g(soft)o(w)o
+(are)f(without)h(sp)q(eci\014c)i(prior)e(written)g(p)q(ermission.)62
+1364 y(THIS)h(SOFTW)-5 b(ARE)15 b(IS)g(PR)o(O)o(VIDED)g(\\AS)g(IS")g(AND)g
+(WITHOUT)g(ANY)g(EXPRESS)h(OR)g(IMPLIED)0 1413 y(W)-5 b(ARRANTIES,)21
+b(INCLUDING,)e(WITHOUT)h(LIMIT)l(A)l(TION,)i(THE)d(IMPLIED)h(W)-5
+b(ARRANTIES)21 b(OF)0 1463 y(MER)o(CHANT)l(ABILITY)c(AND)e(FITNESS)g(F)o(OR)h
+(A)f(P)l(AR)l(TICULAR)i(PURPOSE.)0 1678 y Fm(Source)e(Distribution)62
+1818 y Fo(If)g(y)o(ou)f(ha)o(v)o(e)h(access)f(to)g(the)h(In)o(ternet,)g(y)o
+(ou)f(can)h(get)f(the)g(latest)h(distribution)h(v)o(ersion)f(of)f
+Fp(Amd)j Fo(from)c(host)0 1868 y(`)p Fl(usc.edu)p Fo(')g(using)i(anon)o
+(ymous)g(FTP)l(.)e(Mo)o(v)o(e)h(to)g(the)h(directory)g(`)p
+Fl(/pub/amd)p Fo(')e(on)h(that)g(host)h(and)g(fetc)o(h)f(the)h(\014le)0
+1918 y(`)p Fl(amd.tar.Z)p Fo('.)62 1988 y(If)23 b(y)o(ou)e(are)h(in)h(the)g
+(UK,)f(y)o(ou)g(can)g(get)g(the)g(latest)g(distribution)i(v)o(ersion)e(of)g
+Fp(Amd)i Fo(from)d(the)h(UKnet)0 2038 y(info-serv)o(er.)e(Start)14
+b(b)o(y)i(sending)g(email)g(to)f(`)p Fl(info-server@doc.ic.ac)o(.uk)p
+Fo('.)62 2109 y(Sites)g(on)f(the)g(UK)g(JANET)g(net)o(w)o(ork)f(can)h(get)g
+(the)g(latest)f(distribution)j(b)o(y)e(using)g(anon)o(ymous)g(NIFTP)g(to)0
+2159 y(fetc)o(h)h(the)g(\014le)i(`)p Fl(<AMD>amd.tar.Z)p Fo(')12
+b(from)j(host)f(`)p Fl(uk.ac.imperial.doc.src)p Fo('.)62 2229
+y(Revision)j(5.2)d(w)o(as)h(part)f(of)h(the)g(4.3)g(BSD)g(Reno)h
+(distribution.)62 2300 y(Revision)c(5.3bsdnet,)f(a)f(late)g(alpha)h(v)o
+(ersion)f(of)g(5.3,)g(w)o(as)g(part)f(of)h(the)g(BSD)h(net)o(w)o(ork)e(v)o
+(ersion)h(2)g(distribution)0 2504 y Fq(Bug)15 b(Rep)r(orts)62
+2595 y Fo(Send)i(all)f(bug)g(rep)q(orts)f(to)f(`)p Fl(jsp@doc.ic.ac.uk)p
+Fo(')f(quoting)j(the)f(details)i(of)e(the)g(release)h(and)g(y)o(our)f
+(con\014g-)0 2645 y(uration.)20 b(These)15 b(can)h(b)q(e)g(obtained)g(b)o(y)f
+(running)h(the)f(command)g(`)p Fl(amd)g(-v)p Fo('.)p eop
+%%Page: 2 4
+2 3 bop 15 -83 a Fo(SMM:13-2)912 b(4.4)15 b(BSD)g(Automoun)o(ter)f(Reference)
+j(Man)o(ual)0 158 y Fq(Mailing)g(List)62 250 y Fo(There)11
+b(is)g(a)f(mailing)i(list)f(for)f(p)q(eople)i(in)o(terested)f(in)h(k)o
+(eeping)f(upto)q(date)g(with)f(dev)o(elopmen)o(ts.)19 b(T)l(o)11
+b(subscrib)q(e,)0 299 y(send)16 b(a)f(note)g(to)f(`)p Fl
+(amd-workers-request@acl.l)o(anl.gov)o Fo('.)0 533 y Fm(In)n(tro)r(duction)62
+674 y Fo(An)e Fp(automoun)o(ter)i Fo(main)o(tains)e(a)f(cac)o(he)h(of)g(moun)
+o(ted)f(\014lesystems.)20 b(Filesystems)12 b(are)f(moun)o(ted)h(on)f(demand)0
+724 y(when)16 b(they)f(are)g(\014rst)g(referenced,)g(and)h(unmoun)o(ted)f
+(after)g(a)g(p)q(erio)q(d)h(of)f(inactivit)o(y)l(.)62 795 y
+Fp(Amd)k Fo(ma)o(y)d(b)q(e)h(used)g(as)g(a)f(replacemen)o(t)h(for)f(Sun's)h
+(automoun)o(ter.)23 b(The)17 b(c)o(hoice)h(of)e(whic)o(h)h(\014lesystem)h(to)
+0 844 y(moun)o(t)10 b(can)h(b)q(e)h(con)o(trolled)f(dynamically)i(with)e
+Fp(selectors)p Fo(.)19 b(Selectors)11 b(allo)o(w)g(decisions)h(of)f(the)g
+(form)f(\\hostname)0 894 y(is)15 b Fp(this)p Fo(,")f(or)f(\\arc)o(hitecture)h
+(is)h(not)e Fp(that)p Fo(.")19 b(Selectors)c(ma)o(y)e(b)q(e)i(com)o(bined)g
+(arbitrarily)l(.)20 b Fp(Amd)c Fo(also)e(supp)q(orts)g(a)0
+944 y(v)m(ariet)o(y)e(of)f(\014lesystem)i(t)o(yp)q(es,)f(including)i(NFS,)e
+(UFS)f(and)h(the)g(no)o(v)o(el)g Fp(program)f Fo(\014lesystem.)19
+b(The)12 b(com)o(bination)0 994 y(of)22 b(selectors)h(and)g(m)o(ultiple)h
+(\014lesystem)f(t)o(yp)q(es)g(allo)o(ws)g(iden)o(tical)h(con\014guration)f
+(\014les)g(to)f(b)q(e)h(used)h(on)e(all)0 1044 y(mac)o(hines)16
+b(so)f(reducing)h(the)g(administrativ)o(e)f(o)o(v)o(erhead.)62
+1114 y Fp(Amd)h Fo(ensures)f(that)f(it)g(will)i(not)e(hang)g(if)g(a)g(remote)
+g(serv)o(er)g(go)q(es)g(do)o(wn.)19 b(Moreo)o(v)o(er,)12 b
+Fp(Amd)17 b Fo(can)d(determine)0 1164 y(when)f(a)f(remote)g(serv)o(er)g(has)g
+(b)q(ecome)h(inaccessible)i(and)d(then)h(moun)o(t)f(replacemen)o(t)h
+(\014lesystems)g(as)f(and)g(when)0 1214 y(they)j(b)q(ecome)h(a)o(v)m
+(ailable.)62 1284 y Fp(Amd)h Fo(con)o(tains)f(no)f(proprietary)g(source)g(co)
+q(de)h(and)f(has)g(b)q(een)i(p)q(orted)e(to)g(n)o(umerous)g(\015a)o(v)o(ours)
+f(of)h(Unix.)0 1516 y Fm(1)41 b(Ov)n(erview)62 1658 y Fp(Amd)20
+b Fo(main)o(tains)e(a)g(cac)o(he)g(of)f(moun)o(ted)h(\014lesystems.)28
+b(Filesystems)18 b(are)f Fp(demand-moun)o(ted)k Fo(when)d(they)0
+1708 y(are)12 b(\014rst)g(referenced,)i(and)e(unmoun)o(ted)h(after)f(a)g(p)q
+(erio)q(d)i(of)e(inactivit)o(y)l(.)20 b Fp(Amd)14 b Fo(ma)o(y)e(b)q(e)h(used)
+g(as)f(a)g(replacemen)o(t)0 1757 y(for)17 b(Sun's)g Fk(automoun)o(t)p
+Fo(\(8\))f(program.)25 b(It)18 b(con)o(tains)f(no)g(proprietary)h(source)f
+(co)q(de)h(and)f(has)h(b)q(een)g(p)q(orted)g(to)0 1807 y(n)o(umerous)d(\015a)
+o(v)o(ours)f(of)h(Unix.)21 b(See)16 b(Section)g(2.1)e([Supp)q(orted)i(Op)q
+(erating)g(Systems],)e(page)30 b(SMM:13-6.)62 1878 y Fp(Amd)25
+b Fo(w)o(as)c(designed)j(as)e(the)h(basis)g(for)f(exp)q(erimen)o(ting)i(with)
+e(\014lesystem)i(la)o(y)o(out)d(and)i(managemen)o(t.)0 1928
+y(Although)15 b Fp(Amd)i Fo(has)e(man)o(y)g(direct)g(applications)i(it)e(is)g
+(loaded)h(with)f(additional)i(features)d(whic)o(h)i(ha)o(v)o(e)f(little)0
+1977 y(practical)h(use.)21 b(A)o(t)15 b(some)g(p)q(oin)o(t)h(the)g(infrequen)
+o(tly)h(used)f(comp)q(onen)o(ts)f(ma)o(y)g(b)q(e)h(remo)o(v)o(ed)f(to)g
+(streamline)h(the)0 2027 y(pro)q(duction)g(system.)0 2234 y
+Fq(1.1)33 b(F)-6 b(undamen)n(tals)62 2325 y Fo(The)15 b(fundamen)o(tal)g
+(concept)f(b)q(ehind)j Fp(Amd)f Fo(is)f(the)f(abilit)o(y)i(to)d(separate)h
+(the)g(name)h(used)g(to)e(refer)h(to)g(a)g(\014le)0 2375 y(from)d(the)g(name)
+g(used)h(to)f(refer)g(to)g(its)g(ph)o(ysical)i(storage)d(lo)q(cation.)19
+b(This)12 b(allo)o(ws)g(the)f(same)g(\014les)i(to)d(b)q(e)i(accessed)0
+2425 y(with)g(the)h(same)f(name)g(regardless)g(of)g(where)g(in)h(the)f(net)o
+(w)o(ork)g(the)g(name)g(is)h(used.)19 b(This)13 b(is)f(v)o(ery)g(di\013eren)o
+(t)h(from)0 2475 y(placing)i(`)p Fl(/n/hostname)p Fo(')10 b(in)k(fron)o(t)f
+(of)f(the)i(pathname)f(since)h(that)f(includes)i(lo)q(cation)f(dep)q(enden)o
+(t)h(information)0 2525 y(whic)o(h)h(ma)o(y)f(c)o(hange)g(if)g(\014les)i(are)
+e(mo)o(v)o(ed)f(to)h(another)g(mac)o(hine.)62 2595 y(By)i(placing)i(the)e
+(required)h(mappings)f(in)h(a)e(cen)o(trally)i(administered)g(database,)f
+(\014lesystems)g(can)g(b)q(e)h(re-)0 2645 y(organised)d(without)h(requiring)g
+(c)o(hanges)f(to)g(con\014guration)g(\014les,)h(shell)h(scripts)e(and)h(so)e
+(on.)p eop
+%%Page: 3 5
+3 4 bop 0 -83 a Fo(Chapter)15 b(1:)k(Ov)o(erview)1328 b(SMM:13-3)0
+158 y Fq(1.2)33 b(Filesystems)15 b(and)h(V)-6 b(olumes)62 250
+y Fp(Amd)19 b Fo(views)e(the)g(w)o(orld)g(as)g(a)f(set)h(of)f(\014leserv)o
+(ers,)i(eac)o(h)f(con)o(taing)g(one)g(or)f(more)g(\014lesystems)i(where)f
+(eac)o(h)0 299 y(\014lesystem)g(con)o(tains)f(one)h(or)f(more)g
+Fp(v)o(olumes)p Fo(.)23 b(Here)17 b(the)f(term)g Fp(v)o(olume)j
+Fo(is)e(used)g(to)f(refer)g(to)g(a)g(coheren)o(t)g(set)0 349
+y(of)f(\014les)h(suc)o(h)f(as)g(a)g(user's)g(home)g(directory)h(or)e(a)h(T)
+899 359 y(E)925 349 y(X)g(distribution.)62 420 y(In)i(order)e(to)h(access)g
+(the)g(con)o(ten)o(ts)f(of)g(a)h(v)o(olume,)g Fp(Amd)i Fo(m)o(ust)d(b)q(e)i
+(told)f(in)g(whic)o(h)h(\014lesystem)g(the)f(v)o(olume)0 470
+y(resides)j(and)g(whic)o(h)g(host)g(o)o(wns)e(the)i(\014lesystem.)30
+b(By)19 b(default)g(the)g(host)f(is)h(assumed)f(to)g(b)q(e)i(lo)q(cal)f(and)g
+(the)0 519 y(v)o(olume)c(is)f(assumed)g(to)g(b)q(e)h(the)f(en)o(tire)h
+(\014lesystem.)20 b(If)14 b(a)g(\014lesystem)h(con)o(tains)f(more)g(than)g
+(one)g(v)o(olume,)h(then)0 569 y(a)e Fp(sublink)18 b Fo(is)13
+b(used)h(to)f(refer)g(to)f(the)h(sub-directory)h(within)h(the)e(\014lesystem)
+h(where)f(the)g(v)o(olume)h(can)f(b)q(e)h(found.)0 722 y Fq(1.3)33
+b(V)-6 b(olume)15 b(Naming)62 814 y Fo(V)l(olume)23 b(names)g(are)f
+(de\014ned)h(to)f(b)q(e)h(unique)g(across)f(the)g(en)o(tire)h(net)o(w)o(ork.)
+40 b(A)22 b(v)o(olume)h(name)f(is)h(the)0 864 y(pathname)17
+b(to)g(the)h(v)o(olume's)f(ro)q(ot)g(as)g(kno)o(wn)g(b)o(y)h(the)g(users)f
+(of)g(that)g(v)o(olume.)27 b(Since)19 b(this)f(name)g(uniquely)0
+913 y(iden)o(ti\014es)g(the)e(v)o(olume)h(con)o(ten)o(ts,)e(all)i(v)o(olumes)
+g(can)f(b)q(e)h(named)f(and)h(accessed)f(from)g(eac)o(h)g(host,)g(sub)s(ject)
+g(to)0 963 y(administrativ)o(e)g(con)o(trols.)62 1034 y(V)l(olumes)k(ma)o(y)e
+(b)q(e)h(replicated)h(or)e(duplicated.)32 b(Replicated)21 b(v)o(olumes)e(con)
+o(tain)g(iden)o(tical)h(copies)g(of)e(the)0 1084 y(same)11
+b(data)g(and)g(reside)i(at)d(t)o(w)o(o)g(or)h(more)g(lo)q(cations)h(in)h(the)
+e(net)o(w)o(ork.)18 b(Eac)o(h)11 b(of)g(the)g(replicated)i(v)o(olumes)f(can)f
+(b)q(e)0 1133 y(used)16 b(in)o(terc)o(hangeably)l(.)22 b(Duplicated)17
+b(v)o(olumes)f(eac)o(h)f(ha)o(v)o(e)g(the)h(same)f(name)g(but)h(con)o(tain)g
+(di\013eren)o(t,)f(though)0 1183 y(functionally)21 b(iden)o(tical,)h(data.)32
+b(F)l(or)19 b(example,)i(`)p Fl(/vol/tex)p Fo(')d(migh)o(t)h(b)q(e)h(the)g
+(name)f(of)g(a)g(T)1638 1193 y(E)1664 1183 y(X)g(distribution)0
+1233 y(whic)o(h)d(v)m(aried)g(for)f(eac)o(h)g(mac)o(hine)h(arc)o(hitecture.)
+62 1304 y Fp(Amd)k Fo(pro)o(vides)e(facilities)h(to)e(tak)o(e)g(adv)m(an)o
+(tage)g(of)g(b)q(oth)g(replicated)i(and)f(duplicated)h(v)o(olumes.)27
+b(Con\014g-)0 1353 y(uration)18 b(options)g(allo)o(w)f(a)h(single)h(set)e(of)
+h(con\014guration)f(data)g(to)h(b)q(e)g(shared)g(across)f(an)g(en)o(tire)h
+(net)o(w)o(ork)f(b)o(y)0 1403 y(taking)e(adv)m(an)o(tage)g(of)g(replicated)h
+(and)g(duplicated)h(v)o(olumes.)62 1474 y Fp(Amd)d Fo(can)f(tak)o(e)e(adv)m
+(an)o(tage)h(of)f(replacemen)o(t)i(v)o(olumes)f(b)o(y)h(moun)o(ting)f(them)g
+(as)f(required)j(should)f(an)f(activ)o(e)0 1524 y(\014leserv)o(er)k(b)q
+(ecome)g(una)o(v)m(ailable.)0 1670 y Fq(1.4)33 b(V)-6 b(olume)15
+b(Binding)62 1761 y Fo(Unix)22 b(implemen)o(ts)h(a)d(namespace)i(of)e
+(hierarc)o(hically)k(moun)o(ted)d(\014lesystems.)38 b(Tw)o(o)20
+b(forms)g(of)h(binding)0 1811 y(b)q(et)o(w)o(een)15 b(names)g(and)g(\014les)g
+(are)g(pro)o(vided.)20 b(A)15 b Fp(hard)g(link)k Fo(completes)c(the)g
+(binding)h(when)g(the)e(name)h(is)g(added)0 1861 y(to)f(the)h(\014lesystem.)
+20 b(A)15 b Fp(soft)f(link)19 b Fo(dela)o(ys)c(the)g(binding)i(un)o(til)f
+(the)f(name)f(is)i(accessed.)k(An)15 b Fp(automoun)o(ter)i
+Fo(adds)0 1911 y(a)e(further)g(form)f(in)i(whic)o(h)g(the)g(binding)h(of)e
+(name)g(to)f(\014lesystem)i(is)g(dela)o(y)o(ed)g(un)o(til)g(the)f(name)h(is)f
+(accessed.)62 1981 y(The)h(target)f(v)o(olume,)g(in)i(its)f(general)g(form,)f
+(is)h(a)f(tuple)i(\(host,)d(\014lesystem,)i(sublink\))i(whic)o(h)e(can)g(b)q
+(e)g(used)0 2031 y(to)f(name)g(the)g(ph)o(ysical)i(lo)q(cation)f(of)e(an)o(y)
+h(v)o(olume)h(in)g(the)f(net)o(w)o(ork.)62 2102 y(When)22 b(a)f(target)f(is)i
+(referenced,)h Fp(Amd)g Fo(ignores)e(the)h(sublink)h(elemen)o(t)f(and)f
+(determines)h(whether)g(the)0 2152 y(required)c(\014lesystem)f(is)g(already)g
+(moun)o(ted.)25 b(This)17 b(is)g(done)g(b)o(y)g(computing)g(the)g(lo)q(cal)g
+(moun)o(t)g(p)q(oin)o(t)g(for)f(the)0 2201 y(\014lesystem)g(and)g(c)o(hec)o
+(king)h(for)e(an)h(existing)h(\014lesystem)f(moun)o(ted)g(at)f(the)h(same)g
+(place.)23 b(If)16 b(suc)o(h)g(a)f(\014lesystem)0 2251 y(already)i(exists)h
+(then)f(it)h(is)f(assumed)h(to)e(b)q(e)i(functionally)h(iden)o(tical)g(to)e
+(the)g(target)f(\014lesystem.)26 b(By)17 b(default)0 2301 y(there)d(is)g(a)f
+(one-to-one)g(mapping)i(b)q(et)o(w)o(een)e(the)h(pair)g(\(host,)f
+(\014lesystem\))g(and)h(the)g(lo)q(cal)g(moun)o(t)f(p)q(oin)o(t)h(so)g(this)0
+2351 y(assumption)h(is)h(v)m(alid.)0 2504 y Fq(1.5)33 b(Op)r(erational)15
+b(Principl)q(es)62 2595 y Fp(Amd)e Fo(op)q(erates)e(b)o(y)f(in)o(tro)q
+(ducing)j(new)e(moun)o(t)f(p)q(oin)o(ts)h(in)o(to)g(the)g(namespace.)19
+b(These)11 b(are)g(called)h Fp(automoun)o(t)0 2645 y Fo(p)q(oin)o(ts.)22
+b(The)16 b(k)o(ernel)h(sees)f(these)g(automoun)o(t)e(p)q(oin)o(ts)j(as)e(NFS)
+h(\014lesystems)g(b)q(eing)h(serv)o(ed)f(b)o(y)g Fp(Amd)p Fo(.)22
+b(Ha)o(ving)p eop
+%%Page: 4 6
+4 5 bop 15 -83 a Fo(SMM:13-4)912 b(4.4)15 b(BSD)g(Automoun)o(ter)f(Reference)
+j(Man)o(ual)0 158 y(attac)o(hed)f(itself)h(to)f(the)h(namespace,)g
+Fp(Amd)h Fo(is)f(no)o(w)f(able)i(to)e(con)o(trol)g(the)g(view)i(the)e(rest)g
+(of)g(the)h(system)f(has)0 208 y(of)f(those)g(moun)o(t)f(p)q(oin)o(ts.)21
+b(RPC)15 b(calls)h(are)f(receiv)o(ed)i(from)d(the)h(k)o(ernel)h(one)g(at)e(a)
+h(time.)62 279 y(When)k(a)e Fp(lo)q(okup)j Fo(call)f(is)g(receiv)o(ed)g
+Fp(Amd)h Fo(c)o(hec)o(ks)e(whether)g(the)g(name)g(is)h(already)f(kno)o(wn.)28
+b(If)18 b(it)g(is)h(not,)0 329 y(the)g(required)h(v)o(olume)f(is)g(moun)o
+(ted.)30 b(A)19 b(sym)o(b)q(olic)h(link)g(p)q(oin)o(ting)g(to)e(the)h(v)o
+(olume)g(ro)q(ot)f(is)h(then)g(returned.)0 378 y(Once)g(the)e(sym)o(b)q(olic)
+i(link)g(is)f(returned,)g(the)g(k)o(ernel)g(will)i(send)e(all)g(other)g
+(requests)f(direct)h(to)f(the)h(moun)o(ted)0 428 y(\014lesystem.)62
+499 y(If)d(a)f(v)o(olume)g(is)h(not)f(y)o(et)g(moun)o(ted,)g
+Fp(Amd)i Fo(consults)f(a)f(con\014guration)g Fp(moun)o(t-map)h
+Fo(corresp)q(onding)g(to)f(the)0 549 y(automoun)o(t)h(p)q(oin)o(t.)24
+b Fp(Amd)19 b Fo(then)e(mak)o(es)f(a)g(run)o(time)h(decision)h(on)e(what)g
+(and)h(where)f(to)g(moun)o(t)g(a)g(\014lesystem)0 598 y(based)g(on)f(the)g
+(information)g(obtained)h(from)f(the)g(map.)62 669 y Fp(Amd)21
+b Fo(do)q(es)e(not)g(implemen)o(t)h(all)g(the)f(NFS)g(requests;)h(only)g
+(those)e(relev)m(an)o(t)i(to)e(name)h(binding)i(suc)o(h)e(as)0
+719 y Fp(lo)q(okup)p Fo(,)g Fp(readlink)j Fo(and)c Fp(readdir)p
+Fo(.)28 b(Some)18 b(other)g(calls)g(are)g(also)g(implemen)o(ted)h(but)f(most)
+f(simply)i(return)f(an)0 769 y(error)c(co)q(de;)i(for)e(example)j
+Fp(mkdir)h Fo(alw)o(a)o(ys)d(returns)g(\\read-only)h(\014lesystem".)0
+933 y Fq(1.6)33 b(Moun)n(ting)16 b(a)f(V)-6 b(olume)62 1024
+y Fo(Eac)o(h)21 b(automoun)o(t)e(p)q(oin)o(t)i(has)g(a)f(corresp)q(onding)i
+(moun)o(t)e(map.)36 b(The)20 b(moun)o(t)h(map)f(con)o(tains)h(a)f(list)h(of)0
+1074 y(k)o(ey{v)m(alue)15 b(pairs.)20 b(The)15 b(k)o(ey)f(is)h(the)f(name)h
+(of)f(the)g(v)o(olume)h(to)e(b)q(e)j(moun)o(ted.)j(The)c(v)m(alue)g(is)g(a)f
+(list)h(of)f(lo)q(cations)0 1124 y(describing)i(where)d(the)h(\014lesystem)h
+(is)f(stored)f(in)i(the)e(net)o(w)o(ork.)19 b(In)14 b(the)g(source)g(for)f
+(the)g(map)h(the)g(v)m(alue)h(w)o(ould)0 1173 y(lo)q(ok)g(lik)o(e)120
+1244 y(lo)q(cation1)31 b(lo)q(cation2)g Fj(:)8 b(:)g(:)28 b
+Fo(lo)q(cationN)62 1335 y Fp(Amd)14 b Fo(examines)f(eac)o(h)f(lo)q(cation)g
+(in)h(turn.)19 b(Eac)o(h)12 b(lo)q(cation)g(ma)o(y)f(con)o(tain)h
+Fp(selectors)i Fo(whic)o(h)f(con)o(trol)f(whether)0 1385 y
+Fp(Amd)19 b Fo(can)e(use)h(that)e(lo)q(cation.)27 b(F)l(or)16
+b(example,)i(the)g(lo)q(cation)g(ma)o(y)e(b)q(e)i(restricted)f(to)g(use)g(b)o
+(y)g(certain)h(hosts.)0 1435 y(Those)d(lo)q(cations)h(whic)o(h)g(cannot)f(b)q
+(e)h(used)g(are)f(ignored.)62 1506 y Fp(Amd)23 b Fo(attempts)d(to)g(moun)o(t)
+g(the)h(\014lesystem)g(describ)q(ed)i(b)o(y)d(eac)o(h)h(remaining)h(lo)q
+(cation)f(un)o(til)h(a)e(moun)o(t)0 1555 y(succeeds)c(or)f
+Fp(Amd)i Fo(can)f(no)f(longer)g(pro)q(ceed.)21 b(The)15 b(latter)g(can)g(o)q
+(ccur)h(in)g(three)f(w)o(a)o(ys:)37 1626 y Fn(\017)30 b Fo(If)16
+b(none)h(of)e(the)i(lo)q(cations)f(could)i(b)q(e)e(used,)h(or)e(if)i(all)g
+(of)f(the)g(lo)q(cations)h(caused)f(an)g(error,)f(then)i(the)f(last)90
+1676 y(error)e(is)i(returned.)37 1738 y Fn(\017)30 b Fo(If)17
+b(a)f(lo)q(cation)i(could)f(b)q(e)g(used)h(but)e(w)o(as)g(b)q(eing)i(moun)o
+(ted)f(in)g(the)g(bac)o(kground)f(then)h Fp(Amd)i Fo(marks)d(that)90
+1788 y(moun)o(t)k(as)f(b)q(eing)j(\\in)f(progress")e(and)h(con)o(tin)o(ues)h
+(with)g(the)f(next)g(request;)j(no)d(reply)h(is)f(sen)o(t)g(to)g(the)90
+1838 y(k)o(ernel.)37 1900 y Fn(\017)30 b Fo(Lastly)l(,)23 b(one)e(or)g(more)f
+(of)h(the)g(moun)o(ts)g(ma)o(y)f(ha)o(v)o(e)h(b)q(een)h Fp(deferred)p
+Fo(.)38 b(A)21 b(moun)o(t)g(is)g(deferred)h(if)g(extra)90 1950
+y(information)11 b(is)h(required)g(b)q(efore)f(the)h(moun)o(t)e(can)h(pro)q
+(ceed.)20 b(When)11 b(the)g(information)h(b)q(ecomes)f(a)o(v)m(ailable)90
+1999 y(the)k(moun)o(t)e(will)k(tak)o(e)c(place,)i(but)g(in)g(the)g(mean)f
+(time)h(no)f(reply)i(is)e(sen)o(t)h(to)e(the)i(k)o(ernel.)20
+b(If)15 b(the)g(moun)o(t)e(is)90 2049 y(deferred,)i Fp(Amd)j
+Fo(con)o(tin)o(ues)d(to)g(try)f(an)o(y)h(remaining)i(lo)q(cations.)62
+2141 y(Once)g(a)d(v)o(olume)i(has)f(b)q(een)i(moun)o(ted,)e
+Fp(Amd)i Fo(establishes)f(a)f Fp(v)o(olume)h(mapping)k Fo(whic)o(h)c(is)g
+(used)g(to)e(satisfy)0 2190 y(subsequen)o(t)i(requests.)0 2355
+y Fq(1.7)33 b(Automatic)15 b(Unmoun)n(ting)62 2446 y Fo(T)l(o)e(a)o(v)o(oid)f
+(an)g(ev)o(er)h(increasing)h(n)o(um)o(b)q(er)e(of)h(\014lesystem)g(moun)o
+(ts,)f Fp(Amd)i Fo(remo)o(v)o(es)e(v)o(olume)h(mappings)g(whic)o(h)0
+2496 y(ha)o(v)o(e)19 b(not)g(b)q(een)h(used)g(recen)o(tly)l(.)33
+b(A)19 b(time-to-liv)o(e)i(in)o(terv)m(al)f(is)g(asso)q(ciated)f(with)h(eac)o
+(h)f(mapping)h(and)f(when)0 2545 y(that)g(expires)i(the)e(mapping)i(is)f
+(remo)o(v)o(ed.)32 b(When)20 b(the)g(last)g(reference)g(to)f(a)g
+(\014lesystem)i(is)f(remo)o(v)o(ed,)g(that)0 2595 y(\014lesystem)14
+b(is)h(unmoun)o(ted.)k(If)14 b(the)g(unmoun)o(t)g(fails,)g(for)f(example)i
+(the)f(\014lesystem)g(is)g(still)h(busy)l(,)f(the)g(mapping)0
+2645 y(is)k(re-instated)f(and)g(its)h(time-to-liv)o(e)g(in)o(terv)m(al)g(is)g
+(extended.)26 b(The)18 b(global)g(default)f(for)g(this)g(grace)g(p)q(erio)q
+(d)h(is)p eop
+%%Page: 5 7
+5 6 bop 0 -83 a Fo(Chapter)15 b(1:)k(Ov)o(erview)1328 b(SMM:13-5)0
+158 y(con)o(trolled)14 b(b)o(y)g(the)f(\\-w")g(command-line)i(option)f(\(see)
+f(Section)h(4.11)e([-w)h(Option],)h(page)27 b(SMM:13-19\).)17
+b(It)c(is)0 208 y(also)i(p)q(ossible)i(to)e(set)g(this)g(v)m(alue)i(on)e(a)g
+(p)q(er-moun)o(t)g(basis)h(\(see)f(Section)h(3.3.4.3)d([opts],)g(page)31
+b(SMM:13-15\).)62 279 y(Filesystems)20 b(can)g(b)q(e)f(forcefully)i(timed)f
+(out)f(using)h(the)f Fp(Amq)h Fo(command.)32 b(See)20 b(Chapter)f(6)g
+([Run-time)0 329 y(Administration],)d(page)30 b(SMM:13-27.)0
+513 y Fq(1.8)j(Keep-aliv)n(es)62 604 y Fo(Use)14 b(of)g(some)g(\014lesystem)g
+(t)o(yp)q(es)g(requires)h(the)f(presence)h(of)e(a)h(serv)o(er)g(on)f(another)
+h(mac)o(hine.)20 b(If)14 b(a)g(mac)o(hine)0 654 y(crashes)19
+b(then)g(it)g(is)h(of)e(no)h(concern)g(to)f(pro)q(cesses)i(on)e(that)h(mac)o
+(hine)g(that)f(the)h(\014lesystem)h(is)f(una)o(v)m(ailable.)0
+704 y(Ho)o(w)o(ev)o(er,)14 b(to)h(pro)q(cesses)h(on)f(a)h(remote)f(host)g
+(using)h(that)f(mac)o(hine)h(as)f(a)g(\014leserv)o(er)i(this)e(ev)o(en)o(t)h
+(is)g(imp)q(ortan)o(t.)0 753 y(This)h(situation)f(is)h(most)e(widely)i
+(recognised)g(when)g(an)f(NFS)g(serv)o(er)g(crashes)g(and)g(the)g(b)q(eha)o
+(viour)h(observ)o(ed)0 803 y(on)h(clien)o(t)i(mac)o(hines)f(is)g(that)f(more)
+g(and)h(more)f(pro)q(cesses)h(hang.)29 b(In)19 b(order)f(to)g(pro)o(vide)h
+(the)g(p)q(ossibilit)o(y)h(of)0 853 y(reco)o(v)o(ery)l(,)f
+Fp(Amd)h Fo(implemen)o(ts)g(a)e Fp(k)o(eep-aliv)o(e)23 b Fo(in)o(terv)m(al)c
+(timer)g(for)f(some)g(\014lesystem)i(t)o(yp)q(es.)30 b(Curren)o(tly)18
+b(only)0 903 y(NFS)d(mak)o(es)g(use)g(of)g(this)h(service.)62
+973 y(The)k(basis)h(of)e(the)h(NFS)g(k)o(eep-aliv)o(e)i(implemen)o(tation)f
+(is)f(the)h(observ)m(ation)f(that)f(most)g(sites)h(main)o(tain)0
+1023 y(replicated)j(copies)e(of)g(common)g(system)f(data)h(suc)o(h)g(as)g
+(man)o(ual)g(pages,)h(most)e(or)h(all)g(programs,)g(system)0
+1073 y(source)c(co)q(de)g(and)g(so)f(on.)24 b(If)17 b(one)g(of)f(those)h
+(serv)o(ers)f(go)q(es)h(do)o(wn)f(it)h(w)o(ould)g(b)q(e)g(reasonable)g(to)f
+(moun)o(t)h(one)f(of)0 1123 y(the)f(others)g(as)g(a)g(replacemen)o(t.)62
+1193 y(The)j(\014rst)g(part)f(of)h(the)g(pro)q(cess)g(is)h(to)e(k)o(eep)h
+(trac)o(k)f(of)h(whic)o(h)g(\014leserv)o(ers)h(are)f(up)g(and)g(whic)o(h)h
+(are)f(do)o(wn.)0 1243 y Fp(Amd)j Fo(do)q(es)e(this)g(b)o(y)g(sending)h(RPC)f
+(requests)f(to)h(the)f(serv)o(ers')g(NFS)h Fl(NullProc)f Fo(and)h(c)o(hec)o
+(king)g(whether)g(a)0 1293 y(reply)13 b(is)f(returned.)19 b(While)13
+b(the)f(serv)o(er)f(state)g(is)h(uncertain)h(the)f(requests)g(are)f
+(re-transmitted)h(at)f(three)g(second)0 1343 y(in)o(terv)m(als)19
+b(and)g(if)f(no)h(reply)g(is)f(receiv)o(ed)i(after)d(four)h(attempts)f(the)i
+(serv)o(er)f(is)g(mark)o(ed)g(do)o(wn.)29 b(If)18 b(a)g(reply)h(is)0
+1393 y(receiv)o(ed)f(the)g(\014leserv)o(er)f(is)h(mark)o(ed)f(up)g(and)h(sta)
+o(ys)e(in)i(that)e(state)h(for)f(30)h(seconds)g(at)g(whic)o(h)h(time)f
+(another)0 1442 y(NFS)e(ping)h(is)g(sen)o(t.)62 1513 y(Once)21
+b(a)f(\014leserv)o(er)g(is)h(mark)o(ed)e(do)o(wn,)h(requests)g(con)o(tin)o
+(ue)h(to)e(b)q(e)h(sen)o(t)g(ev)o(ery)g(30)f(seconds)h(in)h(order)f(to)0
+1563 y(determine)c(when)g(the)f(\014leserv)o(er)h(comes)f(bac)o(k)g(up.)21
+b(During)15 b(this)h(time)f(an)o(y)g(reference)h(through)f
+Fp(Amd)i Fo(to)e(the)0 1613 y(\014lesystems)h(on)f(that)g(serv)o(er)g(fail)h
+(with)g(the)f(error)g(\\Op)q(eration)h(w)o(ould)g(blo)q(c)o(k".)21
+b(If)15 b(a)h(replacemen)o(t)g(v)o(olume)f(is)0 1662 y(a)o(v)m(ailable)i
+(then)e(it)h(will)h(b)q(e)f(moun)o(ted,)e(otherwise)i(the)f(error)g(is)g
+(returned)h(to)e(the)i(user.)62 1733 y(Although)g(this)g(action)g(do)q(es)g
+(not)f(protect)g(user)g(\014les,)h(whic)o(h)h(are)e(unique)i(on)e(the)h(net)o
+(w)o(ork,)e(or)h(pro)q(cesses)0 1783 y(whic)o(h)g(do)g(not)f(access)h
+(\014les)g(via)g Fp(Amd)h Fo(or)e(already)h(ha)o(v)o(e)f(op)q(en)i(\014les)f
+(on)f(the)h(h)o(ung)g(\014lesystem,)g(it)f(can)h(prev)o(en)o(t)0
+1833 y(most)f(new)i(pro)q(cesses)f(from)g(hanging.)62 1903
+y(By)k(default,)g(\014leserv)o(er)h(state)d(is)i(not)f(main)o(tained)i(for)e
+(NFS/TCP)f(moun)o(ts.)30 b(The)18 b(remote)g(\014leserv)o(er)h(is)0
+1953 y(alw)o(a)o(ys)14 b(assumed)i(to)e(b)q(e)i(up.)0 2135
+y Fq(1.9)33 b(Non-blo)r(c)n(king)16 b(Op)r(eration)62 2226
+y Fo(Since)e(there)f(is)g(only)g(one)g(instance)g(of)f Fp(Amd)j
+Fo(for)d(eac)o(h)g(automoun)o(t)g(p)q(oin)o(t,)h(and)f(usually)i(only)f(one)g
+(instance)0 2276 y(on)18 b(eac)o(h)g(mac)o(hine,)h(it)g(is)f(imp)q(ortan)o(t)
+g(that)f(it)h(is)h(alw)o(a)o(ys)e(a)o(v)m(ailable)j(to)d(service)i(k)o(ernel)
+g(calls.)30 b Fp(Amd)20 b Fo(go)q(es)e(to)0 2325 y(great)12
+b(lengths)h(to)g(ensure)g(that)f(it)h(do)q(es)g(not)g(blo)q(c)o(k)g(in)h(a)f
+(system)f(call.)20 b(As)13 b(a)g(last)f(resort)g Fp(Amd)j Fo(will)f(fork)f(b)
+q(efore)0 2375 y(it)j(attempts)e(a)i(system)f(call)i(that)d(ma)o(y)h(blo)q(c)
+o(k)i(inde\014nitely)l(,)h(suc)o(h)e(as)f(moun)o(ting)h(an)f(NFS)h
+(\014lesystem.)22 b(Other)0 2425 y(tasks)12 b(suc)o(h)g(as)h(obtaining)g
+(\014lehandle)i(information)d(for)g(an)g(NFS)h(\014lesystem,)g(are)f(done)h
+(using)g(a)f(purp)q(ose)i(built)0 2475 y(non-blo)q(c)o(king)i(RPC)f(library)g
+(whic)o(h)g(is)g(in)o(tegrated)f(with)h Fp(Amd)r Fo('s)f(task)g(sc)o
+(heduler.)21 b(This)15 b(library)g(is)g(also)f(used)0 2525
+y(to)h(implemen)o(t)h(NFS)f(k)o(eep-aliv)o(es)i(\(see)e(Section)h(1.8)e
+([Keep-aliv)o(es],)i(page)30 b(SMM:13-5\).)62 2595 y(Whenev)o(er)11
+b(a)f(moun)o(t)g(is)g(deferred)h(or)f(bac)o(kgrounded,)h Fp(Amd)i
+Fo(m)o(ust)c(w)o(ait)h(for)g(it)g(to)g(complete)h(b)q(efore)g(replying)0
+2645 y(to)f(the)i(k)o(ernel.)19 b(Ho)o(w)o(ev)o(er,)10 b(this)i(w)o(ould)f
+(cause)h Fp(Amd)h Fo(to)d(blo)q(c)o(k)i(w)o(aiting)f(for)f(a)h(reply)h(to)f
+(b)q(e)g(constructed.)19 b(Rather)p eop
+%%Page: 6 8
+6 7 bop 15 -83 a Fo(SMM:13-6)912 b(4.4)15 b(BSD)g(Automoun)o(ter)f(Reference)
+j(Man)o(ual)0 158 y(than)h(do)g(this,)h Fp(Amd)h Fo(simply)f
+Fp(drops)h Fo(the)e(call)h(under)g(the)f(assumption)g(that)f(the)h(k)o(ernel)
+h(RPC)f(mec)o(hanism)0 208 y(will)f(automatically)e(retry)g(the)g(request.)0
+445 y Fm(2)41 b(Supp)r(orted)15 b(Platforms)62 590 y Fp(Amd)20
+b Fo(has)e(b)q(een)g(p)q(orted)g(to)f(a)h(wide)h(v)m(ariet)o(y)e(of)h(mac)o
+(hines)g(and)g(op)q(erating)g(systems.)27 b(The)18 b(table)g(b)q(elo)o(w)0
+640 y(lists)e(those)f(platforms)g(supp)q(orted)g(b)o(y)g(the)h(curren)o(t)f
+(release.)0 852 y Fq(2.1)33 b(Supp)r(orted)16 b(Op)r(erating)g(Systems)62
+943 y Fo(The)j(follo)o(wing)g(op)q(erating)f(systems)g(are)g(curren)o(tly)g
+(supp)q(orted)h(b)o(y)f Fp(Amd)p Fo(.)30 b Fp(Amd)r Fo('s)17
+b(con)o(v)o(en)o(tional)i(name)0 993 y(for)c(eac)o(h)g(system)g(is)g(giv)o
+(en.)0 1064 y Fl(acis43)96 b Fo(4.3)14 b(BSD)i(for)e(IBM)i(R)l(T.)f(Con)o
+(tributed)g(b)o(y)g(Jan-Simon)i(P)o(endry)e Fl(<jsp@doc.ic.ac.uk>)0
+1132 y(aix3)144 b Fo(AIX)16 b(3.1.)j(Con)o(tributed)c(b)o(y)g(Jan-Simon)i(P)o
+(endry)e Fl(<jsp@doc.ic.ac.uk>)0 1200 y(aux)168 b Fo(System)15
+b(V)g(for)g(Mac-I)q(I.)h(Con)o(tributed)f(b)o(y)g(Julian)i(Onions)f
+Fl(<jpo@cs.nott.ac.uk>)0 1269 y(bsd44)120 b Fo(4.4)14 b(BSD.)h(Con)o
+(tributed)h(b)o(y)f(Jan-Simon)h(P)o(endry)f Fl(<jsp@doc.ic.ac.uk>)0
+1337 y(concentrix)240 1405 y Fo(Concen)o(trix)g(5.0.)k(Con)o(tributed)d(b)o
+(y)f(Sjo)q(erd)g(Mullender)j Fl(<sjoerd@cwi.nl>)0 1473 y(convex)96
+b Fo(Con)o(v)o(ex)15 b(OS)g(7.1.)k(Con)o(tributed)d(b)o(y)f(Eitan)g
+(Mizrotsky)g Fl(<eitan@shumuji.ac.il>)0 1542 y(dgux)144 b Fo(Data)14
+b(General)i(DG/UX.)e(Con)o(tributed)h(b)o(y)g(Mark)g(Da)o(vies)g
+Fl(<mark@comp.vuw.ac.nz>)0 1610 y(fpx4)144 b Fo(Celerit)o(y)16
+b(FPX)f(4.1/2.)j(Con)o(tributed)d(b)o(y)h(Stephen)g(P)o(op)q(e)f
+Fl(<scp@grizzly.acl.lanl.gov>)0 1678 y(hcx)168 b Fo(Harris)15
+b(HCX/UX.)g(Con)o(tributed)g(b)o(y)g(Chris)h(Metcalf)f Fl
+(<metcalf@masala.lcs.mit.edu)o(>)0 1746 y(hlh42)120 b Fo(HLH)16
+b(OTS)f(1.)p Fp(x)j Fo(\(4.2)c(BSD\).)g(Con)o(tributed)i(b)o(y)f(Jan-Simon)h
+(P)o(endry)g Fl(<jsp@doc.ic.ac.uk>)0 1815 y(hpux)144 b Fo(HP-UX)16
+b(6.)p Fp(x)h Fo(or)e(7.0.)k(Con)o(tributed)c(b)o(y)g(Jan-Simon)i(P)o(endry)e
+Fl(<jsp@doc.ic.ac.uk>)0 1883 y(irix)144 b Fo(SGI)15 b(Irix.)21
+b(Con)o(tributed)16 b(b)o(y)f(Scott)f(R.)i(Presnell)g Fl(<srp@cgl.ucsf.edu>)0
+1951 y(next)144 b Fo(Mac)o(h)15 b(for)f(NeXT.)h(Con)o(tributed)h(b)o(y)f
+(Bill)i(T)l(rost)d Fl(<trost\045reed@cse.ogi.edu>)0 2019 y(pyrOSx)96
+b Fo(Pyramid)15 b(OSx.)21 b(Con)o(tributed)15 b(b)o(y)g(Stefan)h(P)o(etri)f
+Fl(<petri@tubsibr.UUCP>)0 2088 y(riscix)96 b Fo(Acorn)15 b(RISC)h(iX.)g(Con)o
+(tributed)f(b)o(y)g(Piete)h(Bro)q(oks)f Fl(<pb@cam.cl.ac.uk>)0
+2156 y(sos3)144 b Fo(SunOS)17 b(3.4)d(&)h(3.5.)k(Con)o(tributed)d(b)o(y)f
+(Jan-Simon)h(P)o(endry)f Fl(<jsp@doc.ic.ac.uk>)0 2224 y(sos4)144
+b Fo(SunOS)17 b(4.)p Fp(x)p Fo(.)i(Con)o(tributed)c(b)o(y)g(Jan-Simon)i(P)o
+(endry)e Fl(<jsp@doc.ic.ac.uk>)0 2292 y(u2_2)144 b Fo(Ultrix)16
+b(2.2.)j(Con)o(tributed)c(b)o(y)g(Piete)h(Bro)q(oks)f Fl(<pb@cam.cl.ac.uk>)0
+2361 y(u3_0)144 b Fo(Ultrix)16 b(3.)k(Con)o(tributed)15 b(b)o(y)g(Piete)h
+(Bro)q(oks)f Fl(<pb@cam.cl.ac.uk>)0 2429 y(u4_0)144 b Fo(Ultrix)16
+b(4.0.)j(Con)o(tributed)c(b)o(y)g(Chris)h(Lindblad)i Fl(<cjl@ai.mit.edu>)0
+2497 y(umax43)96 b Fo(Umax)15 b(4.3)f(BSD.)h(Con)o(tributed)g(b)o(y)h(Sjo)q
+(erd)f(Mullender)i Fl(<sjoerd@cwi.nl>)0 2565 y(utek)144 b Fo(Utek)15
+b(4.0.)k(Con)o(tributed)c(b)o(y)h(Bill)h(T)l(rost)d Fl
+(<trost\045reed@cse.ogi.edu>)0 2634 y(xinu43)96 b Fo(m)o(t)14
+b(Xin)o(u)j(MORE/bsd.)j(Con)o(tributed)15 b(b)o(y)h(Jan-Simon)g(P)o(endry)f
+Fl(<jsp@doc.ic.ac.uk>)p eop
+%%Page: 7 9
+7 8 bop 0 -83 a Fo(Chapter)15 b(3:)k(Moun)o(t)c(Maps)1258 b(SMM:13-7)0
+158 y Fq(2.2)33 b(Supp)r(orted)16 b(Mac)n(hine)g(Arc)n(hitectures)0
+250 y Fl(alliant)72 b Fo(Allian)o(t)17 b(FX/4)0 313 y Fl(arm)168
+b Fo(Acorn)15 b(ARM)0 377 y Fl(aviion)96 b Fo(Data)14 b(General)i(A)-5
+b(ViiON)0 440 y Fl(encore)96 b Fo(Encore)0 504 y Fl(fps500)g
+Fo(FPS)15 b(Mo)q(del)h(500)0 567 y Fl(hp9000)96 b Fo(HP)15
+b(9000/300)e(family)0 631 y Fl(hp9k8)120 b Fo(HP)15 b(9000/800)e(family)0
+694 y Fl(ibm032)96 b Fo(IBM)15 b(R)l(T)0 758 y Fl(ibm6000)72
+b Fo(IBM)15 b(RISC)i(System/6000)0 821 y Fl(iris4d)96 b Fo(SGI)15
+b(Iris)h(4D)0 885 y Fl(macII)120 b Fo(Apple)17 b(Mac)d(I)q(I)0
+948 y Fl(mips)144 b Fo(MIPS)15 b(RISC)0 1012 y Fl(multimax)48
+b Fo(Encore)15 b(Multimax)0 1075 y Fl(orion105)48 b Fo(HLH)16
+b(Orion)g(1/05)0 1139 y Fl(sun3)144 b Fo(Sun-3)16 b(family)0
+1202 y Fl(sun4)144 b Fo(Sun-4)16 b(family)0 1266 y Fl(tahoe)120
+b Fo(T)l(aho)q(e)15 b(family)0 1329 y Fl(vax)168 b Fo(DEC)15
+b(V)l(ax)0 1513 y Fm(3)41 b(Moun)n(t)15 b(Maps)62 1639 y Fp(Amd)k
+Fo(has)f(no)f(built-in)i(kno)o(wledge)f(of)f(mac)o(hines)h(or)e
+(\014lesystems.)27 b(External)17 b Fp(moun)o(t-maps)i Fo(are)e(used)h(to)0
+1688 y(pro)o(vide)12 b(the)g(required)h(information.)19 b(Sp)q(eci\014cally)l
+(,)c Fp(Amd)f Fo(needs)e(to)f(kno)o(w)g(when)h(and)g(under)h(what)e
+(conditions)0 1738 y(it)k(should)i(moun)o(t)d(\014lesystems.)62
+1809 y(The)k(map)e(en)o(try)h(corresp)q(onding)h(to)e(the)h(requested)h(name)
+f(con)o(tains)g(a)g(list)h(of)e(p)q(ossible)j(lo)q(cations)f(from)0
+1859 y(whic)o(h)e(to)f(resolv)o(e)h(the)f(request.)21 b(Eac)o(h)15
+b(lo)q(cation)i(sp)q(eci\014es)g(\014lesystem)f(t)o(yp)q(e,)f(information)h
+(required)g(b)o(y)g(that)0 1908 y(\014lesystem)11 b(\(for)f(example)h(the)g
+(blo)q(c)o(k)g(sp)q(ecial)h(device)g(in)g(the)e(case)h(of)f(UFS\),)g(and)g
+(some)g(information)h(describing)0 1958 y(where)k(to)f(moun)o(t)h(the)g
+(\014lesystem)g(\(see)g(Section)h(3.3.4.2)c([fs)j(Option],)g(page)29
+b(SMM:13-14\).)18 b(A)d(lo)q(cation)h(ma)o(y)0 2008 y(also)f(con)o(tain)h
+Fp(selectors)h Fo(\(see)e(Section)h(3.3.3)e([Selectors],)g(page)31
+b(SMM:13-13\).)0 2184 y Fq(3.1)i(Map)15 b(T)n(yp)r(es)62 2276
+y Fo(A)k(moun)o(t-map)f(pro)o(vides)i(the)f(run-time)g(con\014guration)g
+(information)g(to)f Fp(Amd)p Fo(.)31 b(Maps)19 b(can)g(b)q(e)g(imple-)0
+2325 y(men)o(ted)f(in)h(man)o(y)f(w)o(a)o(ys.)27 b(Some)18
+b(of)g(the)g(forms)f(supp)q(orted)i(b)o(y)f Fp(Amd)i Fo(are)e(regular)g
+(\014les,)h(ndbm)g(databases,)0 2375 y(NIS)d(maps)f(the)g Fp(Hesio)q(d)j
+Fo(name)d(serv)o(er)g(and)h(ev)o(en)f(the)g(passw)o(ord)g(\014le.)62
+2446 y(A)g(moun)o(t-map)f Fp(name)k Fo(is)d(a)f(sequence)i(of)f(c)o
+(haracters.)k(When)c(an)f(automoun)o(t)g(p)q(oin)o(t)h(is)g(created)g(a)g
+(handle)0 2496 y(on)j(the)h(moun)o(t-map)f(is)g(obtained.)31
+b(F)l(or)17 b(eac)o(h)i(map)f(t)o(yp)q(e)g(con\014gured)h Fp(Amd)i
+Fo(attempts)c(to)h(reference)h(the)f(a)0 2545 y(map)g(of)g(the)h(appropriate)
+f(t)o(yp)q(e.)29 b(If)19 b(a)f(map)g(is)h(found,)g Fp(Amd)i
+Fo(notes)d(the)g(t)o(yp)q(e)h(for)e(future)i(use)f(and)h(deletes)0
+2595 y(the)14 b(reference,)g(for)f(example)i(closing)g(an)o(y)e(op)q(en)h
+(\014le)h(descriptors.)20 b(The)14 b(a)o(v)m(ailable)h(maps)f(are)f
+(con\014gure)h(when)0 2645 y Fp(Amd)j Fo(is)f(built)g(and)g(can)f(b)q(e)h
+(displa)o(y)o(ed)h(b)o(y)e(running)h(the)f(command)g(`)p Fl(amd)g(-v)p
+Fo('.)p eop
+%%Page: 8 10
+8 9 bop 15 -83 a Fo(SMM:13-8)912 b(4.4)15 b(BSD)g(Automoun)o(ter)f(Reference)
+j(Man)o(ual)62 158 y(By)i(default,)g Fp(Amd)h Fo(cac)o(hes)f(data)f(in)h(a)f
+(mo)q(de)g(dep)q(enden)o(t)i(on)e(the)h(t)o(yp)q(e)f(of)g(map.)29
+b(This)19 b(is)g(the)f(same)g(as)0 208 y(sp)q(ecifying)g(`)p
+Fl(cache:=mapdefault)p Fo(')13 b(and)k(selects)f(a)g(suitable)i(default)e
+(cac)o(he)h(mo)q(de)f(dep)q(ending)j(on)d(the)g(map)0 258 y(t)o(yp)q(e.)j
+(The)12 b(individual)k(defaults)c(are)g(describ)q(ed)i(b)q(elo)o(w.)20
+b(The)12 b Fp(cac)o(he)j Fo(option)e(can)f(b)q(e)h(sp)q(eci\014ed)h(on)e
+(automoun)o(t)0 308 y(p)q(oin)o(ts)j(to)f(alter)g(the)h(cac)o(hing)g(b)q(eha)
+o(viour)g(\(see)g(Section)g(5.8)f([Automoun)o(t)f(Filesystem],)i(page)28
+b(SMM:13-24\).)62 378 y(The)13 b(follo)o(wing)f(map)g(t)o(yp)q(es)g(ha)o(v)o
+(e)g(b)q(een)h(implemen)o(ted,)h(though)e(some)g(are)f(not)h(a)o(v)m(ailable)
+i(on)e(all)h(mac)o(hines.)0 428 y(Run)j(the)f(command)g(`)p
+Fl(amd)g(-v)p Fo(')f(to)h(obtain)g(a)g(list)h(of)f(map)g(t)o(yp)q(es)g
+(con\014gured)h(on)f(y)o(our)g(mac)o(hine.)0 582 y Fi(3.1.1)30
+b(File)15 b(maps)62 673 y Fo(When)i Fp(Amd)i Fo(searc)o(hes)e(a)f(\014le)i
+(for)e(a)g(map)g(en)o(try)h(it)g(do)q(es)f(a)h(simple)h(scan)f(of)f(the)h
+(\014le)g(and)g(supp)q(orts)g(b)q(oth)0 723 y(commen)o(ts)e(and)g(con)o(tin)o
+(uation)h(lines.)62 794 y(Con)o(tin)o(uation)g(lines)h(are)e(indicated)i(b)o
+(y)e(a)g(bac)o(kslash)h(c)o(haracter)e(\(`)p Fl(\\)p Fo('\))g(as)h(the)g
+(last)h(c)o(haracter)e(of)h(a)g(line)i(in)0 843 y(the)h(\014le.)30
+b(The)18 b(bac)o(kslash,)h(newline)h(c)o(haracter)e Fp(and)g(an)o(y)g
+(leading)i(white)e(space)h(on)f(the)g(follo)o(wing)h(line)j
+Fo(are)0 893 y(discarded.)g(A)16 b(maxim)o(um)g(line)h(length)f(of)g(2047)e
+(c)o(haracters)h(is)h(enforced)g(after)f(con)o(tin)o(uation)h(lines)i(are)d
+(read)0 943 y(but)h(b)q(efore)h(commen)o(ts)f(are)g(stripp)q(ed.)24
+b(Eac)o(h)16 b(line)i(m)o(ust)e(end)h(with)g(a)f(newline)i(c)o(haracter;)e
+(that)f(is)i(newlines)0 993 y(are)e(terminators,)f(not)h(separators.)j(The)e
+(follo)o(wing)g(examples)g(illustrate)g(this:)120 1063 y Fl(key)119
+b(valA)71 b(valB;)g(\\)359 1113 y(valC)62 1205 y Fo(sp)q(eci\014es)17
+b Fp(three)h Fo(lo)q(cations,)e(and)f(is)h(iden)o(tical)h(to)120
+1275 y Fl(key)119 b(valA)71 b(valB;)g(valC)62 1366 y Fo(Ho)o(w)o(ev)o(er,)120
+1437 y Fl(key)119 b(valA)71 b(valB;\\)359 1487 y(valC)62 1578
+y Fo(sp)q(eci\014es)17 b(only)f Fp(t)o(w)o(o)g Fo(lo)q(cations,)g(and)f(is)h
+(iden)o(tical)h(to)120 1649 y Fl(key)119 b(valA)71 b(valB;valC)62
+1740 y Fo(After)20 b(a)h(complete)g(line)h(has)f(b)q(een)g(read)g(from)f(the)
+h(\014le,)h(including)h(con)o(tin)o(uations,)f Fp(Amd)h Fo(determines)0
+1790 y(whether)d(there)g(is)h(a)e(commen)o(t)h(on)f(the)i(line.)35
+b(A)20 b(commen)o(t)g(b)q(egins)h(with)f(a)g(hash)g(\(\\`)p
+Fl(#)p Fo('"\))e(c)o(haracter)h(and)0 1840 y(con)o(tin)o(ues)12
+b(to)g(the)f(end)i(of)e(the)h(line.)21 b(There)12 b(is)g(no)g(w)o(a)o(y)e(to)
+i(escap)q(e)g(or)f(c)o(hange)h(the)g(commen)o(t)f(lead-in)j(c)o(haracter.)62
+1910 y(Note)f(that)g(con)o(tin)o(uation)h(lines)h(and)f(commen)o(t)f(supp)q
+(ort)g Fp(only)18 b Fo(apply)d(to)e(\014le)h(maps,)f(or)g(ndbm)h(maps)g
+(built)0 1960 y(with)i(the)f Fl(mk-amd-map)f Fo(program.)62
+2031 y(When)e(cac)o(hing)f(is)h(enabled,)h(\014le)f(maps)e(ha)o(v)o(e)h(a)f
+(default)i(cac)o(he)f(mo)q(de)g(of)g Fl(all)f Fo(\(see)h(Section)h(5.8)e
+([Automoun)o(t)0 2080 y(Filesystem],)15 b(page)30 b(SMM:13-24\).)0
+2234 y Fi(3.1.2)g(ndbm)15 b(maps)62 2325 y Fo(An)20 b(ndbm)f(map)g(ma)o(y)g
+(b)q(e)h(used)f(as)g(a)g(fast)f(access)h(form)g(of)f(a)h(\014le)h(map.)32
+b(The)19 b(program,)g Fl(mk-amd-map)p Fo(,)0 2375 y(con)o(v)o(erts)c(a)g
+(normal)g(map)g(\014le)h(in)o(to)g(an)f(ndbm)h(database.)k(This)c(program)e
+(supp)q(orts)h(the)h(same)f(con)o(tin)o(uation)0 2425 y(and)f(commen)o(t)f
+(con)o(v)o(en)o(tions)h(that)f(are)g(pro)o(vided)i(for)e(\014le)h(maps.)19
+b(Note)14 b(that)f(ndbm)h(format)e(\014les)j(ma)o(y)e Fp(not)h
+Fo(b)q(e)0 2475 y(sharable)h(across)f(mac)o(hine)i(arc)o(hitectures.)j(The)c
+(notion)g(of)f(sp)q(eed)i(generally)g(only)f(applies)h(to)e(large)h(maps;)f
+(a)0 2525 y(small)i(map,)f(less)g(than)g(a)g(single)i(disk)f(blo)q(c)o(k,)f
+(is)h(almost)f(certainly)h(b)q(etter)f(implemen)o(ted)i(as)e(a)g(\014le)h
+(map.)62 2595 y(ndbm)e(maps)e(do)h(not)f(supp)q(ort)h(cac)o(he)g(mo)q(de)f(`)
+p Fl(all)p Fo(')g(and,)h(when)g(cac)o(hing)g(is)h(enabled,)g(ha)o(v)o(e)e(a)g
+(default)i(cac)o(he)0 2645 y(mo)q(de)h(of)g(`)p Fl(inc)p Fo(')f(\(see)h
+(Section)h(5.8)f([Automoun)o(t)f(Filesystem],)h(page)30 b(SMM:13-24\).)p
+eop
+%%Page: 9 11
+9 10 bop 0 -83 a Fo(Chapter)15 b(3:)k(Moun)o(t)c(Maps)1258
+b(SMM:13-9)0 158 y Fi(3.1.3)30 b(NIS)15 b(maps)62 250 y Fo(When)j(using)h
+(NIS)f(\(formerly)f(YP\),)g(an)g Fp(Amd)j Fo(map)d(is)h(implemen)o(ted)i
+(directly)f(b)o(y)e(the)h(underlying)h(NIS)0 299 y(map.)f(Commen)o(ts)11
+b(and)h(con)o(tin)o(uation)g(lines)h(are)f Fp(not)g Fo(supp)q(orted)g(in)g
+(the)g(automoun)o(ter)f(and)g(m)o(ust)g(b)q(e)i(stripp)q(ed)0
+349 y(when)j(constructing)f(the)g(NIS)h(serv)o(er's)f(database.)62
+420 y(NIS)j(maps)e(do)h(not)f(supp)q(ort)h(cac)o(he)f(mo)q(de)h
+Fl(all)f Fo(and,)h(when)g(cac)o(hing)h(is)f(enabled,)h(ha)o(v)o(e)e(a)g
+(default)i(cac)o(he)0 470 y(mo)q(de)d(of)g Fl(inc)g Fo(\(see)g(Section)h(5.8)
+e([Automoun)o(t)h(Filesystem],)g(page)30 b(SMM:13-24\).)62
+540 y(The)15 b(follo)o(wing)h(rule)f(illustrates)h(what)e(could)h(b)q(e)h
+(added)f(to)f(y)o(our)g(NIS)i(`)p Fl(Makefile)p Fo(',)c(in)k(this)f(case)f
+(causing)0 590 y(the)h(`)p Fl(amd.home)p Fo(')f(map)h(to)f(b)q(e)i(rebuilt:)
+120 661 y Fl($\(YPTSDIR\)/amd.home.time:)k($\(ETCDIR\)/amd.home)311
+710 y(-@sed)j(-e)h("s/#.*$$//")e(-e)i("/^$$/d")e($\(ETCDIR\)/amd.home)g(|)i
+(\\)359 760 y(awk)f('{)48 b(\\)526 810 y(for)23 b(\(i)h(=)f(1;)h(i)g(<=)f
+(NF;)h(i++\))f(\\)621 860 y(if)h(\(i)f(==)h(NF\))f({)h(\\)717
+910 y(if)f(\(substr\($$i,)f(length\($$i\),)h(1\))g(==)h("\\\\"\))f(\\)812
+959 y(printf\("\045s",)f(substr\($$i,)h(1,)g(length\($$i\))g(-)g(1\)\);)120
+1009 y(\\)717 1059 y(else)g(\\)812 1109 y(printf\("\045s\\n",)f($$i\);)h(\\)
+621 1159 y(})h(\\)621 1209 y(else)f(\\)717 1258 y(printf\("\045s)f(",)i
+($$i\);)f(\\)430 1308 y(}')h(|)g(\\)311 1358 y($\(MAKEDBM\))e(-)i
+($\(YPDBDIR\)/amd.home;)d(\\)311 1408 y(touch)i($\(YPTSDIR\)/amd.home.time;)e
+(\\)311 1458 y(echo)i("updated)g(amd.home";)f(\\)311 1507 y(if)h([)h(!)g
+($\(NOPUSH\))f(];)g(then)g(\\)502 1557 y($\(YPPUSH\))f(amd.home;)h(\\)502
+1607 y(echo)g("pushed)g(amd.home";)g(\\)311 1657 y(else)g(\\)502
+1707 y(:)h(;)f(\\)311 1757 y(fi)62 1848 y Fo(Here)16 b Fl($\(YPTSDIR\))e
+Fo(con)o(tains)h(the)g(time)h(stamp)e(\014les,)i(and)f Fl($\(YPDBDIR\))f
+Fo(con)o(tains)i(the)f(dbm)g(format)f(NIS)0 1898 y(\014les.)0
+2083 y Fi(3.1.4)30 b(Hesio)r(d)15 b(maps)62 2174 y Fo(When)f(the)g(map)g
+(name)f(b)q(egins)i(with)f(the)g(string)g(`)p Fl(hesiod.)p
+Fo(')e(lo)q(okups)i(are)f(made)h(using)h(the)e Fp(Hesio)q(d)k
+Fo(name)0 2224 y(serv)o(er.)i(The)13 b(string)g(follo)o(wing)g(the)g(dot)g
+(is)g(used)h(as)e(a)h(name)g(quali\014er)h(and)f(is)h(prep)q(ended)h(with)e
+(the)g(k)o(ey)g(b)q(eing)0 2274 y(lo)q(cated.)24 b(The)16 b(en)o(tire)h
+(string)f(is)h(then)g(resolv)o(ed)g(in)g(the)f Fl(automount)f
+Fo(con)o(text.)23 b(F)l(or)15 b(example,)j(if)e(the)h(the)f(k)o(ey)0
+2324 y(is)f(`)p Fl(jsp)p Fo(')e(and)h(map)h(name)f(is)h(`)p
+Fl(hesiod.homes)p Fo(')d(then)i Fp(Hesio)q(d)k Fo(is)c(ask)o(ed)h(to)e
+(resolv)o(e)i(`)p Fl(jsp.homes.automount)p Fo(')o(.)62 2394
+y(Hesio)q(d)21 b(maps)e(do)g(not)g(supp)q(ort)g(cac)o(he)g(mo)q(de)h(`)p
+Fl(all)p Fo(')e(and,)i(when)g(cac)o(hing)g(is)f(enabled,)j(ha)o(v)o(e)c(a)h
+(default)0 2444 y(cac)o(he)c(mo)q(de)h(of)f(`)p Fl(inc)p Fo(')f(\(see)h
+(Section)h(5.8)e([Automoun)o(t)g(Filesystem],)h(page)31 b(SMM:13-24\).)62
+2515 y(The)16 b(follo)o(wing)g(is)f(an)g(example)h(of)f(a)g
+Fp(Hesio)q(d)j Fo(map)d(en)o(try:)120 2585 y Fl(jsp.homes.automount)21
+b(HS)j(TXT)f("rfs:=/home/charm;rhost:=cha)o(rm;subli)o(nk:=jsp)o(")120
+2635 y(njw.homes.automount)e(HS)j(TXT)f("rfs:=/home/dylan/dk2;rhost:)o
+(=dylan;s)o(ublink:)o(=njw")p eop
+%%Page: 10 12
+10 11 bop 15 -83 a Fo(SMM:13-10)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fi(3.1.5)30 b(P)n(assw)n(ord)16
+b(maps)62 250 y Fo(The)g(passw)o(ord)g(map)f(supp)q(ort)i(is)f(unlik)o(e)i
+(the)e(four)f(previous)i(map)f(t)o(yp)q(es.)22 b(When)16 b(the)h(map)e(name)h
+(is)h(the)0 299 y(string)g(`)p Fl(/etc/passwd)p Fo(')d Fp(Amd)19
+b Fo(can)e(lo)q(okup)h(a)e(user)h(name)g(in)h(the)f(passw)o(ord)f(\014le)i
+(and)f(re-arrange)f(the)h(home)0 349 y(directory)e(\014eld)i(to)d(pro)q(duce)
+j(a)d(usable)j(map)e(en)o(try)l(.)62 420 y Fp(Amd)20 b Fo(assumes)e(the)g
+(home)g(directory)g(has)g(the)g(format)f(`)p Fl(/)p Fp(an)o(ydir)s
+Fl(/)p Fp(dom1)t Fl(/../)p Fp(domN)5 b Fl(/)p Fp(login)p Fo('.)27
+b(It)18 b(breaks)0 470 y(this)d(string)g(in)o(to)g(a)f(map)g(en)o(try)h
+(where)g Fl(${rfs})f Fo(has)g(the)h(v)m(alue)h(`)p Fl(/)p Fp(an)o(ydir)s
+Fl(/)p Fp(domN)5 b Fo(',)14 b Fl(${rhost})f Fo(has)i(the)g(v)m(alue)0
+519 y(`)p Fp(domN)5 b Fl(.)p Fp(...)p Fl(.)p Fp(dom1)t Fo(',)12
+b(and)j Fl(${sublink})f Fo(has)h(the)g(v)m(alue)i(`)p Fl(login)p
+Fo('.)62 590 y(Th)o(us)e(if)h(the)f(passw)o(ord)g(\014le)h(en)o(try)f(w)o(as)
+120 661 y Fl(/home/achilles/jsp)62 752 y Fo(the)h(map)f(en)o(try)f(used)i(b)o
+(y)f Fp(Amd)i Fo(w)o(ould)f(b)q(e)120 823 y Fl(rfs:=/home/achilles;rhost:)o
+(=achill)o(es;subli)o(nk:=jsp)62 914 y Fo(Similarly)l(,)h(if)f(the)f(passw)o
+(ord)g(\014le)h(en)o(try)f(w)o(as)120 984 y Fl(/home/cc/sugar/mjh)62
+1076 y Fo(the)h(map)f(en)o(try)f(used)i(b)o(y)f Fp(Amd)i Fo(w)o(ould)f(b)q(e)
+120 1146 y Fl(rfs:=/home/sugar;rhost:=su)o(gar.cc;)o(sublink:)o(=jsp)0
+1279 y Fi(3.1.6)30 b(Union)15 b(maps)62 1371 y Fo(The)d(union)h(map)e(supp)q
+(ort)g(is)h(pro)o(vided)h(sp)q(eci\014cally)h(for)d(use)h(with)f(the)h(union)
+h(\014lesystem,)f(see)g(Section)g(5.10)0 1420 y([Union)k(Filesystem],)f(page)
+30 b(SMM:13-25.)62 1491 y(It)17 b(is)g(iden)o(ti\014ed)h(b)o(y)e(the)h
+(string)f(`)p Fl(union:)p Fo(')f(whic)o(h)i(is)g(follo)o(w)o(ed)g(b)o(y)f(a)g
+(colon)h(separated)f(list)h(of)f(directories.)0 1541 y(The)e(directories)g
+(are)f(read)g(in)i(order,)e(and)g(the)h(names)f(of)g(all)h(en)o(tries)g(are)f
+(recorded)h(in)g(the)f(map)h(cac)o(he.)19 b(Later)0 1591 y(directories)f(tak)
+o(e)e(precedence)j(o)o(v)o(er)d(earlier)i(ones.)25 b(The)18
+b(union)g(\014lesystem)f(t)o(yp)q(e)g(then)h(uses)f(the)g(map)g(cac)o(he)0
+1640 y(to)e(determine)h(the)f(union)h(of)f(the)g(names)h(in)g(all)g(the)f
+(directories.)0 1790 y Fq(3.2)33 b(Ho)n(w)14 b(k)n(eys)h(are)g(lo)r(ok)n(ed)h
+(up)62 1881 y Fo(The)g(k)o(ey)f(is)h(lo)q(cated)g(in)g(the)g(map)f(whose)g(t)
+o(yp)q(e)g(w)o(as)g(determined)i(when)e(the)h(automoun)o(t)e(p)q(oin)o(t)i(w)
+o(as)e(\014rst)0 1931 y(created.)19 b(In)14 b(general)g(the)f(k)o(ey)g(is)h
+(a)f(pathname)g(comp)q(onen)o(t.)19 b(In)14 b(some)f(circumstances)h(this)f
+(ma)o(y)g(b)q(e)h(mo)q(di\014ed)0 1981 y(b)o(y)h(v)m(ariable)i(expansion)f
+(\(see)f(Section)h(3.3.2)e([V)l(ariable)i(Expansion],)f(page)31
+b(SMM:13-12\))13 b(and)j(pre\014xing.)21 b(If)0 2031 y(the)13
+b(automoun)o(t)e(p)q(oin)o(t)i(has)g(a)f(pre\014x,)h(sp)q(eci\014ed)i(b)o(y)e
+(the)f Fp(pref)22 b Fo(option,)13 b(then)g(that)f(is)h(prep)q(ended)h(to)e
+(the)h(searc)o(h)0 2081 y(k)o(ey)i(b)q(efore)h(the)f(map)g(is)h(searc)o(hed.)
+62 2151 y(If)e(the)f(map)g(cac)o(he)h(is)g(a)e(`)p Fl(regexp)p
+Fo(')g(cac)o(he)i(then)f(the)h(k)o(ey)f(is)h(treated)e(as)h(an)g(egrep-st)o
+(yle)h(regular)f(expression,)0 2201 y(otherwise)i(a)g(normal)g(string)h
+(comparison)f(is)h(made.)62 2271 y(If)k(the)f(k)o(ey)h(cannot)f(b)q(e)h
+(found)g(then)f(a)g Fp(wildcard)k Fo(matc)o(h)c(is)h(attempted.)31
+b Fp(Amd)22 b Fo(rep)q(eatedly)e(strips)g(the)0 2321 y(basename)15
+b(from)f(the)h(k)o(ey)l(,)f(app)q(ends)i(`)p Fl(/*)p Fo(')e(and)h(attempts)e
+(a)i(lo)q(okup.)20 b(Finally)l(,)c Fp(Amd)h Fo(attempts)d(to)g(lo)q(cate)h
+(the)0 2371 y(sp)q(ecial)i(k)o(ey)e(`)p Fl(*)p Fo('.)62 2421
+y(F)l(or)g(example,)g(the)h(follo)o(wing)g(sequence)g(w)o(ould)g(b)q(e)g(c)o
+(hec)o(k)o(ed)f(if)h(`)p Fl(home/dylan/dk2)p Fo(')c(w)o(as)j(b)q(eing)h(lo)q
+(cated:)192 2492 y Fl(home/dylan/dk2)192 2541 y(home/dylan/*)192
+2591 y(home/*)192 2641 y(*)p eop
+%%Page: 11 13
+11 12 bop 0 -83 a Fo(Chapter)15 b(3:)k(Moun)o(t)c(Maps)1236
+b(SMM:13-11)62 158 y(A)o(t)14 b(an)o(y)f(p)q(oin)o(t)h(when)h(a)e(wildcard)i
+(is)g(found,)f Fp(Amd)i Fo(pro)q(ceeds)e(as)g(if)g(an)g(exact)f(matc)o(h)h
+(had)g(b)q(een)h(found)f(and)0 208 y(the)19 b(v)m(alue)h(\014eld)g(is)f(then)
+g(used)g(to)f(resolv)o(e)h(the)g(moun)o(t)f(request,)h(otherwise)g(an)f
+(error)g(co)q(de)h(is)h(propagated)0 258 y(bac)o(k)15 b(to)g(the)g(k)o
+(ernel.)21 b(\(see)15 b(Chapter)g(5)f([Filesystem)i(T)o(yp)q(es],)f(page)30
+b(SMM:13-20\).)0 437 y Fq(3.3)j(Lo)r(cation)15 b(F)-6 b(ormat)62
+528 y Fo(The)17 b(v)m(alue)h(\014eld)f(from)f(the)h(lo)q(okup)g(pro)o(vides)g
+(the)f(information)h(required)h(to)d(moun)o(t)h(a)g(\014lesystem.)25
+b(The)0 578 y(information)15 b(is)h(parsed)f(according)h(to)f(the)g(syn)o
+(tax)f(sho)o(wn)h(b)q(elo)o(w.)120 648 y Fp(lo)q(cation-list)q
+Fo(:)393 698 y Fp(lo)q(cation-selection)393 748 y(lo)q(cation-list)j
+(white-space)g Fl(||)d Fp(white-space)k(lo)q(cation-selection)120
+798 y(lo)q(cation-selection)p Fo(:)393 848 y Fp(lo)q(cation)393
+897 y(lo)q(cation-selection)e(white-space)i(lo)q(cation)120
+947 y(lo)q(cation)p Fo(:)393 997 y Fp(lo)q(cation-info)393
+1047 y Fl(-)p Fp(lo)q(cation-info)393 1097 y Fl(-)120 1147
+y Fp(lo)q(cation-info)r Fo(:)393 1196 y Fp(sel-or-opt)393 1246
+y(lo)q(cation-info)r Fl(;)p Fp(sel-or-opt)393 1296 y Fl(;)120
+1346 y Fp(sel-or-opt)q Fo(:)393 1396 y Fp(selection)393 1445
+y(opt-ass)120 1495 y(selection)p Fo(:)393 1545 y(selector)p
+Fl(==)p Fp(v)m(alue)393 1595 y Fo(selector)p Fl(!=)p Fp(v)m(alue)120
+1645 y(opt-ass)r Fo(:)393 1694 y(option)p Fl(:=)p Fp(v)m(alue)120
+1744 y(white-space)s Fo(:)393 1794 y(space)393 1844 y(tab)62
+1935 y(Note)g(that)f(unquoted)h(whitespace)h(is)f(not)f(allo)o(w)o(ed)h(in)h
+(a)e(lo)q(cation)i(description.)32 b(White)19 b(space)g(is)g(only)0
+1985 y(allo)o(w)o(ed,)c(and)h(is)f(mandatory)l(,)f(where)i(sho)o(wn)f(with)g
+(non-terminal)i(`)p Fl(white-space)p Fo('.)62 2056 y(A)j Fp(lo)q
+(cation-selection)h Fo(is)f(a)f(list)h(of)f(p)q(ossible)i(v)o(olumes)f(with)f
+(whic)o(h)i(to)d(satisfy)h(the)h(request.)32 b Fp(lo)q(cation-)0
+2105 y(selection)p Fo(s)23 b(are)f(separated)f(b)o(y)h(the)g(`)p
+Fl(||)p Fo(')f(op)q(erator.)39 b(The)22 b(e\013ect)f(of)h(this)g(op)q(erator)
+f(is)h(to)g(prev)o(en)o(t)f(use)h(of)0 2155 y(lo)q(cation-selections)d(to)c
+(its)i(righ)o(t)f(if)h(an)o(y)f(of)g(the)g(lo)q(cation-selections)j(on)d(its)
+h(left)f(w)o(ere)g(selected)i(whether)e(or)0 2205 y(not)f(an)o(y)g(of)f(them)
+i(w)o(ere)f(successfully)i(moun)o(ted)e(\(see)g(Section)h(3.3.3)e
+([Selectors],)g(page)31 b(SMM:13-13\).)62 2276 y(The)17 b(lo)q
+(cation-selection,)h(and)e(singleton)h Fp(lo)q(cation-list)p
+Fo(,)h(`)p Fl(type:=ufs;dev:=/dev/)o(xd1g)p Fo(')12 b(w)o(ould)17
+b(inform)0 2325 y Fp(Amd)g Fo(to)e(moun)o(t)f(a)h(UFS)g(\014lesystem)h(from)f
+(the)g(blo)q(c)o(k)h(sp)q(ecial)h(device)g(`)p Fl(/dev/xd1g)p
+Fo('.)62 2396 y(The)h Fp(sel-or-opt)g Fo(comp)q(onen)o(t)f(is)h(either)f(the)
+h(name)f(of)f(an)h(option)h(required)g(b)o(y)f(a)g(sp)q(eci\014c)i
+(\014lesystem,)e(or)0 2446 y(it)h(is)g(the)g(name)f(of)h(a)f(built-in,)j
+(prede\014ned)f(selector)f(suc)o(h)g(as)g(the)f(arc)o(hitecture)h(t)o(yp)q
+(e.)28 b(The)17 b(v)m(alue)i(ma)o(y)e(b)q(e)0 2496 y(quoted)g(with)g(double)h
+(quotes)f(`)p Fl(")p Fo(',)f(for)g(example)i(`)p Fl(type:="ufs";dev:="/dev/)o
+(xd1g")p Fo(')o(.)k(These)c(quotes)e(are)0 2545 y(stripp)q(ed)k(when)g(the)g
+(v)m(alue)g(is)g(parsed)f(and)h(there)f(is)h(no)f(w)o(a)o(y)f(to)h(get)g(a)g
+(double)h(quote)f(in)o(to)h(a)f(v)m(alue)h(\014eld.)0 2595
+y(Double)h(quotes)g(are)f(used)h(to)f(get)h(white)g(space)g(in)o(to)f(a)h(v)m
+(alue)h(\014eld,)h(whic)o(h)e(is)g(needed)h(for)e(the)h(program)0
+2645 y(\014lesystem)16 b(\(see)f(Section)h(5.5)e([Program)g(Filesystem],)h
+(page)30 b(SMM:13-23\).)p eop
+%%Page: 12 14
+12 13 bop 15 -83 a Fo(SMM:13-12)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fi(3.3.1)30 b(Map)15 b(Defaults)62
+250 y Fo(A)h(lo)q(cation)h(b)q(eginning)h(with)e(a)g(dash)g(`)p
+Fl(-)p Fo(')f(is)h(used)h(to)e(sp)q(ecify)i(default)g(v)m(alues)g(for)e
+(subsequen)o(t)i(lo)q(cations.)0 299 y(An)o(y)12 b(previously)i(sp)q
+(eci\014ed)g(defaults)f(in)g(the)f(lo)q(cation-list)i(are)e(discarded.)20
+b(The)13 b(default)g(string)f(can)g(b)q(e)h(empt)o(y)0 349
+y(in)j(whic)o(h)g(case)f(no)g(defaults)h(apply)l(.)62 420 y(The)c(lo)q
+(cation)h(`)p Fl(-fs:=/mnt;opts:=ro)p Fo(')8 b(w)o(ould)k(set)g(the)f(lo)q
+(cal)i(moun)o(t)e(p)q(oin)o(t)h(to)f(`)p Fl(/mnt)p Fo(')g(and)h(cause)g(moun)
+o(ts)0 470 y(to)h(b)q(e)g(read-only)h(b)o(y)f(default.)20 b(Defaults)13
+b(sp)q(eci\014ed)i(this)f(w)o(a)o(y)e(are)h(app)q(ended)i(to,)d(and)i(so)e(o)
+o(v)o(erride,)i(an)o(y)e(global)0 519 y(map)j(defaults)h(giv)o(en)f(with)h(`)
+p Fl(/defaults)p Fo('\).)0 805 y Fi(3.3.2)30 b(V)-5 b(ariable)15
+b(Expansion)62 896 y Fo(T)l(o)g(allo)o(w)g(generic)h(lo)q(cation)g(sp)q
+(eci\014cations)h Fp(Amd)g Fo(do)q(es)e(v)m(ariable)i(expansion)f(on)f(eac)o
+(h)g(lo)q(cation)h(and)f(also)0 946 y(on)f(some)f(of)g(the)h(option)g
+(strings.)19 b(An)o(y)13 b(option)h(or)f(selector)h(app)q(earing)h(in)f(the)g
+(form)f Fl($)p Fp(v)m(ar)j Fo(is)e(replaced)h(b)o(y)f(the)0
+996 y(curren)o(t)f(v)m(alue)i(of)e(that)g(option)h(or)f(selector.)19
+b(F)l(or)13 b(example,)h(if)g(the)g(v)m(alue)h(of)e Fl(${key})f
+Fo(w)o(as)h(`)p Fl(bin)p Fo(',)f Fl(${autodir})0 1046 y Fo(w)o(as)k(`)p
+Fl(/a)p Fo(')f(and)i Fl(${fs})f Fo(w)o(as)g(`)p Fl(${autodir}/local/${key})p
+Fo(')d(then)k(after)f(expansion)i Fl(${fs})e Fo(w)o(ould)h(ha)o(v)o(e)f(the)0
+1095 y(v)m(alue)g(`)p Fl(/a/local/bin)p Fo('.)i(An)o(y)d(en)o(vironmen)o(t)h
+(v)m(ariable)g(can)f(b)q(e)h(accessed)g(in)g(a)f(similar)h(w)o(a)o(y)l(.)62
+1166 y(Tw)o(o)f(pathname)g(op)q(erators)g(are)g(a)o(v)m(ailable)i(when)f
+(expanding)h(a)e(v)m(ariable.)23 b(If)16 b(the)f(v)m(ariable)i(name)f(b)q
+(egins)0 1216 y(with)h(`)p Fl(/)p Fo(')g(then)g(only)h(the)f(last)g(comp)q
+(onen)o(t)g(of)g(then)g(pathname)g(is)h(substituted.)26 b(F)l(or)16
+b(example,)i(if)g Fl(${path})0 1266 y Fo(w)o(as)f(`)p Fl(/foo/bar)p
+Fo(')e(then)j Fl(${/path})e Fo(w)o(ould)i(b)q(e)g(expanded)h(to)d(`)p
+Fl(bar)p Fo('.)26 b(Similarly)l(,)20 b(if)e(the)f(v)m(ariable)i(name)e(ends)0
+1315 y(with)f(`)p Fl(/)p Fo(')e(then)h(all)i(but)e(the)g(last)g(comp)q(onen)o
+(t)h(of)f(the)g(pathname)g(is)h(substituted.)k(In)c(the)g(previous)f
+(example,)0 1365 y Fl(${path/})f Fo(w)o(ould)i(b)q(e)g(expanded)g(to)e(`)p
+Fl(/foo)p Fo('.)62 1436 y(Tw)o(o)i(domain)g(name)h(op)q(erators)e(are)h(also)
+g(pro)o(vided.)24 b(If)16 b(the)h(v)m(ariable)g(name)f(b)q(egins)i(with)f(`)p
+Fl(.)p Fo(')e(then)h(only)0 1486 y(the)h(domain)g(part)f(of)g(the)g(name)h
+(is)g(substituted.)25 b(F)l(or)16 b(example,)h(if)g Fl(${rhost})e
+Fo(w)o(as)h(`)p Fl(swan.doc.ic.ac.uk)p Fo(')0 1535 y(then)g
+Fl(${.rhost})f Fo(w)o(ould)i(b)q(e)f(expanded)h(to)f(`)p Fl(doc.ic.ac.uk)p
+Fo('.)k(Similarly)l(,)e(if)e(the)h(v)m(ariable)g(name)f(ends)h(with)0
+1585 y(`)p Fl(.)p Fo(')h(then)h(only)g(the)g(host)f(comp)q(onen)o(t)h(is)g
+(substituted.)31 b(In)19 b(the)g(previous)g(example,)h Fl(${rhost.})d
+Fo(w)o(ould)i(b)q(e)0 1635 y(expanded)d(to)f(`)p Fl(swan)p
+Fo('.)62 1706 y(V)l(ariable)k(expansion)f(is)g(a)f(t)o(w)o(o)f(phase)h(pro)q
+(cess.)26 b(Before)18 b(a)f(lo)q(cation)h(is)f(parsed,)h(all)g(references)g
+(to)f(selec-)0 1755 y(tors,)f Fp(eg)k Fl(${path})p Fo(,)c(are)g(expanded.)25
+b(The)17 b(lo)q(cation)g(is)g(then)g(parsed,)g(selections)h(are)e(ev)m
+(aluated)i(and)f(option)0 1805 y(assignmen)o(ts)h(recorded.)31
+b(If)19 b(there)g(w)o(ere)f(no)h(selections)h(or)e(they)g(all)i(succeeded)g
+(the)f(lo)q(cation)g(is)h(used)f(and)0 1855 y(the)c(v)m(alues)h(of)f(the)g
+(follo)o(wing)h(options)f(are)g(expanded)h(in)g(the)f(order)g(giv)o(en:)20
+b Fp(sublink)p Fo(,)d Fp(rfs)p Fo(,)d Fp(fs)p Fo(,)h Fp(opts)p
+Fo(,)f Fp(remopts)p Fo(,)0 1905 y Fp(moun)o(t)i Fo(and)f Fp(unmoun)o(t)p
+Fo(.)62 1975 y(Note)f(that)f(expansion)h(of)g(option)f(v)m(alues)i(is)g(done)
+f(after)f Fp(all)j Fo(assignmen)o(ts)e(ha)o(v)o(e)f(b)q(een)i(completed)f
+(and)g(not)0 2025 y(in)20 b(a)f(purely)h(left)g(to)e(righ)o(t)h(order)g(as)g
+(is)g(done)h(b)o(y)f(the)g(shell.)33 b(This)20 b(generally)g(has)f(the)h
+(desired)g(e\013ect)f(but)0 2075 y(care)14 b(m)o(ust)g(b)q(e)h(tak)o(en)f(if)
+g(one)h(of)f(the)g(options)h(references)g(another,)e(in)i(whic)o(h)h(case)e
+(the)g(ordering)h(can)f(b)q(ecome)0 2125 y(signi\014can)o(t.)62
+2195 y(There)i(are)f(t)o(w)o(o)e(sp)q(ecial)k(cases)f(concerning)g(v)m
+(ariable)h(expansion:)25 2266 y(1.)29 b(b)q(efore)12 b(a)f(map)h(is)g
+(consulted,)h(an)o(y)e(selectors)h(in)g(the)g(name)g(receiv)o(ed)h(from)d
+(the)i(k)o(ernel)h(are)e(expanded.)20 b(F)l(or)90 2316 y(example,)f(if)f(the)
+f(request)h(from)e(the)i(k)o(ernel)g(w)o(as)f(for)g(`)p Fl(${arch}.bin)p
+Fo(')e(and)j(the)f(mac)o(hine)i(arc)o(hitecture)90 2366 y(w)o(as)14
+b(`)p Fl(vax)p Fo(',)g(the)h(v)m(alue)i(giv)o(en)e(to)g Fl(${key})f
+Fo(w)o(ould)i(b)q(e)g(`)p Fl(vax.bin)p Fo('.)25 2446 y(2.)29
+b(the)13 b(v)m(alue)h(of)e Fl(${rhost})g Fo(is)h(expanded)h(and)f(normalized)
+i(b)q(efore)e(the)g(other)f(options)h(are)g(expanded.)20 b(The)90
+2496 y(normalization)g(pro)q(cess)g(strips)g(an)o(y)f(lo)q(cal)i(sub-domain)g
+(comp)q(onen)o(ts.)33 b(F)l(or)19 b(example,)i(if)f Fl(${domain})90
+2545 y Fo(w)o(as)12 b(`)p Fl(Berkeley.EDU)p Fo(')e(and)j Fl(${rhost})f
+Fo(w)o(as)g(initially)j(`)p Fl(snow.Berkeley.EDU)p Fo(',)10
+b(after)i(the)h(normalization)90 2595 y(it)21 b(w)o(ould)g(simply)h(b)q(e)g
+(`)p Fl(snow)p Fo('.)35 b(Hostname)21 b(normalization)g(is)h(curren)o(tly)f
+(done)g(in)h(a)e Fp(case-dep)q(enden)o(t)90 2645 y Fo(manner.)p
+eop
+%%Page: 13 15
+13 14 bop 0 -83 a Fo(Chapter)15 b(3:)k(Moun)o(t)c(Maps)1236
+b(SMM:13-13)0 158 y Fi(3.3.3)30 b(Selectors)62 250 y Fo(Selectors)15
+b(are)g(used)g(to)f(con)o(trol)g(the)h(use)g(of)f(a)h(lo)q(cation.)20
+b(It)15 b(is)g(p)q(ossible)h(to)e(share)h(a)f(moun)o(t)g(map)h(b)q(et)o(w)o
+(een)0 299 y(man)o(y)c(mac)o(hines)h(in)g(suc)o(h)g(a)f(w)o(a)o(y)g(that)f
+(\014lesystem)i(lo)q(cation,)h(arc)o(hitecture)f(and)f(op)q(erating)h(system)
+f(di\013erences)0 349 y(are)18 b(hidden)j(from)d(the)h(users.)31
+b(A)18 b(selector)h(of)g(the)g(form)f(`)p Fl(arch==sun3;os==sos4)p
+Fo(')d(w)o(ould)k(only)g(apply)h(on)0 399 y(Sun-3s)c(running)g(SunOS)h(4.x.)
+62 470 y(Selectors)22 b(are)f(ev)m(aluated)h(left)g(to)e(righ)o(t.)38
+b(If)21 b(a)g(selector)g(fails)h(then)g(that)e(lo)q(cation)i(is)g(ignored.)38
+b(Th)o(us)0 519 y(the)21 b(selectors)h(form)f(a)g(conjunction)h(and)g(the)f
+(lo)q(cations)h(form)f(a)g(disjunction.)40 b(If)21 b(all)i(the)e(lo)q
+(cations)h(are)0 569 y(ignored)17 b(or)f(otherwise)h(fail)h(then)f
+Fp(Amd)h Fo(uses)f(the)g Fp(error)i Fo(\014lesystem)e(\(see)g(Section)g(5.11)
+f([Error)f(Filesystem],)0 619 y(page)43 b(SMM:13-26\).)38 b(This)22
+b(is)g(equiv)m(alen)o(t)i(to)d(ha)o(ving)h(a)f(lo)q(cation)i(`)p
+Fl(type:=error)p Fo(')c(at)i(the)h(end)h(of)e(eac)o(h)0 669
+y(moun)o(t-map)15 b(en)o(try)l(.)62 739 y(The)h(selectors)f(curren)o(tly)h
+(implemen)o(ted)h(are:)0 823 y(`)p Fl(arch)p Fo(')118 b(the)19
+b(mac)o(hine)g(arc)o(hitecture)g(whic)o(h)g(w)o(as)e(automatically)i
+(determined)h(at)e(compile)i(time.)30 b(The)240 873 y(arc)o(hitecture)16
+b(t)o(yp)q(e)f(can)h(b)q(e)g(displa)o(y)o(ed)h(b)o(y)e(running)i(the)f
+(command)f(`)p Fl(amd)f(-v)p Fo('.)20 b(See)d(Section)f(2.2)240
+923 y([Supp)q(orted)g(Mac)o(hine)g(Arc)o(hitectures],)f(page)30
+b(SMM:13-7.)0 985 y(`)p Fl(autodir)p Fo(')46 b(the)16 b(default)h(directory)g
+(under)g(whic)o(h)g(to)f(moun)o(t)g(\014lesystems.)24 b(This)17
+b(ma)o(y)f(b)q(e)h(c)o(hanged)g(b)o(y)f(the)240 1035 y(\\-a")e(command)i
+(line)g(option.)21 b(See)15 b(the)h Fp(fs)g Fo(option.)0 1098
+y(`)p Fl(byte)p Fo(')118 b(the)16 b(mac)o(hine's)g(b)o(yte)f(ordering.)21
+b(This)c(is)f(either)g(`)p Fl(little)p Fo(',)e(indicating)j(little-endian,)h
+(or)e(`)p Fl(big)p Fo(',)240 1148 y(indicating)k(big-endian.)31
+b(One)18 b(p)q(ossible)i(use)f(is)f(to)g(share)g(`)p Fl(rwho)p
+Fo(')e(databases)i(\(see)g(Section)h(8.5)240 1197 y([rwho)c(serv)o(ers],)h
+(page)32 b(SMM:13-49\).)21 b(Another)16 b(is)g(to)g(share)g(ndbm)h
+(databases,)e(ho)o(w)o(ev)o(er)h(this)240 1247 y(use)g(can)f(b)q(e)h
+(considered)g(a)f(courageous)g(juggling)h(act.)0 1310 y(`)p
+Fl(cluster)p Fo(')46 b(is)19 b(pro)o(vided)h(as)e(a)h(ho)q(ok)g(for)f(the)h
+(name)g(of)f(the)h(lo)q(cal)h(cluster.)32 b(This)19 b(can)g(b)q(e)h(used)f
+(to)f(decide)240 1360 y(whic)o(h)h(serv)o(ers)f(to)g(use)g(for)g(copies)h(of)
+f(replicated)i(\014lesystems.)30 b Fl(${cluster})16 b Fo(defaults)j(to)f(the)
+240 1410 y(v)m(alue)e(of)f Fl(${domain})f Fo(unless)i(a)f(di\013eren)o(t)h(v)
+m(alue)g(is)g(set)f(with)g(the)h(\\-C")e(command)h(line)i(option.)0
+1472 y(`)p Fl(domain)p Fo(')70 b(the)15 b(lo)q(cal)i(domain)e(name)g(as)g(sp)
+q(eci\014ed)j(b)o(y)d(the)g(\\-d")g(command)g(line)i(option.)j(See)c(`)p
+Fl(host)p Fo('.)0 1535 y(`)p Fl(host)p Fo(')118 b(the)13 b(lo)q(cal)h
+(hostname)e(as)h(determined)h(b)o(y)f Fk(gethostname)p Fo(\(2\).)18
+b(If)13 b(no)g(domain)g(name)g(w)o(as)f(sp)q(eci\014ed)240
+1585 y(on)19 b(the)g(command)f(line)j(and)e(the)f(hostname)h(con)o(tains)g(a)
+f(p)q(erio)q(d)i(`)p Fl(.)p Fo(')e(then)h(the)g(string)g(b)q(efore)240
+1635 y(the)i(p)q(erio)q(d)g(is)g(used)g(as)f(the)h(host)f(name,)h(and)g(the)f
+(string)h(after)e(the)i(p)q(erio)q(d)h(is)f(assigned)g(to)240
+1684 y Fl(${domain})p Fo(.)d(F)l(or)13 b(example,)h(if)f(the)h(hostname)f(is)
+g(`)p Fl(styx.doc.ic.ac.uk)p Fo(')d(then)k Fl(host)f Fo(w)o(ould)g(b)q(e)240
+1734 y(`)p Fl(styx)p Fo(')h(and)h Fl(domain)g Fo(w)o(ould)g(b)q(e)h(`)p
+Fl(doc.ic.ac.uk)p Fo('.)h Fl(hostd)e Fo(w)o(ould)h(b)q(e)f(`)p
+Fl(styx.doc.ic.ac.uk)p Fo('.)0 1797 y(`)p Fl(hostd)p Fo(')94
+b(is)16 b Fl(${host})e Fo(and)i Fl(${domain})e Fo(concatenated)h(with)h(a)f
+(`)p Fl(.)p Fo(')f(inserted)i(b)q(et)o(w)o(een)g(them)f(if)h(required.)240
+1847 y(If)f Fl(${domain})f Fo(is)i(an)f(empt)o(y)g(string)g(then)h
+Fl(${host})e Fo(and)h Fl(${hostd})f Fo(will)j(b)q(e)f(iden)o(tical.)0
+1909 y(`)p Fl(karch)p Fo(')94 b(is)13 b(pro)o(vided)g(as)f(a)g(ho)q(ok)h(for)
+e(the)i(k)o(ernel)g(arc)o(hitecture.)19 b(This)13 b(is)g(used)g(on)g(SunOS)g
+(4,)g(for)e(example,)240 1959 y(to)i(distinguish)i(b)q(et)o(w)o(een)f
+(di\013eren)o(t)f(`)p Fl(/usr/kvm)p Fo(')f(v)o(olumes.)20 b
+Fl(${karch})12 b Fo(defaults)i(to)e(the)i(v)m(alue)g(of)240
+2009 y Fl(${arch})g Fo(unless)j(a)d(di\013eren)o(t)i(v)m(alue)g(is)g(set)f
+(with)g(the)h(\\-k")e(command)i(line)g(option.)0 2072 y(`)p
+Fl(os)p Fo(')166 b(the)15 b(op)q(erating)g(system.)k(Lik)o(e)d(the)f(mac)o
+(hine)h(arc)o(hitecture,)f(this)g(is)g(automatically)h(determined)240
+2122 y(at)11 b(compile)h(time.)19 b(The)12 b(op)q(erating)f(system)g(name)g
+(can)h(b)q(e)g(displa)o(y)o(ed)g(b)o(y)f(running)i(the)e(command)240
+2171 y(`)p Fl(amd)j(-v)p Fo('.)20 b(See)15 b(Section)h(2.1)f([Supp)q(orted)g
+(Op)q(erating)h(Systems],)f(page)30 b(SMM:13-6.)62 2263 y(The)15
+b(follo)o(wing)g(selectors)g(are)f(also)h(pro)o(vided.)20 b(Unlik)o(e)c(the)f
+(other)f(selectors,)h(they)f(v)m(ary)h(for)f(eac)o(h)h(lo)q(okup.)0
+2313 y(Note)h(that)h(when)g(the)g(name)g(from)f(the)h(k)o(ernel)g(is)g
+(expanded)h(prior)f(to)f(a)h(map)g(lo)q(okup,)g(these)g(selectors)g(are)0
+2362 y(all)f(de\014ned)h(as)e(empt)o(y)f(strings.)0 2433 y(`)p
+Fl(key)p Fo(')142 b(the)13 b(name)f(b)q(eing)i(resolv)o(ed.)19
+b(F)l(or)12 b(example,)i(if)e(`)p Fl(/home)p Fo(')f(is)i(an)g(automoun)o(t)e
+(p)q(oin)o(t,)i(then)g(accessing)240 2483 y(`)p Fl(/home/foo)p
+Fo(')c(w)o(ould)i(set)g Fl(${key})f Fo(to)g(the)h(string)f(`)p
+Fl(foo)p Fo('.)18 b(The)11 b(k)o(ey)f(is)i(pre\014xed)f(b)o(y)g(the)g
+Fp(pref)20 b Fo(option)240 2533 y(set)15 b(in)g(the)g(paren)o(t)f(moun)o(t)h
+(p)q(oin)o(t.)20 b(The)15 b(default)g(pre\014x)g(is)h(an)e(empt)o(y)h
+(string.)20 b(If)15 b(the)g(pre\014x)g(w)o(as)240 2582 y(`)p
+Fl(blah/)p Fo(')f(then)h Fl(${key})g Fo(w)o(ould)g(b)q(e)h(set)f(to)g(`)p
+Fl(blah/foo)p Fo('.)0 2645 y(`)p Fl(map)p Fo(')142 b(the)15
+b(name)g(of)g(the)h(moun)o(t)e(map)h(b)q(eing)i(used.)p eop
+%%Page: 14 16
+14 15 bop 15 -83 a Fo(SMM:13-14)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y(`)p Fl(path)p Fo(')118 b(the)12
+b(full)i(pathname)e(of)g(the)h(name)f(b)q(eing)i(resolv)o(ed.)19
+b(F)l(or)12 b(example)h(`)p Fl(/home/foo)p Fo(')d(in)k(the)e(example)240
+208 y(ab)q(o)o(v)o(e.)0 272 y(`)p Fl(wire)p Fo(')118 b(the)21
+b(name)g(of)g(the)g(net)o(w)o(ork)f(to)h(whic)o(h)h(the)f(primary)g(net)o(w)o
+(ork)g(in)o(terface)g(is)h(attac)o(hed.)37 b(If)21 b(a)240
+322 y(sym)o(b)q(olic)i(name)e(cannot)h(b)q(e)g(found)g(in)g(the)g(net)o(w)o
+(orks)e(or)h(hosts)g(database)g(then)h(dotted)g(IP)240 372
+y(address)15 b(format)f(is)i(used.)k(This)c(v)m(alue)g(is)g(also)f(output)g
+(b)o(y)g(the)h(\\-v")f(option.)62 463 y(Selectors)j(can)f(b)q(e)h(negated)f
+(b)o(y)h(using)f(`)p Fl(!=)p Fo(')g(instead)g(of)g(`)p Fl(==)p
+Fo('.)25 b(F)l(or)16 b(example)j(to)d(select)i(a)f(lo)q(cation)h(on)f(all)0
+513 y(non-V)l(ax)f(mac)o(hines)g(the)f(selector)g(`)p Fl(arch!=vax)p
+Fo(')e(w)o(ould)j(b)q(e)g(used.)0 669 y Fi(3.3.4)30 b(Map)15
+b(Options)62 760 y Fo(Options)e(are)f(parsed)g(concurren)o(tly)h(with)g
+(selectors.)19 b(The)12 b(di\013erence)i(is)f(that)e(when)i(an)f(option)g(is)
+h(seen)g(the)0 810 y(string)g(follo)o(wing)i(the)e(`)p Fl(:=)p
+Fo(')g(is)h(recorded)g(for)e(later)i(use.)20 b(As)13 b(a)g(minim)o(um)i(the)e
+Fp(t)o(yp)q(e)j Fo(option)e(m)o(ust)f(b)q(e)h(sp)q(eci\014ed.)0
+860 y(Eac)o(h)k(\014lesystem)h(t)o(yp)q(e)g(has)f(other)g(options)g(whic)o(h)
+i(m)o(ust)e(also)g(b)q(e)h(sp)q(eci\014ed.)31 b(See)19 b(Chapter)g(5)f
+([Filesystem)0 910 y(T)o(yp)q(es],)d(page)30 b(SMM:13-20,)13
+b(for)h(details)j(on)e(the)g(\014lesystem)h(sp)q(eci\014c)h(options.)62
+980 y(Sup)q(er\015uous)g(option)e(sp)q(eci\014cations)i(are)e(ignored)h(and)f
+(are)g(not)g(rep)q(orted)g(as)g(errors.)62 1051 y(The)h(follo)o(wing)g
+(options)f(apply)h(to)f(more)f(than)h(one)h(\014lesystem)g(t)o(yp)q(e.)0
+1207 y Fi(3.3.4.1)30 b(dela)n(y)15 b(Option)62 1298 y Fo(The)21
+b(dela)o(y)l(,)h(in)f(seconds,)h(b)q(efore)f(an)f(attempt)g(will)i(b)q(e)f
+(made)f(to)g(moun)o(t)g(from)g(the)g(curren)o(t)h(lo)q(cation.)0
+1348 y(Auxilliary)g(data,)d(suc)o(h)g(as)g(net)o(w)o(ork)f(address,)i(\014le)
+g(handles)h(and)e(so)g(on)h(are)f(computed)g(regardless)h(of)f(this)0
+1398 y(v)m(alue.)62 1468 y(A)23 b(dela)o(y)g(can)g(b)q(e)h(used)f(to)f
+(implemen)o(t)i(the)f(notion)g(of)f(primary)h(and)g(secondary)g(\014le)h
+(serv)o(ers.)42 b(The)0 1518 y(secondary)14 b(serv)o(ers)g(w)o(ould)h(ha)o(v)
+o(e)e(a)h(dela)o(y)h(of)f(a)g(few)g(seconds,)g(th)o(us)g(giving)i(the)e
+(primary)g(serv)o(ers)g(a)g(c)o(hance)h(to)0 1568 y(resp)q(ond)h(\014rst.)0
+1724 y Fi(3.3.4.2)30 b(fs)15 b(Option)62 1815 y Fo(The)h(lo)q(cal)g(moun)o(t)
+f(p)q(oin)o(t.)20 b(The)15 b(seman)o(tics)h(of)f(this)g(option)h(v)m(ary)f(b)
+q(et)o(w)o(een)g(\014lesystems.)62 1885 y(F)l(or)i(NFS)h(and)g(UFS)f
+(\014lesystems)h(the)g(v)m(alue)h(of)e Fl(${fs})g Fo(is)h(used)g(as)f(the)h
+(lo)q(cal)h(moun)o(t)e(p)q(oin)o(t.)27 b(F)l(or)17 b(other)0
+1935 y(\014lesystem)f(t)o(yp)q(es)f(it)g(has)g(other)f(meanings)i(whic)o(h)f
+(are)g(describ)q(ed)i(in)f(the)f(section)g(describing)i(the)e(resp)q(ectiv)o
+(e)0 1985 y(\014lesystem)d(t)o(yp)q(e.)19 b(It)11 b(is)h(imp)q(ortan)o(t)f
+(that)g(this)h(string)f(uniquely)j(iden)o(ti\014es)f(the)f(\014lesystem)g(b)q
+(eing)h(moun)o(ted.)18 b(T)l(o)0 2035 y(satisfy)d(this)g(requiremen)o(t,)g
+(it)g(should)h(con)o(tain)f(the)g(name)g(of)f(the)h(host)f(on)h(whic)o(h)h
+(the)f(\014lesystem)g(is)g(residen)o(t)0 2085 y(and)g(the)h(pathname)f(of)g
+(the)g(\014lesystem)h(on)f(the)g(lo)q(cal)h(or)f(remote)g(host.)62
+2155 y(The)21 b(reason)g(for)f(requiring)i(the)f(hostname)f(is)h(clear)h(if)f
+(replicated)h(\014lesystems)g(are)e(considered.)38 b(If)21
+b(a)0 2205 y(\014leserv)o(er)g(go)q(es)f(do)o(wn)f(and)i(a)e(replacemen)o(t)i
+(\014lesystem)g(is)f(moun)o(ted)g(then)g(the)h Fp(lo)q(cal)i
+Fo(moun)o(t)c(p)q(oin)o(t)i Fp(m)o(ust)0 2255 y Fo(b)q(e)e(di\013eren)o(t)f
+(from)g(that)g(of)f(the)i(\014lesystem)g(whic)o(h)g(is)g(h)o(ung.)29
+b(Some)18 b(enco)q(ding)i(of)e(the)g(\014lesystem)h(name)f(is)0
+2305 y(required)e(if)g(more)f(than)g(one)g(\014lesystem)h(is)g(to)e(b)q(e)i
+(moun)o(ted)f(from)g(an)o(y)g(giv)o(en)g(host.)62 2375 y(If)21
+b(the)f(hostname)f(is)i(\014rst)e(in)i(the)f(path)g(then)g(all)h(moun)o(ts)f
+(from)f(a)h(particular)g(host)g(will)h(b)q(e)g(gathered)0 2425
+y(b)q(elo)o(w)16 b(a)e(single)j(directory)l(.)j(If)c(that)e(serv)o(er)h(go)q
+(es)g(do)o(wn)f(then)i(the)f(h)o(ung)g(moun)o(t)g(p)q(oin)o(ts)g(are)g(less)h
+(lik)o(ely)h(to)d(b)q(e)0 2475 y(acciden)o(tally)j(referenced,)e(for)g
+(example)g(when)h Fk(get)o(wd)p Fo(\(3\))d(tra)o(v)o(erses)h(the)h(namespace)
+g(to)f(\014nd)i(the)f(pathname)0 2525 y(of)g(the)g(curren)o(t)g(directory)l
+(.)62 2595 y(The)i(`)p Fl(fs)p Fo(')e(option)h(defaults)g(to)g
+Fl(${autodir}/${rhost}${rfs)o(})p Fo(.)k(In)c(addition,)h(`)p
+Fl(rhost)p Fo(')e(defaults)h(to)g(the)0 2645 y(lo)q(cal)k(host)e(name)h(\()p
+Fl(${host})p Fo(\))e(and)i(`)p Fl(rfs)p Fo(')e(defaults)i(to)f(the)h(v)m
+(alue)h(of)e Fl(${path})p Fo(,)g(whic)o(h)i(is)f(the)g(full)h(path)e(of)p
+eop
+%%Page: 15 17
+15 16 bop 0 -83 a Fo(Chapter)15 b(3:)k(Moun)o(t)c(Maps)1236
+b(SMM:13-15)0 158 y(the)15 b(requested)h(\014le;)g(`)p Fl(/home/foo)p
+Fo(')d(in)j(the)f(example)h(ab)q(o)o(v)o(e)f(\(see)g(Section)h(3.3.3)d
+([Selectors],)i(page)30 b(SMM:13-)0 208 y(13\).)23 b Fl(${autodir})16
+b Fo(defaults)h(to)f(`)p Fl(/a)p Fo(')f(but)i(ma)o(y)f(b)q(e)i(c)o(hanged)f
+(with)g(the)f(\\-a")g(command)h(line)h(option.)25 b(Sun's)0
+258 y(automoun)o(ter)15 b(defaults)i(to)e(`)p Fl(/tmp_mnt)p
+Fo('.)22 b(Note)15 b(that)h(there)g(is)h(no)f(`)p Fl(/)p Fo(')f(b)q(et)o(w)o
+(een)i(the)f Fl(${rhost})f Fo(and)i Fl(${rfs})0 308 y Fo(since)f
+Fl(${rfs})f Fo(b)q(egins)h(with)g(a)f(`)p Fl(/)p Fo('.)0 437
+y Fi(3.3.4.3)30 b(opts)15 b(Option)62 528 y Fo(The)20 b(options)f(to)f(pass)h
+(to)g(the)g(moun)o(t)g(system)g(call.)32 b(A)20 b(leading)g(`)p
+Fl(-)p Fo(')e(is)i(silen)o(tly)h(ignored.)32 b(The)19 b(moun)o(t)0
+578 y(options)h(supp)q(orted)h(generally)g(corresp)q(ond)f(to)f(those)h(used)
+h(b)o(y)f Fk(moun)o(t)p Fo(\(8\))e(and)i(are)g(listed)h(b)q(elo)o(w.)35
+b(Some)0 628 y(additional)17 b(pseudo-options)f(are)f(in)o(terpreted)g(b)o(y)
+h Fp(Amd)h Fo(and)e(are)g(also)g(listed.)62 698 y(Unless)k(sp)q(eci\014cally)
+h(o)o(v)o(erridden,)e(eac)o(h)f(of)g(the)g(system)g(default)h(moun)o(t)e
+(options)i(applies.)28 b(An)o(y)17 b(options)0 748 y(not)12
+b(recognised)h(are)f(ignored.)19 b(If)12 b(no)g(options)h(list)g(is)f
+(supplied)j(the)d(string)g(`)p Fl(rw,defaults)p Fo(')e(is)j(used)f(and)h(all)
+g(the)0 798 y(system)k(default)g(moun)o(t)g(options)g(apply)l(.)26
+b(Options)18 b(whic)o(h)f(are)g(not)g(applicable)i(for)d(a)h(particular)h(op)
+q(erating)0 848 y(system)d(are)h(silen)o(tly)h(ignored.)22
+b(F)l(or)15 b(example,)h(only)g(4.4)f(BSD)h(is)g(kno)o(wn)f(to)g(implemen)o
+(t)i(the)f Fl(compress)f Fo(and)0 898 y Fl(spongy)f Fo(options.)0
+968 y Fl(compress)48 b Fo(Use)15 b(NFS)h(compression)f(proto)q(col.)0
+1027 y Fl(grpid)120 b Fo(Use)15 b(BSD)h(directory)f(group-id)h(seman)o(tics.)
+0 1087 y Fl(intr)144 b Fo(Allo)o(w)16 b(k)o(eyb)q(oard)f(in)o(terrupts)g(on)g
+(hard)h(moun)o(ts.)0 1146 y Fl(noconn)96 b Fo(Don't)14 b(mak)o(e)h(a)g
+(connection)h(on)f(datagram)f(transp)q(orts.)0 1205 y Fl(nocto)120
+b Fo(No)15 b(close-to-op)q(en)h(consistency)l(.)0 1265 y Fl(nodevs)96
+b Fo(Don't)14 b(allo)o(w)i(lo)q(cal)g(sp)q(ecial)h(devices)f(on)g(this)f
+(\014lesystem.)0 1324 y Fl(nosuid)96 b Fo(Don't)14 b(allo)o(w)i(set-uid)g(or)
+f(set-gid)g(executables)i(on)e(this)g(\014lesystem.)0 1383
+y Fl(quota)120 b Fo(Enable)16 b(quota)f(c)o(hec)o(king)h(on)f(this)h(moun)o
+(t.)0 1442 y Fl(retrans=)p Fp(n)240 1502 y Fo(The)21 b(n)o(um)o(b)q(er)g(of)f
+(NFS)h(retransmits)f(made)h(b)q(efore)f(a)h(user)g(error)f(is)h(generated)f
+(b)o(y)h(a)f(`)p Fl(soft)p Fo(')240 1551 y(moun)o(ted)15 b(\014lesystem,)h
+(and)g(b)q(efore)f(a)g(`)p Fl(hard)p Fo(')f(moun)o(ted)i(\014lesystem)g(rep)q
+(orts)f(`)p Fl(NFS)f(server)g Fp(y)o(o)o(y)o(o)240 1601 y Fl(not)h
+(responding)f(still)g(trying)p Fo('.)0 1660 y Fl(ro)192 b Fo(Moun)o(t)14
+b(this)i(\014lesystem)g(readonly)l(.)0 1720 y Fl(rsize=)p Fp(n)71
+b Fo(The)12 b(NFS)g(read)f(pac)o(k)o(et)g(size.)20 b(Y)l(ou)12
+b(ma)o(y)f(need)h(to)f(set)h(this)g(if)g(y)o(ou)f(are)h(using)g(NFS/UDP)f
+(through)240 1770 y(a)k(gatew)o(a)o(y)l(.)0 1829 y Fl(soft)144
+b Fo(Giv)o(e)15 b(up)h(after)e Fp(retrans)j Fo(retransmissions.)0
+1888 y Fl(spongy)96 b Fo(Lik)o(e)16 b(`)p Fl(soft)p Fo(')e(for)h(status)f
+(requests,)h(and)g(`)p Fl(hard)p Fo(')f(for)g(data)h(transfers.)0
+1947 y Fl(tcp)168 b Fo(Use)15 b(TCP/IP)f(instead)h(of)f(UDP/IP)l(,)g(ignored)
+h(if)g(the)g(NFS)f(implemen)o(tation)i(do)q(es)f(not)f(supp)q(ort)240
+1997 y(TCP/IP)h(moun)o(ts.)0 2056 y Fl(timeo=)p Fp(n)71 b Fo(The)15
+b(NFS)h(timeout,)e(in)i(ten)o(th-seconds,)g(b)q(efore)f(a)g(request)g(is)h
+(retransmitted.)0 2116 y Fl(wsize=)p Fp(n)71 b Fo(The)21 b(NFS)h(write)f(pac)
+o(k)o(et)g(size.)39 b(Y)l(ou)21 b(ma)o(y)g(need)h(to)e(set)h(this)h(if)g(y)o
+(ou)f(are)g(using)h(NFS/UDP)240 2165 y(through)15 b(a)g(gatew)o(a)o(y)l(.)62
+2257 y(The)h(follo)o(wing)g(options)f(are)g(implemen)o(ted)i(b)o(y)e
+Fp(Amd)p Fo(,)g(rather)g(than)g(b)q(eing)h(passed)g(to)e(the)h(k)o(ernel.)0
+2327 y Fl(nounmount)240 2387 y Fo(Con\014gures)f(the)g(moun)o(t)g(so)g(that)g
+(its)g(time-to-liv)o(e)h(will)h(nev)o(er)f(expire.)20 b(This)15
+b(is)g(also)f(the)g(default)240 2436 y(for)h(some)f(\014lesystem)i(t)o(yp)q
+(es.)0 2496 y Fl(ping=)p Fp(n)95 b Fo(The)16 b(in)o(terv)m(al,)h(in)g
+(seconds,)f(b)q(et)o(w)o(een)h(k)o(eep-aliv)o(e)g(pings.)23
+b(When)17 b(four)f(consecutiv)o(e)h(pings)f(ha)o(v)o(e)240
+2545 y(failed)h(the)f(moun)o(t)f(p)q(oin)o(t)h(is)g(mark)o(ed)f(as)h(h)o
+(ung.)21 b(This)16 b(in)o(terv)m(al)h(defaults)f(to)f(30)g(seconds.)22
+b(If)16 b(the)240 2595 y(ping)g(in)o(terv)m(al)h(is)f(less)g(than)g(zero,)f
+(no)g(pings)i(are)e(sen)o(t)g(and)h(the)g(host)f(is)h(assumed)g(to)e(b)q(e)j
+(alw)o(a)o(ys)240 2645 y(up.)j(By)c(default,)f(pings)h(are)f(not)g(sen)o(t)g
+(for)f(an)h(NFS/TCP)g(moun)o(t.)p eop
+%%Page: 16 18
+16 17 bop 15 -83 a Fo(SMM:13-16)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fl(retry=)p Fp(n)71 b Fo(The)15
+b(n)o(um)o(b)q(er)h(of)f(times)g(to)g(retry)f(the)i(moun)o(t)e(system)h
+(call.)0 220 y Fl(utimeout=)p Fp(n)240 282 y Fo(The)k(in)o(terv)m(al,)h(in)g
+(seconds,)f(b)o(y)g(whic)o(h)h(the)e(moun)o(t's)g(time-to-liv)o(e)i(is)f
+(extended)h(after)e(an)g(un-)240 332 y(moun)o(t)k(attempt)f(has)h(failed.)42
+b(In)23 b(fact)f(the)g(in)o(terv)m(al)h(is)g(extended)g(b)q(efore)g(the)f
+(unmoun)o(t)g(is)240 382 y(attempted)13 b(to)g(a)o(v)o(oid)g(thrashing.)20
+b(The)14 b(default)g(v)m(alue)h(is)f(120)e(seconds)i(\(t)o(w)o(o)e(min)o
+(utes\))i(or)f(as)g(set)240 432 y(b)o(y)i(the)g(\\-w")g(command)g(line)i
+(option.)0 572 y Fi(3.3.4.4)30 b(remopts)15 b(Option)62 663
+y Fo(This)j(option)f(has)g(the)h(same)f(use)g(as)g Fl(${opts})f
+Fo(but)h(applies)i(only)f(when)f(the)h(remote)e(host)h(is)h(on)f(a)g(non-)0
+713 y(lo)q(cal)g(net)o(w)o(ork.)j(F)l(or)15 b(example,)h(when)g(using)g(NFS)g
+(across)e(a)i(gatew)o(a)o(y)d(it)j(is)g(often)g(necessary)f(to)g(use)h
+(smaller)0 763 y(v)m(alues)g(for)e(the)g(data)g(read)g(and)h(write)g(sizes.)
+20 b(This)15 b(can)g(simply)h(b)q(e)f(done)g(b)o(y)f(sp)q(ecifying)j(the)d
+(small)h(v)m(alues)h(in)0 812 y Fp(remopts)p Fo(.)j(When)d(a)f(non-lo)q(cal)h
+(host)f(is)h(accessed,)f(the)h(smaller)g(sizes)g(will)g(automatically)g(b)q
+(e)g(used.)62 883 y Fp(Amd)21 b Fo(determines)f(whether)f(a)f(host)g(is)i(lo)
+q(cal)f(b)o(y)g(examining)h(the)f(net)o(w)o(ork)f(in)o(terface)h
+(con\014guration)g(at)0 933 y(startup.)24 b(An)o(y)17 b(in)o(terface)h(c)o
+(hanges)f(made)g(after)f Fp(Amd)j Fo(has)e(b)q(een)h(started)e(will)j(not)d
+(b)q(e)i(noticed.)26 b(The)17 b(lik)o(ely)0 983 y(e\013ect)e(will)i(b)q(e)f
+(that)e(a)h(host)g(ma)o(y)f(incorrectly)j(b)q(e)e(declared)i(non-lo)q(cal.)62
+1053 y(Unless)f(otherwise)g(set,)e(the)i(v)m(alue)g(of)f Fl(${rem})f
+Fo(is)i(the)f(same)g(as)g(the)g(v)m(alue)i(of)d Fl(${opts})p
+Fo(.)0 1193 y Fi(3.3.4.5)30 b(sublink)16 b(Option)62 1284 y
+Fo(The)22 b(sub)q(directory)h(within)g(the)e(moun)o(ted)h(\014lesystem)g(to)f
+(whic)o(h)i(the)f(reference)g(should)h(p)q(oin)o(t.)39 b(This)0
+1334 y(can)16 b(b)q(e)h(used)f(to)f(prev)o(en)o(t)h(duplicate)h(moun)o(ts)f
+(in)g(cases)g(where)g(m)o(ultiple)i(directories)f(in)g(the)e(same)h(moun)o
+(ted)0 1384 y(\014lesystem)g(are)f(used.)0 1524 y Fi(3.3.4.6)30
+b(t)n(yp)r(e)15 b(Option)62 1615 y Fo(The)h(\014lesystem)g(t)o(yp)q(e)f(to)g
+(b)q(e)h(used.)k(See)c(Chapter)f(5)g([Filesystem)h(T)o(yp)q(es],)e(page)31
+b(SMM:13-20,)13 b(for)i(a)g(full)0 1665 y(description)i(of)d(eac)o(h)i(t)o
+(yp)q(e.)0 1853 y Fm(4)41 b Fh(Amd)16 b Fm(Command)g(Line)f(Options)62
+1973 y Fo(Man)o(y)g(of)g Fp(Amd)r Fo('s)g(parameters)g(can)g(b)q(e)h(set)f
+(from)g(the)h(command)f(line.)22 b(The)16 b(command)f(line)i(is)f(also)f
+(used)0 2022 y(to)g(sp)q(ecify)h(automoun)o(t)e(p)q(oin)o(ts)i(and)f(maps.)62
+2093 y(The)h(general)f(format)f(of)h(a)g(command)g(line)i(is)120
+2164 y Fl(amd)23 b([)p Fp(options)r Fl(])h({)g Fp(directory)k(map-name)e
+Fl([-)p Fp(map-options)r Fl(])e(})g(...)62 2255 y Fo(F)l(or)11
+b(eac)o(h)h(directory)g(and)f(map-name)h(giv)o(en,)g Fp(Amd)i
+Fo(establishes)f(an)e(automoun)o(t)g(p)q(oin)o(t.)19 b(The)12
+b Fp(map-options)0 2305 y Fo(ma)o(y)h(b)q(e)i(an)o(y)e(sequence)j(of)d
+(options)h(or)f(selectors|see)i(Section)g(3.3)e([Lo)q(cation)h(F)l(ormat],)e
+(page)28 b(SMM:13-11.)0 2355 y(The)15 b Fp(map-options)j Fo(apply)e(only)f
+(to)g Fp(Amd)r Fo('s)g(moun)o(t)f(p)q(oin)o(t.)62 2425 y(`)p
+Fl(type:=toplvl;cache:=mapde)o(fault;fs)o(:=${map)o(})p Fo(')c(is)j(the)f
+(default)i(v)m(alue)g(for)e(the)g(map)h(options.)19 b(De-)0
+2475 y(fault)12 b(options)f(for)g(a)h(map)f(are)g(read)h(from)f(a)g(sp)q
+(ecial)i(en)o(try)f(in)g(the)g(map)f(whose)h(k)o(ey)f(is)h(the)g(string)f(`)p
+Fl(/defaults)p Fo('.)0 2525 y(When)16 b(default)g(options)f(are)g(giv)o(en)h
+(they)f(are)g(prep)q(ended)j(to)c(an)o(y)h(options)h(sp)q(eci\014ed)h(in)f
+(the)g(moun)o(t-map)e(lo-)0 2575 y(cations)h(as)g(explained)i(in.)k(See)16
+b(Section)g(3.3.1)e([Map)g(Defaults],)g(page)31 b(SMM:13-12,)13
+b(for)h(more)h(details.)62 2645 y(The)h Fp(options)h Fo(are)e(an)o(y)g(com)o
+(bination)g(of)g(those)g(listed)i(b)q(elo)o(w.)p eop
+%%Page: 17 19
+17 18 bop 0 -83 a Fo(Chapter)15 b(4:)k Fp(Amd)f Fo(Command)c(Line)j(Options)
+899 b(SMM:13-17)62 158 y(Once)14 b(the)f(command)g(line)h(has)f(b)q(een)h
+(parsed,)f(the)g(automoun)o(t)f(p)q(oin)o(ts)h(are)g(moun)o(ted.)19
+b(The)13 b(moun)o(t)g(p)q(oin)o(ts)0 208 y(are)21 b(created)g(if)g(they)g(do)
+g(not)f(already)h(exist,)i(in)e(whic)o(h)h(case)f(they)g(will)i(b)q(e)e(remo)
+o(v)o(ed)g(when)g Fp(Amd)i Fo(exits.)0 258 y(Finally)l(,)17
+b Fp(Amd)g Fo(disasso)q(ciates)f(itself)g(from)e(its)i(con)o(trolling)g
+(terminal)g(and)f(forks)f(in)o(to)i(the)f(bac)o(kground.)62
+329 y(Note:)k(Ev)o(en)c(if)f Fp(Amd)j Fo(has)d(b)q(een)h(built)h(with)f(`)p
+Fl(-DDEBUG)p Fo(')d(it)j(will)h(still)f(bac)o(kground)g(itself)g(and)f
+(disasso)q(ciate)0 378 y(itself)j(from)e(the)h(con)o(trolling)g(terminal.)23
+b(T)l(o)15 b(use)h(a)g(debugger)g(it)g(is)g(necessary)g(to)f(sp)q(ecify)i(`)p
+Fl(-D)e(nodaemon)p Fo(')f(on)0 428 y(the)h(command)g(line.)0
+648 y Fq(4.1)33 b Fg(-a)14 b Ff(directory)62 739 y Fo(Sp)q(eci\014es)25
+b(the)d(default)h(moun)o(t)f(directory)l(.)41 b(This)23 b(option)g(c)o
+(hanges)f(the)h(v)m(ariable)g Fl(${autodir})e Fo(whic)o(h)0
+789 y(otherwise)15 b(defaults)h(to)f(`)p Fl(/a)p Fo('.)j(F)l(or)d(example,)h
+(some)f(sites)g(prefer)g(`)p Fl(/amd)p Fo('.)120 860 y Fl(amd)23
+b(-a)h(/amd)f(...)0 1080 y Fq(4.2)33 b Fg(-c)14 b Ff(cac)n(he-in)n(terv)m(al)
+62 1171 y Fo(Selects)k(the)e(p)q(erio)q(d,)i(in)f(seconds,)g(for)e(whic)o(h)j
+(a)e(name)g(is)h(cac)o(hed)g(b)o(y)f Fp(Amd)p Fo(.)23 b(If)17
+b(no)f(reference)h(is)g(made)g(to)0 1221 y(the)e(v)o(olume)h(in)g(this)g(p)q
+(erio)q(d,)g Fp(Amd)h Fo(discards)f(the)f(v)o(olume)h(name)f(to)f
+(\014lesystem)i(mapping.)62 1291 y(Once)e(the)f(last)g(reference)h(to)e(a)g
+(\014lesystem)i(has)f(b)q(een)h(remo)o(v)o(ed,)e Fp(Amd)j Fo(attempts)d(to)g
+(unmoun)o(t)h(the)g(\014lesys-)0 1341 y(tem.)35 b(If)21 b(the)f(unmoun)o(t)h
+(fails)g(the)f(in)o(terv)m(al)i(is)f(extended)g(b)o(y)g(a)f(further)g(p)q
+(erio)q(d)i(as)e(sp)q(eci\014ed)i(b)o(y)f(the)f(`)p Fl(-w)p
+Fo(')0 1391 y(command)15 b(line)i(option)e(or)g(b)o(y)g(the)g(`)p
+Fl(utimeout)p Fo(')f(moun)o(t)g(option.)62 1461 y(The)i(default)f
+Fp(cac)o(he-in)o(terv)m(al)k Fo(is)d(300)e(seconds)i(\(\014v)o(e)f(min)o
+(utes\).)0 1691 y Fq(4.3)33 b Fg(-d)14 b Ff(domain)62 1782
+y Fo(Sp)q(eci\014es)i(the)e(host's)e(domain.)20 b(This)14 b(sets)g(the)f(in)o
+(ternal)i(v)m(ariable)g Fl(${domain})d Fo(and)i(a\013ects)e(the)i
+Fl(${hostd})0 1832 y Fo(v)m(ariable.)62 1902 y(If)i(this)h(option)f(is)h(not)
+e(sp)q(eci\014ed)j(and)e(the)g(hostname)g(already)g(con)o(tains)g(the)g(lo)q
+(cal)h(domain)g(then)f(that)f(is)0 1952 y(used,)g(otherwise)h(the)f(default)h
+(v)m(alue)g(of)f Fl(${domain})f Fo(is)i(`)p Fl(unknown.domain)p
+Fo('.)62 2023 y(F)l(or)f(example,)g(if)h(the)f(lo)q(cal)i(domain)e(w)o(as)g
+(`)p Fl(doc.ic.ac.uk)p Fo(',)d Fp(Amd)17 b Fo(could)g(b)q(e)e(started)g(as)g
+(follo)o(ws:)120 2093 y Fl(amd)23 b(-d)h(doc.ic.ac.uk)e(...)0
+2313 y Fq(4.4)33 b Fg(-k)14 b Ff(k)n(ernel-arc)n(hitecture)62
+2404 y Fo(Sp)q(eci\014es)19 b(the)e(k)o(ernel)g(arc)o(hitecture)g(of)f(the)g
+(system.)24 b(This)17 b(is)g(usually)h(the)f(output)f(of)g(`)p
+Fl(arch)e(-k)p Fo(')i(and)h(its)0 2454 y(only)d(e\013ect)f(is)h(to)f(set)g
+(the)h(v)m(ariable)h Fl(${karch})p Fo(.)j(If)c(this)g(option)f(is)h(not)f
+(giv)o(en,)h Fl(${karch})f Fo(has)g(the)h(same)f(v)m(alue)0
+2504 y(as)i Fl(${arch})p Fo(.)62 2575 y(This)h(w)o(ould)g(b)q(e)f(used)h(as)f
+(follo)o(ws:)120 2645 y Fl(amd)23 b(-k)h(`arch)f(-k`)h(...)p
+eop
+%%Page: 18 20
+18 19 bop 15 -83 a Fo(SMM:13-18)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fq(4.5)33 b Fg(-l)14 b Ff(log-option)62
+250 y Fo(Selects)j(the)e(form)f(of)h(logging)h(to)e(b)q(e)i(made.)k(Tw)o(o)14
+b(sp)q(ecial)j Fp(log-options)h Fo(are)c(recognised.)25 320
+y(1.)29 b(If)15 b Fp(log-option)h Fo(is)g(the)f(string)g(`)p
+Fl(syslog)p Fo(',)e Fp(Amd)18 b Fo(will)e(use)g(the)f Fk(syslog)p
+Fo(\(3\))f(mec)o(hanism.)25 384 y(2.)29 b(If)12 b Fp(log-option)h
+Fo(is)g(the)f(string)g(`)p Fl(/dev/stderr)p Fo(',)e Fp(Amd)k
+Fo(will)g(use)f(standard)f(error,)f(whic)o(h)i(is)g(also)f(the)g(default)90
+434 y(target)i(for)h(log)g(messages.)k(T)l(o)c(implemen)o(t)i(this,)e
+Fp(Amd)i Fo(sim)o(ulates)f(the)f(e\013ect)g(of)g(the)g(`)p
+Fl(/dev/fd)p Fo(')e(driv)o(er.)62 525 y(An)o(y)18 b(other)f(string)g(is)h
+(tak)o(en)e(as)h(a)g(\014lename)i(to)d(use)i(for)f(logging.)26
+b(Log)17 b(messages)g(are)g(app)q(ended)i(to)e(the)0 575 y(\014le)f(if)f(it)g
+(already)g(exists,)g(otherwise)g(a)f(new)h(\014le)h(is)g(created.)j(The)c
+(\014le)h(is)f(op)q(ened)h(once)g(and)e(then)i(held)g(op)q(en,)0
+625 y(rather)f(than)g(b)q(eing)h(re-op)q(ened)h(for)d(eac)o(h)h(message.)62
+695 y(If)j(the)f(`)p Fl(syslog)p Fo(')e(option)j(is)f(sp)q(eci\014ed)j(but)d
+(the)g(system)g(do)q(es)g(not)g(supp)q(ort)g(syslog)g(or)g(if)g(the)h(named)f
+(\014le)0 745 y(cannot)e(b)q(e)h(op)q(ened)h(or)e(created,)g
+Fp(Amd)i Fo(will)g(use)f(standard)f(error.)k(Error)c(messages)g(generated)g
+(b)q(efore)h Fp(Amd)0 795 y Fo(has)f(\014nished)i(parsing)e(the)h(command)f
+(line)i(are)e(prin)o(ted)h(on)f(standard)f(error.)62 866 y(Using)i(`)p
+Fl(syslog)p Fo(')e(is)h(usually)i(b)q(est,)e(in)h(whic)o(h)g(case)f
+Fp(Amd)i Fo(w)o(ould)f(b)q(e)g(started)e(as)h(follo)o(ws:)120
+936 y Fl(amd)23 b(-l)h(syslog)f(...)0 1107 y Fq(4.6)33 b Fg(-n)62
+1199 y Fo(Normalises)17 b(the)f(remote)g(hostname)g(b)q(efore)g(using)h(it.)
+24 b(Normalisation)16 b(is)h(done)g(b)o(y)f(replacing)h(the)g(v)m(alue)0
+1248 y(of)e Fl(${rhost})f Fo(with)h(the)h(primary)f(name)g(returned)h(b)o(y)f
+(a)g(hostname)f(lo)q(okup.)62 1319 y(This)i(option)f(should)i(b)q(e)f(used)f
+(if)h(sev)o(eral)f(names)g(are)g(used)h(to)f(refer)g(to)f(a)h(single)i(host)d
+(in)i(a)f(moun)o(t)g(map.)0 1490 y Fq(4.7)33 b Fg(-p)62 1581
+y Fo(Causes)14 b Fp(Amd)r Fo('s)f(pro)q(cess)h(id)g(to)f(b)q(e)h(prin)o(ted)h
+(on)e(standard)g(output.)20 b(This)14 b(can)f(b)q(e)i(redirected)f(to)f(a)h
+(suitable)0 1631 y(\014le)i(for)f(use)g(with)h(kill:)120 1702
+y Fl(amd)23 b(-p)h(>)g(/var/run/amd.pid)d(...)62 1793 y Fo(This)c(option)f
+(only)h(has)f(an)g(a\013ect)f(if)h Fp(Amd)i Fo(is)f(running)g(in)g(daemon)f
+(mo)q(de.)22 b(If)17 b Fp(Amd)h Fo(is)e(started)g(with)g(the)0
+1843 y Fl(-D)f(nodaemon)f Fo(debug)i(\015ag,)e(this)i(option)f(is)h(ignored.)
+0 2014 y Fq(4.8)33 b Fg(-r)62 2105 y Fo(T)l(ells)16 b Fp(Amd)f
+Fo(to)f(restart)e(existing)j(moun)o(ts)e(\(see)h(Section)h(5.14)e
+([Inheritance)i(Filesystem],)f(page)27 b(SMM:13-)0 2155 y(26\).)0
+2334 y Fq(4.9)33 b Fg(-t)14 b Ff(timeout.retransmit)62 2425
+y Fo(Sp)q(eci\014es)i(the)d(RPC)g Fp(timeout)i Fo(and)e Fp(retransmit)h
+Fo(in)o(terv)m(als)g(used)g(b)o(y)f(the)g(k)o(ernel)h(to)f(comm)o(unicate)h
+(to)e Fp(Amd)p Fo(.)0 2475 y(These)k(are)e(used)i(to)f(set)g(the)g(`)p
+Fl(timeo)p Fo(')f(and)h(`)p Fl(retrans)p Fo(')f(moun)o(t)g(options.)62
+2545 y Fp(Amd)21 b Fo(relies)g(on)e(the)g(k)o(ernel)h(RPC)f(retransmit)g(mec)
+o(hanism)h(to)e(trigger)h(moun)o(t)g(retries.)32 b(The)19 b(v)m(alue)h(of)0
+2595 y(this)14 b(parameter)g(c)o(hanges)g(the)g(retry)f(in)o(terv)m(al.)21
+b(T)l(o)q(o)13 b(long)i(an)f(in)o(terv)m(al)h(giv)o(es)f(p)q(o)q(or)g(in)o
+(teractiv)o(e)g(resp)q(onse,)h(to)q(o)0 2645 y(short)g(an)g(in)o(terv)m(al)h
+(causes)f(excessiv)o(e)h(retries.)p eop
+%%Page: 19 21
+19 20 bop 0 -83 a Fo(Chapter)15 b(4:)k Fp(Amd)f Fo(Command)c(Line)j(Options)
+899 b(SMM:13-19)0 158 y Fq(4.10)32 b Fg(-v)62 250 y Fo(Prin)o(t)15
+b(v)o(ersion)h(information)f(on)g(standard)g(error)g(and)g(then)h(exit.)k
+(The)15 b(output)g(is)h(of)f(the)g(form:)120 320 y Fl(amd)23
+b(5.2.1.11)g(of)h(91/03/17)f(18:04:05)f(5.3Alpha11)h(#0:)g(Sun)h(Mar)f(17)h
+(18:07:28)f(GMT)g(1991)120 370 y(Built)g(by)h(pendry@vangogh.Berkeley.)o(EDU)
+d(for)i(a)h(hp300)f(running)g(bsd44)g(\(big-endian\).)120 420
+y(Map)g(support)g(for:)h(root,)f(passwd,)g(union,)g(file,)g(error.)120
+470 y(FS:)g(ufs,)h(nfs,)f(nfsx,)g(host,)g(link,)h(program,)e(union,)h(auto,)h
+(direct,)f(toplvl,)f(error.)120 519 y(Primary)h(network)g(is)g(128.32.130.0.)
+62 611 y Fo(The)12 b(information)f(includes)i(the)f(v)o(ersion)f(n)o(um)o(b)q
+(er,)h(release)g(date)f(and)g(name)g(of)g(the)g(release.)19
+b(The)11 b(arc)o(hitec-)0 661 y(ture)16 b(\(see)f(Section)i(2.2)e([Supp)q
+(orted)h(Mac)o(hine)h(Arc)o(hitectures],)e(page)32 b(SMM:13-7\),)14
+b(op)q(erating)i(system)f(\(see)0 710 y(Section)j(2.1)f([Supp)q(orted)h(Op)q
+(erating)g(Systems],)f(page)35 b(SMM:13-6\))15 b(and)j(b)o(yte)f(ordering)h
+(are)f(also)g(prin)o(ted)0 760 y(as)e(they)g(app)q(ear)g(in)h(the)g
+Fl(${os})p Fo(,)e Fl(${arch})g Fo(and)h Fl(${byte})g Fo(v)m(ariables.)0
+918 y Fq(4.11)32 b Fg(-w)15 b Ff(w)n(ait-timeout)62 1009 y
+Fo(Selects)j(the)e(in)o(terv)m(al)i(in)f(seconds)g(b)q(et)o(w)o(een)g(unmoun)
+o(t)g(attempts)e(after)h(the)h(initial)h(time-to-liv)o(e)g(has)f(ex-)0
+1059 y(pired.)62 1129 y(This)f(defaults)g(to)e(120)h(seconds)g(\(t)o(w)o(o)f
+(min)o(utes\).)0 1293 y Fq(4.12)32 b Fg(-x)15 b Ff(opts)62
+1384 y Fo(Sp)q(eci\014es)k(the)d(t)o(yp)q(e)h(and)f(v)o(erb)q(osit)o(y)h(of)f
+(log)g(messages.)23 b Fp(opts)18 b Fo(is)f(a)f(comma)g(separated)g(list)h
+(selected)h(from)0 1434 y(the)d(follo)o(wing)h(options:)0 1505
+y Fl(fatal)120 b Fo(F)l(atal)15 b(errors)0 1567 y Fl(error)120
+b Fo(Non-fatal)15 b(errors)0 1629 y Fl(user)144 b Fo(Non-fatal)15
+b(user)g(errors)0 1691 y Fl(warn)144 b Fo(Reco)o(v)o(erable)16
+b(errors)0 1753 y Fl(warning)72 b Fo(Alias)16 b(for)f Fl(warn)0
+1815 y(info)144 b Fo(Information)15 b(messages)0 1877 y Fl(map)168
+b Fo(Moun)o(t)14 b(map)h(usage)0 1940 y Fl(stats)120 b Fo(Additional)17
+b(statistics)0 2002 y Fl(all)168 b Fo(All)16 b(of)f(the)h(ab)q(o)o(v)o(e)62
+2093 y(Initially)g(a)d(set)h(of)f(default)h(logging)g(\015ags)f(is)h
+(enabled.)21 b(This)14 b(is)g(as)f(if)h(`)p Fl(-x)g(all,nomap,nostats)p
+Fo(')d(had)j(b)q(een)0 2143 y(selected.)23 b(The)16 b(command)g(line)h(is)g
+(parsed)f(and)g(logging)g(is)g(con)o(trolled)h(b)o(y)e(the)h(\\-x")g(option.)
+22 b(The)16 b(v)o(ery)f(\014rst)0 2193 y(set)h(of)g(logging)h(\015ags)g(is)g
+(sa)o(v)o(ed)f(and)g(can)h(not)f(b)q(e)h(subsequen)o(tly)h(disabled)h(using)e
+Fp(Amq)p Fo(.)24 b(This)17 b(default)g(set)f(of)0 2243 y(options)f(is)h
+(useful)g(for)f(general)h(pro)q(duction)g(use.)62 2313 y(The)h(`)p
+Fl(info)p Fo(')f(messages)g(include)j(details)f(of)e(what)g(is)h(moun)o(ted)g
+(and)g(unmoun)o(ted)g(and)g(when)g(\014lesystems)0 2363 y(ha)o(v)o(e)e(timed)
+h(out.)k(If)c(y)o(ou)f(w)o(an)o(t)f(to)h(ha)o(v)o(e)g(the)h(default)g(set)f
+(of)g(messages)g(without)g(the)h(`)p Fl(info)p Fo(')e(messages)h(then)0
+2413 y(y)o(ou)f(simply)i(need)f(`)p Fl(-x)f(noinfo)p Fo('.)19
+b(The)14 b(messages)g(giv)o(en)h(b)o(y)f(`)p Fl(user)p Fo(')f(relate)i(to)e
+(errors)h(in)h(the)g(moun)o(t)e(maps,)h(so)0 2463 y(these)g(are)f(useful)i
+(when)g(new)f(maps)f(are)h(installed.)21 b(The)14 b(follo)o(wing)h(table)f
+(lists)g(the)g(syslog)g(priorites)g(used)h(for)0 2512 y(eac)o(h)g(of)g(the)g
+(message)g(t)o(yp)q(es.)0 2583 y Fl(fatal)120 b Fo(LOG)p 342
+2583 14 2 v 17 w(CRIT)0 2645 y Fl(error)g Fo(LOG)p 342 2645
+V 17 w(ERR)p eop
+%%Page: 20 22
+20 21 bop 15 -83 a Fo(SMM:13-20)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fl(user)144 b Fo(LOG)p 342 158
+14 2 v 17 w(W)-5 b(ARNING)0 220 y Fl(warning)72 b Fo(LOG)p
+342 220 V 17 w(W)-5 b(ARNING)0 281 y Fl(info)144 b Fo(LOG)p
+342 281 V 17 w(INF)o(O)0 343 y Fl(debug)120 b Fo(LOG)p 342
+343 V 17 w(DEBUG)0 404 y Fl(map)168 b Fo(LOG)p 342 404 V 17
+w(DEBUG)0 466 y Fl(stats)120 b Fo(LOG)p 342 466 V 17 w(INF)o(O)62
+557 y(The)15 b(options)g(can)f(b)q(e)h(pre\014xed)h(b)o(y)e(the)h(string)f(`)
+p Fl(no)p Fo(')g(to)f(indicate)j(that)e(this)h(option)g(should)g(b)q(e)g
+(turned)g(o\013.)0 607 y(F)l(or)g(example,)g(to)g(obtain)g(all)h(but)g(`)p
+Fl(info)p Fo(')e(messages)g(the)h(option)h(`)p Fl(-x)e(all,noinfo)p
+Fo(')g(w)o(ould)h(b)q(e)h(used.)62 678 y(If)f Fp(Amd)i Fo(w)o(as)d(built)j
+(with)e(debugging)h(enabled)g(the)f Fl(debug)f Fo(option)i(is)f
+(automatically)g(enabled)i(regardless)0 728 y(of)e(the)g(command)g(line)i
+(options.)0 889 y Fq(4.13)32 b Fg(-y)15 b Ff(NIS-domain)62
+980 y Fo(Selects)d(an)e(alternate)g(NIS)h(domain.)19 b(This)11
+b(is)f(useful)i(for)e(debugging)h(and)f(cross-domain)h(shared)f(moun)o(ting.)
+0 1030 y(If)15 b(this)h(\015ag)f(is)h(sp)q(eci\014ed,)h Fp(Amd)g
+Fo(immediately)g(attempts)d(to)g(bind)j(to)d(a)h(serv)o(er)g(for)g(this)g
+(domain.)0 1192 y Fq(4.14)32 b Fg(-C)15 b Ff(cluster-name)62
+1283 y Fo(Sp)q(eci\014es)f(the)e(name)g(of)f(the)h(cluster)g(of)g(whic)o(h)g
+(the)g(lo)q(cal)h(mac)o(hine)f(is)h(a)e(mem)o(b)q(er.)19 b(The)12
+b(only)g(e\013ect)g(is)g(to)f(set)0 1333 y(the)k(v)m(ariable)i
+Fl(${cluster})p Fo(.)h(The)e Fp(cluster-name)j Fo(is)c(will)i(usually)g
+(obtained)f(b)o(y)f(running)h(another)f(command)0 1383 y(whic)o(h)k(uses)f(a)
+f(database)g(to)g(map)h(the)g(lo)q(cal)h(hostname)e(in)o(to)h(a)f(cluster)h
+(name.)28 b Fl(${cluster})16 b Fo(can)i(then)g(b)q(e)0 1433
+y(used)f(as)f(a)f(selector)i(to)e(restrict)h(moun)o(ting)h(of)e(replicated)j
+(data.)k(If)16 b(this)h(option)f(is)h(not)f(giv)o(en,)g Fl(${cluster})0
+1482 y Fo(has)f(the)g(same)g(v)m(alue)i(as)d Fl(${domain})p
+Fo(.)19 b(This)d(w)o(ould)f(b)q(e)h(used)g(as)f(follo)o(ws:)120
+1553 y Fl(amd)23 b(-C)h(`clustername`)e(...)0 1708 y Fq(4.15)32
+b Fg(-D)15 b Ff(opts)62 1799 y Fo(Con)o(trols)20 b(the)h(v)o(erb)q(osit)o(y)f
+(and)h(co)o(v)o(erage)f(of)g(the)g(debugging)i(trace;)h Fp(opts)f
+Fo(is)f(a)f(comma)g(separated)g(list)0 1849 y(of)g(debugging)h(options.)36
+b(The)20 b(\\-D")g(option)h(is)g(only)f(a)o(v)m(ailable)j(if)d
+Fp(Amd)j Fo(w)o(as)c(compiled)j(with)f(`)p Fl(-DDEBUG)p Fo('.)0
+1899 y(The)c(memory)g(debugging)h(facilities)h(are)e(only)h(a)o(v)m(ailable)h
+(if)f Fp(Amd)h Fo(w)o(as)d(compiled)j(with)f(`)p Fl(-DDEBUG_MEM)p
+Fo(')c(\(in)0 1948 y(addition)i(to)f(`)p Fl(-DDEBUG)p Fo('\).)62
+2019 y(The)j(most)f(common)g(options)h(to)f(use)h(are)f(`)p
+Fl(-D)d(trace)p Fo(')j(and)h(`)p Fl(-D)c(test)p Fo(')j(\(whic)o(h)h(turns)f
+(on)h(all)g(the)g(useful)0 2069 y(debug)e(options\).)k(See)15
+b(the)h(program)e(source)h(for)g(a)f(more)h(detailed)i(explanation)f(of)f
+(the)g(a)o(v)m(ailable)i(options.)0 2258 y Fm(5)41 b(Filesystem)13
+b(T)n(yp)r(es)62 2375 y Fo(T)l(o)i(moun)o(t)g(a)g(v)o(olume,)g
+Fp(Amd)i Fo(m)o(ust)e(b)q(e)h(told)f(the)g(t)o(yp)q(e)h(of)e(\014lesystem)i
+(to)f(b)q(e)h(used.)k(Eac)o(h)15 b(\014lesystem)h(t)o(yp)q(e)0
+2425 y(t)o(ypically)h(requires)f(additional)g(information)g(suc)o(h)f(as)g
+(the)g(\014leserv)o(er)h(name)f(for)g(NFS.)62 2496 y(F)l(rom)j(the)i(p)q(oin)
+o(t)f(of)g(view)g(of)g Fp(Amd)p Fo(,)g(a)g Fp(\014lesystem)h
+Fo(is)f(an)o(ything)g(that)g(can)g(resolv)o(e)g(an)g(incoming)h(name)0
+2545 y(lo)q(okup.)g(An)12 b(imp)q(ortan)o(t)f(feature)g(is)h(supp)q(ort)g
+(for)f(m)o(ultiple)j(\014lesystem)e(t)o(yp)q(es.)19 b(Some)12
+b(of)f(these)h(\014lesystems)g(are)0 2595 y(implemen)o(ted)k(in)g(the)f(lo)q
+(cal)g(k)o(ernel)h(and)f(some)f(on)g(remote)g(\014leserv)o(ers,)h(whilst)h
+(the)f(others)f(are)g(implemen)o(ted)0 2645 y(in)o(ternally)j(b)o(y)e
+Fp(Amd)p Fo(.)p eop
+%%Page: 21 23
+21 22 bop 0 -83 a Fo(Chapter)15 b(5:)k(Filesystem)d(T)o(yp)q(es)1145
+b(SMM:13-21)62 158 y(The)21 b(t)o(w)o(o)f(common)g(\014lesystem)i(t)o(yp)q
+(es)f(are)f(UFS)h(and)g(NFS.)g(F)l(our)f(other)h(user)g(accessible)h
+(\014lesystems)0 208 y(\(`)p Fl(link)p Fo(',)c(`)p Fl(program)p
+Fo(',)g(`)p Fl(auto)p Fo(')g(and)i(`)p Fl(direct)p Fo('\))d(are)i(also)g
+(implemen)o(ted)i(in)o(ternally)g(b)o(y)e Fp(Amd)i Fo(and)f(these)f(are)0
+258 y(describ)q(ed)d(b)q(elo)o(w.)21 b(There)14 b(are)h(t)o(w)o(o)e
+(additional)j(\014lesystem)f(t)o(yp)q(es)f(in)o(ternal)i(to)e
+Fp(Amd)i Fo(whic)o(h)f(are)g(not)f(directly)0 308 y(accessible)j(to)e(the)g
+(user)h(\(`)p Fl(inherit)p Fo(')d(and)j(`)p Fl(error)p Fo('\).)j(Their)d(use)
+f(is)h(describ)q(ed)i(since)e(they)g(ma)o(y)e(still)j(ha)o(v)o(e)e(an)0
+358 y(e\013ect)g(visible)i(to)e(the)g(user.)0 508 y Fq(5.1)33
+b(Net)n(w)n(ork)15 b(Filesystem)g(\(`)p Fg(type:=nfs)p Fq('\))62
+599 y Fo(The)h Fp(nfs)h Fo(\014lesystem)f(t)o(yp)q(e)f(pro)o(vides)h(access)f
+(to)f(Sun's)i(NFS.)0 670 y(The)f(follo)o(wing)h(options)g(m)o(ust)e(b)q(e)i
+(sp)q(eci\014ed:)0 751 y Fl(rhost)120 b Fo(the)17 b(remote)g(\014leserv)o
+(er.)26 b(This)17 b(m)o(ust)g(b)q(e)h(an)f(en)o(try)f(in)i(the)f(hosts)g
+(database.)25 b(IP)17 b(addresses)g(are)240 801 y(not)i(accepted.)34
+b(The)20 b(default)g(v)m(alue)h(is)f(tak)o(en)g(from)e(the)i(lo)q(cal)h(host)
+e(name)h(\()p Fl(${host})p Fo(\))e(if)i(no)240 851 y(other)15
+b(v)m(alue)h(is)g(sp)q(eci\014ed.)0 911 y Fl(rfs)168 b Fo(the)19
+b(remote)g(\014lesystem.)33 b(If)19 b(no)g(v)m(alue)i(is)f(sp)q(eci\014ed)h
+(for)e(this)g(option,)h(an)f(in)o(ternal)i(default)e(of)240
+961 y Fl(${path})14 b Fo(is)i(used.)62 1052 y(NFS)d(moun)o(ts)g(require)g(a)g
+(t)o(w)o(o)f(stage)g(pro)q(cess.)19 b(First,)13 b(the)g Fp(\014le)h(handle)j
+Fo(of)c(the)g(remote)f(\014le)i(system)f(m)o(ust)f(b)q(e)0
+1102 y(obtained)i(from)f(the)h(serv)o(er.)19 b(Then)14 b(a)f(moun)o(t)g
+(system)g(call)i(m)o(ust)d(b)q(e)j(done)f(on)f(the)h(lo)q(cal)g(system.)19
+b Fp(Amd)d Fo(k)o(eeps)0 1152 y(a)f(cac)o(he)g(of)g(\014le)h(handles)h(for)d
+(remote)h(\014le)h(systems.)k(The)15 b(cac)o(he)g(en)o(tries)h(ha)o(v)o(e)f
+(a)g(lifetime)i(of)d(a)h(few)g(min)o(utes.)62 1223 y(If)g(a)f(required)h
+(\014le)g(handle)h(is)f(not)f(in)h(the)f(cac)o(he,)g Fp(Amd)j
+Fo(sends)d(a)g(request)h(to)e(the)i(remote)e(serv)o(er)h(to)g(obtain)0
+1272 y(it.)19 b Fp(Amd)14 b(do)q(es)d(not)i Fo(w)o(ait)e(for)g(a)g(resp)q
+(onse;)i(it)f(notes)f(that)g(one)h(of)f(the)h(lo)q(cations)g(needs)h
+(retrying,)f(but)f(con)o(tin)o(ues)0 1322 y(with)17 b(an)o(y)f(remaining)h
+(lo)q(cations.)24 b(When)17 b(the)g(\014le)g(handle)h(b)q(ecomes)f(a)o(v)m
+(ailable,)h(and)e(assuming)h(none)g(of)f(the)0 1372 y(other)11
+b(lo)q(cations)h(w)o(as)e(successfully)j(moun)o(ted,)e Fp(Amd)j
+Fo(will)e(retry)f(the)g(moun)o(t.)18 b(This)12 b(mec)o(hanism)g(allo)o(ws)f
+(sev)o(eral)0 1422 y(NFS)17 b(\014lesystems)h(to)e(b)q(e)i(moun)o(ted)f(in)h
+(parallel.)28 b(The)17 b(\014rst)g(one)g(whic)o(h)h(resp)q(onds)g(with)g(a)f
+(v)m(alid)h(\014le)h(handle)0 1472 y(will)e(b)q(e)f(used.)0
+1542 y(An)f(NFS)h(en)o(try)e(migh)o(t)i(b)q(e:)120 1613 y Fl(jsp)47
+b(host!=charm;type:=nfs;rhost:)o(=charm;r)o(fs:=/ho)o(me/char)o(m;sublin)o
+(k:=jsp)62 1704 y Fo(The)16 b(moun)o(t)f(system)g(call)i(and)f(an)o(y)f
+(unmoun)o(t)h(attempts)f(are)g(alw)o(a)o(ys)g(done)h(in)g(a)g(new)g(task)e
+(to)h(a)o(v)o(oid)h(the)0 1754 y(p)q(ossibilt)o(y)h(of)e(blo)q(c)o(king)h
+Fp(Amd)p Fo(.)0 1914 y Fq(5.2)33 b(Net)n(w)n(ork)15 b(Host)f(Filesystem)h
+(\(`)p Fg(type:=host)p Fq('\))62 2006 y Fo(The)d Fp(host)g
+Fo(\014lesystem)g(allo)o(ws)g(access)g(to)f(the)g(en)o(tire)h(exp)q(ort)g
+(tree)f(of)g(an)h(NFS)g(serv)o(er.)18 b(The)12 b(implemen)o(tation)0
+2056 y(is)18 b(la)o(y)o(ered)g(ab)q(o)o(v)o(e)f(the)h(`)p Fl(nfs)p
+Fo(')e(implemen)o(tation)j(so)e(k)o(eep-aliv)o(es)i(w)o(ork)d(in)j(the)e
+(same)h(w)o(a)o(y)l(.)26 b(The)18 b(only)g(option)0 2105 y(whic)o(h)e(needs)g
+(to)f(sp)q(eci\014ed)i(is)f(`)p Fl(rhost)p Fo(')d(whic)o(h)j(is)g(the)f(name)
+h(of)e(the)i(\014leserv)o(er)g(to)e(moun)o(t.)62 2176 y(The)e(`)p
+Fl(host)p Fo(')e(\014lesystem)j(t)o(yp)q(e)e(w)o(orks)g(b)o(y)g(querying)i
+(the)e(moun)o(t)h(daemon)f(on)h(the)f(giv)o(en)h(\014leserv)o(er)h(to)e
+(obtain)0 2226 y(its)i(exp)q(ort)f(list.)19 b Fp(Amd)c Fo(then)d(obtains)h
+(\014lehandles)h(for)e(eac)o(h)h(of)e(the)i(exp)q(orted)f(\014lesystems.)20
+b(An)o(y)12 b(errors)g(at)g(this)0 2276 y(stage)17 b(cause)i(that)e
+(particular)i(\014lesystem)g(to)f(b)q(e)g(ignored.)30 b(Finally)19
+b(eac)o(h)g(\014lesystem)f(is)h(moun)o(ted.)29 b(Again,)0 2325
+y(errors)14 b(are)g(logged)g(but)h(ignored.)20 b(One)15 b(common)f(reason)g
+(for)g(moun)o(ts)g(to)g(fail)h(is)g(that)e(the)i(moun)o(t)f(p)q(oin)o(t)h(do)
+q(es)0 2375 y(not)e(exist.)19 b(Although)13 b Fp(Amd)i Fo(attempts)d(to)g
+(automatically)i(create)e(the)h(moun)o(t)g(p)q(oin)o(t,)g(it)g(ma)o(y)g(b)q
+(e)g(on)g(a)g(remote)0 2425 y(\014lesystem)j(to)e(whic)o(h)i
+Fp(Amd)i Fo(do)q(es)d(not)g(ha)o(v)o(e)g(write)g(p)q(ermission.)62
+2496 y(When)j(an)f(attempt)f(to)h(unmoun)o(t)g(a)g(`)p Fl(host)p
+Fo(')e(\014lesystem)j(moun)o(t)f(fails,)h Fp(Amd)h Fo(remoun)o(ts)e(an)o(y)f
+(\014lesystems)0 2545 y(whic)o(h)21 b(had)e(succesfully)j(b)q(een)f(unmoun)o
+(ted.)34 b(T)l(o)19 b(do)h(this)g Fp(Amd)i Fo(queries)e(the)g(moun)o(t)f
+(daemon)h(again)g(and)0 2595 y(obtains)d(a)g(fresh)g(cop)o(y)g(of)g(the)g
+(exp)q(ort)g(list.)26 b Fp(Amd)19 b Fo(then)f(tries)f(to)g(moun)o(t)f(an)o(y)
+h(exp)q(orted)g(\014lesystems)h(whic)o(h)0 2645 y(are)d(not)g(curren)o(tly)g
+(moun)o(ted.)p eop
+%%Page: 22 24
+22 23 bop 15 -83 a Fo(SMM:13-22)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)62 158 y(Sun's)22 b(automoun)o(ter)e(pro)o(vides)i(a)f
+(sp)q(ecial)i(`)p Fl(-hosts)p Fo(')d(map.)38 b(T)l(o)21 b(ac)o(hiev)o(e)h
+(the)f(same)g(e\013ect)g(with)h Fp(Amd)0 208 y Fo(requires)16
+b(t)o(w)o(o)e(steps.)20 b(First)14 b(a)h(moun)o(t)g(map)g(m)o(ust)g(b)q(e)h
+(created)f(as)g(follo)o(ws:)120 279 y Fl(/defaults)46 b
+(type:=host;fs:=${autodir}/${rh)o(ost}/ro)o(ot;rhos)o(t:=${key)o(})120
+329 y(*)238 b(opts:=rw,nosuid,grpid)0 420 y Fo(and)15 b(then)h(start)e
+Fp(Amd)j Fo(with)f(the)f(follo)o(wing)h(command)120 490 y Fl(amd)23
+b(/n)h(net.map)0 582 y Fo(where)17 b(`)p Fl(net.map)p Fo(')d(is)j(the)g(name)
+f(of)g(map)g(describ)q(ed)i(ab)q(o)o(v)o(e.)23 b(Note)16 b(that)g(the)g(v)m
+(alue)i(of)e Fl(${fs})g Fo(is)g(o)o(v)o(erridden)0 632 y(in)f(the)f(map.)19
+b(This)c(is)f(done)h(to)e(a)o(v)o(oid)h(a)g(clash)h(b)q(et)o(w)o(een)f(the)g
+(moun)o(t)g(tree)f(and)i(an)o(y)e(other)h(\014lesystem)h(already)0
+681 y(moun)o(ted)g(from)g(the)g(same)g(\014leserv)o(er.)62
+752 y(If)g(di\013eren)o(t)f(moun)o(t)g(options)g(are)g(needed)h(for)f
+(di\013eren)o(t)g(hosts)g(then)g(additional)i(en)o(tries)f(can)f(b)q(e)h
+(added)g(to)0 802 y(the)g(map,)g(for)f(example)120 872 y Fl(host2)166
+b(opts:=ro,nosuid,soft)0 964 y Fo(w)o(ould)16 b(soft)e(moun)o(t)h(`)p
+Fl(host2)p Fo(')e(read-only)l(.)0 1130 y Fq(5.3)33 b(Net)n(w)n(ork)15
+b(Filesystem)g(Group)h(\(`)p Fg(type:=nfsx)p Fq('\))62 1221
+y Fo(The)f Fp(nfsx)k Fo(\014lesystem)c(allo)o(ws)g(a)g(group)g(of)f
+(\014lesystems)i(to)e(b)q(e)h(moun)o(ted)g(from)g(a)f(single)i(NFS)f(serv)o
+(er.)20 b(The)0 1271 y(implemen)o(tation)c(is)g(la)o(y)o(ered)g(ab)q(o)o(v)o
+(e)e(the)i(`)p Fl(nfs)p Fo(')e(implemen)o(tation)i(so)f(k)o(eep-aliv)o(es)i
+(w)o(ork)d(in)i(the)f(same)g(w)o(a)o(y)l(.)62 1342 y(The)h(options)f(are)g
+(the)g(same)g(as)g(for)f(the)i(`)p Fl(nfs)p Fo(')e(\014lesystem)i(with)f(one)
+g(di\013erence.)0 1412 y(The)g(follo)o(wing)h(options)g(m)o(ust)e(b)q(e)i(sp)
+q(eci\014ed:)0 1483 y Fl(rhost)120 b Fo(the)17 b(remote)g(\014leserv)o(er.)26
+b(This)17 b(m)o(ust)g(b)q(e)h(an)f(en)o(try)f(in)i(the)f(hosts)g(database.)25
+b(IP)17 b(addresses)g(are)240 1533 y(not)i(accepted.)34 b(The)20
+b(default)g(v)m(alue)h(is)f(tak)o(en)g(from)e(the)i(lo)q(cal)h(host)e(name)h
+(\()p Fl(${host})p Fo(\))e(if)i(no)240 1582 y(other)15 b(v)m(alue)h(is)g(sp)q
+(eci\014ed.)0 1644 y Fl(rfs)168 b Fo(as)15 b(a)f(list)i(of)f(\014lesystems)g
+(to)f(moun)o(t.)20 b(The)15 b(list)h(is)f(in)h(the)f(form)f(of)h(a)f(comma)h
+(separated)f(strings.)0 1736 y(F)l(or)h(example:)120 1806 y
+Fl(pub)143 b(type:=nfsx;rhost:=gould;)o(\\)120 1856 y
+(rfs:=/public,/,graphics,us)o(enet;fs)o(:=${auto)o(dir}/${)o(rhost}/)o(root)
+62 1947 y Fo(The)14 b(\014rst)g(string)f(de\014nes)i(the)f(ro)q(ot)f(of)g
+(the)h(tree,)g(and)g(is)g(applied)i(as)d(a)h(pre\014x)g(to)f(the)h(remaining)
+h(mem)o(b)q(ers)0 1997 y(of)e(the)h(list)h(whic)o(h)g(de\014ne)g(the)e
+(individual)k(\014lesystems.)j(The)15 b(\014rst)e(string)h(is)g
+Fp(not)g Fo(used)h(as)e(a)h(\014lesystem)g(name.)0 2047 y(A)h(parallel)h(op)q
+(eration)f(is)h(used)f(to)g(determine)h(the)e(lo)q(cal)i(moun)o(t)f(p)q(oin)o
+(ts)g(to)f(ensure)i(a)e(consisten)o(t)i(la)o(y)o(out)e(of)g(a)0
+2097 y(tree)h(of)g(moun)o(ts.)62 2167 y(Here,)20 b(the)e Fp(three)k
+Fo(\014lesystems,)d(`)p Fl(/public)p Fo(',)f(`)p Fl(/public/graphics)p
+Fo(')d(and)k(`)p Fl(/public/usenet)p Fo(',)d(w)o(ould)j(b)q(e)0
+2217 y(moun)o(ted.)62 2288 y(A)g(lo)q(cal)g(moun)o(t)f(p)q(oin)o(t,)h
+Fl(${fs})p Fo(,)f Fp(m)o(ust)h Fo(b)q(e)g(sp)q(eci\014ed.)32
+b(The)19 b(default)g(lo)q(cal)g(moun)o(t)f(p)q(oin)o(t)h(will)h(not)e(w)o
+(ork)0 2338 y(correctly)d(in)h(the)g(general)f(case.)20 b(A)c(suggestion)f
+(is)g(to)g(use)h(`)p Fl(fs:=${autodir}/${rho)o(st}/roo)o(t)p
+Fo('.)0 2504 y Fq(5.4)33 b(Unix)16 b(Filesystem)g(\(`)p Fg(type:=ufs)p
+Fq('\))62 2595 y Fo(The)22 b Fp(ufs)i Fo(\014lesystem)e(t)o(yp)q(e)g(pro)o
+(vides)g(access)g(to)f(the)h(system's)e(standard)i(disk)g
+(\014lesystem|usually)i(a)0 2645 y(deriv)m(ativ)o(e)16 b(of)f(the)h(Berk)o
+(eley)g(F)l(ast)e(Filesystem.)p eop
+%%Page: 23 25
+23 24 bop 0 -83 a Fo(Chapter)15 b(5:)k(Filesystem)d(T)o(yp)q(es)1145
+b(SMM:13-23)0 158 y(The)15 b(follo)o(wing)h(option)g(m)o(ust)e(b)q(e)i(sp)q
+(eci\014ed:)0 246 y Fl(dev)168 b Fo(the)15 b(blo)q(c)o(k)h(sp)q(ecial)h
+(device)g(to)d(b)q(e)i(moun)o(ted.)62 338 y(A)g(UFS)f(en)o(try)f(migh)o(t)i
+(b)q(e:)120 408 y Fl(jsp)71 b(host==charm;type:=ufs;dev:=)o(/dev/xd0)o
+(g;subli)o(nk:=jsp)0 617 y Fq(5.5)33 b(Program)15 b(Filesystem)g(\(`)p
+Fg(type:=program)p Fq('\))62 709 y Fo(The)21 b Fp(program)f
+Fo(\014lesystem)i(t)o(yp)q(e)f(allo)o(ws)g(a)f(program)g(to)g(b)q(e)i(run)f
+(whenev)o(er)g(a)g(moun)o(t)f(or)h(unmoun)o(t)f(is)0 758 y(required.)43
+b(This)24 b(allo)o(ws)f(easy)f(addition)i(of)e(supp)q(ort)h(for)f(other)g
+(\014lesystem)i(t)o(yp)q(es,)g(suc)o(h)f(as)f(MIT's)g(Re-)0
+808 y(mote)16 b(Virtual)h(Disk)g(\(R)-5 b(VD\))16 b(whic)o(h)h(has)g(a)f
+(programmatic)g(in)o(terface)g(via)h(the)g(commands)f(`)p Fl(rvdmount)p
+Fo(')f(and)0 858 y(`)p Fl(rvdunmount)p Fo('.)0 929 y(The)g(follo)o(wing)h
+(options)g(m)o(ust)e(b)q(e)i(sp)q(eci\014ed:)0 1017 y Fl(mount)120
+b Fo(the)15 b(program)f(whic)o(h)i(will)h(p)q(erform)e(the)h(moun)o(t.)0
+1084 y Fl(unmount)72 b Fo(the)15 b(program)f(whic)o(h)i(will)h(p)q(erform)e
+(the)h(unmoun)o(t.)62 1175 y(The)f(exit)h(co)q(de)f(from)f(these)h(t)o(w)o(o)
+f(programs)f(is)i(in)o(terpreted)h(as)e(a)h(Unix)h(error)e(co)q(de.)20
+b(As)15 b(usual,)g(exit)g(co)q(de)0 1225 y(zero)i(indicates)h(success.)26
+b(T)l(o)17 b(execute)g(the)g(program)f Fp(Amd)j Fo(splits)f(the)f(string)g
+(on)g(whitespace)h(to)e(create)h(an)0 1275 y(arra)o(y)h(of)h(substrings.)33
+b(Single)21 b(quotes)e(`)p Fl(')p Fo(')g(can)g(b)q(e)h(used)g(to)f(quote)g
+(whitespace)i(if)f(that)e(is)i(required)h(in)f(an)0 1325 y(argumen)o(t.)f
+(There)d(is)f(no)g(w)o(a)o(y)g(to)f(escap)q(e)i(or)f(c)o(hange)g(the)g(quote)
+g(c)o(haracter.)62 1395 y(T)l(o)d(run)g(the)f(program)g(`)p
+Fl(rvdmount)p Fo(')f(with)i(a)f(host)g(name)h(and)g(\014lesystem)g(as)g
+(argumen)o(ts)e(w)o(ould)i(b)q(e)h(sp)q(eci\014ed)0 1445 y(b)o(y)i(`)p
+Fl(mount:="/etc/rvdmount)d(rvdmount)i(fserver)g(${path}")p
+Fo('.)62 1516 y(The)j(\014rst)f(elemen)o(t)h(in)g(the)f(arra)o(y)f(is)i(tak)o
+(en)f(as)g(the)g(pathname)h(of)f(the)g(program)f(to)h(execute.)24
+b(The)16 b(other)0 1566 y(mem)o(b)q(ers)g(of)f(the)h(arra)o(y)e(form)h(the)h
+(argumen)o(t)f(v)o(ector)g(to)g(b)q(e)h(passed)g(to)f(the)h(program,)e
+Fp(including)19 b(argumen)o(t)0 1615 y(zero)p Fo(.)27 b(This)18
+b(means)f(that)g(the)h(split)g(string)g(m)o(ust)e(ha)o(v)o(e)i(at)e(least)i
+(t)o(w)o(o)e(elemen)o(ts.)28 b(The)17 b(program)g(is)h(directly)0
+1665 y(executed)23 b(b)o(y)f Fp(Amd)p Fo(,)h(not)f(via)g(a)f(shell.)42
+b(This)22 b(means)g(that)g(scripts)g(m)o(ust)f(b)q(egin)i(with)g(a)e
+Fl(#!)h Fo(in)o(terpreter)0 1715 y(sp)q(eci\014cation.)62 1786
+y(If)c(a)g(\014lesystem)g(t)o(yp)q(e)g(is)g(to)f(b)q(e)i(hea)o(vily)g(used,)f
+(it)g(ma)o(y)f(b)q(e)i(w)o(orth)o(while)f(adding)g(a)g(new)f(\014lesystem)i
+(t)o(yp)q(e)0 1835 y(in)o(to)c Fp(Amd)p Fo(,)g(but)h(for)e(most)g(uses)i(the)
+f(program)f(\014lesystem)i(should)g(su\016ce.)62 1906 y(When)k(the)f(program)
+f(is)i(run,)g(standard)e(input)i(and)g(standard)e(error)h(are)g(inherited)i
+(from)d(the)h(curren)o(t)0 1956 y(v)m(alues)f(used)g(b)o(y)f
+Fp(Amd)p Fo(.)26 b(Standard)17 b(output)g(is)h(a)f(duplicate)i(of)e(standard)
+f(error.)25 b(The)18 b(v)m(alue)g(sp)q(eci\014ed)i(with)0 2006
+y(the)15 b(\\-l")h(command)f(line)i(option)e(has)g(no)g(e\013ect)g(on)g
+(standard)g(error.)0 2213 y Fq(5.6)33 b(Sym)n(b)r(olic)17 b(Link)g
+(Filesystem)f(\(`)p Fg(type:=link)p Fq('\))62 2305 y Fo(Eac)o(h)k
+(\014lesystem)g(t)o(yp)q(e)f(creates)h(a)f(sym)o(b)q(olic)h(link)h(to)e(p)q
+(oin)o(t)h(from)f(the)h(v)o(olume)g(name)f(to)g(the)h(ph)o(ysical)0
+2355 y(moun)o(t)15 b(p)q(oin)o(t.)22 b(The)16 b(`)p Fl(link)p
+Fo(')e(\014lesystem)i(do)q(es)g(the)g(same)f(without)h(an)o(y)f(other)g(side)
+i(e\013ects.)j(This)d(allo)o(ws)e(an)o(y)0 2404 y(part)g(of)f(the)i(mac)o
+(hines)g(name)f(space)g(to)g(b)q(e)h(accessed)g(via)f Fp(Amd)p
+Fo(.)62 2475 y(One)h(common)f(use)g(for)f(the)h(symlink)i(\014lesystem)e(is)h
+(`)p Fl(/homes)p Fo(')d(whic)o(h)j(can)f(b)q(e)h(made)f(to)f(con)o(tain)h(an)
+g(en)o(try)0 2525 y(for)e(eac)o(h)g(user)g(whic)o(h)i(p)q(oin)o(ts)e(to)g
+(their)h(\(auto-moun)o(ted\))e(home)h(directory)l(.)20 b(Although)14
+b(this)f(ma)o(y)g(seem)h(rather)0 2575 y(exp)q(ensiv)o(e,)i(it)g(pro)o(vides)
+g(a)e(great)h(deal)h(of)e(administrativ)o(e)i(\015exibili)q(t)o(y)l(.)0
+2645 y(The)f(follo)o(wing)h(option)g(m)o(ust)e(b)q(e)i(de\014ned:)p
+eop
+%%Page: 24 26
+24 25 bop 15 -83 a Fo(SMM:13-24)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fl(fs)192 b Fo(The)16 b(v)m(alue)h(of)f
+Fp(fs)h Fo(option)f(sp)q(eci\014es)i(the)e(destination)g(of)g(the)g(link,)h
+(as)e(mo)q(di\014ed)i(b)o(y)f(the)g Fp(sublink)240 208 y Fo(option.)k(If)14
+b Fp(sublink)k Fo(is)c(non-n)o(ull,)i(it)e(is)g(app)q(ended)i(to)d
+Fl(${fs}/)g Fo(and)h(the)f(resulting)i(string)f(is)g(used)240
+258 y(as)h(the)g(target.)62 349 y(The)g(`)p Fl(link)p Fo(')f(\014lesystem)h
+(can)g(b)q(e)h(though)f(of)f(as)g(iden)o(tical)j(to)d(the)h(`)p
+Fl(ufs)p Fo(')f(\014lesystem)h(but)g(without)g(actually)0 399
+y(moun)o(ting)g(an)o(ything.)62 470 y(An)h(example)g(en)o(try)f(migh)o(t)g(b)
+q(e:)120 540 y Fl(jsp)71 b(host==charm;type:=link;fs:=)o(/home/ch)o(arm;sub)o
+(link:=j)o(sp)62 632 y Fo(whic)o(h)16 b(w)o(ould)g(return)f(a)g(sym)o(b)q
+(olic)h(link)h(p)q(oin)o(ting)f(to)f(`)p Fl(/home/charm/jsp)p
+Fo('.)0 792 y Fq(5.7)33 b(Sym)n(b)r(olic)17 b(Link)g(Filesystem)f(I)r(I)f
+(\(`)p Fg(type:=link)p Fq('\))62 884 y Fo(The)h(`)p Fl(linkx)p
+Fo(')e(\014lesystem)i(t)o(yp)q(e)f(is)h(iden)o(tical)h(to)e(`)p
+Fl(link)p Fo(')f(with)i(the)f(exception)i(that)d(the)i(target)e(of)h(the)h
+(link)0 933 y(m)o(ust)f(exist.)20 b(Existence)c(is)g(c)o(hec)o(k)o(ed)f(with)
+h(the)f(`)p Fl(lstat)p Fo(')f(system)h(call.)62 1004 y(The)f(`)p
+Fl(linkx)p Fo(')e(\014lesystem)j(t)o(yp)q(e)f(is)g(particularly)h(useful)g
+(for)e(wildcard)i(map)e(en)o(tries.)20 b(In)15 b(this)f(case,)f(a)h(list)g
+(of)0 1054 y(p)q(ossible)j(targets)d(can)h(b)q(e)h(giv)o(e)f(and)h
+Fp(Amd)h Fo(will)g(c)o(ho)q(ose)e(the)g(\014rst)g(one)h(whic)o(h)g(exists)f
+(on)g(the)g(lo)q(cal)i(mac)o(hine.)0 1213 y Fq(5.8)33 b(Automoun)n(t)15
+b(Filesystem)h(\(`)p Fg(type:=auto)p Fq('\))62 1305 y Fo(The)j
+Fp(auto)g Fo(\014lesystem)g(t)o(yp)q(e)f(creates)g(a)g(new)g(automoun)o(t)f
+(p)q(oin)o(t)h(b)q(elo)o(w)h(an)f(existing)h(automoun)o(t)e(p)q(oin)o(t.)0
+1354 y(T)l(op-lev)o(el)g(automoun)o(t)e(p)q(oin)o(ts)h(app)q(ear)f(as)h
+(system)f(moun)o(t)g(p)q(oin)o(ts.)22 b(An)16 b(automoun)o(t)e(moun)o(t)h(p)q
+(oin)o(t)h(can)g(also)0 1404 y(app)q(ear)h(as)g(a)g(sub-directory)h(of)f(an)g
+(existing)i(automoun)o(t)d(p)q(oin)o(t.)26 b(This)18 b(allo)o(ws)g(some)e
+(additional)j(structure)0 1454 y(to)c(b)q(e)g(added,)h(for)e(example)i(to)f
+(mimic)h(the)g(moun)o(t)e(tree)h(of)g(another)g(mac)o(hine.)62
+1525 y(The)h(follo)o(wing)g(options)f(ma)o(y)f(b)q(e)i(sp)q(eci\014ed:)0
+1605 y Fl(cache)120 b Fo(sp)q(eci\014es)19 b(whether)e(the)g(data)f(in)i
+(this)g(moun)o(t-map)e(should)i(b)q(e)g(cac)o(hed.)25 b(The)18
+b(default)f(v)m(alue)h(is)240 1655 y(`)p Fl(none)p Fo(',)13
+b(in)i(whic)o(h)g(case)f(no)g(cac)o(hing)h(is)g(done)f(in)h(order)f(to)g
+(conserv)o(e)g(memory)l(.)19 b(Ho)o(w)o(ev)o(er,)13 b(b)q(etter)240
+1705 y(p)q(erformance)i(and)h(reliabilit)o(y)h(can)f(b)q(e)g(obtained)f(b)o
+(y)h(cac)o(hing)f(some)g(or)g(all)h(of)f(a)g(moun)o(t-map.)240
+1765 y(If)f(the)g(cac)o(he)g(option)g(sp)q(eci\014es)h(`)p
+Fl(all)p Fo(',)e(the)g(en)o(tire)i(map)e(is)h(en)o(umerated)g(when)g(the)g
+(moun)o(t)f(p)q(oin)o(t)240 1815 y(is)j(created.)240 1875 y(If)h(the)g(cac)o
+(he)g(option)h(sp)q(eci\014es)g(`)p Fl(inc)p Fo(',)e(cac)o(hing)i(is)f(done)g
+(incremen)o(tally)i(as)e(and)g(when)g(data)f(is)240 1925 y(required.)k(Some)
+13 b(map)f(t)o(yp)q(es)h(do)g(not)f(supp)q(ort)h(cac)o(he)g(mo)q(de)f(`)p
+Fl(all)p Fo(',)g(in)i(whic)o(h)f(case)g(`)p Fl(inc)p Fo(')e(is)i(used)240
+1975 y(whenev)o(er)j(`)p Fl(all)p Fo(')e(is)h(requested.)240
+2035 y(Cac)o(hing)h(can)f(b)q(e)h(en)o(tirely)g(disabled)h(b)o(y)e(using)h
+(cac)o(he)g(mo)q(de)f(`)p Fl(none)p Fo('.)240 2095 y(If)f(the)g(cac)o(he)h
+(option)f(sp)q(eci\014es)h(`)p Fl(regexp)p Fo(')e(then)h(the)g(en)o(tire)h
+(map)e(will)j(b)q(e)f(en)o(umerated)f(and)g(eac)o(h)240 2145
+y(k)o(ey)i(will)i(b)q(e)g(treated)d(as)i(an)f(egrep-st)o(yle)h(regular)f
+(expression.)25 b(The)17 b(order)f(in)h(whic)o(h)g(a)f(cac)o(hed)240
+2195 y(map)f(is)i(searc)o(hed)f(do)q(es)f(not)h(corresp)q(ond)g(to)f(the)g
+(ordering)h(in)h(the)f(source)f(map)h(so)f(the)h(regular)240
+2245 y(expressions)g(should)g(b)q(e)g(m)o(utually)g(exclusiv)o(e)h(to)d(a)o
+(v)o(oid)h(confusion.)240 2305 y(Eac)o(h)i(moun)o(t)g(map)g(t)o(yp)q(e)h(has)
+f(a)g(default)h(cac)o(he)g(t)o(yp)q(e,)g(usually)g(`)p Fl(inc)p
+Fo(',)f(whic)o(h)h(can)g(b)q(e)g(selected)240 2355 y(b)o(y)d(sp)q(ecifying)i
+(`)p Fl(mapdefault)p Fo('.)240 2415 y(The)e(cac)o(he)g(mo)q(de)g(for)f(a)g
+(moun)o(t)g(map)h(can)g(only)g(b)q(e)g(selected)h(on)f(the)f(command)h(line.)
+21 b(Starting)240 2465 y Fp(Amd)c Fo(with)f(the)f(command:)360
+2525 y Fl(amd)23 b(/homes)g(hesiod.homes)g(-cache:=inc)240
+2595 y Fo(will)17 b(cause)f(`)p Fl(/homes)p Fo(')d(to)i(b)q(e)h(automoun)o
+(ted)f(using)h(the)f Fp(Hesio)q(d)j Fo(name)e(serv)o(er)f(with)g(lo)q(cal)i
+(incre-)240 2645 y(men)o(tal)e(cac)o(hing)h(of)f(all)h(succesfully)h(resolv)o
+(ed)f(names.)p eop
+%%Page: 25 27
+25 26 bop 0 -83 a Fo(Chapter)15 b(5:)k(Filesystem)d(T)o(yp)q(es)1145
+b(SMM:13-25)240 158 y(All)21 b(cac)o(hed)f(data)g(is)g(forgotten)e(whenev)o
+(er)j Fp(Amd)h Fo(receiv)o(es)e(a)g(`)p Fl(SIGHUP)p Fo(')e(signal)j(and,)f
+(if)h(cac)o(he)240 208 y(`)p Fl(all)p Fo(')14 b(mo)q(de)i(w)o(as)f(selected,)
+i(the)e(cac)o(he)h(will)i(b)q(e)e(reloaded.)22 b(This)16 b(can)g(b)q(e)g
+(used)g(to)f(inform)h Fp(Amd)240 258 y Fo(that)i(a)g(map)g(has)g(b)q(een)h
+(up)q(dated.)30 b(In)19 b(addition,)h(whenev)o(er)f(a)f(cac)o(he)g(lo)q(okup)
+h(fails)g(and)g Fp(Amd)240 308 y Fo(needs)g(to)f(examine)h(a)f(map,)h(the)f
+(map's)g(mo)q(dify)h(time)g(is)g(examined.)31 b(If)18 b(the)h(cac)o(he)f(is)h
+(out)f(of)240 358 y(date)d(with)h(resp)q(ect)f(to)g(the)g(map)g(then)h(it)f
+(is)h(\015ushed)g(as)f(if)h(a)e(`)p Fl(SIGHUP)p Fo(')g(had)h(b)q(een)i
+(receiv)o(ed.)240 422 y(An)c(additional)g(option)g(\(`)p Fl(sync)p
+Fo('\))d(ma)o(y)i(b)q(e)h(sp)q(eci\014ed)h(to)e(force)g Fp(Amd)i
+Fo(to)e(c)o(hec)o(k)g(the)h(map's)e(mo)q(dify)240 472 y(time)h(whenev)o(er)h
+(a)f(cac)o(hed)g(en)o(try)g(is)g(b)q(eing)i(used.)19 b(F)l(or)11
+b(example,)i(an)f(incremen)o(tal,)i(sync)o(hronised)240 522
+y(cac)o(he)h(w)o(ould)h(b)q(e)g(created)f(b)o(y)g(the)h(follo)o(wing)f
+(command:)360 587 y Fl(amd)23 b(/homes)g(hesiod.homes)g(-cache:=inc,sync)0
+652 y(fs)192 b Fo(sp)q(eci\014es)17 b(the)e(name)h(of)e(the)i(moun)o(t)e(map)
+h(to)g(use)g(for)g(the)g(new)h(moun)o(t)e(p)q(oin)o(t.)240
+716 y(Arguably)g(this)g(should)g(ha)o(v)o(e)f(b)q(een)i(sp)q(eci\014ed)h
+(with)d(the)h Fl(${rfs})f Fo(option)g(but)h(w)o(e)f(are)g(no)o(w)g(stuc)o(k)
+240 766 y(with)j(it)f(due)h(to)e(historical)j(acciden)o(t.)0
+831 y Fl(pref)144 b Fo(alters)13 b(the)h(name)f(that)g(is)h(lo)q(ok)o(ed)g
+(up)g(in)g(the)g(moun)o(t)f(map.)19 b(If)13 b Fl(${pref})p
+Fo(,)g(the)g Fp(pre\014x)p Fo(,)h(is)g(non-n)o(ull)240 881
+y(then)i(it)f(is)h(prep)q(ended)h(to)d(the)i(name)f(requested)g(b)o(y)h(the)f
+(k)o(ernel)h Fp(b)q(efore)i Fo(the)d(map)g(is)h(searc)o(hed.)62
+972 y(The)22 b(serv)o(er)e(`)p Fl(dylan.doc.ic.ac.uk)p Fo(')e(has)j(t)o(w)o
+(o)f(user)h(disks:)33 b(`)p Fl(/dev/dsk/2s0)p Fo(')18 b(and)k(`)p
+Fl(/dev/dsk/5s0)p Fo('.)0 1022 y(These)e(are)f(accessed)h(as)f(`)p
+Fl(/home/dylan/dk2)p Fo(')e(and)i(`)p Fl(/home/dylan/dk5)p
+Fo(')e(resp)q(ectiv)o(ely)l(.)35 b(Since)20 b(`)p Fl(/home)p
+Fo(')e(is)0 1072 y(already)d(an)h(automoun)o(t)e(p)q(oin)o(t,)h(this)h
+(naming)f(is)h(ac)o(hiev)o(ed)g(with)g(the)f(follo)o(wing)h(map)f(en)o
+(tries:)120 1142 y Fl(dylan)190 b(type:=auto;fs:=${map};pref:=)o(${key}/)120
+1192 y(dylan/dk2)94 b(type:=ufs;dev:=/dev/dsk/2s0)120 1242
+y(dylan/dk5)g(type:=ufs;dev:=/dev/dsk/5s0)0 1432 y Fq(5.9)33
+b(Direct)15 b(Automoun)n(t)h(Filesystem)g(\(`)p Fg(type:=direct)p
+Fq(')o(\))62 1523 y Fo(The)h Fp(direct)i Fo(\014lesystem)e(is)h(almost)e
+(iden)o(tical)j(to)d(the)h(automoun)o(t)f(\014lesystem.)25
+b(Instead)18 b(of)e(app)q(earing)i(to)0 1573 y(b)q(e)e(a)f(directory)g(of)g
+(moun)o(t)f(p)q(oin)o(ts,)h(it)h(app)q(ears)f(as)g(a)f(sym)o(b)q(olic)j(link)
+f(to)f(a)g(moun)o(ted)g(\014lesystem.)20 b(The)15 b(moun)o(t)0
+1622 y(is)f(done)h(at)e(the)h(time)g(the)g(link)h(is)f(accessed.)20
+b(See)15 b(Section)g(5.8)d([Automoun)o(t)h(Filesystem],)h(page)28
+b(SMM:13-24)0 1672 y(for)15 b(a)f(list)i(of)f(required)i(options.)62
+1743 y(Direct)c(automoun)o(t)e(p)q(oin)o(ts)i(are)g(created)f(b)o(y)h(sp)q
+(ecifying)h(the)f(`)p Fl(direct)p Fo(')e(\014lesystem)i(t)o(yp)q(e)g(on)f
+(the)h(command)0 1793 y(line:)120 1863 y Fl(amd)23 b(...)h(/usr/man)f
+(auto.direct)f(-type:=direct)62 1955 y Fo(where)16 b(`)p Fl(auto.direct)p
+Fo(')d(w)o(ould)i(con)o(tain)h(an)f(en)o(try)f(suc)o(h)i(as:)120
+2025 y Fl(usr/man)94 b(-type:=nfs;rfs:=/usr/man)21 b(\\)382
+2075 y(rhost:=man-server1)46 b(rhost:=man-server2)62 2166 y
+Fo(In)19 b(this)f(example,)h(`)p Fl(man-server1)p Fo(')d(and)i(`)p
+Fl(man-server2)p Fo(')d(are)j(\014le)h(serv)o(ers)e(whic)o(h)i(exp)q(ort)f
+(copies)g(of)g(the)0 2216 y(man)o(ual)e(pages.)22 b(Note)16
+b(that)f(the)i(k)o(ey)f(whic)o(h)g(is)h(lo)q(ok)o(ed)f(up)h(is)g(the)f(name)g
+(of)f(the)i(automoun)o(t)d(p)q(oin)o(t)j(without)0 2266 y(the)e(leading)i(`)p
+Fl(/)p Fo('.)0 2454 y Fq(5.10)32 b(Union)16 b(Filesystem)g(\(`)p
+Fg(type:=union)p Fq('\))62 2545 y Fo(The)21 b Fp(union)g Fo(\014lesystem)g(t)
+o(yp)q(e)f(allo)o(ws)h(the)f(con)o(ten)o(ts)g(of)g(sev)o(eral)g(directories)i
+(to)d(b)q(e)i(merged)f(and)h(made)0 2595 y(visible)16 b(in)f(a)f(single)h
+(directory)l(.)20 b(This)14 b(can)g(b)q(e)h(used)g(to)e(o)o(v)o(ercome)g(one)
+h(of)g(the)g(ma)s(jor)e(limitations)j(of)f(the)g(Unix)0 2645
+y(moun)o(t)h(mec)o(hanism)h(whic)o(h)g(only)f(allo)o(ws)h(complete)g
+(directories)g(to)e(b)q(e)i(moun)o(ted.)p eop
+%%Page: 26 28
+26 27 bop 15 -83 a Fo(SMM:13-26)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)62 158 y(F)l(or)g(example,)i(supp)q(osing)g(`)p
+Fl(/tmp)p Fo(')e(and)h(`)p Fl(/var/tmp)p Fo(')d(w)o(ere)j(to)f(b)q(e)h
+(merged)g(in)o(to)g(a)f(new)h(directory)g(called)0 208 y(`)p
+Fl(/mtmp)p Fo(',)j(with)g(\014les)h(in)g(`)p Fl(/var/tmp)p
+Fo(')e(taking)h(precedence.)39 b(The)22 b(follo)o(wing)g(command)f(could)h(b)
+q(e)g(used)g(to)0 258 y(ac)o(hiev)o(e)16 b(this)f(e\013ect:)120
+329 y Fl(amd)23 b(...)h(/mtmp)f(union:/tmp:/var/tmp)e(-type:=union)62
+420 y Fo(Curren)o(tly)l(,)12 b(the)f(unioned)h(directories)g(m)o(ust)f
+Fp(not)g Fo(b)q(e)h(automoun)o(ted.)18 b(That)10 b(w)o(ould)h(cause)g(a)g
+(deadlo)q(c)o(k.)19 b(This)0 470 y(seriously)d(limits)h(the)e(curren)o(t)g
+(usefulness)i(of)e(this)h(\014lesystem)f(t)o(yp)q(e)h(and)f(the)h(problem)g
+(will)g(b)q(e)g(addressed)g(in)0 519 y(a)f(future)g(release)h(of)f
+Fp(Amd)p Fo(.)62 590 y(Files)20 b(created)e(in)i(the)e(union)i(directory)e
+(are)h(actually)g(created)f(in)i(the)e(last)g(named)h(directory)l(.)30
+b(This)19 b(is)0 640 y(done)h(b)o(y)g(creating)f(a)h(wildcard)h(en)o(try)e
+(whic)o(h)i(p)q(oin)o(ts)f(to)f(the)g(correct)h(directory)l(.)33
+b(The)20 b(wildcard)h(en)o(try)e(is)0 690 y(visible)e(if)f(the)f(union)i
+(directory)e(is)h(listed,)g(so)f(allo)o(wing)h(y)o(ou)f(to)f(see)i(whic)o(h)g
+(directory)f(has)g(priorit)o(y)l(.)62 760 y(The)j(\014les)g(visible)h(in)f
+(the)f(union)h(directory)f(are)g(computed)g(at)g(the)g(time)g
+Fp(Amd)i Fo(is)f(started,)e(and)i(are)e(not)0 810 y(k)o(ept)c(upto)q(date)g
+(with)g(resp)q(ect)h(to)e(the)h(underlying)i(directories.)20
+b(Similarly)l(,)15 b(if)d(a)g(link)h(is)g(remo)o(v)o(ed,)f(for)f(example)0
+860 y(with)16 b(the)f(`)p Fl(rm)p Fo(')f(command,)h(it)g(will)i(b)q(e)f(lost)
+f(forev)o(er.)0 1019 y Fq(5.11)32 b(Error)16 b(Filesystem)g(\(`)p
+Fg(type:=error)p Fq('\))62 1111 y Fo(The)i Fp(error)i Fo(\014lesystem)e(t)o
+(yp)q(e)f(is)h(used)g(in)o(ternally)h(as)e(a)g(catc)o(h-all)h(in)g(the)f
+(case)h(where)f(none)h(of)f(the)g(other)0 1160 y(\014lesystems)g(w)o(as)e
+(selected,)i(or)e(some)h(other)g(error)f(o)q(ccurred.)23 b(Lo)q(okups)16
+b(and)h(moun)o(ts)e(alw)o(a)o(ys)g(fail)i(with)f(\\No)0 1210
+y(suc)o(h)g(\014le)g(or)e(directory".)20 b(All)d(other)e(op)q(erations)g
+(trivially)i(succeed.)62 1281 y(The)f(error)e(\014lesystem)i(is)g(not)f
+(directly)h(accessible.)0 1440 y Fq(5.12)32 b(T)-6 b(op-lev)n(el)17
+b(Filesystem)f(\(`)p Fg(type:=toplvl)p Fq('\))62 1532 y Fo(The)23
+b Fp(toplvl)i Fo(\014lesystems)d(is)h(deriv)o(ed)g(from)f(the)g(`)p
+Fl(auto)p Fo(')f(\014lesystem)i(and)f(is)h(used)g(to)e(moun)o(t)h(the)g(top-)
+0 1581 y(lev)o(el)17 b(automoun)o(t)d(no)q(des.)21 b(Requests)16
+b(of)f(this)g(t)o(yp)q(e)h(are)f(automatically)h(generated)f(from)g(the)g
+(command)g(line)0 1631 y(argumen)o(ts)f(and)i(can)f(also)g(b)q(e)h(passed)g
+(in)g(b)o(y)f(using)h(the)f(\\-M")f(option)i(of)f(the)g Fp(Amq)h
+Fo(command.)0 1787 y Fq(5.13)32 b(Ro)r(ot)15 b(Filesystem)62
+1879 y Fo(The)j Fp(ro)q(ot)g Fo(\(`)p Fl(type:=root)p Fo('\))e(\014lesystem)i
+(t)o(yp)q(e)g(acts)f(as)h(an)g(in)o(ternal)h(placeholder)g(on)o(to)e(whic)o
+(h)i Fp(Amd)h Fo(can)0 1929 y(pin)c(`)p Fl(toplvl)p Fo(')e(moun)o(ts.)20
+b(Only)d(one)e(no)q(de)h(of)f(this)h(t)o(yp)q(e)g(need)g(ev)o(er)f(exist)h
+(and)g(one)f(is)h(created)g(automatically)0 1978 y(during)g(startup.)j(The)d
+(e\013ect)f(of)f(creating)i(a)f(second)g(ro)q(ot)g(no)q(de)h(is)f
+(unde\014ned.)0 2135 y Fq(5.14)32 b(Inheritance)17 b(Filesystem)62
+2226 y Fo(The)c Fp(inheritance)k Fo(\(`)p Fl(type:=inherit)p
+Fo('\))10 b(\014lesystem)k(is)f(not)f(directly)j(accessible.)20
+b(Instead,)14 b(in)o(ternal)f(moun)o(t)0 2276 y(no)q(des)j(of)f(this)h(t)o
+(yp)q(e)f(are)g(automatically)h(generated)f(when)h Fp(Amd)i
+Fo(is)e(started)e(with)i(the)f(\\-r")g(option.)21 b(A)o(t)15
+b(this)0 2325 y(time)j(the)g(system)f(moun)o(t)g(table)h(is)g(scanned)g(to)f
+(lo)q(cate)h(an)o(y)f(\014lesystems)h(whic)o(h)h(are)e(already)h(moun)o(ted.)
+27 b(If)0 2375 y(an)o(y)17 b(reference)h(to)f(these)h(\014lesystems)g(is)g
+(made)f(through)g Fp(Amd)i Fo(then)f(instead)g(of)f(attempting)g(to)g(moun)o
+(t)g(it,)0 2425 y Fp(Amd)k Fo(sim)o(ulates)e(the)g(moun)o(t)f(and)h
+Fp(inherits)j Fo(the)d(\014lesystem.)31 b(This)19 b(allo)o(ws)g(a)f(new)h(v)o
+(ersion)g(of)g Fp(Amd)h Fo(to)e(b)q(e)0 2475 y(installed)d(on)e(a)g(liv)o(e)i
+(system)e(simply)h(b)o(y)f(killing)j(the)d(old)h(daemon)f(with)h
+Fl(SIGTERM)e Fo(and)i(starting)e(the)i(new)f(one.)62 2545 y(This)18
+b(\014lesystem)g(t)o(yp)q(e)f(is)g(not)g(generally)h(visible)h(externally)l
+(,)g(but)e(it)g(is)h(p)q(ossible)g(that)f(the)g(output)g(from)0
+2595 y(`)p Fl(amq)d(-m)p Fo(')g(ma)o(y)f(list)h(`)p Fl(inherit)p
+Fo(')f(as)g(the)h(\014lesystem)h(t)o(yp)q(e.)k(This)c(happ)q(ens)g(when)f(an)
+g(inherit)h(op)q(eration)f(cannot)0 2645 y(b)q(e)i(completed)g(for)f(some)g
+(reason,)f(usually)i(b)q(ecause)h(a)e(\014leserv)o(er)g(is)h(do)o(wn.)p
+eop
+%%Page: 27 29
+27 28 bop 0 -83 a Fo(Chapter)15 b(6:)k(Run-time)e(Administration)987
+b(SMM:13-27)0 158 y Fm(6)41 b(Run-time)14 b(Administration)0
+379 y Fq(6.1)33 b(Starting)16 b Ff(Amd)62 470 y Fp(Amd)h Fo(is)f(b)q(est)g
+(started)e(from)g(`)p Fl(/etc/rc.local)p Fo(':)120 540 y Fl(if)24
+b([)f(-f)h(/etc/amd.start)e(];)h(then)311 590 y(sh)g(/etc/amd.start;)f
+(\(echo)h(-n)h(')g(amd'\))142 b(>/dev/console)120 640 y(fi)0
+731 y Fo(The)15 b(shell)i(script,)e(`)p Fl(amd.start)p Fo(',)e(con)o(tains:)
+120 802 y Fl(#!/bin/sh)23 b(-)120 852 y(PATH=/etc:/bin:/usr/bin:/u)o(sr/ucb:)
+o($PATH)e(export)i(PATH)120 951 y(#)120 1001 y(#)h(Either)f(name)g(of)h
+(logfile)f(or)g("syslog")120 1051 y(#)120 1101 y(LOGFILE=syslog)120
+1151 y(#LOGFILE=/var/log/amd)120 1250 y(#)120 1300 y(#)h(Figure)f(out)g
+(whether)g(domain)g(name)g(is)h(in)g(host)f(name)120 1350 y(#)h(If)f(the)h
+(hostname)f(is)g(just)g(the)h(machine)f(name)g(then)120 1400
+y(#)h(pass)f(in)h(the)f(name)g(of)h(the)f(local)h(domain)f(so)g(that)h(the)
+120 1450 y(#)g(hostnames)e(in)i(the)f(map)h(are)f(domain)g(stripped)g
+(correctly.)120 1499 y(#)120 1549 y(case)g(`hostname`)g(in)120
+1599 y(*.*\))g(dmn=)h(;;)120 1649 y(*\))g(dmn='-d)e(doc.ic.ac.uk')120
+1699 y(esac)120 1798 y(#)120 1848 y(#)i(Zap)f(earlier)g(log)h(file)120
+1898 y(#)120 1948 y(case)f("$LOGFILE")g(in)120 1998 y(*/*\))311
+2047 y(mv)g("$LOGFILE")g("$LOGFILE"-)311 2097 y(>)h("$LOGFILE")311
+2147 y(;;)120 2197 y(syslog\))311 2247 y(:)g(nothing)311 2296
+y(;;)120 2346 y(esac)120 2446 y(cd)g(/usr/sbin)120 2496 y(#)120
+2545 y(#)g(-r)286 b(restart)120 2595 y(#)24 b(-d)f(dmn)191
+b(local)23 b(domain)120 2645 y(#)h(-w)f(wait)167 b(wait)23
+b(between)g(unmount)g(attempts)p eop
+%%Page: 28 30
+28 29 bop 15 -83 a Fo(SMM:13-28)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)120 158 y Fl(#)24 b(-l)f(log)191 b(logfile)23
+b(or)g("syslog")120 208 y(#)120 258 y(eval)g(./amd)g(-r)h($dmn)f(-w)h(240)f
+(-l)h("$LOGFILE")f(\\)311 308 y(/homes)g(amd.homes)g(-cache:=inc)f(\\)311
+358 y(/home)h(amd.home)g(-cache:=inc)f(\\)311 407 y(/vol)h(amd.vol)g
+(-cache:=inc)f(\\)311 457 y(/n)h(amd.net)g(-cache:=inc)62 549
+y Fo(If)12 b(the)g(list)g(of)f(automoun)o(t)f(p)q(oin)o(ts)i(and)g(maps)f(is)
+h(con)o(tained)g(in)h(a)e(\014le)i(or)e(NIS)h(map)f(it)h(is)g(easily)g
+(incorp)q(orated)0 598 y(on)o(to)i(the)i(command)f(line:)120
+669 y Fl(...)120 719 y(eval)23 b(./amd)g(-r)h($dmn)f(-w)h(240)f(-l)h
+("$LOGFILE")f(`ypcat)g(-k)g(auto.master`)0 904 y Fq(6.2)33
+b(Stopping)16 b Ff(Amd)62 995 y Fp(Amd)h Fo(stops)e(in)h(resp)q(onse)g(to)e
+(t)o(w)o(o)g(signals.)0 1066 y(`)p Fl(SIGTERM)p Fo(')46 b(causes)18
+b(the)f(top-lev)o(el)i(automoun)o(t)d(p)q(oin)o(ts)i(to)f(b)q(e)h(unmoun)o
+(ted)f(and)h(then)g Fp(Amd)h Fo(to)e(exit.)27 b(An)o(y)240
+1116 y(automoun)o(ted)16 b(\014lesystems)g(are)g(left)h(moun)o(ted.)23
+b(They)17 b(can)f(b)q(e)h(reco)o(v)o(ered)f(b)o(y)g(restarting)g
+Fp(Amd)240 1166 y Fo(with)g(the)f(\\-r")f(command)h(line)i(option.)0
+1230 y(`)p Fl(SIGINT)p Fo(')70 b(causes)22 b Fp(Amd)i Fo(to)d(attempt)g(to)g
+(unmoun)o(t)h(an)o(y)g(\014lesystems)g(whic)o(h)h(it)f(has)g(automoun)o(ted,)
+g(in)240 1280 y(addition)16 b(to)f(the)g(actions)g(of)g(`)p
+Fl(SIGTERM)p Fo('.)j(This)e(signal)g(is)g(primarly)g(used)g(for)e(debugging.)
+62 1371 y(Actions)i(tak)o(en)f(for)f(other)h(signals)h(are)f(unde\014ned.)0
+1556 y Fq(6.3)33 b(Con)n(trolling)17 b Ff(Amd)62 1647 y Fo(It)f(is)h
+(sometimes)f(desirable)i(or)d(necessary)i(to)e(exercise)i(external)g(con)o
+(trol)f(o)o(v)o(er)f(some)h(of)f Fp(Amd)r Fo('s)h(in)o(ternal)0
+1697 y(state.)j(T)l(o)c(supp)q(ort)g(this)h(requiremen)o(t,)f
+Fp(Amd)i Fo(implemen)o(ts)g(an)e(RPC)g(in)o(terface)g(whic)o(h)h(is)g(used)g
+(b)o(y)f(the)g Fp(Amq)0 1746 y Fo(program.)k(A)c(v)m(ariet)o(y)g(of)g
+(information)g(is)h(a)o(v)m(ailable.)62 1817 y Fp(Amq)e Fo(generally)h
+(applies)f(an)f(op)q(eration,)h(sp)q(eci\014ed)h(b)o(y)e(a)g(single)h(letter)
+f(option,)h(to)e(a)h(list)h(of)e(moun)o(t)h(p)q(oin)o(ts.)0
+1867 y(The)i(default)g(op)q(eration)g(is)g(to)f(obtain)g(statistics)h(ab)q
+(out)f(eac)o(h)h(moun)o(t)f(p)q(oin)o(t.)20 b(This)15 b(is)g(similar)h(to)e
+(the)g(output)0 1917 y(sho)o(wn)f(ab)q(o)o(v)o(e)g(but)h(includes)h
+(information)f(ab)q(out)f(the)h(n)o(um)o(b)q(er)g(and)f(t)o(yp)q(e)h(of)f
+(accesses)h(to)e(eac)o(h)i(moun)o(t)f(p)q(oin)o(t.)0 2077 y
+Fi(6.3.1)30 b Fe(Amq)16 b Fi(default)f(information)62 2169
+y Fo(With)k(no)f(argumen)o(ts,)f Fp(Amq)i Fo(obtains)f(a)g(brief)h(list)g(of)
+e(all)i(existing)h(moun)o(ts)d(created)h(b)o(y)g Fp(Amd)p Fo(.)29
+b(This)18 b(is)0 2218 y(di\013eren)o(t)d(from)g(the)g(list)h(displa)o(y)o(ed)
+h(b)o(y)e Fk(df)p Fo(\(1\))f(since)j(the)e(latter)g(only)g(includes)j(system)
+d(moun)o(t)f(p)q(oin)o(ts.)0 2289 y(The)h(output)g(from)g(this)h(option)f
+(includes)i(the)f(follo)o(wing)g(information:)37 2360 y Fn(\017)30
+b Fo(the)15 b(automoun)o(t)f(p)q(oin)o(t,)37 2424 y Fn(\017)30
+b Fo(the)15 b(\014lesystem)h(t)o(yp)q(e,)37 2489 y Fn(\017)30
+b Fo(the)15 b(moun)o(t)g(map)g(or)g(moun)o(t)f(information,)37
+2554 y Fn(\017)30 b Fo(the)15 b(in)o(ternal,)h(or)f(system)f(moun)o(t)h(p)q
+(oin)o(t.)0 2645 y(F)l(or)g(example:)p eop
+%%Page: 29 31
+29 30 bop 0 -83 a Fo(Chapter)15 b(6:)k(Run-time)e(Administration)987
+b(SMM:13-29)120 158 y Fl(/)286 b(root)71 b("root")477 b(sky:\(pid75\))120
+208 y(/homes)166 b(toplvl)23 b(/usr/local/etc/amd.homes)45
+b(/homes)120 258 y(/home)190 b(toplvl)23 b(/usr/local/etc/amd.home)69
+b(/home)120 308 y(/homes/jsp)h(nfs)95 b(charm:/home/charm)213
+b(/a/charm/home/charm/jsp)120 358 y(/homes/phjk)46 b(nfs)95
+b(toytown:/home/toytown)117 b(/a/toytown/home/toytown/)o(ai/phjk)0
+449 y Fo(If)15 b(an)h(argumen)o(t)e(is)i(giv)o(en)f(then)h(statistics)f(for)g
+(that)f(v)o(olume)i(name)f(will)i(b)q(e)f(output.)j(F)l(or)c(example:)120
+519 y Fl(What)286 b(Uid)71 b(Getattr)23 b(Lookup)g(RdDir)71
+b(RdLnk)g(Statfs)23 b(Mounted@)120 569 y(/homes)238 b(0)119
+b(1196)95 b(512)g(22)143 b(0)167 b(30)119 b(90/09/14)23 b(12:32:55)120
+619 y(/homes/jsp)142 b(0)119 b(0)167 b(0)143 b(0)167 b(1180)95
+b(0)143 b(90/10/13)23 b(12:56:58)0 690 y(What)144 b Fo(the)15
+b(v)o(olume)h(name.)0 752 y Fl(Uid)168 b Fo(ignored.)0 815
+y Fl(Getattr)72 b Fo(the)21 b(coun)o(t)g(of)f(NFS)h Fp(getattr)i
+Fo(requests)e(on)g(this)g(no)q(de.)38 b(This)21 b(should)h(only)g(b)q(e)f
+(non-zero)h(for)240 865 y(directory)15 b(no)q(des.)0 928 y
+Fl(Lookup)96 b Fo(the)21 b(coun)o(t)g(of)g(NFS)g Fp(lo)q(okup)j
+Fo(requests)d(on)g(this)h(no)q(de.)38 b(This)22 b(should)g(only)g(b)q(e)g
+(non-zero)g(for)240 978 y(directory)15 b(no)q(des.)0 1040 y
+Fl(RdDir)120 b Fo(the)21 b(coun)o(t)f(of)g(NFS)h Fp(readdir)j
+Fo(requests)d(on)g(this)g(no)q(de.)36 b(This)22 b(should)f(only)g(b)q(e)h
+(non-zero)f(for)240 1090 y(directory)15 b(no)q(des.)0 1153
+y Fl(RdLnk)120 b Fo(the)19 b(coun)o(t)g(of)g(NFS)g Fp(readlink)k
+Fo(requests)c(on)h(this)f(no)q(de.)32 b(This)20 b(should)g(b)q(e)g(zero)f
+(for)g(directory)240 1203 y(no)q(des.)0 1266 y Fl(Statfs)96
+b Fo(the)11 b(could)h(of)f(NFS)g Fp(statfs)h Fo(requests)f(on)g(this)h(no)q
+(de.)19 b(This)11 b(should)h(only)g(b)q(e)g(non-zero)f(for)g(top-lev)o(el)240
+1315 y(automoun)o(t)j(p)q(oin)o(ts.)0 1378 y Fl(Mounted@)48
+b Fo(the)15 b(date)g(and)h(time)f(the)g(v)o(olume)h(name)f(w)o(as)g(\014rst)f
+(referenced.)0 1523 y Fi(6.3.2)30 b Fe(Amq)16 b Fi(-f)f(option)62
+1615 y Fo(The)i(\\-f)t(")f(option)h(causes)g Fp(Amd)i Fo(to)d(\015ush)h(the)g
+(in)o(ternal)h(moun)o(t)e(map)g(cac)o(he.)25 b(This)18 b(is)f(useful)h(for)e
+(Hesio)q(d)0 1664 y(maps)f(since)i Fp(Amd)g Fo(will)g(not)e(automatically)h
+(notice)g(when)g(they)g(ha)o(v)o(e)f(b)q(een)i(up)q(dated.)k(The)16
+b(map)f(cac)o(he)h(can)0 1714 y(also)g(b)q(e)g(sync)o(hronised)g(with)g(the)g
+(map)f(source)h(b)o(y)g(using)g(the)f(`)p Fl(sync)p Fo(')g(option)h(\(see)f
+(Section)h(5.8)f([Automoun)o(t)0 1764 y(Filesystem],)g(page)30
+b(SMM:13-24\).)0 1909 y Fi(6.3.3)g Fe(Amq)16 b Fi(-h)g(option)62
+2000 y Fo(By)g(default)g(the)g(lo)q(cal)g(host)f(is)h(used.)22
+b(In)16 b(an)f(HP-UX)h(cluster)g(the)g(ro)q(ot)e(serv)o(er)h(is)h(used)g
+(since)h(that)e(is)h(the)0 2050 y(only)k(place)g(in)g(the)f(cluster)h(where)f
+Fp(Amd)i Fo(will)g(b)q(e)f(running.)33 b(T)l(o)19 b(query)g
+Fp(Amd)i Fo(on)e(another)g(host)g(the)g(\\-h")0 2100 y(option)c(should)i(b)q
+(e)e(used.)0 2245 y Fi(6.3.4)30 b Fe(Amq)16 b Fi(-m)g(option)62
+2336 y Fo(The)c(\\-m")e(option)h(displa)o(ys)h(similar)h(information)e(ab)q
+(out)g(moun)o(ted)g(\014lesystems,)h(rather)e(than)h(automoun)o(t)0
+2386 y(p)q(oin)o(ts.)20 b(The)c(output)f(includes)i(the)e(follo)o(wing)h
+(information:)37 2457 y Fn(\017)30 b Fo(the)15 b(moun)o(t)g(information,)37
+2520 y Fn(\017)30 b Fo(the)15 b(moun)o(t)g(p)q(oin)o(t,)37
+2582 y Fn(\017)30 b Fo(the)15 b(\014lesystem)h(t)o(yp)q(e,)37
+2645 y Fn(\017)30 b Fo(the)15 b(n)o(um)o(b)q(er)h(of)f(references)g(to)g
+(this)h(\014lesystem,)p eop
+%%Page: 30 32
+30 31 bop 15 -83 a Fo(SMM:13-30)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)37 158 y Fn(\017)30 b Fo(the)15 b(serv)o(er)g
+(hostname,)37 221 y Fn(\017)30 b Fo(the)15 b(state)g(of)f(the)i(\014le)g
+(serv)o(er,)37 284 y Fn(\017)30 b Fo(an)o(y)15 b(error)f(whic)o(h)i(has)f(o)q
+(ccured.)62 375 y(F)l(or)g(example:)120 446 y Fl("root")262
+b(truth:\(pid602\))117 b(root)71 b(1)24 b(localhost)e(is)i(up)120
+496 y(hesiod.home)142 b(/home)333 b(toplvl)23 b(1)h(localhost)e(is)i(up)120
+546 y(hesiod.vol)166 b(/vol)357 b(toplvl)23 b(1)h(localhost)e(is)i(up)120
+595 y(hesiod.homes)118 b(/homes)309 b(toplvl)23 b(1)h(localhost)e(is)i(up)120
+645 y(amy:/home/amy)94 b(/a/amy/home/amy)f(nfs)i(5)24 b(amy)f(is)h(up)120
+695 y(swan:/home/swan)46 b(/a/swan/home/swan)f(nfs)95 b(0)24
+b(swan)f(is)h(up)f(\(Permission)g(denied\))120 745 y(ex:/home/ex)142
+b(/a/ex/home/ex)f(nfs)95 b(0)24 b(ex)f(is)h(down)62 836 y Fo(When)15
+b(the)g(reference)g(coun)o(t)f(is)h(zero)g(the)f(\014lesystem)i(is)f(not)f
+(moun)o(ted)g(but)h(the)g(moun)o(t)f(p)q(oin)o(t)h(and)f(serv)o(er)0
+886 y(information)h(is)h(still)h(b)q(eing)f(main)o(tained)g(b)o(y)f
+Fp(Amd)p Fo(.)0 1032 y Fi(6.3.5)30 b Fe(Amq)16 b Fi(-M)g(option)62
+1123 y Fo(The)j(\\-M")f(option)i(passes)e(a)h(new)g(map)g(en)o(try)f(to)g
+Fp(Amd)j Fo(and)e(w)o(aits)g(for)f(it)h(to)f(b)q(e)i(ev)m(aluated,)g(p)q
+(ossibly)0 1173 y(causing)i(a)f(moun)o(t.)38 b(F)l(or)21 b(example,)j(the)d
+(follo)o(wing)h(command)g(w)o(ould)f(cause)h(`)p Fl(/home/toytown)p
+Fo(')d(on)i(host)0 1223 y(`)p Fl(toytown)p Fo(')13 b(to)i(b)q(e)h(moun)o(ted)
+f(lo)q(cally)i(on)e(`)p Fl(/mnt/toytown)p Fo('.)120 1293 y
+Fl(amq)23 b(-M)h('/mnt/toytown)e(type:=nfs;rfs:=/home/toytow)o(n;rhost)o
+(:=toytow)o(n;fs:=$)o({key}')62 1385 y Fp(Amd)13 b Fo(applies)g(some)e
+(simple)i(securit)o(y)e(c)o(hec)o(ks)h(b)q(efore)f(allo)o(wing)h(this)g(op)q
+(eration.)18 b(The)12 b(c)o(hec)o(k)f(tests)g(whether)0 1434
+y(the)16 b(incoming)h(request)f(is)g(from)f(a)h(privileged)i(UDP)d(p)q(ort)h
+(on)g(the)f(lo)q(cal)i(mac)o(hine.)23 b(\\P)o(ermission)16
+b(denied")h(is)0 1484 y(returned)f(if)f(the)h(c)o(hec)o(k)f(fails.)62
+1555 y(A)f(future)f(release)h(of)e Fp(Amd)j Fo(will)g(include)h(co)q(de)e(to)
+e(allo)o(w)i(the)f Fk(moun)o(t)p Fo(\(8\))f(command)h(to)f(moun)o(t)h
+(automoun)o(t)0 1605 y(p)q(oin)o(ts:)120 1675 y Fl(mount)23
+b(-t)h(amd)f(/vol)h(hesiod.vol)62 1766 y Fo(This)16 b(will)h(then)e(allo)o(w)
+h Fp(Amd)h Fo(to)e(b)q(e)g(con)o(trolled)h(from)f(the)g(standard)g(system)g
+(\014lesystem)h(moun)o(t)e(list.)0 1912 y Fi(6.3.6)30 b Fe(Amq)16
+b Fi(-s)g(option)62 2004 y Fo(The)h(\\-s")f(option)h(displa)o(ys)h(global)f
+(statistics.)24 b(If)17 b(an)o(y)g(other)f(options)h(are)f(sp)q(eci\014ed)j
+(or)d(an)o(y)g(\014lesystems)0 2053 y(named)f(then)h(this)g(option)f(is)h
+(ignored.)k(F)l(or)15 b(example:)120 2124 y Fl(requests)47
+b(stale)118 b(mount)h(mount)g(unmount)120 2174 y(deferred)47
+b(fhandles)f(ok)191 b(failed)95 b(failed)120 2224 y(1054)143
+b(1)214 b(487)167 b(290)g(7017)0 2294 y Fo(`)p Fl(Deferred)14
+b(requests)p Fo(')240 2357 y(are)k(those)f(for)h(whic)o(h)h(an)f(immediate)h
+(reply)f(could)h(not)f(b)q(e)h(constructed.)28 b(F)l(or)17
+b(example,)j(this)240 2407 y(w)o(ould)c(happ)q(en)g(if)g(a)e(bac)o(kground)i
+(moun)o(t)e(w)o(as)h(required.)0 2470 y(`)p Fl(Stale)f(filehandles)p
+Fo(')240 2532 y(coun)o(ts)f(the)g(n)o(um)o(b)q(er)g(of)g(times)g(the)g(k)o
+(ernel)h(passes)f(a)g(stale)g(\014lehandle)i(to)e Fp(Amd)p
+Fo(.)19 b(Large)13 b(n)o(um)o(b)q(ers)240 2582 y(indicate)k(problems.)0
+2645 y(`)p Fl(Mount)d(ok)p Fo(')32 b(coun)o(ts)15 b(the)g(n)o(um)o(b)q(er)h
+(of)f(automoun)o(ts)f(whic)o(h)i(w)o(ere)e(successful.)p eop
+%%Page: 31 33
+31 32 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-31)0
+158 y(`)p Fl(Mount)14 b(failed)p Fo(')240 222 y(coun)o(ts)h(the)g(n)o(um)o(b)
+q(er)h(of)f(automoun)o(ts)f(whic)o(h)i(failed.)0 286 y(`)p
+Fl(Unmount)e(failed)p Fo(')240 350 y(coun)o(ts)h(the)g(n)o(um)o(b)q(er)g(of)f
+(times)h(a)g(\014lesystem)g(could)h(not)f(b)q(e)g(unmoun)o(ted.)21
+b(V)l(ery)15 b(large)g(n)o(um)o(b)q(ers)240 400 y(here)h(indicate)g(that)f
+(the)g(time)h(b)q(et)o(w)o(een)f(unmoun)o(t)g(attempts)f(should)j(b)q(e)f
+(increased.)0 554 y Fi(6.3.7)30 b Fe(Amq)16 b Fi(-u)g(option)62
+645 y Fo(The)f(\\-u")g(option)g(causes)h(the)f(time-to-liv)o(e)h(in)o(terv)m
+(al)g(of)e(the)h(named)h(moun)o(t)e(p)q(oin)o(ts)h(to)g(b)q(e)g(expired,)h
+(th)o(us)0 695 y(causing)f(an)e(unmoun)o(t)h(attempt.)19 b(This)14
+b(is)g(the)g(only)h(safe)e(w)o(a)o(y)g(to)g(unmoun)o(t)h(an)g(automoun)o(ted)
+f(\014lesystem.)20 b(It)0 745 y(is)c(not)f(p)q(ossible)h(to)f(unmoun)o(t)g(a)
+g(\014lesystem)h(whic)o(h)g(has)f(b)q(een)h(moun)o(ted)f(with)h(the)f(`)p
+Fl(nounmount)p Fo(')e(\015ag.)0 899 y Fi(6.3.8)30 b Fe(Amq)16
+b Fi(-v)g(option)62 990 y Fo(The)g(\\-v")e(option)i(displa)o(ys)g(the)f(v)o
+(ersion)h(of)f Fp(Amd)i Fo(in)f(a)f(similar)h(w)o(a)o(y)e(to)h
+Fp(Amd)r Fo('s)f(\\-v")h(option.)0 1145 y Fi(6.3.9)30 b(Other)15
+b Fe(Amq)h Fi(options)62 1236 y Fo(Three)j(other)g(op)q(erations)f(are)h
+(implemen)o(ted.)32 b(These)19 b(mo)q(dify)g(the)g(state)f(of)g
+Fp(Amd)j Fo(as)d(a)h(whole,)h(rather)0 1286 y(than)e(an)o(y)g(particular)h
+(\014lesystem.)30 b(The)19 b(\\-l",)g(\\-x")f(and)h(\\-D")e(options)i(ha)o(v)
+o(e)f(exactly)h(the)f(same)g(e\013ect)g(as)0 1336 y Fp(Amd)r
+Fo('s)g(corresp)q(onding)h(command)g(line)h(options.)30 b(The)18
+b(\\-l")h(option)g(is)g(rejected)f(b)o(y)h Fp(Amd)h Fo(in)g(the)e(curren)o(t)
+0 1385 y(v)o(ersion)e(for)e(ob)o(vious)i(securit)o(y)g(reasons.)j(When)d
+Fp(Amd)h Fo(receiv)o(es)g(a)e(\\-x"\015ag)f(it)i(limits)g(the)g(log)f
+(options)h(b)q(eing)0 1435 y(mo)q(di\014ed)g(to)e(those)h(whic)o(h)g(w)o(ere)
+g(not)f(enabled)j(at)d(startup.)19 b(This)c(prev)o(en)o(ts)g(a)f(user)h
+(turning)g Fp(o\013)23 b Fo(an)o(y)15 b(logging)0 1485 y(option)h(whic)o(h)h
+(w)o(as)f(sp)q(eci\014ed)i(at)d(startup,)h(though)g(an)o(y)g(whic)o(h)h(ha)o
+(v)o(e)e(b)q(een)j(turned)e(o\013)f(since)j(then)e(can)h(still)0
+1535 y(b)q(e)f(turned)f(o\013.)20 b(The)15 b(\\-D")f(option)i(has)f(a)g
+(similar)h(b)q(eha)o(viour.)0 1737 y Fm(7)41 b(FSinfo)0 1964
+y Fq(7.1)33 b Ff(FSinfo)16 b Fq(o)n(v)n(erview)62 2056 y Fp(FSinfo)h
+Fo(is)d(a)f(\014lesystem)h(managemen)o(t)f(to)q(ol.)19 b(It)14
+b(has)g(b)q(een)g(designed)h(to)e(w)o(ork)g(with)h Fp(Amd)i
+Fo(to)c(help)j(system)0 2105 y(administrators)g(k)o(eep)g(trac)o(k)g(of)f
+(the)i(ev)o(er)f(increasing)h(\014lesystem)g(namespace)g(under)g(their)f(con)
+o(trol.)62 2176 y(The)20 b(purp)q(ose)g(of)f Fp(FSinfo)j Fo(is)e(to)e
+(generate)h(all)i(the)e(imp)q(ortan)o(t)g(standard)g(\014lesystem)h(data)e
+(\014les)j(from)d(a)0 2226 y(single)g(set)e(of)g(input)h(data.)23
+b(Starting)16 b(with)h(a)f(single)h(data)f(source)h(guaran)o(tees)e(that)h
+(all)h(the)g(generated)f(\014les)0 2276 y(are)i(self-consisten)o(t.)28
+b(One)19 b(of)e(the)h(p)q(ossible)i(output)e(data)f(formats)f(is)j(a)e(set)h
+(of)f Fp(Amd)j Fo(maps)e(whic)o(h)g(can)g(b)q(e)0 2325 y(used)e(amongst)e
+(the)h(set)g(of)g(hosts)g(describ)q(ed)i(in)f(the)f(input)h(data.)62
+2396 y Fp(FSinfo)i Fo(implemen)o(ts)f(a)e(declarativ)o(e)h(language.)k(This)c
+(language)g(is)g(sp)q(eci\014cally)i(designed)e(for)f(describing)0
+2446 y(\014lesystem)21 b(namespace)g(and)f(ph)o(ysical)i(la)o(y)o(outs.)34
+b(The)21 b(basic)g(declaration)g(de\014nes)g(a)f(moun)o(ted)g(\014lesystem)0
+2496 y(including)e(its)e(device)h(name,)e(moun)o(t)g(p)q(oin)o(t,)g(and)h
+(all)g(the)g(v)o(olumes)g(and)f(access)h(p)q(ermissions.)22
+b Fp(FSinfo)c Fo(reads)0 2545 y(this)e(information)g(and)f(builds)j(an)d(in)o
+(ternal)h(map)f(of)h(the)f(en)o(tire)h(net)o(w)o(ork)e(of)h(hosts.)21
+b(Using)16 b(this)f(map,)g(man)o(y)0 2595 y(di\013eren)o(t)d(data)g(formats)f
+(can)h(b)q(e)h(pro)q(duced)h(including)h(`)p Fl(/etc/fstab)p
+Fo(',)10 b(`)p Fl(/etc/exports)p Fo(',)g Fp(Amd)k Fo(moun)o(t)e(maps)0
+2645 y(and)j(`)p Fl(/etc/bootparams)p Fo('.)p eop
+%%Page: 32 34
+32 33 bop 15 -83 a Fo(SMM:13-32)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fq(7.2)33 b(Using)15 b Ff(FSinfo)62
+250 y Fo(The)20 b(basic)h(strategy)d(when)i(using)h Fp(FSinfo)h
+Fo(is)e(to)f(gather)g(all)i(the)f(information)g(ab)q(out)f(all)i(disks)f(on)g
+(all)0 299 y(mac)o(hines)i(in)o(to)e(one)h(set)g(of)g(declarations.)37
+b(F)l(or)20 b(eac)o(h)h(mac)o(hine)h(b)q(eing)g(managed,)g(the)f(follo)o
+(wing)g(data)f(is)0 349 y(required:)37 420 y Fn(\017)30 b Fo(Hostname)37
+482 y Fn(\017)g Fo(List)16 b(of)f(all)h(\014lesystems)f(and,)g(optionally)l
+(,)i(their)e(moun)o(t)g(p)q(oin)o(ts.)37 544 y Fn(\017)30 b
+Fo(Names)15 b(of)g(v)o(olumes)g(stored)g(on)g(eac)o(h)g(\014lesystem.)37
+606 y Fn(\017)30 b Fo(NFS)15 b(exp)q(ort)g(information)h(for)e(eac)o(h)h(v)o
+(olume.)37 668 y Fn(\017)30 b Fo(The)15 b(list)h(of)f(static)g(\014lesystem)h
+(moun)o(ts.)62 759 y(The)g(follo)o(wing)g(information)f(can)h(also)f(b)q(e)h
+(en)o(tered)g(in)o(to)f(the)h(same)f(con\014guration)g(\014les)i(so)e(that)f
+(all)j(data)0 809 y(can)e(b)q(e)h(k)o(ept)f(in)h(one)g(place.)37
+879 y Fn(\017)30 b Fo(List)16 b(of)f(net)o(w)o(ork)f(in)o(terfaces)37
+941 y Fn(\017)30 b Fo(IP)16 b(address)f(of)g(eac)o(h)g(in)o(terface)37
+1003 y Fn(\017)30 b Fo(Hardw)o(are)14 b(address)i(of)e(eac)o(h)i(in)o
+(terface)37 1065 y Fn(\017)30 b Fo(Dumpset)15 b(to)g(whic)o(h)h(eac)o(h)f
+(\014lesystem)h(b)q(elongs)37 1127 y Fn(\017)30 b Fo(and)15
+b(more)g Fj(:)8 b(:)g(:)62 1218 y Fo(T)l(o)13 b(generate)f
+Fp(Amd)j Fo(moun)o(t)d(maps,)g(the)h(automoun)o(t)f(tree)g(m)o(ust)g(also)h
+(b)q(e)g(de\014ned)h(\(see)f(Section)g(7.8)f([FSinfo)0 1268
+y(automoun)o(t)k(de\014nitions],)j(page)34 b(SMM:13-39\).)23
+b(This)18 b(will)h(ha)o(v)o(e)d(b)q(een)j(designed)f(at)f(the)g(time)g(the)h
+(v)o(olume)0 1318 y(names)f(w)o(ere)f(allo)q(cated.)26 b(Some)17
+b(v)o(olume)g(names)f(will)j(not)d(b)q(e)i(automoun)o(ted,)e(so)g
+Fp(FSinfo)k Fo(needs)d(an)g(explicit)0 1368 y(list)f(of)f(whic)o(h)h(v)o
+(olumes)f(should)i(b)q(e)e(automoun)o(ted.)62 1438 y(Hostnames)k(are)f
+(required)j(at)d(sev)o(eral)h(places)h(in)g(the)f Fp(FSinfo)j
+Fo(language.)32 b(It)19 b(is)g(imp)q(ortan)o(t)g(to)f(stic)o(k)i(to)0
+1488 y(either)15 b(fully)h(quali\014ed)g(names)e(or)g(unquali\014ed)j(names.)
+i(Using)c(a)f(mixture)h(of)f(the)g(t)o(w)o(o)f(will)j(inevitably)h(result)0
+1538 y(in)f(confusion.)62 1609 y(Sometimes)c(v)o(olumes)f(need)h(to)e(b)q(e)i
+(referenced)g(whic)o(h)g(are)e(not)h(de\014ned)h(in)g(the)f(set)g(of)f(hosts)
+h(b)q(eing)h(managed)0 1658 y(with)19 b Fp(FSinfo)p Fo(.)31
+b(The)18 b(required)i(action)f(is)g(to)f(add)h(a)f(dumm)o(y)h(set)f(of)g
+(de\014nitions)j(for)d(the)h(host)f(and)h(v)o(olume)0 1708
+y(names)d(required.)24 b(Since)17 b(the)g(\014les)g(generated)f(for)f(those)h
+(particular)h(hosts)f(will)i(not)d(b)q(e)i(used)g(on)f(them,)g(the)0
+1758 y(exact)f(v)m(alues)h(used)g(is)g(not)f(critical.)0 1914
+y Fq(7.3)33 b Ff(FSinfo)16 b Fq(grammar)62 2006 y Fp(FSinfo)24
+b Fo(has)d(a)g(relativ)o(ely)i(simple)g(grammar.)36 b(Distinct)22
+b(syn)o(tactic)f(constructs)g(exist)h(for)f(eac)o(h)g(of)g(the)0
+2056 y(di\013eren)o(t)c(t)o(yp)q(es)f(of)g(data,)g(though)g(they)h(share)f(a)
+g(common)g(\015a)o(v)o(our.)23 b(Sev)o(eral)17 b(con)o(v)o(en)o(tions)f(are)h
+(used)g(in)g(the)0 2105 y(grammar)d(fragmen)o(ts)g(b)q(elo)o(w.)62
+2176 y(The)g(notation,)f Fp(list\()t Fl(xxx)p Fp(\))p Fo(,)g(indicates)i(a)e
+(list)h(of)f(zero)h(or)e(more)h Fl(xxx)p Fo('s.)19 b(The)13
+b(notation,)g Fp(opt\()t Fl(xxx)p Fp(\))p Fo(,)g(indicates)0
+2226 y(zero)22 b(or)g(one)g Fl(xxx)p Fo(.)41 b(Items)23 b(in)g(double)g
+(quotes,)h Fp(eg)i Fl("host")p Fo(,)d(represen)o(t)f(input)h(tok)o(ens.)41
+b(Items)22 b(in)h(angle)0 2276 y(brac)o(k)o(ets,)d Fp(eg)j
+Fl(<)p Fp(hostname)p Fl(>)p Fo(,)d(represen)o(t)g(strings)g(in)g(the)g
+(input.)35 b(Strings)20 b(need)g(not)g(b)q(e)g(in)h(double)g(quotes,)0
+2325 y(except)d(to)e(di\013eren)o(tiate)i(them)f(from)f(reserv)o(ed)i(w)o
+(ords.)25 b(Quoted)17 b(strings)g(ma)o(y)g(include)i(the)f(usual)f(set)g(of)g
+(C)0 2375 y(\\)p Fl(\\)p Fo(")12 b(escap)q(e)h(sequences)g(with)f(one)h
+(exception:)19 b(a)12 b(bac)o(kslash-newline-whi)q(tespace)j(sequence)e(is)g
+(squashed)g(in)o(to)0 2425 y(a)i(single)i(space)g(c)o(haracter.)j(T)l(o)c
+(defeat)f(this)i(feature,)e(put)h(a)f(further)h(bac)o(kslash)g(at)f(the)h
+(start)e(of)i(the)f(second)0 2475 y(line.)62 2545 y(A)o(t)f(the)h(outermost)e
+(lev)o(el)j(of)e(the)g(grammar,)f(the)i(input)g(consists)g(of)f(a)g(sequence)
+h(of)f(host)g(and)h(automoun)o(t)0 2595 y(declarations.)34
+b(These)20 b(declarations)h(are)e(all)i(parsed)f(b)q(efore)g(they)g(are)f
+(analyzed.)35 b(This)20 b(means)g(they)g(can)0 2645 y(app)q(ear)15
+b(in)h(an)o(y)f(order)g(and)h(cyclic)h(host)d(references)i(are)f(p)q
+(ossible.)p eop
+%%Page: 33 35
+33 34 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-33)120
+158 y Fl(fsinfo)142 b(:)24 b Fp(list\()t Fl(fsinfo_attr)p Fp(\))g
+Fl(;)120 258 y(fsinfo_attr)e(:)i(host)f(|)h(automount)f(;)0
+460 y Fq(7.4)33 b Ff(FSinfo)16 b Fq(host)f(de\014nitions)62
+552 y Fo(A)h(host)g(declaration)g(consists)g(of)g(three)g(parts:)k(a)c(set)f
+(of)h(mac)o(hine)g(attribute)g(data,)f(a)g(list)i(of)e(\014lesystems)0
+601 y(ph)o(ysically)i(attac)o(hed)e(to)f(the)i(mac)o(hine,)f(and)h(a)e(list)i
+(of)f(additional)i(statically)f(moun)o(ted)f(\014lesystems.)120
+672 y Fl(host)190 b(:)24 b("host")f(host_data)g Fp(list\()t
+Fl(filesystem)p Fp(\))h(list\()t Fl(mount)p Fp(\))g Fl(;)62
+763 y Fo(Eac)o(h)15 b(host)f(m)o(ust)g(b)q(e)i(declared)g(in)f(this)h(w)o(a)o
+(y)d(exactly)i(once.)20 b(Suc)o(h)c(things)f(as)f(the)h(hardw)o(are)f
+(address,)h(the)0 813 y(arc)o(hitecture)e(and)f(op)q(erating)h(system)f(t)o
+(yp)q(es)h(and)f(the)h(cluster)g(name)g(are)f(all)h(sp)q(eci\014ed)i(within)e
+(the)g Fp(host)f(data)p Fo(.)62 884 y(All)h(the)e(disks)h(the)f(mac)o(hine)h
+(has)f(should)h(then)g(b)q(e)f(describ)q(ed)j(in)e(the)f Fp(list)h(of)e
+(\014lesystems)p Fo(.)20 b(When)11 b(describing)0 933 y(disks,)17
+b(y)o(ou)f(can)h(sp)q(ecify)h(what)e Fp(v)o(olname)j Fo(the)e(disk/partition)
+g(should)h(ha)o(v)o(e)e(and)h(all)g(suc)o(h)g(en)o(tries)g(are)g(built)0
+983 y(up)f(in)o(to)f(a)g(dictionary)h(whic)o(h)g(can)f(then)h(b)q(e)g(used)f
+(for)g(building)j(the)d(automoun)o(ter)f(maps.)62 1054 y(The)f
+Fp(list)g(of)e(moun)o(ts)j Fo(sp)q(eci\014es)g(all)f(the)f(\014lesystems)h
+(that)e(should)i(b)q(e)g(statically)g(moun)o(ted)f(on)g(the)g(mac)o(hine.)0
+1263 y Fq(7.5)33 b Ff(FSinfo)16 b Fq(host)f(attributes)62 1354
+y Fo(The)20 b(host)g(data,)f Fp(host)p 472 1354 14 2 v 16 w(data)p
+Fo(,)h(alw)o(a)o(ys)f(includes)j(the)e Fp(hostname)p Fo(.)33
+b(In)20 b(addition,)i(sev)o(eral)e(other)f(host)g(at-)0 1404
+y(tributes)d(can)f(b)q(e)h(giv)o(en.)120 1474 y Fl(host_data)70
+b(:)24 b(<)p Fp(hostname)p Fl(>)406 1524 y(|)g("{")g Fp(list\()t
+Fl(host_attrs)p Fp(\))f Fl("}")h(<)p Fp(hostname)p Fl(>)406
+1574 y(;)120 1674 y(host_attrs)46 b(:)24 b(host_attr)f("=")g(<)p
+Fp(string)p Fl(>)406 1724 y(|)h(netif)406 1773 y(;)120 1873
+y(host_attr)70 b(:)24 b("config")406 1923 y(|)g("arch")406
+1973 y(|)g("os")406 2022 y(|)g("cluster")406 2072 y(;)62 2164
+y Fo(The)16 b Fp(hostname)h Fo(is,)e(t)o(ypically)l(,)i(the)e(fully)i
+(quali\014ed)g(hostname)e(of)f(the)i(mac)o(hine.)62 2234 y(Examples:)120
+2305 y Fl(host)23 b(dylan.doc.ic.ac.uk)120 2404 y(host)g({)215
+2454 y(os)h(=)g(hpux)215 2504 y(arch)g(=)f(hp300)120 2554 y(})h
+(dougal.doc.ic.ac.uk)62 2645 y Fo(The)16 b(options)f(that)g(can)g(b)q(e)h
+(giv)o(en)f(as)g(host)g(attributes)g(are)g(sho)o(wn)g(b)q(elo)o(w.)p
+eop
+%%Page: 34 36
+34 35 bop 15 -83 a Fo(SMM:13-34)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fi(7.5.1)30 b(netif)15 b(Option)62
+250 y Fo(This)j(de\014nes)g(the)f(set)g(of)g(net)o(w)o(ork)f(in)o(terfaces)h
+(con\014gured)h(on)f(the)g(mac)o(hine.)26 b(The)18 b(in)o(terface)f
+(attributes)0 299 y(collected)k(b)o(y)e Fp(FSinfo)j Fo(are)d(the)g(IP)g
+(address,)h(subnet)g(mask)e(and)i(hardw)o(are)e(address.)32
+b(Multiple)21 b(in)o(terfaces)0 349 y(ma)o(y)c(b)q(e)h(de\014ned)h(for)d
+(hosts)h(with)h(sev)o(eral)g(in)o(terfaces)f(b)o(y)h(an)f(en)o(try)g(for)g
+(eac)o(h)g(in)o(terface.)27 b(The)18 b(v)m(alues)g(giv)o(en)0
+399 y(are)d(sanit)o(y)g(c)o(hec)o(k)o(ed,)g(but)h(are)e(curren)o(tly)i(un)o
+(used)g(for)f(an)o(ything)g(else.)120 470 y Fl(netif)166 b(:)24
+b("netif")f(<)p Fp(string)p Fl(>)h("{")f Fp(list\()t Fl(netif_attrs)p
+Fp(\))h Fl("}")f(;)120 569 y(netif_attrs)f(:)i(netif_attr)f("=")g(<)p
+Fp(string)p Fl(>)h(;)120 669 y(netif_attr)46 b(:)24 b("inaddr")f(|)h
+("netmask")e(|)i("hwaddr")f(;)62 760 y Fo(Examples:)120 831
+y Fl(netif)g(ie0)h({)215 881 y(inaddr)47 b(=)24 b(129.31.81.37)215
+930 y(netmask)f(=)h(0xfffffe00)215 980 y(hwaddr)47 b(=)24 b
+("08:00:20:01:a6:a5")120 1030 y(})120 1130 y(netif)f(ec0)h({)f(})0
+1292 y Fi(7.5.2)30 b(con\014g)15 b(Option)62 1383 y Fo(This)g(option)e(allo)o
+(ws)h(y)o(ou)g(to)f(sp)q(ecify)i(con\014guration)e(v)m(ariables)i(for)e(the)h
+(startup)f(scripts)h(\(`)p Fl(rc)p Fo(')e(scripts\).)20 b(A)0
+1433 y(simple)d(string)e(should)h(immediately)h(follo)o(w)e(the)g(k)o(eyw)o
+(ord.)62 1503 y(Example:)120 1574 y Fl(config)23 b("NFS_SERVER=true")120
+1624 y(config)g("ZEPHYR=true")62 1715 y Fo(This)16 b(option)f(is)h(curren)o
+(tly)g(unsupp)q(orted.)0 1877 y Fi(7.5.3)30 b(arc)n(h)16 b(Option)62
+1968 y Fo(This)g(de\014nes)g(the)g(arc)o(hitecture)f(of)g(the)g(mac)o(hine.)
+21 b(F)l(or)14 b(example:)120 2039 y Fl(arch)23 b(=)h(hp300)62
+2130 y Fo(This)12 b(is)g(in)o(tended)h(to)e(b)q(e)h(of)f(use)h(when)g
+(building)i(arc)o(hitecture)e(sp)q(eci\014c)h(moun)o(tmaps,)e(ho)o(w)o(ev)o
+(er,)g(the)h(option)0 2180 y(is)k(curren)o(tly)f(unsupp)q(orted.)0
+2342 y Fi(7.5.4)30 b(os)15 b(Option)62 2433 y Fo(This)h(de\014nes)g(the)g(op)
+q(erating)f(system)g(t)o(yp)q(e)g(of)g(the)g(host.)k(F)l(or)c(example:)120
+2504 y Fl(os)24 b(=)f(hpux)62 2595 y Fo(This)16 b(information)g(is)g(used)g
+(when)g(creating)g(the)g(`)p Fl(fstab)p Fo(')e(\014les,)i(for)f(example)i(in)
+f(c)o(ho)q(osing)g(whic)o(h)g(format)0 2645 y(to)f(use)g(for)g(the)g(`)p
+Fl(fstab)p Fo(')f(en)o(tries)h(within)i(the)e(\014le.)p eop
+%%Page: 35 37
+35 36 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-35)0
+158 y Fi(7.5.5)30 b(cluster)16 b(Option)62 250 y Fo(This)g(is)g(used)g(for)e
+(sp)q(ecifying)j(in)f(whic)o(h)g(cluster)g(the)f(mac)o(hine)h(b)q(elongs.)21
+b(F)l(or)15 b(example:)120 320 y Fl(cluster)23 b(=)h("theory")62
+412 y Fo(The)13 b(cluster)f(is)h(in)o(tended)g(to)e(b)q(e)i(used)g(when)f
+(generating)g(the)h(automoun)o(t)d(maps,)i(although)h(it)f(is)g(curren)o(tly)
+0 461 y(unsupp)q(orted.)0 657 y Fq(7.6)33 b Ff(FSinfo)16 b
+Fq(\014lesystems)62 748 y Fo(The)h(list)g(of)f(ph)o(ysically)j(attac)o(hed)d
+(\014lesystems)h(follo)o(ws)f(the)h(mac)o(hine)g(attributes.)24
+b(These)16 b(should)i(de\014ne)0 798 y(all)e(the)f(\014lesystems)h(a)o(v)m
+(ailable)g(from)f(this)g(mac)o(hine,)h(whether)f(exp)q(orted)g(or)g(not.)k
+(In)d(addition)g(to)e(the)i(device)0 848 y(name,)g(\014lesystems)g(ha)o(v)o
+(e)f(sev)o(eral)h(attributes,)f(suc)o(h)i(as)e(\014lesystem)h(t)o(yp)q(e,)g
+(moun)o(t)f(options,)h(and)g(`)p Fl(fsck)p Fo(')e(pass)0 897
+y(n)o(um)o(b)q(er)i(whic)o(h)g(are)e(needed)j(to)e(generate)f(`)p
+Fl(fstab)p Fo(')g(en)o(tries.)120 968 y Fl(filesystem)46 b(:)24
+b("fs")f(<)p Fp(device)p Fl(>)i("{")f Fp(list\()t Fl(fs_data)p
+Fp(\))g Fl("}")g(;)120 1068 y(fs_data)118 b(:)24 b(fs_data_attr)e("=")i(<)p
+Fp(string)p Fl(>)406 1117 y(|)g(mount)406 1167 y(;)120 1267
+y(fs_data_attr)406 1317 y(:)g("fstype")f(|)h("opts")f(|)g("passno")406
+1367 y(|)h("freq")f(|)h("dumpset")e(|)i("log")406 1416 y(;)62
+1508 y Fo(Here,)15 b Fl(<)p Fp(device)p Fl(>)h Fo(is)g(the)f(device)h(name)f
+(of)g(the)g(disk)h(\(for)e(example,)h(`)p Fl(/dev/dsk/2s0)p
+Fo('\).)i(The)f(device)g(name)0 1558 y(is)g(used)h(for)e(building)j(the)e
+(moun)o(t)g(maps)f(and)h(for)f(the)h(`)p Fl(fstab)p Fo(')f(\014le.)23
+b(The)16 b(attributes)f(that)g(can)h(b)q(e)h(sp)q(eci\014ed)0
+1607 y(are)e(sho)o(wn)g(in)h(the)f(follo)o(wing)h(section.)62
+1678 y(The)g Fp(FSinfo)i Fo(con\014guration)d(\014le)h(for)f
+Fl(dylan.doc.ic.ac.uk)d Fo(is)k(listed)h(b)q(elo)o(w.)120 1748
+y Fl(host)23 b(dylan.doc.ic.ac.uk)120 1848 y(fs)h(/dev/dsk/0s0)e({)120
+1898 y(fstype)h(=)h(swap)120 1948 y(})120 2047 y(fs)g(/dev/dsk/0s0)e({)120
+2097 y(fstype)h(=)h(hfs)120 2147 y(opts)f(=)h(rw,noquota,grpid)120
+2197 y(passno)f(=)h(0;)120 2247 y(freq)f(=)h(1;)120 2296 y(mount)f(/)h({)g(})
+120 2346 y(})120 2446 y(fs)g(/dev/dsk/1s0)e({)120 2496 y(fstype)h(=)h(hfs)120
+2545 y(opts)f(=)h(defaults)120 2595 y(passno)f(=)h(1;)120 2645
+y(freq)f(=)h(1;)p eop
+%%Page: 36 38
+36 37 bop 15 -83 a Fo(SMM:13-36)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)120 158 y Fl(mount)23 b(/usr)g({)120
+208 y(local)g({)120 258 y(exportfs)g("dougal)g(eden)g(dylan)g(zebedee)g
+(brian")120 308 y(volname)g(/nfs/hp300/local)120 358 y(})120
+407 y(})120 457 y(})120 557 y(fs)h(/dev/dsk/2s0)e({)120 607
+y(fstype)h(=)h(hfs)120 656 y(opts)f(=)h(defaults)120 706 y(passno)f(=)h(1;)
+120 756 y(freq)f(=)h(1;)120 806 y(mount)f(default)g({)120 856
+y(exportfs)g("toytown_clients)e(hangers_on")120 906 y(volname)i
+(/home/dylan/dk2)120 955 y(})120 1005 y(})120 1105 y(fs)h(/dev/dsk/3s0)e({)
+120 1155 y(fstype)h(=)h(hfs)120 1204 y(opts)f(=)h(defaults)120
+1254 y(passno)f(=)h(1;)120 1304 y(freq)f(=)h(1;)120 1354 y(mount)f(default)g
+({)120 1404 y(exportfs)g("toytown_clients)e(hangers_on")120
+1453 y(volname)i(/home/dylan/dk3)120 1503 y(})120 1553 y(})120
+1653 y(fs)h(/dev/dsk/5s0)e({)120 1703 y(fstype)h(=)h(hfs)120
+1752 y(opts)f(=)h(defaults)120 1802 y(passno)f(=)h(1;)120 1852
+y(freq)f(=)h(1;)120 1902 y(mount)f(default)g({)120 1952 y(exportfs)g
+("toytown_clients)e(hangers_on")120 2001 y(volname)i(/home/dylan/dk5)120
+2051 y(})120 2101 y(})0 2234 y Fi(7.6.1)30 b(fst)n(yp)r(e)15
+b(Option)62 2325 y Fo(This)g(sp)q(eci\014es)h(the)f(t)o(yp)q(e)f(of)g
+(\014lesystem)h(b)q(eing)h(declared)f(and)g(will)h(b)q(e)e(placed)i(in)o(to)e
+(the)h(`)p Fl(fstab)p Fo(')e(\014le)i(as)f(is.)0 2375 y(The)g(v)m(alue)g(of)f
+(this)h(option)f(will)i(b)q(e)f(handed)g(to)f Fl(mount)g Fo(as)f(the)i
+(\014lesystem)g(t)o(yp)q(e|it)g(should)g(ha)o(v)o(e)f(suc)o(h)h(v)m(alues)0
+2425 y(as)h Fl(4.2)p Fo(,)f Fl(nfs)h Fo(or)g Fl(swap)p Fo(.)k(The)c(v)m(alue)
+i(is)e(not)g(examined)i(for)d(correctness.)62 2496 y(There)21
+b(is)g(one)f(sp)q(ecial)i(case.)35 b(If)21 b(the)f(\014lesystem)h(t)o(yp)q(e)
+f(is)h(sp)q(eci\014ed)i(as)d(`)p Fl(export)p Fo(')e(then)j(the)f
+(\014lesystem)0 2545 y(information)d(will)h(not)f(b)q(e)g(added)h(to)e(the)h
+(host's)f(`)p Fl(fstab)p Fo(')f(information,)i(but)g(it)g(will)h(still)h(b)q
+(e)e(visible)i(on)e(the)0 2595 y(net)o(w)o(ork.)h(This)13 b(is)f(useful)h
+(for)f(de\014ning)i(hosts)d(whic)o(h)i(con)o(tain)g(referenced)g(v)o(olumes)f
+(but)h(whic)o(h)g(are)e(not)h(under)0 2645 y(full)17 b(con)o(trol)d(of)h
+Fp(FSinfo)p Fo(.)p eop
+%%Page: 37 39
+37 38 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-37)62
+158 y(Example:)120 229 y Fl(fstype)23 b(=)h(swap)0 378 y Fi(7.6.2)30
+b(opts)15 b(Option)62 470 y Fo(This)h(de\014nes)g(an)o(y)f(options)g(that)g
+(should)h(b)q(e)g(giv)o(en)g(to)e Fk(moun)o(t)p Fo(\(8\))g(in)i(the)f(`)p
+Fl(fstab)p Fo(')f(\014le.)21 b(F)l(or)15 b(example:)120 540
+y Fl(opts)23 b(=)h(rw,nosuid,grpid)0 690 y Fi(7.6.3)30 b(passno)15
+b(Option)62 781 y Fo(This)g(de\014nes)g(the)f Fk(fsc)o(k)p
+Fo(\(8\))f(pass)h(n)o(um)o(b)q(er)g(in)h(whic)o(h)g(to)f(c)o(hec)o(k)g(the)g
+(\014lesystem.)20 b(This)15 b(v)m(alue)g(will)h(b)q(e)f(placed)0
+831 y(in)o(to)g(the)g(`)p Fl(fstab)p Fo(')f(\014le.)62 902
+y(Example:)120 972 y Fl(passno)23 b(=)h(1)0 1122 y Fi(7.6.4)30
+b(freq)15 b(Option)62 1213 y Fo(This)k(de\014nes)f(the)g(in)o(terv)m(al)h
+(\(in)f(da)o(ys\))f(b)q(et)o(w)o(een)h(dumps.)28 b(The)18 b(v)m(alue)h(is)f
+(placed)h(as)f(is)g(in)o(to)g(the)f(`)p Fl(fstab)p Fo(')0 1263
+y(\014le.)62 1333 y(Example:)120 1404 y Fl(freq)23 b(=)h(3)0
+1553 y Fi(7.6.5)30 b(moun)n(t)15 b(Option)62 1645 y Fo(This)e(de\014nes)g
+(the)f(moun)o(tp)q(oin)o(t)g(at)f(whic)o(h)i(to)f(place)h(the)f
+(\014lesystem.)19 b(If)12 b(the)h(moun)o(tp)q(oin)o(t)f(of)f(the)h
+(\014lesystem)0 1694 y(is)19 b(sp)q(eci\014ed)h(as)e Fl(default)p
+Fo(,)f(then)i(the)f(\014lesystem)h(will)g(b)q(e)g(moun)o(ted)f(in)h(the)f
+(automoun)o(ter's)f(tree)h(under)h(its)0 1744 y(v)o(olume)d(name)f(and)g(the)
+g(moun)o(t)g(will)i(automatically)f(b)q(e)f(inherited)j(b)o(y)d(the)g
+(automoun)o(ter.)62 1815 y(F)l(ollo)o(wing)21 b(the)e(moun)o(tp)q(oin)o(t,)i
+(namespace)f(information)f(for)g(the)h(\014lesystem)g(ma)o(y)f(b)q(e)i
+(describ)q(ed.)35 b(The)0 1865 y(options)15 b(that)g(can)g(b)q(e)h(giv)o(en)g
+(here)f(are)g Fl(exportfs)p Fo(,)f Fl(volname)g Fo(and)h Fl(sel)p
+Fo(.)62 1935 y(The)h(format)e(is:)120 2006 y Fl(mount)166 b(:)24
+b("mount")f(vol_tree)g(;)120 2105 y(vol_tree)94 b(:)24 b Fp(list\()t
+Fl(vol_tree_attr)p Fp(\))f Fl(;)120 2205 y(vol_tree_attr)406
+2255 y(:)48 b(<)p Fp(string)p Fl(>)24 b("{")f Fp(list\()t Fl(vol_tree_info)p
+Fp(\))g Fl(vol_tree)g("}")h(;)120 2355 y(vol_tree_info)406
+2404 y(:)g("exportfs")f(<)p Fp(exp)q(ort-data)p Fl(>)406 2454
+y(|)h("volname")f(<)p Fp(v)o(olname)p Fl(>)406 2504 y(|)h("sel")f(<)p
+Fp(selector-list)p Fl(>)406 2554 y(;)62 2645 y Fo(Example:)p
+eop
+%%Page: 38 40
+38 39 bop 15 -83 a Fo(SMM:13-38)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)120 158 y Fl(mount)23 b(default)g({)215
+208 y(exportfs)g("dylan)g(dougal)g(florence)g(zebedee")215
+258 y(volname)g(/vol/andrew)120 308 y(})62 399 y Fo(In)15 b(the)f(ab)q(o)o(v)
+o(e)f(example,)i(the)f(\014lesystem)g(curren)o(tly)h(b)q(eing)g(declared)g
+(will)g(ha)o(v)o(e)f(an)f(en)o(try)h(placed)h(in)o(to)f(the)0
+449 y(`)p Fl(exports)p Fo(')d(\014le)j(allo)o(wing)g(the)f(\014lesystem)h(to)
+e(b)q(e)i(exp)q(orted)f(to)g(the)g(mac)o(hines)g Fl(dylan)p
+Fo(,)g Fl(dougal)p Fo(,)f Fl(florence)g Fo(and)0 499 y Fl(zebedee)p
+Fo(.)18 b(The)d(v)o(olume)f(name)g(b)o(y)g(whic)o(h)h(the)f(\014lesystem)g
+(will)i(b)q(e)f(referred)f(to)f(remotely)l(,)h(is)h(`)p Fl(/vol/andrew)p
+Fo('.)0 549 y(By)h(declaring)i(the)e(moun)o(tp)q(oin)o(t)g(to)f(b)q(e)i
+Fl(default)p Fo(,)e(the)h(\014lesystem)h(will)g(b)q(e)g(moun)o(ted)f(on)g
+(the)g(lo)q(cal)h(mac)o(hine)0 598 y(in)f(the)f(automoun)o(ter)f(tree,)h
+(where)g Fp(Amd)j Fo(will)f(automatically)e(inherit)i(the)e(moun)o(t)g(as)f
+(`)p Fl(/vol/andrew)p Fo('.)0 669 y(`)p Fl(exportfs)p Fo(')240
+732 y(a)g(string)h(de\014ning)h(whic)o(h)f(mac)o(hines)g(the)g(\014lesystem)g
+(ma)o(y)f(b)q(e)h(exp)q(orted)g(to.)k(This)c(is)g(copied,)g(as)240
+781 y(is,)g(in)o(to)h(the)f(`)p Fl(exports)p Fo(')e(\014le|no)k(sanit)o(y)e
+(c)o(hec)o(king)h(is)g(p)q(erformed)f(on)g(this)h(string.)0
+844 y(`)p Fl(volname)p Fo(')46 b(a)19 b(string)h(whic)o(h)g(declares)h(the)f
+(remote)f(name)h(b)o(y)f(whic)o(h)i(to)e(reference)h(the)g(\014lesystem.)34
+b(The)240 894 y(string)18 b(is)h(en)o(tered)g(in)o(to)f(a)h(dictionary)g(and)
+g(allo)o(ws)f(y)o(ou)g(to)g(refer)g(to)g(this)h(\014lesystem)g(in)g(other)240
+944 y(places)d(b)o(y)f(this)h(v)o(olume)f(name.)0 1006 y(`)p
+Fl(sel)p Fo(')142 b(a)15 b(string)g(whic)o(h)h(is)g(placed)g(in)o(to)f(the)h
+(automoun)o(ter)e(maps)h(as)f(a)h(selector)h(for)e(the)i(\014lesystem.)0
+1150 y Fi(7.6.6)30 b(dumpset)15 b(Option)62 1242 y Fo(This)d(pro)o(vides)f
+(supp)q(ort)g(for)f(Imp)q(erial)j(College's)e(lo)q(cal)h(\014le)g(bac)o(kup)g
+(to)q(ols)e(and)h(is)h(not)e(do)q(cumen)o(ted)i(further)0 1292
+y(here.)0 1436 y Fi(7.6.7)30 b(log)14 b(Option)62 1527 y Fo(Sp)q(eci\014es)f
+(the)e(log)g(device)i(for)d(the)h(curren)o(t)g(\014lesystem.)19
+b(This)11 b(is)h(ignored)f(if)h(not)e(required)i(b)o(y)f(the)g(particular)0
+1577 y(\014lesystem)16 b(t)o(yp)q(e.)0 1744 y Fq(7.7)33 b Ff(FSinfo)16
+b Fq(static)g(moun)n(ts)62 1836 y Fo(Eac)o(h)j(host)g(ma)o(y)f(also)h(ha)o(v)
+o(e)g(a)g(n)o(um)o(b)q(er)g(of)g(statically)h(moun)o(ted)f(\014lesystems.)32
+b(F)l(or)19 b(example,)h(the)f(host)0 1885 y(ma)o(y)14 b(b)q(e)h(a)f
+(diskless)i(w)o(orkstation)e(in)h(whic)o(h)g(case)g(it)g(will)h(ha)o(v)o(e)e
+(no)h Fl(fs)f Fo(declarations.)20 b(In)15 b(this)g(case)g(the)g
+Fl(mount)0 1935 y Fo(declaration)i(is)g(used)f(to)g(determine)h(from)e(where)
+i(its)f(\014lesystems)h(will)h(b)q(e)e(moun)o(ted.)23 b(In)17
+b(addition)g(to)f(b)q(eing)0 1985 y(added)e(to)e(the)h(`)p
+Fl(fstab)p Fo(')f(\014le,)i(this)g(information)f(can)g(also)g(b)q(e)h(used)g
+(to)e(generate)h(a)g(suitable)h(`)p Fl(bootparams)p Fo(')d(\014le.)120
+2056 y Fl(mount)166 b(:)24 b("mount")f(<)p Fp(v)o(olname)p
+Fl(>)h Fp(list\()t Fl(localinfo)p Fp(\))g Fl(;)120 2155 y(localinfo)70
+b(:)24 b(localinfo_attr)e(<)p Fp(string)p Fl(>)i(;)120 2255
+y(localinfo_attr)406 2305 y(:)g("as")406 2355 y(|)g("from")406
+2404 y(|)g("fstype")406 2454 y(|)g("opts")406 2504 y(;)62 2595
+y Fo(The)17 b(\014lesystem)g(sp)q(eci\014ed)h(to)e(b)q(e)h(moun)o(ted)f(will)
+i(b)q(e)f(searc)o(hed)f(for)g(in)h(the)f(dictionary)i(of)d(v)o(olume)i(names)
+0 2645 y(built)g(when)e(scanning)h(the)g(list)g(of)e(hosts')h(de\014nitions.)
+p eop
+%%Page: 39 41
+39 40 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-39)62
+158 y(The)16 b(attributes)f(ha)o(v)o(e)f(the)i(follo)o(wing)g(seman)o(tics:)0
+229 y(`)p Fl(from)e Fp(mac)o(hine)s Fo(')240 293 y(moun)o(t)h(the)g
+(\014lesystem)h(from)e(the)i(mac)o(hine)g(with)f(the)g(hostname)g(of)g
+Fp(mac)o(hine)p Fo(.)0 356 y(`)p Fl(as)g Fp(moun)o(tp)q(oin)o(t)q
+Fo(')240 420 y(moun)o(t)e(the)h(\014lesystem)g(lo)q(cally)i(as)d(the)h(name)f
+(giv)o(en,)h(in)h(case)e(this)h(is)h(di\013eren)o(t)f(from)e(the)i(adv)o(er-)
+240 470 y(tised)i(v)o(olume)f(name)h(of)e(the)i(\014lesystem.)0
+534 y(`)p Fl(opts)e Fp(options)r Fo(')240 598 y(nativ)o(e)h
+Fk(moun)o(t)p Fo(\(8\))f(options.)0 661 y(`)p Fl(fstype)g Fp(t)o(yp)q(e)s
+Fo(')240 725 y(t)o(yp)q(e)h(of)g(\014lesystem)h(to)e(b)q(e)i(moun)o(ted.)62
+816 y(An)g(example:)120 887 y Fl(mount)23 b(/export/exec/hp300/local)e(as)i
+(/usr/local)62 978 y Fo(If)15 b(the)g(moun)o(tp)q(oin)o(t)g(sp)q(eci\014ed)i
+(is)f(either)g(`)p Fl(/)p Fo(')e(or)g(`)p Fl(swap)p Fo(',)f(the)i(mac)o(hine)
+h(will)h(b)q(e)e(considered)i(to)d(b)q(e)h(b)q(o)q(oting)0
+1028 y(o\013)f(the)h(net)f(and)h(this)g(will)i(b)q(e)e(noted)g(for)f(use)h
+(in)g(generating)g(a)g(`)p Fl(bootparams)p Fo(')d(\014le)k(for)e(the)h(host)f
+(whic)o(h)i(o)o(wns)0 1078 y(the)f(\014lesystems.)0 1254 y
+Fq(7.8)33 b(De\014ning)15 b(an)h Ff(Amd)g Fq(Moun)n(t)g(Map)f(in)h
+Ff(FSinfo)62 1346 y Fo(The)i(maps)f(used)i(b)o(y)e Fp(Amd)j
+Fo(can)d(b)q(e)i(constructed)e(from)g Fp(FSinfo)j Fo(b)o(y)e(de\014ning)h
+(all)f(the)g(automoun)o(t)f(trees.)0 1396 y Fp(FSinfo)h Fo(tak)o(es)c(all)i
+(the)g(de\014nitions)h(found)e(and)h(builds)h(one)e(map)g(for)g(eac)o(h)g
+(top)g(lev)o(el)h(tree.)62 1466 y(The)23 b(automoun)o(t)e(tree)i(is)g
+(usually)h(de\014ned)f(last.)42 b(A)23 b(single)g(automoun)o(t)f
+(con\014guration)g(will)j(usually)0 1516 y(apply)e(to)f(an)g(en)o(tire)h
+(managemen)o(t)e(domain.)41 b(One)23 b Fl(automount)e Fo(declaration)i(is)g
+(needed)h(for)d(eac)o(h)i Fp(Amd)0 1566 y Fo(automoun)o(t)11
+b(p)q(oin)o(t.)20 b Fp(FSinfo)15 b Fo(determines)f(whether)f(the)f(automoun)o
+(t)g(p)q(oin)o(t)h(is)g Fp(direct)h Fo(\(see)f(Section)g(5.9)f([Direct)0
+1616 y(Automoun)o(t)20 b(Filesystem],)i(page)41 b(SMM:13-25\))18
+b(or)j Fp(indirect)i Fo(\(see)d(Section)i(5.12)d([T)l(op-lev)o(el)j
+(Filesystem],)0 1665 y(page)e(SMM:13-26\).)c(Direct)11 b(automoun)o(t)e(p)q
+(oin)o(ts)h(are)g(distinguished)j(b)o(y)d(the)g(fact)g(that)f(there)h(is)h
+(no)f(underlying)0 1715 y Fp(automoun)o(t)p 220 1715 14 2 v
+15 w(tree)p Fo(.)120 1786 y Fl(automount)70 b(:)24 b("automount")e
+(opt\(auto_opts)p Fp(\))h Fl(automount_tree)f(;)120 1885 y(auto_opts)70
+b(:)24 b("opts")f(<)p Fp(moun)o(t-options)p Fl(>)h(;)120 1985
+y(automount_tree)406 2035 y(:)g Fp(list\()t Fl(automount_attr)p
+Fp(\))406 2085 y Fl(;)120 2184 y(automount_attr)406 2234 y(:)g(<)p
+Fp(string)p Fl(>)g("=")f(<)p Fp(v)o(olname)p Fl(>)406 2284
+y(|)h(<)p Fp(string)p Fl(>)g("->")f(<)p Fp(symlink)p Fl(>)406
+2334 y(|)h(<)p Fp(string)p Fl(>)g("{")f(automount_tree)f("}")406
+2384 y(;)62 2475 y Fo(If)15 b Fl(<)p Fp(moun)o(t-options)p
+Fl(>)e Fo(is)i(giv)o(en,)f(then)g(it)g(is)h(the)f(string)g(to)f(b)q(e)i
+(placed)g(in)g(the)f(maps)g(for)f Fp(Amd)j Fo(for)d(the)i Fl(opts)0
+2525 y Fo(option.)62 2595 y(A)d Fp(map)g Fo(is)g(t)o(ypically)h(a)e(tree)g
+(of)g(\014lesystems,)i(for)d(example)j(`)p Fl(home)p Fo(')d(normally)i(con)o
+(tains)f(a)g(tree)g(of)g(\014lesystems)0 2645 y(represen)o(ting)16
+b(other)f(mac)o(hines)h(in)g(the)f(net)o(w)o(ork.)p eop
+%%Page: 40 42
+40 41 bop 15 -83 a Fo(SMM:13-40)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)62 158 y(A)g(map)g(can)h(either)f(b)q(e)h(giv)o(en)g
+(as)f(a)f(name)h(represen)o(ting)h(an)f(already)h(de\014ned)g(v)o(olume)g
+(name,)f(or)f(it)i(can)0 208 y(b)q(e)g(a)g(tree.)27 b(A)18
+b(tree)g(is)g(represen)o(ted)g(b)o(y)g(placing)h(braces)f(after)f(the)h
+(name.)28 b(F)l(or)17 b(example,)i(to)e(de\014ne)i(a)e(tree)0
+258 y(`)p Fl(/vol)p Fo(',)c(the)j(follo)o(wing)g(map)f(w)o(ould)g(b)q(e)h
+(de\014ned:)120 329 y Fl(automount)23 b(/vol)g({)h(})62 420
+y Fo(Within)17 b(a)d(tree,)h(the)g(only)h(items)g(that)e(can)h(app)q(ear)h
+(are)f(more)f(maps.)20 b(F)l(or)15 b(example:)120 490 y Fl(automount)23
+b(/vol)g({)215 540 y(andrew)g({)h(})215 590 y(X11)g({)g(})120
+640 y(})62 731 y Fo(In)13 b(this)g(case,)g Fp(FSinfo)i Fo(will)f(lo)q(ok)e
+(for)g(v)o(olumes)h(named)f(`)p Fl(/vol/andrew)p Fo(')e(and)j(`)p
+Fl(/vol/X11)p Fo(')e(and)h(a)g(map)g(en)o(try)0 781 y(will)17
+b(b)q(e)e(generated)h(for)e(eac)o(h.)20 b(If)15 b(the)g(v)o(olumes)h(are)f
+(de\014ned)h(more)f(than)g(once,)g(then)g Fp(FSinfo)j Fo(will)e(generate)f(a)
+0 831 y(series)h(of)f(alternate)g(en)o(tries)g(for)g(them)g(in)h(the)f(maps.)
+62 901 y(Instead)j(of)g(a)f(tree,)h(either)g(a)f(link)i(\()p
+Fp(name)h Fl(->)d Fp(destination)p Fo(\))i(or)e(a)g(reference)h(can)g(b)q(e)g
+(sp)q(eci\014ed)i(\()p Fp(name)g Fl(=)0 951 y Fp(destination)p
+Fo(\).)i(A)16 b(link)h(creates)f(a)f(sym)o(b)q(olic)i(link)g(to)f(the)f
+(string)h(sp)q(eci\014ed,)i(without)e(further)f(pro)q(cessing)i(the)0
+1001 y(en)o(try)l(.)i(A)13 b(reference)h(will)h(examine)f(the)f(destination)h
+(\014lesystem)g(and)g(optimise)g(the)f(reference.)20 b(F)l(or)12
+b(example,)0 1051 y(to)j(create)g(an)g(en)o(try)f(for)h Fl(njw)g
+Fo(in)h(the)f(`)p Fl(/homes)p Fo(')f(map,)g(either)i(of)f(the)g(t)o(w)o(o)f
+(forms)h(can)g(b)q(e)h(used:)120 1121 y Fl(automount)23 b(/homes)g({)215
+1171 y(njw)h(->)f(/home/dylan/njw)120 1221 y(})62 1312 y Fo(or)120
+1383 y Fl(automount)g(/homes)g({)215 1433 y(njw)h(=)g(/home/dylan/njw)120
+1483 y(})62 1574 y Fo(In)13 b(the)e(\014rst)h(example,)g(when)h(`)p
+Fl(/homes/njw)p Fo(')c(is)j(referenced)h(from)e Fp(Amd)p Fo(,)h(a)f(link)i
+(will)h(b)q(e)e(created)g(leading)h(to)0 1624 y(`)p Fl(/home/dylan/njw)p
+Fo(')f(and)j(the)g(automoun)o(ter)e(will)j(b)q(e)g(referenced)g(a)e(second)h
+(time)g(to)f(resolv)o(e)h(this)g(\014lename.)0 1673 y(The)g(map)g(en)o(try)g
+(w)o(ould)h(b)q(e:)120 1744 y Fl(njw)23 b(type:=link;fs:=/home/dylan/nj)o(w)
+62 1835 y Fo(In)17 b(the)g(second)g(example,)g(the)f(destination)i(directory)
+e(is)h(analysed)g(and)g(found)g(to)e(b)q(e)j(in)f(the)f(\014lesystem)0
+1885 y(`)p Fl(/home/dylan)p Fo(')c(whic)o(h)j(has)g(previously)g(b)q(een)h
+(de\014ned)g(in)f(the)f(maps.)20 b(Hence)15 b(the)f(map)g(en)o(try)g(will)j
+(lo)q(ok)d(lik)o(e:)120 1956 y Fl(njw)23 b(rhost:=dylan;rfs:=/home/dylan)o
+(;sublink)o(:=njw)62 2047 y Fo(Creating)15 b(only)h(one)f(sym)o(b)q(olic)i
+(link,)f(and)f(one)h(access)f(to)g Fp(Amd)p Fo(.)0 2292 y Fq(7.9)33
+b Ff(FSinfo)16 b Fq(Command)f(Line)h(Options)62 2384 y Fp(FSinfo)i
+Fo(is)e(started)e(from)h(the)g(command)g(line)i(b)o(y)e(using)h(the)f
+(command:)120 2454 y Fl(fsinfo)23 b([)p Fp(options)r Fl(])h(files)f(...)62
+2545 y Fo(The)16 b(input)h(to)d Fp(FSinfo)19 b Fo(is)d(a)f(single)i(set)e(of)
+g(de\014nitions)i(of)e(mac)o(hines)i(and)e(automoun)o(t)g(maps.)20
+b(If)c(m)o(ultiple)0 2595 y(\014les)21 b(are)e(giv)o(en)h(on)f(the)h
+(command-line,)i(then)e(the)f(\014les)i(are)e(concatenated)h(together)f(to)f
+(form)h(the)h(input)0 2645 y(source.)g(The)15 b(\014les)i(are)d(passed)i
+(individuall)q(y)i(through)d(the)g(C)g(pre-pro)q(cessor)g(b)q(efore)h(b)q
+(eing)g(parsed.)p eop
+%%Page: 41 43
+41 42 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-41)62
+158 y(Sev)o(eral)18 b(options)f(de\014ne)i(a)e(pre\014x)h(for)e(the)i(name)f
+(of)g(an)g(output)g(\014le.)27 b(If)18 b(the)f(pre\014x)h(is)g(not)f(sp)q
+(eci\014ed)i(no)0 208 y(output)14 b(of)f(that)g(t)o(yp)q(e)h(is)g(pro)q
+(duced.)20 b(The)14 b(su\016x)g(used)g(will)i(corresp)q(ond)e(either)g(to)f
+(the)h(hostname)g(to)f(whic)o(h)h(a)0 258 y(\014le)j(b)q(elongs,)f(or)f(to)g
+(the)g(t)o(yp)q(e)h(of)f(output)g(if)h(only)g(one)g(\014le)g(is)g(pro)q
+(duced.)22 b(Dumpsets)16 b(and)g(the)f(`)p Fl(bootparams)p
+Fo(')0 308 y(\014le)h(are)e(in)h(the)g(latter)f(class.)20 b(T)l(o)14
+b(put)g(the)h(output)f(in)o(to)h(a)f(sub)q(directory)h(simply)h(put)f(a)f(`)p
+Fl(/)p Fo(')f(at)h(the)h(end)g(of)f(the)0 358 y(pre\014x,)h(making)h(sure)f
+(that)f(the)i(directory)f(has)g(already)h(b)q(een)g(made)f(b)q(efore)h
+(running)g(`)p Fl(fsinfo)p Fo('.)0 550 y Fi(7.9.1)30 b Fd(-a)15
+b Fe(auto)q(dir)62 642 y Fo(Sp)q(eci\014es)h(the)e(directory)g(name)g(in)g
+(whic)o(h)h(to)e(place)i(the)f(automoun)o(ter's)e(moun)o(tp)q(oin)o(ts.)19
+b(This)14 b(defaults)h(to)0 691 y(`)p Fl(/a)p Fo('.)k(Some)c(sites)h(ha)o(v)o
+(e)e(the)i(auto)q(dir)f(set)g(to)g(b)q(e)g(`)p Fl(/amd)p Fo(',)f(and)h(this)h
+(w)o(ould)g(b)q(e)f(ac)o(hiev)o(ed)i(b)o(y:)120 762 y Fl(fsinfo)23
+b(-a)h(/amd)f(...)0 955 y Fi(7.9.2)30 b Fd(-b)15 b Fe(b)q(o)q(otparams)62
+1046 y Fo(This)i(sp)q(eci\014es)h(the)f(pre\014x)g(for)f(the)g(`)p
+Fl(bootparams)p Fo(')e(\014lename.)25 b(If)16 b(it)h(is)g(not)f(giv)o(en,)h
+(then)f(the)h(\014le)g(will)h(not)0 1096 y(b)q(e)h(generated.)27
+b(The)18 b(`)p Fl(bootparams)p Fo(')e(\014le)j(will)h(b)q(e)e(constructed)g
+(for)f(the)h(destination)h(mac)o(hine)g(and)f(will)h(b)q(e)0
+1146 y(placed)g(in)o(to)f(a)f(\014le)i(named)f(`)p Fl(bootparams)p
+Fo(')e(and)i(pre\014xed)h(b)o(y)f(this)g(string.)28 b(The)18
+b(\014le)h(generated)e(con)o(tains)h(a)0 1195 y(list)e(of)f(en)o(tries)g
+(describing)i(eac)o(h)f(diskless)g(clien)o(t)h(that)d(can)i(b)q(o)q(ot)f
+(from)f(the)h(destination)h(mac)o(hine.)62 1266 y(As)f(an)g(example,)g(to)f
+(create)g(a)h(`)p Fl(bootparams)p Fo(')d(\014le)k(in)g(the)e(directory)h(`)p
+Fl(generic)p Fo(',)e(the)i(follo)o(wing)g(w)o(ould)g(b)q(e)0
+1316 y(used:)120 1386 y Fl(fsinfo)23 b(-b)h(generic/)e(...)0
+1579 y Fi(7.9.3)30 b Fd(-d)15 b Fe(dumpsets)62 1670 y Fo(This)k(sp)q
+(eci\014es)g(the)f(pre\014x)g(for)f(the)h(`)p Fl(dumpsets)p
+Fo(')d(\014le.)29 b(If)18 b(it)g(is)g(not)f(sp)q(eci\014ed,)j(then)e(the)g
+(\014le)h(will)g(not)e(b)q(e)0 1720 y(generated.)h(The)12 b(\014le)g(will)g
+(b)q(e)g(for)e(the)h(destination)h(mac)o(hine)f(and)h(will)g(b)q(e)g(placed)g
+(in)o(to)f(a)f(\014lename)i(`)p Fl(dumpsets)p Fo(',)0 1770
+y(pre\014xed)k(b)o(y)f(this)h(string.)k(The)15 b(`)p Fl(dumpsets)p
+Fo(')e(\014le)k(is)e(for)g(use)h(b)o(y)f(Imp)q(erial)i(College's)e(lo)q(cal)i
+(bac)o(kup)e(system.)62 1840 y(F)l(or)22 b(example,)i(to)d(create)g(a)h
+(dumpsets)g(\014le)h(in)g(the)f(directory)g(`)p Fl(generic)p
+Fo(',)g(then)g(y)o(ou)f(w)o(ould)i(use)f(the)0 1890 y(follo)o(wing:)120
+1961 y Fl(fsinfo)h(-d)h(generic/)e(...)0 2153 y Fi(7.9.4)30
+b Fd(-e)15 b Fe(exp)q(ortfs)62 2245 y Fo(De\014nes)d(the)g(pre\014x)g(for)f
+(the)g(`)p Fl(exports)p Fo(')f(\014les.)20 b(If)11 b(it)h(is)g(not)f(giv)o
+(en,)i(then)e(the)h(\014le)h(will)g(not)e(b)q(e)h(generated.)19
+b(F)l(or)0 2295 y(eac)o(h)14 b(mac)o(hine)h(de\014ned)g(in)f(the)g
+(con\014guration)g(\014les)h(as)e(ha)o(ving)h(disks,)h(an)f(`)p
+Fl(exports)p Fo(')e(\014le)j(is)f(constructed)g(and)0 2344
+y(giv)o(en)k(a)e(\014lename)j(determined)f(b)o(y)f(the)g(name)g(of)g(the)g
+(mac)o(hine,)h(pre\014xed)g(with)g(this)f(string.)26 b(If)17
+b(a)g(mac)o(hine)0 2394 y(is)j(de\014ned)h(as)e(diskless,)j(then)e(no)f(`)p
+Fl(exports)p Fo(')f(\014le)j(will)g(b)q(e)f(created)g(for)e(it.)34
+b(The)19 b(\014les)i(con)o(tain)f(en)o(tries)g(for)0 2444 y(directories)c(on)
+f(the)h(mac)o(hine)g(that)e(ma)o(y)h(b)q(e)g(exp)q(orted)h(to)f(clien)o(ts.)
+62 2515 y(Example:)k(T)l(o)10 b(create)h(the)g(`)p Fl(exports)p
+Fo(')e(\014les)j(for)e(eac)o(h)h(diskful)h(mac)o(hine)g(and)f(place)h(them)f
+(in)o(to)g(the)g(directory)0 2564 y(`)p Fl(exports)p Fo(':)120
+2635 y Fl(fsinfo)23 b(-e)h(exports/)e(...)p eop
+%%Page: 42 44
+42 43 bop 15 -83 a Fo(SMM:13-42)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fi(7.9.5)30 b Fd(-f)15 b Fe(fstab)62
+250 y Fo(This)f(de\014nes)g(the)f(pre\014x)h(for)e(the)h(`)p
+Fl(fstab)p Fo(')f(\014les.)20 b(The)13 b(\014les)i(will)f(only)g(b)q(e)g
+(created)f(if)g(this)h(pre\014x)f(is)h(de\014ned.)0 299 y(F)l(or)21
+b(eac)o(h)h(mac)o(hine)g(de\014ned)h(in)g(the)f(con\014guration)g(\014les,)i
+(a)d(`)p Fl(fstab)p Fo(')f(\014le)j(is)f(created)g(with)g(the)g(\014lename)0
+349 y(determined)c(b)o(y)f(pre\014xing)h(this)g(string)f(with)g(the)g(name)h
+(of)e(the)h(mac)o(hine.)27 b(These)17 b(\014les)h(con)o(tain)f(en)o(tries)h
+(for)0 399 y(\014lesystems)e(and)f(partitions)h(to)e(moun)o(t)h(at)f(b)q(o)q
+(ot)h(time.)62 470 y(Example,)h(to)e(create)h(the)g(\014les)i(in)f(the)f
+(directory)g(`)p Fl(fstabs)p Fo(':)120 540 y Fl(fsinfo)23 b(-f)h(fstabs/)f
+(...)0 686 y Fi(7.9.6)30 b Fd(-h)15 b Fe(hostname)62 778 y
+Fo(De\014nes)d(the)g(hostname)f(of)g(the)h(destination)g(mac)o(hine)g(to)f
+(pro)q(cess)h(for.)18 b(If)12 b(this)g(is)g(not)f(sp)q(eci\014ed,)j(it)d
+(defaults)0 827 y(to)k(the)g(lo)q(cal)h(mac)o(hine)g(name,)f(as)g(returned)g
+(b)o(y)h Fk(gethostname)p Fo(\(2\).)62 898 y(Example:)120 969
+y Fl(fsinfo)23 b(-h)h(dylan.doc.ic.ac.uk)d(...)0 1115 y Fi(7.9.7)30
+b Fd(-m)15 b Fe(moun)o(t-maps)62 1206 y Fo(De\014nes)k(the)f(pre\014x)g(for)g
+(the)g(automoun)o(ter)f(\014les.)29 b(The)18 b(maps)g(will)i(only)e(b)q(e)h
+(pro)q(duced)g(if)g(this)f(pre\014x)g(is)0 1256 y(de\014ned.)j(The)15
+b(moun)o(t)f(maps)g(suitable)i(for)e(the)h(net)o(w)o(ork)e(de\014ned)j(b)o(y)
+f(the)g(con\014guration)g(\014les)g(will)h(b)q(e)g(placed)0
+1306 y(in)o(to)f(\014les)h(with)g(names)f(calculated)i(b)o(y)e(pre\014xing)h
+(this)g(string)f(to)f(the)i(name)f(of)g(eac)o(h)g(map.)62 1376
+y(F)l(or)g(example,)g(to)g(create)g(the)g(automoun)o(ter)f(maps)h(and)h
+(place)g(them)f(in)h(the)f(directory)h(`)p Fl(automaps)p Fo(':)120
+1447 y Fl(fsinfo)23 b(-m)h(automaps/)e(...)0 1593 y Fi(7.9.8)30
+b Fd(-q)62 1684 y Fo(Selects)21 b(quiet)f(mo)q(de.)34 b Fp(FSinfo)23
+b Fo(suppress)d(the)g(\\running)g(commen)o(tary")f(and)h(only)g(outputs)f(an)
+o(y)h(error)0 1734 y(messages)15 b(whic)o(h)h(are)f(generated.)0
+1880 y Fi(7.9.9)30 b Fd(-v)62 1971 y Fo(Selects)21 b(v)o(erb)q(ose)e(mo)q
+(de.)34 b(When)19 b(this)h(is)g(activ)m(ated,)h(the)f(program)e(will)j
+(displa)o(y)g(more)e(messages,)h(and)0 2021 y(displa)o(y)c(all)g(the)e
+(information)h(disco)o(v)o(ered)h(when)f(p)q(erforming)g(the)g(seman)o(tic)g
+(analysis)g(phase.)20 b(Eac)o(h)15 b(v)o(erb)q(ose)0 2071 y(message)g(is)g
+(output)g(to)g(`)p Fl(stdout)p Fo(')f(on)h(a)g(line)h(starting)f(with)h(a)e
+(`)p Fl(#)p Fo(')h(c)o(haracter.)0 2217 y Fi(7.9.10)29 b Fd(-D)16
+b Fe(name[=defn])62 2308 y Fo(De\014nes)f(a)g(sym)o(b)q(ol)f
+Fp(name)j Fo(for)d(the)h(prepro)q(cessor)g(when)g(reading)g(the)f
+(con\014guration)h(\014les.)21 b(Equiv)m(alen)o(t)16 b(to)0
+2358 y Fl(#define)e Fo(directiv)o(e.)0 2504 y Fi(7.9.11)29
+b Fd(-I)16 b Fe(directory)62 2595 y Fo(This)g(option)g(is)g(passed)g(in)o(to)
+f(the)h(prepro)q(cessor)f(for)g(the)h(con\014guration)f(\014les.)22
+b(It)15 b(sp)q(eci\014es)j(directories)e(in)0 2645 y(whic)o(h)g(to)f(\014nd)h
+(include)h(\014les)p eop
+%%Page: 43 45
+43 44 bop 0 -83 a Fo(Chapter)15 b(7:)k(FSinfo)1362 b(SMM:13-43)0
+158 y Fi(7.9.12)29 b Fd(-U)16 b Fe(name)62 250 y Fo(Remo)o(v)o(es)f(an)o(y)g
+(initial)i(de\014nition)g(of)e(the)h(sym)o(b)q(ol)f Fp(name)p
+Fo(.)20 b(In)o(v)o(erse)15 b(of)g(the)g Fl(-D)g Fo(option.)0
+423 y Fq(7.10)32 b(Errors)16 b(pro)r(duced)g(b)n(y)g Ff(FSinfo)62
+514 y Fo(The)g(follo)o(wing)g(table)f(do)q(cumen)o(ts)h(the)f(errors)f(and)i
+(w)o(arnings)f(whic)o(h)h Fp(FSinfo)i Fo(ma)o(y)c(pro)q(duce.)0
+585 y Fl(can't)23 b(open)g Fp(\014lename)28 b Fl(for)c(writing)240
+648 y Fo(Occurs)16 b(if)g(an)o(y)e(errors)h(are)g(encoun)o(tered)h(when)f(op)
+q(ening)i(an)e(output)g(\014le.)0 712 y Fl(unknown)23 b(host)g(attribute)240
+775 y Fo(Occurs)16 b(if)g(an)f(unrecognised)h(k)o(eyw)o(ord)f(is)g(used)h
+(when)g(de\014ning)h(a)d(host.)0 839 y Fl(unknown)23 b(filesystem)f
+(attribute)240 902 y Fo(Occurs)16 b(if)g(an)f(unrecognised)h(k)o(eyw)o(ord)f
+(is)g(used)h(when)g(de\014ning)h(a)d(host's)h(\014lesystems.)0
+965 y Fl(not)23 b(allowed)g('/')h(in)f(a)h(directory)f(name)240
+1029 y Fo(When)14 b(reading)g(the)g(con\014guration)g(input,)h(if)f(there)g
+(is)g(a)f(\014lesystem)i(de\014nition)g(whic)o(h)g(con)o(tains)240
+1079 y(a)f(pathname)g(with)g(m)o(ultiple)i(directories)f(for)e(an)o(y)h(part)
+f(of)g(the)i(moun)o(tp)q(oin)o(t)f(elemen)o(t,)g(and)g(it)g(is)240
+1128 y(not)h(a)g(single)h(absolute)g(path,)e(then)i(this)g(message)e(will)j
+(b)q(e)f(pro)q(duced)g(b)o(y)g(the)f(parser.)0 1192 y Fl(unknown)23
+b(directory)g(attribute)240 1255 y Fo(If)d(an)g(unkno)o(wn)h(k)o(eyw)o(ord)e
+(is)h(found)h(while)g(reading)g(the)f(de\014nition)i(of)e(a)f(hosts's)g
+(\014lesystem)240 1305 y(moun)o(t)c(option.)0 1368 y Fl(unknown)23
+b(mount)g(attribute)240 1432 y Fo(Occurs)16 b(if)g(an)f(unrecognised)h(k)o
+(eyw)o(ord)f(is)g(found)h(while)h(parsing)e(the)g(list)h(of)f(static)g(moun)o
+(ts.)0 1495 y Fl(")24 b(expected)240 1558 y Fo(Occurs)16 b(if)g(an)f(unescap)
+q(ed)h(newline)i(is)d(found)h(in)g(a)f(quoted)g(string.)0 1622
+y Fl(unknown)23 b(\\)h(sequence)240 1685 y Fo(Occurs)12 b(if)h(an)e(unkno)o
+(wn)h(escap)q(e)h(sequence)g(is)f(found)g(inside)i(a)d(string.)19
+b(Within)13 b(a)e(string,)h(y)o(ou)g(can)240 1735 y(giv)o(e)j(the)g(standard)
+g(C)g(escap)q(e)h(sequences)g(for)e(strings,)h(suc)o(h)h(as)e(newlines)j(and)
+e(tab)g(c)o(haracters.)0 1798 y Fp(\014lename)s Fl(:)24 b(cannot)f(open)h
+(for)f(reading)240 1862 y Fo(If)18 b(a)f(\014le)h(sp)q(eci\014ed)i(on)d(the)h
+(command)f(line)i(as)e(con)o(taining)h(con\014guration)g(data)f(could)h(not)f
+(b)q(e)240 1912 y(op)q(ened.)0 1975 y Fl(end)23 b(of)h(file)f(within)g
+(comment)240 2038 y Fo(A)15 b(commen)o(t)g(w)o(as)f(un)o(terminated)i(b)q
+(efore)g(the)f(end)h(of)e(one)i(of)f(the)g(con\014guration)g(\014les.)0
+2102 y Fl(host)23 b(field)g(")p Fp(\014eld-name)s Fl(")i(already)e(set)240
+2165 y Fo(If)15 b(duplicate)i(de\014nitions)g(are)e(giv)o(en)h(for)f(an)o(y)f
+(of)h(the)g(\014elds)i(with)e(a)g(host)g(de\014nition.)0 2229
+y Fl(duplicate)23 b(host)g Fp(hostname)s Fl(!)240 2292 y Fo(If)15
+b(a)g(host)g(has)g(more)g(than)g(one)g(de\014nition.)0 2355
+y Fl(netif)23 b(field)g Fp(\014eld-name)28 b Fl(already)23
+b(set)240 2419 y Fo(Occurs)16 b(if)g(y)o(ou)e(attempt)h(to)f(de\014ne)j(an)e
+(attribute)g(of)f(an)i(in)o(terface)f(more)g(than)g(once.)0
+2482 y Fl(malformed)23 b(IP)g(dotted)g(quad:)g Fp(address)240
+2545 y Fo(If)e(the)g(In)o(ternet)h(address)f(of)f(an)h(in)o(terface)g(is)h
+(incorrectly)g(sp)q(eci\014ed.)39 b(An)22 b(In)o(ternet)f(address)240
+2595 y(de\014nition)e(is)e(handled)i(to)d Fk(inet)p 801 2595
+14 3 v 17 w(addr)p Fo(\(3N\))h(to)f(see)i(if)f(it)g(can)g(cop)q(e.)26
+b(If)17 b(not,)g(then)g(this)g(message)240 2645 y(will)g(b)q(e)f(displa)o(y)o
+(ed.)p eop
+%%Page: 44 46
+44 45 bop 15 -83 a Fo(SMM:13-44)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fl(malformed)23 b(netmask:)f
+Fp(netmask)240 223 y Fo(If)16 b(the)g(netmask)f(cannot)g(b)q(e)i(deco)q(ded)g
+(as)e(though)h(it)g(w)o(ere)f(a)g(hexadecimal)j(n)o(um)o(b)q(er,)d(then)i
+(this)240 273 y(message)i(will)h(b)q(e)g(displa)o(y)o(ed.)32
+b(It)19 b(will)i(t)o(ypically)f(b)q(e)g(caused)g(b)o(y)e(incorrect)i(c)o
+(haracters)e(in)i(the)240 322 y Fp(netmask)e Fo(v)m(alue.)0
+387 y Fl(fs)24 b(field)f(")p Fp(\014eld-name)s Fl(")h(already)f(set)240
+451 y Fo(Occurs)16 b(when)g(m)o(ultiple)h(de\014nitions)g(are)e(giv)o(en)h
+(for)f(one)g(of)g(the)g(attributes)h(of)e(a)h(host's)g(\014lesys-)240
+501 y(tem.)0 565 y Fl(mount)23 b(tree)g(field)h(")p Fp(\014eld-name)s
+Fl(")g(already)f(set)240 630 y Fo(Occurs)13 b(when)h(the)f
+Fp(\014eld-name)j Fo(is)e(de\014ned)g(more)e(than)h(once)g(during)h(the)f
+(de\014nition)h(of)e(a)h(\014lesys-)240 680 y(tems)i(moun)o(tp)q(oin)o(t.)0
+744 y Fl(mount)23 b(field)g(")p Fp(\014eld-name)s Fl(")i(already)e(set)240
+809 y Fo(Occurs)16 b(when)g(a)e(static)h(moun)o(t)g(has)g(m)o(ultiple)i
+(de\014nitions)g(of)e(the)g(same)g(\014eld.)0 873 y Fl(no)24
+b(disk)f(mounts)g(on)h Fp(hostname)240 937 y Fo(If)11 b(there)g(are)g(no)g
+(static)g(moun)o(ts,)g(nor)f(lo)q(cal)i(disk)g(moun)o(ts)f(sp)q(eci\014ed)i
+(for)d(a)h(mac)o(hine,)h(this)f(message)240 987 y(will)17 b(b)q(e)f(displa)o
+(y)o(ed.)0 1052 y Fp(host)q Fl(:)p Fp(device)27 b Fl(needs)d(field)f(")p
+Fp(\014eld-name)s Fl(")240 1116 y Fo(Occurs)13 b(when)f(a)g(\014lesystem)g
+(is)h(missing)f(a)g(required)h(\014eld.)20 b Fp(\014eld-name)c
+Fo(could)d(b)q(e)g(one)f(of)f Fl(fstype)p Fo(,)240 1166 y Fl(opts)p
+Fo(,)j Fl(passno)h Fo(or)f Fl(mount)p Fo(.)0 1230 y Fp(\014lesystem)25
+b Fl(has)e(a)h(volname)f(but)g(no)h(exportfs)e(data)240 1295
+y Fo(Occurs)13 b(when)f(a)g(v)o(olume)h(name)f(is)g(declared)i(for)d(a)h
+(\014le)h(system,)f(but)g(the)g(string)g(sp)q(ecifying)j(what)240
+1345 y(mac)o(hines)h(the)f(\014lesystem)h(can)f(b)q(e)h(exp)q(orted)g(to)e
+(is)i(missing.)0 1409 y Fl(sub-directory)22 b Fp(directory)28
+b Fl(of)c Fp(directory-tree)i Fl(starts)d(with)h('/')240 1473
+y Fo(Within)13 b(the)f(\014lesystem)h(sp)q(eci\014cation)h(for)d(a)h(host,)f
+(if)i(an)f(elemen)o(t)g Fp(directory)k Fo(of)c(the)g(moun)o(tp)q(oin)o(t)240
+1523 y(b)q(egins)k(with)g(a)f(`)p Fl(/)p Fo(')f(and)h(it)h(is)g(not)e(the)i
+(start)e(of)g(the)i(tree.)0 1588 y Fp(host)q Fl(:)p Fp(device)27
+b Fl(has)d(no)f(mount)h(point)240 1652 y Fo(Occurs)16 b(if)g(the)f(`)p
+Fl(mount)p Fo(')f(option)h(is)h(not)e(sp)q(eci\014ed)k(for)c(a)h(host's)g
+(\014lesystem.)0 1717 y Fp(host)q Fl(:)p Fp(device)27 b Fl(has)d(more)f(than)
+g(one)h(mount)f(point)240 1781 y Fo(Occurs)17 b(if)g(the)g(moun)o(t)f(option)
+h(for)f(a)g(host's)g(\014lesystem)h(sp)q(eci\014es)h(m)o(ultiple)h(trees)d
+(at)g(whic)o(h)i(to)240 1831 y(place)e(the)f(moun)o(tp)q(oin)o(t.)0
+1895 y Fl(no)24 b(volname)e(given)i(for)f Fp(host)q Fl(:)p
+Fp(device)240 1960 y Fo(Occurs)15 b(when)h(a)e(\014lesystem)h(is)g(de\014ned)
+h(to)e(b)q(e)i(moun)o(ted)e(on)h(`)p Fl(default)p Fo(',)e(but)h(no)h(v)o
+(olume)g(name)240 2009 y(is)h(giv)o(en)f(for)g(the)g(\014le)h(system,)f(then)
+g(the)h(moun)o(tp)q(oin)o(t)f(cannot)g(b)q(e)h(determined.)0
+2074 y Fp(host)q Fl(:mount)23 b(field)g(specified)f(for)i(swap)f(partition)
+240 2138 y Fo(Occurs)16 b(if)g(a)e(moun)o(tp)q(oin)o(t)i(is)f(giv)o(en)h(for)
+f(a)f(\014lesystem)i(whose)f(t)o(yp)q(e)h(is)f(declared)i(to)d(b)q(e)i
+Fl(swap)p Fo(.)0 2203 y Fl(ambiguous)23 b(mount:)g Fp(v)o(olume)k
+Fl(is)c(a)h(replicated)e(filesystem)240 2267 y Fo(If)17 b(sev)o(eral)f
+(\014lesystems)h(are)f(declared)h(as)f(ha)o(ving)g(the)h(same)f(v)o(olume)g
+(name,)h(they)f(will)i(b)q(e)f(con-)240 2317 y(sidered)j(replicated)h
+(\014lesystems.)33 b(T)l(o)19 b(moun)o(t)g(a)g(replicated)h(\014lesystem)g
+(statically)l(,)h(a)e(sp)q(eci\014c)240 2367 y(host)e(will)h(need)g(to)e(b)q
+(e)i(named,)f(to)g(sa)o(y)f(whic)o(h)i(particular)f(cop)o(y)g(to)g(try)f(and)
+h(moun)o(t,)g(else)h(this)240 2417 y(error)c(will)j(result.)0
+2481 y Fl(cannot)23 b(determine)g(localname)f(since)h(volname)g
+Fp(v)o(olume)k Fl(is)d(not)f(uniquely)g(defined)240 2545 y
+Fo(If)c(a)g(v)o(olume)h(is)g(replicated)g(and)g(an)f(attempt)f(is)i(made)f
+(to)f(moun)o(t)h(the)g(\014lesystem)h(statically)240 2595 y(without)d(sp)q
+(ecifying)j(a)d(lo)q(cal)h(moun)o(tp)q(oin)o(t,)g Fp(FSinfo)i
+Fo(cannot)d(calculate)h(a)f(moun)o(tp)q(oin)o(t,)h(as)f(the)240
+2645 y(desired)f(pathname)g(w)o(ould)f(b)q(e)h(am)o(biguous.)p
+eop
+%%Page: 45 47
+45 46 bop 0 -83 a Fo(Chapter)15 b(8:)k(Examples)1300 b(SMM:13-45)0
+158 y Fl(volname)23 b Fp(v)o(olume)k Fl(is)c(unknown)240 223
+y Fo(Occurs)14 b(if)g(an)f(attempt)f(is)i(made)f(to)f(moun)o(t)h(or)g
+(reference)g(a)g(v)o(olume)h(name)f(whic)o(h)h(has)f(not)g(b)q(een)240
+273 y(declared)j(during)g(the)g(host)f(\014lesystem)g(de\014nitions.)0
+338 y Fl(volname)23 b Fp(v)o(olume)k Fl(not)c(exported)g(from)g
+Fp(mac)o(hine)240 402 y Fo(Occurs)d(if)h(y)o(ou)e(attempt)g(to)g(moun)o(t)g
+(the)h(v)o(olume)g Fp(v)o(olume)j Fo(from)c(a)g(mac)o(hine)i(whic)o(h)g(has)e
+(not)240 452 y(declared)d(itself)h(to)d(ha)o(v)o(e)h(suc)o(h)g(a)g
+(\014lesystem)h(a)o(v)m(ailable.)0 517 y Fl(network)23 b(booting)g(requires)g
+(both)g(root)g(and)h(swap)f(areas)240 581 y Fo(Occurs)18 b(if)g(a)f(mac)o
+(hine)h(has)f(moun)o(t)g(declarations)h(for)e(either)i(the)f(ro)q(ot)g
+(partition)g(or)g(the)h(sw)o(ap)240 631 y(area,)12 b(but)f(not)h(b)q(oth.)19
+b(Y)l(ou)12 b(cannot)f(de\014ne)i(a)f(mac)o(hine)g(to)g(only)g(partially)h(b)
+q(o)q(ot)e(via)i(the)e(net)o(w)o(ork.)0 696 y Fl(unknown)23
+b(volname)g Fp(v)o(olume)k Fl(automounted)22 b Fp([)29 b Fl(on)24
+b(<name>)f Fp(])240 761 y Fo(Occurs)c(if)f Fp(v)o(olume)j Fo(is)e(used)g(in)g
+(a)e(de\014nition)j(of)e(an)g(automoun)o(t)f(map)h(but)g(the)g(v)o(olume)h
+(name)240 810 y(has)c(not)g(b)q(een)h(declared)h(during)f(the)f(host)g
+(\014lesystem)h(de\014nitions.)0 875 y Fl(not)23 b(allowed)g('/')h(in)f(a)h
+(directory)f(name)240 940 y Fo(Occurs)15 b(when)g(a)f(pathname)g(with)h(m)o
+(ultiple)h(directory)f(elemen)o(ts)g(is)g(sp)q(eci\014ed)i(as)d(the)g(name)h
+(for)240 990 y(an)g(automoun)o(ter)f(tree.)20 b(A)15 b(tree)g(should)h(only)g
+(ha)o(v)o(e)f(one)g(name)g(at)g(eac)o(h)g(lev)o(el.)0 1054
+y Fp(device)28 b Fl(has)23 b(duplicate)g(exportfs)g(data)240
+1119 y Fo(Pro)q(duced)16 b(if)h(the)e(`)p Fl(exportfs)p Fo(')f(option)i(is)g
+(used)g(m)o(ultiple)i(times)d(within)i(the)f(same)f(branc)o(h)h(of)f(a)240
+1169 y(\014lesytem)e(de\014nition.)21 b(F)l(or)12 b(example,)h(if)g(y)o(ou)f
+(attempt)f(to)h(set)g(the)h(`)p Fl(exportfs)p Fo(')d(data)i(at)g(di\013eren)o
+(t)240 1219 y(lev)o(els)k(of)f(the)h(moun)o(tp)q(oin)o(t)f(directory)g(tree.)
+0 1283 y Fl(sub-directory)22 b(of)i Fp(directory-tree)i Fl(is)e(named)f
+("default")240 1348 y Fo(`)p Fl(default)p Fo(')17 b(is)h(a)g(k)o(eyw)o(ord)g
+(used)h(to)f(sp)q(ecify)h(if)g(a)f(moun)o(tp)q(oin)o(t)g(should)i(b)q(e)f
+(automatically)f(cal-)240 1398 y(culated)g(b)o(y)f Fp(FSinfo)p
+Fo(.)25 b(If)17 b(y)o(ou)g(attempt)f(to)g(sp)q(ecify)i(a)f(directory)g(name)g
+(as)f(this,)i(it)f(will)i(use)e(the)240 1448 y(\014lename)f(of)f(`)p
+Fl(default)p Fo(')f(but)h(will)i(pro)q(duce)f(this)f(w)o(arning.)0
+1512 y Fl(pass)23 b(number)g(for)h Fp(host)q Fl(:)p Fp(device)j
+Fl(is)d(non-zero)240 1577 y Fo(Occurs)14 b(if)h Fp(device)i
+Fo(has)d(its)g(`)p Fl(fstype)p Fo(')e(declared)j(to)e(b)q(e)h(`)p
+Fl(swap)p Fo(')f(or)g(`)p Fl(export)p Fo(')f(and)i(the)g Fk(fsc)o(k)p
+Fo(\(8\))e(pass)240 1627 y(n)o(um)o(b)q(er)i(is)h(set.)k(Sw)o(ap)14
+b(devices)h(should)g(not)e(b)q(e)i(fsc)o(k'd.)k(See)14 b(Section)h(7.6.1)d
+([FSinfo)i(\014lesystems)240 1677 y(fst)o(yp)q(e],)g(page)31
+b(SMM:13-36)0 1741 y Fl(dump)23 b(frequency)g(for)g Fp(host)q
+Fl(:)p Fp(device)28 b Fl(is)23 b(non-zero)240 1806 y Fo(Occurs)12
+b(if)h Fp(device)i Fo(has)d(its)g(`)p Fl(fstype)p Fo(')e(declared)j(to)e(b)q
+(e)h(`)p Fl(swap)p Fo(')e(or)i(`)p Fl(export)p Fo(')e(and)i(the)f(`)p
+Fl(dump)p Fo(')g(option)240 1856 y(is)16 b(set)f(to)f(a)h(v)m(alue)i(greater)
+d(than)h(zero.)20 b(Sw)o(ap)15 b(devices)h(should)g(not)f(b)q(e)h(dump)q(ed.)
+0 2065 y Fm(8)41 b(Examples)0 2313 y Fq(8.1)33 b(User)14 b(Filesystems)62
+2404 y Fo(With)g(more)g(than)g(one)g(\014leserv)o(er,)g(the)g(directories)h
+(most)e(frequen)o(tly)i(cross-moun)o(ted)e(are)h(those)g(con)o(tain-)0
+2454 y(ing)19 b(user)g(home)f(directories.)31 b(A)19 b(common)f(con)o(v)o(en)
+o(tion)h(used)g(at)f(Imp)q(erial)i(College)f(is)g(to)f(moun)o(t)g(the)h(user)
+0 2504 y(disks)d(under)g Fl(/home/)p Fp(mac)o(hine)p Fo(.)62
+2575 y(T)o(ypically)l(,)h(the)e(`)p Fl(/etc/fstab)p Fo(')e(\014le)j(con)o
+(tained)g(a)f(long)h(list)g(of)e(en)o(tries)i(suc)o(h)f(as:)120
+2645 y Fp(mac)o(hine)s Fl(:/home/)p Fp(mac)o(hine)27 b Fl(/home/)p
+Fp(mac)o(hine)f Fl(nfs)e(...)p eop
+%%Page: 46 48
+46 47 bop 15 -83 a Fo(SMM:13-46)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)62 158 y(for)e(eac)o(h)g(\014leserv)o(er)h(on)f(the)g
+(net)o(w)o(ork.)62 229 y(There)20 b(are)e(n)o(umerous)h(problems)h(with)f
+(this)h(system.)31 b(The)19 b(moun)o(t)f(list)i(can)f(b)q(ecome)h(quite)g
+(large)f(and)0 279 y(some)d(of)h(the)f(mac)o(hines)i(ma)o(y)e(b)q(e)h(do)o
+(wn)g(when)g(a)f(system)h(is)g(b)q(o)q(oted.)24 b(When)18 b(a)e(new)h
+(\014leserv)o(er)g(is)g(installed,)0 329 y(`)p Fl(/etc/fstab)p
+Fo(')d(m)o(ust)h(b)q(e)i(up)q(dated)g(on)f(ev)o(ery)g(mac)o(hine,)g(the)g
+(moun)o(t)g(directory)g(created)g(and)g(the)g(\014lesystem)0
+378 y(moun)o(ted.)62 449 y(In)f(man)o(y)f(en)o(vironmen)o(ts)h(most)e(p)q
+(eople)j(use)f(the)f(same)g(few)g(w)o(orkstations,)f(but)i(it)f(is)h(con)o(v)
+o(enien)o(t)g(to)f(go)g(to)0 499 y(a)i(colleague's)g(mac)o(hine)h(and)f
+(access)g(y)o(our)f(o)o(wn)h(\014les.)23 b(When)16 b(a)f(serv)o(er)h(go)q(es)
+f(do)o(wn,)h(it)g(can)g(cause)g(a)g(pro)q(cess)0 549 y(on)e(a)g(clien)o(t)h
+(mac)o(hine)g(to)e(hang.)20 b(By)14 b(minimising)i(the)e(moun)o(ted)g
+(\014lesystems)h(to)e(only)i(include)h(those)e(activ)o(ely)0
+598 y(b)q(eing)i(used,)g(there)f(is)h(less)g(c)o(hance)f(that)g(a)g
+(\014lesystem)h(will)h(b)q(e)e(moun)o(ted)h(when)f(a)g(serv)o(er)g(go)q(es)g
+(do)o(wn.)62 669 y(The)f(follo)o(wing)g(is)g(a)f(short)g(extract)f(from)h(a)g
+(map)g(tak)o(en)g(from)g(a)g(researc)o(h)g(\014leserv)o(er)i(at)d(Imp)q
+(erial)j(College.)62 739 y(Note)g(the)h(en)o(try)f(for)f(`)p
+Fl(localhost)p Fo(')g(whic)o(h)i(is)f(used)h(for)f(users)g(suc)o(h)h(as)f
+(the)g(op)q(erator)g(\(`)p Fl(opr)p Fo('\))e(who)i(ha)o(v)o(e)g(a)0
+789 y(home)g(directory)h(on)f(most)f(mac)o(hine)i(as)f(`)p
+Fl(/home/localhost/opr)p Fo('.)120 860 y Fl(/defaults)166 b
+(opts:=rw,intr,grpid,nosui)o(d)120 910 y(charm)262 b
+(host!=${key};type:=nfs;rh)o(ost:=${)o(key};rf)o(s:=/home)o(/${key})20
+b(\\)502 959 y(host==${key};type:=ufs;de)o(v:=/dev)o(/xd0g)120
+1009 y(#)120 1059 y(...)120 1159 y(#)120 1209 y(localhost)166
+b(type:=link;fs:=${host})120 1258 y(...)120 1308 y(#)120 1358
+y(#)24 b(dylan)f(has)g(two)h(user)f(disks)g(so)h(have)f(a)120
+1408 y(#)h(top)f(directory)g(in)g(which)h(to)f(mount)g(them.)120
+1458 y(#)120 1507 y(dylan)262 b(type:=auto;fs:=${map};pre)o(f:=${ke)o(y}/)120
+1557 y(#)120 1607 y(dylan/dk2)166 b(host!=dylan;type:=nfs;rho)o(st:=dyl)o
+(an;rfs:)o(=/home/$)o({key})21 b(\\)502 1657 y(host==dylan;type:=ufs;dev)o
+(:=/dev/)o(dsk/2s0)120 1707 y(#)120 1757 y(dylan/dk5)166 b
+(host!=dylan;type:=nfs;rho)o(st:=dyl)o(an;rfs:)o(=/home/$)o({key})21
+b(\\)502 1806 y(host==dylan;type:=ufs;dev)o(:=/dev/)o(dsk/5s0)120
+1856 y(...)120 1906 y(#)120 1956 y(toytown)214 b(host!=${key};type:=nfs;rh)o
+(ost:=${)o(key};rf)o(s:=/home)o(/${key})20 b(\\)502 2006 y
+(host==${key};type:=ufs;de)o(v:=/dev)o(/xy1g)120 2055 y(...)120
+2105 y(#)120 2155 y(zebedee)214 b(host!=${key};type:=nfs;rh)o(ost:=${)o
+(key};rf)o(s:=/home)o(/${key})20 b(\\)502 2205 y(host==${key};type:=ufs;de)o
+(v:=/dev)o(/dsk/1s)o(0)120 2255 y(#)120 2304 y(#)k(Just)f(for)g(access...)120
+2354 y(#)120 2404 y(gould)262 b(type:=auto;fs:=${map};pre)o(f:=${ke)o(y}/)120
+2454 y(gould/staff)118 b(host!=gould;type:=nfs;rho)o(st:=gou)o(ld;rfs:)o
+(=/home/$)o({key})120 2504 y(#)120 2554 y(gummo)262 b
+(host!=${key};type:=nfs;rh)o(ost:=${)o(key};rf)o(s:=/home)o(/${key})120
+2603 y(...)p eop
+%%Page: 47 49
+47 48 bop 0 -83 a Fo(Chapter)15 b(8:)k(Examples)1300 b(SMM:13-47)62
+158 y(This)17 b(map)e(is)h(shared)g(b)o(y)g(most)e(of)i(the)f(mac)o(hines)i
+(listed)g(so)e(on)g(those)h(systems)f(an)o(y)g(of)h(the)f(user)h(disks)g(is)0
+208 y(accessible)h(via)f(a)e(consisten)o(t)i(name.)k Fp(Amd)d
+Fo(is)f(started)e(with)i(the)f(follo)o(wing)h(command)120 279
+y Fl(amd)23 b(/home)h(amd.home)62 370 y Fo(Note)16 b(that)g(when)g(moun)o
+(ting)h(a)e(remote)h(\014lesystem,)h(the)f Fp(automoun)o(ted)h
+Fo(moun)o(t)f(p)q(oin)o(t)h(is)f(referenced,)h(so)0 420 y(that)c(the)h
+(\014lesystem)h(will)g(b)q(e)g(moun)o(ted)f(if)g(it)g(is)g(not)g(y)o(et)f
+(\(at)g(the)h(time)g(the)g(remote)g(`)p Fl(mountd)p Fo(')e(obtains)i(the)g
+(\014le)0 470 y(handle\).)0 628 y Fq(8.2)33 b(Home)14 b(Directories)62
+719 y Fo(One)e(con)o(v)o(en)o(tion)e(for)g(home)h(directories)h(is)f(to)f(lo)
+q(cate)h(them)f(in)i(`)p Fl(/homes)p Fo(')d(so)h(user)h(`)p
+Fl(jsp)p Fo(''s)e(home)i(directory)f(is)0 769 y(`)p Fl(/homes/jsp)p
+Fo('.)17 b(With)e(more)f(than)h(a)f(single)i(\014leserv)o(er)f(it)f(is)h(con)
+o(v)o(enien)o(t)h(to)d(spread)i(user)g(\014les)g(across)f(sev)o(eral)0
+819 y(mac)o(hines.)34 b(All)21 b(that)f(is)g(required)h(is)f(a)f(moun)o
+(t-map)h(whic)o(h)g(con)o(v)o(erts)f(login)i(names)f(to)f(an)h(automoun)o
+(ted)0 868 y(directory)l(.)62 939 y(Suc)o(h)c(a)f(map)g(migh)o(t)g(b)q(e)h
+(started)e(b)o(y)h(the)h(command:)120 1010 y Fl(amd)23 b(/homes)g(amd.homes)
+62 1101 y Fo(where)16 b(the)f(map)g(`)p Fl(amd.homes)p Fo(')e(con)o(tained)j
+(the)f(en)o(tries:)120 1171 y Fl(/defaults)70 b(type:=link)h(#)23
+b(All)h(the)f(entries)g(are)h(of)f(type:=link)120 1221 y(jsp)214
+b(fs:=/home/charm/jsp)120 1271 y(njw)g(fs:=/home/dylan/dk5/njw)120
+1321 y(...)120 1371 y(phjk)190 b(fs:=/home/toytown/ai/phjk)120
+1421 y(sjv)214 b(fs:=/home/ganymede/sjv)62 1512 y Fo(Whenev)o(er)21
+b(a)e(login)i(name)f(is)g(accessed)h(in)g(`)p Fl(/homes)p Fo(')d(a)i(sym)o(b)
+q(olic)h(link)g(app)q(ears)f(p)q(oin)o(ting)h(to)f(the)g(real)0
+1562 y(lo)q(cation)12 b(of)f(that)f(user's)h(home)h(directory)l(.)19
+b(In)12 b(this)f(example,)i(`)p Fl(/homes/jsp)p Fo(')c(w)o(ould)j(app)q(ear)f
+(to)g(b)q(e)h(a)f(sym)o(b)q(olic)0 1611 y(link)17 b(p)q(oin)o(ting)f(to)e(`)p
+Fl(/home/charm/jsp)p Fo('.)k(Of)d(course,)g(`)p Fl(/home)p
+Fo(')f(w)o(ould)h(also)g(b)q(e)h(an)f(automoun)o(t)f(p)q(oin)o(t.)62
+1682 y(This)j(system)f(causes)h(an)f(extra)g(lev)o(el)h(of)f(sym)o(b)q(olic)i
+(links)f(to)f(b)q(e)h(used.)24 b(Although)17 b(that)e(turns)i(out)f(to)f(b)q
+(e)0 1732 y(relativ)o(ely)i(inexp)q(ensiv)o(e,)i(an)d(alternativ)o(e)g(is)h
+(to)f(directly)h(moun)o(t)f(the)g(required)h(\014lesystems)g(in)g(the)g(`)p
+Fl(/homes)p Fo(')0 1782 y(map.)i(The)14 b(required)g(map)f(is)h(simple,)h
+(but)e(long,)h(and)f(its)h(creation)f(is)h(b)q(est)g(automated.)k(The)c(en)o
+(try)e(for)h(`)p Fl(jsp)p Fo(')0 1831 y(could)j(b)q(e:)120
+1902 y Fl(jsp)71 b(-sublink:=${key};rfs:=/home)o(/charm)21
+b(\\)478 1952 y(host==charm;type:=ufs;dev:)o(=/dev/x)o(d0g)g(\\)478
+2002 y(host!=charm;type:=nfs;rhos)o(t:=char)o(m)62 2093 y Fo(This)14
+b(map)g(can)f(b)q(ecome)h(quite)h(big)f(if)f(it)h(con)o(tains)g(a)f(large)g
+(n)o(um)o(b)q(er)h(of)f(en)o(tries.)20 b(By)14 b(com)o(bining)g(t)o(w)o(o)e
+(other)0 2143 y(features)j(of)g Fp(Amd)i Fo(it)e(can)h(b)q(e)f(greatly)g
+(simpli\014ed.)62 2213 y(First)e(the)g(UFS)g(partitions)g(should)h(b)q(e)g
+(moun)o(ted)f(under)h(the)f(con)o(trol)f(of)h(`)p Fl(/etc/fstab)p
+Fo(',)e(taking)i(care)g(that)0 2263 y(they)j(are)f(moun)o(ted)g(in)i(the)e
+(same)h(place)g(that)f Fp(Amd)i Fo(w)o(ould)f(ha)o(v)o(e)f(automoun)o(ted)g
+(them.)21 b(In)16 b(most)f(cases)h(this)0 2313 y(w)o(ould)e(b)q(e)h
+(something)f(lik)o(e)h(`)p Fl(/a/)p Fp(host)q Fl(/home/)p Fp(host)q
+Fo(')c(and)j(`)p Fl(/etc/fstab)p Fo(')e(on)i(host)f(`)p Fl(charm)p
+Fo(')f(w)o(ould)j(ha)o(v)o(e)e(a)h(line:)120 2384 y Fl(/dev/xy0g)23
+b(/a/charm/home/charm)e(4.2)i(rw,nosuid,grpid)f(1)i(5)62 2475
+y Fo(The)16 b(map)f(can)g(then)h(b)q(e)f(c)o(hanged)h(to:)120
+2545 y Fl(/defaults)94 b(type:=nfs;sublink:=${key};op)o(ts:=rw,)o(intr,no)o
+(suid,grp)o(id)120 2595 y(jsp)238 b(rhost:=charm;rfs:=/home/char)o(m)120
+2645 y(njw)g(rhost:=dylan;rfs:=/home/dyla)o(n/dk5)p eop
+%%Page: 48 50
+48 49 bop 15 -83 a Fo(SMM:13-48)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)120 158 y Fl(...)120 208 y(phjk)214
+b(rhost:=toytown;rfs:=/home/to)o(ytown;s)o(ublink:)o(=ai/${ke)o(y})120
+258 y(sjv)238 b(rhost:=ganymede;rfs:=/home/g)o(anymede)62 349
+y Fo(This)17 b(map)e(op)q(erates)h(as)f(usual)h(on)g(a)f(remote)h(mac)o(hine)
+g(\()p Fp(ie)j Fl(${host})c Fo(not)g(equal)h(to)g Fl(${rhost})p
+Fo(\).)k(On)c(the)0 399 y(mac)o(hine)f(where)f(the)f(\014lesystem)i(is)f
+(stored)f(\()p Fp(ie)k Fl(${host})c Fo(equal)h(to)g Fl(${rhost})p
+Fo(\),)e Fp(Amd)k Fo(will)f(construct)e(a)h(lo)q(cal)0 449
+y(\014lesystem)k(moun)o(t)g(p)q(oin)o(t)g(whic)o(h)h(corresp)q(onds)f(to)f
+(the)h(name)g(of)f(the)h(lo)q(cally)h(moun)o(ted)f(UFS)g(partition.)28
+b(If)0 499 y Fp(Amd)18 b Fo(is)f(started)f(with)h(the)f(\\-r")g(option)g
+(then)h(instead)g(of)f(attempting)g(an)g(NFS)h(moun)o(t,)e
+Fp(Amd)k Fo(will)f(simply)0 549 y(inherit)d(the)f(UFS)g(moun)o(t)f(\(see)h
+(Section)h(5.14)d([Inheritance)j(Filesystem],)f(page)28 b(SMM:13-26\).)17
+b(If)d(\\-r")f(is)h(not)0 598 y(used)i(then)g(a)f(lo)q(opbac)o(k)g(NFS)h
+(moun)o(t)e(will)j(b)q(e)f(made.)21 b(This)16 b(t)o(yp)q(e)f(of)g(moun)o(t)g
+(is)h(kno)o(wn)f(to)f(cause)i(a)f(deadlo)q(c)o(k)0 648 y(on)g(man)o(y)g
+(systems.)0 810 y Fq(8.3)33 b(Arc)n(hitecture)16 b(Sharing)62
+902 y Fo(Often)h(a)f(\014lesystem)h(will)h(b)q(e)f(shared)f(b)o(y)h(mac)o
+(hines)g(of)f(di\013eren)o(t)g(arc)o(hitectures.)24 b(Separate)16
+b(trees)g(can)g(b)q(e)0 951 y(main)o(tained)f(for)f(the)g(executable)h
+(images)f(for)g(eac)o(h)g(arc)o(hitecture,)g(but)h(it)f(ma)o(y)g(b)q(e)g
+(more)g(con)o(v)o(enien)o(t)h(to)e(ha)o(v)o(e)0 1001 y(a)i(shared)g(tree,)g
+(with)g(distinct)i(sub)q(directories.)62 1072 y(A)23 b(shared)f(tree)h(migh)o
+(t)f(ha)o(v)o(e)g(the)h(follo)o(wing)g(structure)f(on)g(the)h(\014leserv)o
+(er)g(\(called)h(`)p Fl(fserver)p Fo(')d(in)i(the)0 1122 y(example\):)120
+1192 y Fl(local/tex)120 1242 y(local/tex/fonts)120 1292 y(local/tex/lib)120
+1342 y(local/tex/bin)120 1391 y(local/tex/bin/sun3)120 1441
+y(local/tex/bin/sun4)120 1491 y(local/tex/bin/hp9000)120 1541
+y(...)62 1632 y Fo(In)15 b(this)g(example,)g(the)g(sub)q(directories)h(of)e
+(`)p Fl(local/tex/bin)p Fo(')e(should)j(b)q(e)g(hidden)h(when)f(accessed)g
+(via)g(the)0 1682 y(automoun)o(t)f(p)q(oin)o(t)i(\(con)o(v)o(en)o(tionally)g
+(`)p Fl(/vol)p Fo('\).)i(A)d(moun)o(t-map)g(for)f(`)p Fl(/vol)p
+Fo(')g(to)h(ac)o(hiev)o(e)h(this)f(w)o(ould)h(lo)q(ok)f(lik)o(e:)120
+1752 y Fl(/defaults)70 b(sublink:=${/key};rhost:=fserv)o(er;type)o(:=link)120
+1802 y(tex)214 b(type:=auto;fs:=${map};pref:=$)o({key}/)120
+1852 y(tex/fonts)70 b(host!=fserver;type:=nfs;rfs:=)o(/vol/te)o(x)21
+b(\\)406 1902 y(host==fserver;fs:=/usr/local/)o(tex)120 1952
+y(tex/lib)118 b(host!=fserver;type:=nfs;rfs:=)o(/vol/te)o(x)21
+b(\\)406 2002 y(host==fserver;fs:=/usr/local/)o(tex)120 2051
+y(tex/bin)118 b(-sublink:=${/key}/${arch})21 b(host!=fserver;type:=nfs;r)o
+(fs:=/vo)o(l/tex)120 2101 y(\\)406 2151 y(host:=fserver;fs:=/usr/local/)o
+(tex)62 2242 y Fo(When)12 b(`)p Fl(/vol/tex/bin)p Fo(')d(is)k(referenced,)g
+(the)e(curren)o(t)h(mac)o(hine)g(arc)o(hitecture)g(is)g(automatically)g(app)q
+(ended)0 2292 y(to)j(the)h(path)g(b)o(y)f(the)h Fl(${sublink})e
+Fo(v)m(ariable.)23 b(This)17 b(means)e(that)g(users)h(can)g(ha)o(v)o(e)g(`)p
+Fl(/vol/tex/bin)p Fo(')d(in)j(their)0 2342 y(`)p Fl(PATH)p
+Fo(')e(without)h(concern)h(for)e(arc)o(hitecture)i(dep)q(endencies.)0
+2504 y Fq(8.4)33 b(Wildcard)17 b(names)e(&)g(Replicated)i(Serv)n(ers)62
+2595 y Fo(By)h(using)g(the)g(wildcard)h(facilit)o(y)l(,)g Fp(Amd)h
+Fo(can)e Fp(o)o(v)o(erla)o(y)j Fo(an)c(existing)i(directory)f(with)g
+(additional)h(en)o(tries.)0 2645 y(The)12 b(system)f(\014les)i(are)e(usually)
+j(moun)o(ted)d(under)i(`)p Fl(/usr)p Fo('.)k(If)12 b(instead)g
+Fp(Amd)i Fo(is)e(moun)o(ted)g(on)g(`)p Fl(/usr)p Fo(',)f(additional)p
+eop
+%%Page: 49 51
+49 50 bop 0 -83 a Fo(Chapter)15 b(8:)k(Examples)1300 b(SMM:13-49)0
+158 y(names)18 b(can)g(b)q(e)h(o)o(v)o(erla)o(y)o(ed)e(to)h(augmen)o(t)f(or)h
+(replace)h(names)f(in)g(the)h(\\master")d(`)p Fl(/usr)p Fo('.)27
+b(A)18 b(map)g(to)g(do)g(this)0 208 y(w)o(ould)e(ha)o(v)o(e)e(the)i(form:)120
+279 y Fl(local)47 b(type:=auto;fs:=local-map)120 329 y(share)g
+(type:=auto;fs:=share-map)120 378 y(*)143 b(-type:=nfs;rfs:=/export/ex)o
+(ec/${arc)o(h};subl)o(ink:="$)o({key}")21 b(\\)311 428 y(rhost:=fserv1)46
+b(rhost:=fserv2)g(rhost:=fserv3)62 519 y Fo(Note)11 b(that)g(the)g(assignmen)
+o(t)g(to)g Fl(${sublink})f Fo(is)i(surrounded)g(b)o(y)f(double)i(quotes)e(to)
+f(prev)o(en)o(t)h(the)h(incoming)0 569 y(k)o(ey)j(from)f(causing)i(the)f(map)
+f(to)h(b)q(e)g(misin)o(terpreted.)21 b(This)16 b(map)f(has)f(the)h(e\013ect)g
+(of)g(directing)h(an)o(y)f(access)g(to)0 619 y(`)p Fl(/usr/local)p
+Fo(')e(or)i(`)p Fl(/usr/share)p Fo(')e(to)h(another)h(automoun)o(t)f(p)q(oin)
+o(t.)62 690 y(In)i(this)g(example,)g(it)g(is)f(assumed)h(that)f(the)g(`)p
+Fl(/usr)p Fo(')f(\014les)i(are)f(replicated)i(on)f(three)f(\014leserv)o(ers:)
+21 b(`)p Fl(fserv1)p Fo(',)0 739 y(`)p Fl(fserv2)p Fo(')15
+b(and)h(`)p Fl(fserv3)p Fo('.)21 b(F)l(or)16 b(an)o(y)g(references)h(other)f
+(than)g(to)f(`)p Fl(local)p Fo(')g(and)h(`)p Fl(share)p Fo(')f(one)i(of)e
+(the)i(serv)o(ers)e(is)0 789 y(used)j(and)g(a)f(sym)o(b)q(olic)i(link)g(to)e
+Fl(${autodir}/${rhost}/expo)o(rt/exec/)o(${arch})o(/)p Fp(whatev)o(er)g
+Fo(is)i(returned)0 839 y(once)d(an)f(appropriate)g(\014lesystem)h(has)f(b)q
+(een)h(moun)o(ted.)0 1011 y Fq(8.5)33 b(`)p Fg(rwho)p Fq(')13
+b(serv)n(ers)62 1102 y Fo(The)j(`)p Fl(/usr/spool/rwho)p Fo(')c(directory)j
+(is)h(a)f(go)q(o)q(d)g(candidate)h(for)f(automoun)o(ting.)k(F)l(or)c
+(e\016ciency)h(reasons)0 1152 y(it)d(is)f(b)q(est)h(to)f(capture)g(the)h
+(rwho)e(data)h(on)g(a)g(small)i(n)o(um)o(b)q(er)e(of)g(mac)o(hines)h(and)g
+(then)f(moun)o(t)g(that)g(information)0 1202 y(on)o(to)g(a)h(large)g(n)o(um)o
+(b)q(er)h(of)f(clien)o(ts.)20 b(The)14 b(data)e(written)i(in)o(to)f(the)g
+(rwho)g(\014les)h(is)g(b)o(yte)f(order)g(dep)q(enden)o(t)i(so)d(only)0
+1252 y(serv)o(ers)j(with)g(the)h(correct)e(b)o(yte)h(ordering)h(can)f(b)q(e)h
+(used)g(b)o(y)f(a)g(clien)o(t:)120 1322 y Fl(/defaults)214
+b(type:=nfs)120 1372 y(usr/spool/rwho)94 b(-byte==little;rfs:=/usr)o(/spool/)
+o(rwho)21 b(\\)645 1422 y(rhost:=vaxA)46 b(rhost:=vaxB)23 b(\\)550
+1472 y(||)g(-rfs:=/usr/spool/rwho)e(\\)645 1521 y(rhost:=sun4)46
+b(rhost:=hp300)0 1694 y Fq(8.6)33 b(`)p Fg(/vol)p Fq(')62 1786
+y Fo(`)p Fl(/vol)p Fo(')14 b(is)i(used)g(as)e(a)h(catc)o(h-all)h(for)f(v)o
+(olumes)g(whic)o(h)i(do)e(not)f(ha)o(v)o(e)h(other)g(con)o(v)o(en)o(tional)h
+(names.)62 1856 y(Belo)o(w)21 b(is)f(part)g(of)f(the)h(`)p
+Fl(/vol)p Fo(')f(map)h(for)g(the)g(domain)g(`)p Fl(doc.ic.ac.uk)p
+Fo('.)32 b(The)21 b(`)p Fl(r+d)p Fo(')d(tree)i(is)h(used)g(for)0
+1906 y(new)15 b(or)e(exp)q(erimen)o(tal)j(soft)o(w)o(are)d(that)g(needs)i(to)
+f(b)q(e)h(a)o(v)m(ailable)h(ev)o(erywhere)e(without)h(installing)h(it)e(on)h
+(all)g(the)0 1956 y(\014leserv)o(ers.)24 b(Users)16 b(wishing)i(to)d(try)h
+(out)g(the)g(new)h(soft)o(w)o(are)d(then)j(simply)h(include)g(`)p
+Fl(/vol/r+d/{bin,ucb})p Fo(')0 2006 y(in)e(their)g(path.)62
+2076 y(The)e(main)g(tree)f(resides)h(on)g(one)f(host)g(`)p
+Fl(gould.doc.ic.ac.uk)p Fo(',)d(whic)o(h)15 b(has)e(di\013eren)o(t)h(`)p
+Fl(bin)p Fo(',)e(`)p Fl(etc)p Fo(',)g(`)p Fl(lib)p Fo(')0 2126
+y(and)k(`)p Fl(ucb)p Fo(')e(sub-directories)k(for)d(eac)o(h)g(mac)o(hine)i
+(arc)o(hitecture.)k(F)l(or)15 b(example,)i(`)p Fl(/vol/r+d/bin)p
+Fo(')c(for)i(a)g(Sun-4)0 2176 y(w)o(ould)e(b)q(e)g(stored)e(in)j(the)e
+(sub-directory)h(`)p Fl(bin/sun4)p Fo(')d(of)i(the)h(\014lesystem)g(`)p
+Fl(/usr/r+d)p Fo('.)k(When)12 b(it)h(w)o(as)e(accessed)0 2226
+y(a)k(sym)o(b)q(olic)h(link)h(p)q(oin)o(ting)f(to)f(`)p Fl
+(/a/gould/usr/r+d/bin/s)o(un4)p Fo(')d(w)o(ould)j(b)q(e)h(returned.)120
+2296 y Fl(/defaults)94 b(type:=nfs;opts:=rw,grpid,nos)o(uid,int)o(r,soft)120
+2346 y(wp)262 b(-opts:=rw,grpid,nosuid;rhost)o(:=charm)20 b(\\)430
+2396 y(host==charm;type:=link;fs:=/)o(usr/loc)o(al/wp)h(\\)430
+2446 y(host!=charm;type:=nfs;rfs:=/)o(vol/wp)120 2496 y(...)120
+2545 y(#)120 2595 y(src)238 b(-opts:=rw,grpid,nosuid;rhost)o(:=charm)20
+b(\\)430 2645 y(host==charm;type:=link;fs:=/)o(usr/src)g(\\)p
+eop
+%%Page: 50 52
+50 51 bop 15 -83 a Fo(SMM:13-50)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)430 158 y Fl(host!=charm;type:=nfs;rfs:=/)o(vol/src)
+120 208 y(#)120 258 y(r+d)238 b(type:=auto;fs:=${map};pref:=)o(r+d/)120
+308 y(#)24 b(per)f(architecture)f(bin,etc,lib&ucb...)120 358
+y(r+d/bin)142 b(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)o(blink:=$)o
+({/key}/)o(${arch})120 407 y(r+d/etc)g(rhost:=gould.doc.ic.ac.uk;rf)o
+(s:=/usr)o(/r+d;su)o(blink:=$)o({/key}/)o(${arch})120 457 y(r+d/include)46
+b(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)o(blink:=$)o({/key})120
+507 y(r+d/lib)142 b(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)o
+(blink:=$)o({/key}/)o(${arch})120 557 y(r+d/man)g
+(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)o(blink:=$)o({/key})120
+607 y(r+d/src)g(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)o(blink:=$)o
+({/key})120 656 y(r+d/ucb)g(rhost:=gould.doc.ic.ac.uk;rf)o(s:=/usr)o(/r+d;su)
+o(blink:=$)o({/key}/)o(${arch})120 706 y(#)24 b(hades)f(pictures)120
+756 y(pictures)118 b(-opts:=rw,grpid,nosuid;rhost)o(:=thpfs)20
+b(\\)430 806 y(host==thpfs;type:=link;fs:=/)o(nbsd/pi)o(ctures)g(\\)430
+856 y(host!=thpfs;type:=nfs;rfs:=/)o(nbsd;su)o(blink:=)o(pictures)120
+906 y(#)k(hades)f(tools)120 955 y(hades)190 b(-opts:=rw,grpid,nosuid;rhost)o
+(:=thpfs)20 b(\\)430 1005 y(host==thpfs;type:=link;fs:=/)o(nbsd/ha)o(des)h
+(\\)430 1055 y(host!=thpfs;type:=nfs;rfs:=/)o(nbsd;su)o(blink:=)o(hades)120
+1105 y(#)j(bsd)f(tools)g(for)h(hp.)120 1155 y(bsd)238 b
+(-opts:=rw,grpid,nosuid;arch=)o(=hp9000)o(;rhost:)o(=thpfs)21
+b(\\)430 1204 y(host==thpfs;type:=link;fs:=/)o(nbsd/bs)o(d)g(\\)430
+1254 y(host!=thpfs;type:=nfs;rfs:=/)o(nbsd;su)o(blink:=)o(bsd)0
+1468 y Fm(9)41 b(In)n(ternals)0 1709 y Fq(9.1)33 b(Log)14 b(Messages)62
+1800 y Fo(In)h(the)f(follo)o(wing)h(sections)g(a)f(brief)g(explanation)i(is)e
+(giv)o(en)h(of)e(some)h(of)g(the)g(log)g(messages)g(made)g(b)o(y)g
+Fp(Amd)p Fo(.)0 1850 y(Where)20 b(the)f(message)g(is)h(in)h(`)p
+Fl(typewriter)p Fo(')c(fon)o(t,)i(it)h(corresp)q(onds)g(exactly)g(to)f(the)g
+(message)g(pro)q(duced)i(b)o(y)0 1900 y Fp(Amd)p Fo(.)i(W)l(ords)16
+b(in)i Fp(italic)i Fo(are)c(replaced)i(b)o(y)e(an)g(appropriate)g(string.)24
+b(V)l(ariables,)17 b Fl(${var})p Fo(,)e(indicate)j(that)e(the)0
+1950 y(v)m(alue)g(of)f(the)g(appropriate)h(v)m(ariable)g(is)g(output.)62
+2020 y(Log)h(messages)f(are)g(either)h(sen)o(t)g(direct)g(to)f(a)g(\014le,)i
+(or)e(logged)h(via)g(the)f Fk(syslog)p Fo(\(3\))g(mec)o(hanism.)25
+b(Messages)0 2070 y(are)15 b(logged)g(with)g(facilit)o(y)h(`)p
+Fl(LOG_DAEMON)p Fo(')d(when)i(using)h Fk(syslog)p Fo(\(3\).)j(In)c(either)h
+(case,)f(en)o(tries)g(in)h(the)f(\014le)h(are)e(of)0 2120 y(the)h(form:)120
+2191 y Fp(date-string)52 b(hostname)26 b Fl(amd[)p Fp(pid)r
+Fl(])48 b Fp(message)0 2355 y Fi(9.1.1)30 b(F)-5 b(atal)14
+b(errors)62 2446 y Fp(Amd)20 b Fo(attempts)c(to)h(deal)h(with)g(un)o(usual)g
+(ev)o(en)o(ts.)27 b(Whenev)o(er)17 b(it)h(is)g(not)f(p)q(ossible)i(to)e(deal)
+h(with)g(suc)o(h)g(an)0 2496 y(error,)d Fp(Amd)k Fo(will)f(log)e(an)g
+(appropriate)h(message)e(and,)i(if)f(it)h(cannot)f(p)q(ossibly)i(con)o(tin)o
+(ue,)f(will)h(either)f(exit)f(or)0 2545 y(ab)q(ort.)24 b(These)17
+b(messages)f(are)g(selected)i(b)o(y)e(`)p Fl(-x)f(fatal)p Fo(')g(on)i(the)g
+(command)f(line.)26 b(When)17 b Fk(syslog)p Fo(\(3\))f(is)h(b)q(eing)0
+2595 y(used,)22 b(they)e(are)g(logged)h(with)g(lev)o(el)g(`)p
+Fl(LOG_FATAL)p Fo('.)34 b(Ev)o(en)20 b(if)h Fp(Amd)h Fo(con)o(tin)o(ues)f(to)
+f(op)q(erate)g(it)h(is)f(lik)o(ely)j(to)0 2645 y(remain)16
+b(in)g(a)f(precarious)g(state)g(and)g(should)h(b)q(e)g(restarted)e(at)h(the)g
+(earliest)h(opp)q(ortunit)o(y)l(.)p eop
+%%Page: 51 53
+51 52 bop 0 -83 a Fo(Chapter)15 b(9:)k(In)o(ternals)1317 b(SMM:13-51)0
+158 y Fl(Attempting)22 b(to)i(inherit)f(not-a-filesystem)240
+219 y Fo(The)14 b(protot)o(yp)q(e)g(moun)o(t)g(p)q(oin)o(t)g(created)h
+(during)g(a)f(\014lesystem)h(restart)e(did)i(not)f(con)o(tain)g(a)g(refer-)
+240 269 y(ence)i(to)f(the)g(restarted)f(\014lesystem.)21 b(This)16
+b(erorr)e(\\should)i(nev)o(er)f(happ)q(en".)0 330 y Fl(Can't)23
+b(bind)g(to)h(domain)f(")p Fp(NIS-domain)p Fl(")240 391 y Fo(A)e(sp)q
+(eci\014c)i(NIS)e(domain)h(w)o(as)e(requested)h(on)g(the)g(command)f(line,)k
+(but)d(no)g(serv)o(er)f(for)h(that)240 441 y(domain)16 b(is)f(a)o(v)m
+(ailable)i(on)e(the)h(lo)q(cal)g(net.)0 502 y Fl(Can't)23 b(determine)g(IP)g
+(address)g(of)h(this)f(host)h(\()p Fp(hostname)s Fl(\))240
+563 y Fo(When)11 b Fp(Amd)h Fo(starts)d(it)i(determines)g(its)g(o)o(wn)e(IP)i
+(address.)18 b(If)11 b(this)g(lo)q(okup)g(fails)g(then)g Fp(Amd)h
+Fo(cannot)240 612 y(con)o(tin)o(ue.)19 b(The)11 b(hostname)e(it)i(lo)q(oks)g
+(up)g(is)f(that)g(obtained)h(returned)g(b)o(y)f Fk(gethostname)p
+Fo(\(2\))f(system)240 662 y(call.)0 723 y Fl(Can't)23 b(find)g(root)h(file)f
+(handle)g(for)h Fp(automoun)o(t)14 b(p)q(oin)o(t)240 784 y(Amd)19
+b Fo(creates)d(its)h(o)o(wn)g(\014le)g(handles)h(for)f(the)f(automoun)o(t)g
+(p)q(oin)o(ts.)25 b(When)17 b(it)g(moun)o(ts)g(itself)g(as)240
+834 y(a)i(serv)o(er,)i(it)f(m)o(ust)f(pass)h(these)g(\014le)g(handles)h(to)f
+(the)g(lo)q(cal)g(k)o(ernel.)35 b(If)20 b(the)g(\014lehandle)i(is)e(not)240
+884 y(obtainable)c(the)g(moun)o(t)e(p)q(oin)o(t)i(is)g(ignored.)k(This)c
+(error)e(\\should)i(nev)o(er)g(happ)q(en".)0 945 y Fl(Must)23
+b(be)h(root)f(to)h(mount)f(filesystems)f(\(euid)i(=)f Fp(euid)r
+Fl(\))240 1006 y Fo(T)l(o)13 b(prev)o(en)o(t)f(em)o(barrassmen)o(t,)g
+Fp(Amd)j Fo(mak)o(es)d(sure)h(it)g(has)g(appropriate)g(system)f(privileges.)
+21 b(This)240 1055 y(amoun)o(ts)12 b(to)g(ha)o(ving)h(an)f(euid)i(of)f(0.)18
+b(The)13 b(c)o(hec)o(k)g(is)g(made)g(after)f(argumen)o(t)g(pro)q(cessing)h
+(complete)240 1105 y(to)i(giv)o(e)g(non-ro)q(ot)g(users)g(a)g(c)o(hance)h(to)
+e(access)h(the)h(\\-v")f(option.)0 1166 y Fl(No)24 b(work)f(to)g(do)h(-)g
+(quitting)240 1227 y Fo(No)15 b(automoun)o(t)f(p)q(oin)o(ts)i(w)o(ere)f(giv)o
+(en)g(on)g(the)h(command)f(line)i(and)e(so)g(there)g(is)h(no)f(w)o(ork)f(to)h
+(do.)0 1288 y Fl(Out)23 b(of)h(memory)f(in)h(realloc)240 1349
+y Fo(While)c(attempting)e(to)g(reallo)q(c)h(some)f(memory)l(,)h(the)f(memory)
+g(space)h(a)o(v)m(ailable)h(to)d Fp(Amd)k Fo(w)o(as)240 1399
+y(exhausted.)f(This)c(is)g(an)f(unreco)o(v)o(erable)h(error.)0
+1460 y Fl(Out)23 b(of)h(memory)240 1521 y Fo(While)c(attempting)e(to)g(mallo)
+q(c)h(some)f(memory)l(,)h(the)f(memory)g(space)h(a)o(v)m(ailable)h(to)d
+Fp(Amd)k Fo(w)o(as)240 1570 y(exhausted.)f(This)c(is)g(an)f(unreco)o(v)o
+(erable)h(error.)0 1631 y Fl(cannot)23 b(create)g(rpc/udp)g(service)240
+1692 y Fo(Either)16 b(the)f(NFS)g(or)g(AMQ)g(endp)q(oin)o(t)h(could)h(not)d
+(b)q(e)i(created.)0 1753 y Fl(gethostname:)e Fp(description)240
+1814 y Fo(The)h Fk(gethostname)p Fo(\(2\))f(system)h(call)i(failed)f(during)g
+(startup.)0 1875 y Fl(host)23 b(name)h(is)f(not)h(set)240 1936
+y Fo(The)14 b Fk(gethostname)p Fo(\(2\))g(system)f(call)j(returned)e(a)g
+(zero)h(length)f(host)g(name.)20 b(This)15 b(can)f(happ)q(en)h(if)240
+1986 y Fp(Amd)i Fo(is)f(started)e(in)i(single)h(user)e(mo)q(de)h(just)f
+(after)f(b)q(o)q(oting)i(the)f(system.)0 2047 y Fl(ifs_match)23
+b(called!)240 2108 y Fo(An)i(in)o(ternal)g(error)f(o)q(ccurred)h(while)i
+(restarting)d(a)g(pre-moun)o(ted)h(\014lesystem.)48 b(This)26
+b(error)240 2158 y(\\should)16 b(nev)o(er)f(happ)q(en".)0 2219
+y Fl(mount_afs:)f Fp(description)240 2279 y Fo(An)h(error)g(o)q(ccured)h
+(while)h Fp(Amd)g Fo(w)o(as)d(moun)o(ting)i(itself.)0 2340
+y Fl(run_rpc)23 b(failed)240 2401 y Fo(Someho)o(w)15 b(the)g(main)h(NFS)f
+(serv)o(er)g(lo)q(op)g(failed.)22 b(This)15 b(error)g(\\should)h(nev)o(er)f
+(happ)q(en".)0 2462 y Fl(unable)23 b(to)h(free)f(rpc)g(arguments)g(in)h
+(amqprog_1)240 2523 y Fo(The)15 b(incoming)i(argumen)o(ts)d(to)h(the)g(AMQ)g
+(serv)o(er)g(could)h(not)f(b)q(e)h(free'ed.)0 2584 y Fl(unable)23
+b(to)h(free)f(rpc)g(arguments)g(in)h(nfs_program_1)240 2645
+y Fo(The)15 b(incoming)i(argumen)o(ts)d(to)h(the)g(NFS)g(serv)o(er)g(could)h
+(not)f(b)q(e)h(free'ed.)p eop
+%%Page: 52 54
+52 53 bop 15 -83 a Fo(SMM:13-52)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fl(unable)23 b(to)h(register)e(\(AMQ_PROGRAM,)
+g(AMQ_VERSION,)h(udp\))240 221 y Fo(The)d(AMQ)g(serv)o(er)g(could)g(not)g(b)q
+(e)g(registered)h(with)f(the)g(lo)q(cal)h(p)q(ortmapp)q(er)f(or)f(the)h(in)o
+(ternal)240 271 y(RPC)15 b(dispatc)o(her.)0 334 y Fl(unable)23
+b(to)h(register)e(\(NFS_PROGRAM,)g(NFS_VERSION,)h(0\))240 397
+y Fo(The)15 b(NFS)h(serv)o(er)e(could)j(not)d(b)q(e)i(registered)g(with)f
+(the)h(in)o(ternal)g(RPC)f(dispatc)o(her.)0 543 y Fi(9.1.2)30
+b(Info)14 b(messages)62 634 y Fp(Amd)f Fo(generates)e(information)g(messages)
+g(to)f(record)i(state)e(c)o(hanges.)18 b(These)12 b(messages)e(are)h
+(selected)i(b)o(y)e(`)p Fl(-x)0 684 y(info)p Fo(')j(on)h(the)h(command)f
+(line.)21 b(When)16 b Fk(syslog)p Fo(\(3\))e(is)i(b)q(eing)g(used,)g(they)f
+(are)g(logged)g(with)h(lev)o(el)g(`)p Fl(LOG_INFO)p Fo('.)62
+754 y(The)h(messages)f(listed)i(b)q(elo)o(w)g(can)f(b)q(e)g(generated)g(and)g
+(are)f(in)i(a)e(format)f(suitable)j(for)e(simple)j(statistical)0
+804 y(analysis.)24 b Fp(moun)o(t-info)18 b Fo(is)f(the)g(string)f(that)f(is)i
+(displa)o(y)o(ed)h(b)o(y)e Fp(Amq)h Fo(in)g(its)g(moun)o(t)e(information)i
+(column)g(and)0 854 y(placed)f(in)g(the)g(system)e(moun)o(t)h(table.)0
+924 y Fl(mount)23 b(of)h("${)p Fp(path)p Fl(}")f(on)g(${)p
+Fp(fs)r Fl(})h(timed)f(out)240 987 y Fo(A)o(ttempts)13 b(to)h(moun)o(t)f(a)h
+(\014lesystem)h(for)f(the)g(giv)o(en)h(automoun)o(t)e(p)q(oin)o(t)h(ha)o(v)o
+(e)g(failed)i(to)d(complete)240 1037 y(within)j(30)f(seconds.)0
+1100 y Fl("${)p Fp(path)p Fl(}")23 b(forcibly)g(timed)g(out)240
+1163 y Fo(An)15 b(automoun)o(t)g(p)q(oin)o(t)g(has)g(b)q(een)i(timed)e(out)g
+(b)o(y)g(the)h Fp(Amq)g Fo(command.)0 1226 y Fl(restarting)22
+b Fp(moun)o(t-info)27 b Fl(on)c(${)p Fp(fs)r Fl(})240 1288
+y Fo(A)15 b(pre-moun)o(ted)h(\014le)g(system)f(has)g(b)q(een)h(noted.)0
+1351 y Fl("${)p Fp(path)p Fl(}")23 b(has)h(timed)f(out)240
+1414 y Fo(No)15 b(access)g(to)g(the)g(automoun)o(t)f(p)q(oin)o(t)i(has)f(b)q
+(een)h(made)f(within)i(the)e(timeout)g(p)q(erio)q(d.)0 1477
+y Fl(file)23 b(server)g(${)p Fp(rhost)q Fl(})g(is)h(down)f(-)h(timeout)f(of)g
+("${)p Fp(path)p Fl(}")g(ignored)240 1540 y Fo(An)18 b(automoun)o(t)e(p)q
+(oin)o(t)i(has)f(timed)h(out,)f(but)h(the)g(corresp)q(onding)g(\014le)g(serv)
+o(er)f(is)h(kno)o(wn)g(to)e(b)q(e)240 1590 y(do)o(wn.)23 b(This)17
+b(message)f(is)h(only)g(pro)q(duced)g(once)g(for)f(eac)o(h)g(moun)o(t)g(p)q
+(oin)o(t)h(for)f(whic)o(h)h(the)f(serv)o(er)240 1639 y(is)g(do)o(wn.)0
+1702 y Fl(Re-synchronizing)22 b(cache)h(for)g(map)h(${)p Fp(map)q
+Fl(})240 1765 y Fo(The)15 b(named)h(map)f(has)g(b)q(een)h(mo)q(di\014ed)h
+(and)e(the)h(in)o(ternal)g(cac)o(he)f(is)h(b)q(eing)g(re-sync)o(hronized.)0
+1828 y Fl(Filehandle)22 b(denied)i(for)f("${)p Fp(rhost)q Fl(}:${)p
+Fp(rfs)r Fl(}")240 1891 y Fo(The)15 b(moun)o(t)g(daemon)g(refused)h(to)f
+(return)g(a)g(\014le)h(handle)g(for)f(the)g(requested)h(\014lesystem.)0
+1954 y Fl(Filehandle)22 b(error)i(for)f("${)p Fp(rhost)q Fl(}:${)p
+Fp(rfs)r Fl(}":)13 b Fp(description)240 2017 y Fo(The)i(moun)o(t)g(daemon)g
+(ga)o(v)o(e)g(some)f(other)h(error)g(for)f(the)i(requested)f(\014lesystem.)0
+2079 y Fl(file)23 b(server)g(${)p Fp(rhost)q Fl(})g(type)h(nfs)f(starts)g(up)
+240 2142 y Fo(A)15 b(new)h(NFS)f(\014le)h(serv)o(er)f(has)g(b)q(een)h
+(referenced)g(and)g(is)g(kno)o(wn)e(to)h(b)q(e)h(up.)0 2205
+y Fl(file)23 b(server)g(${)p Fp(rhost)q Fl(})g(type)h(nfs)f(starts)g(down)240
+2268 y Fo(A)15 b(new)h(NFS)f(\014le)h(serv)o(er)f(has)g(b)q(een)h(referenced)
+g(and)g(is)g(kno)o(wn)e(to)h(b)q(e)h(do)o(wn.)0 2331 y Fl(file)23
+b(server)g(${)p Fp(rhost)q Fl(})g(type)h(nfs)f(is)h(up)240
+2394 y Fo(An)15 b(NFS)h(\014le)g(serv)o(er)f(that)f(w)o(as)h(previously)h(do)
+o(wn)f(is)h(no)o(w)e(up.)0 2457 y Fl(file)23 b(server)g(${)p
+Fp(rhost)q Fl(})g(type)h(nfs)f(is)h(down)240 2519 y Fo(An)15
+b(NFS)h(\014le)g(serv)o(er)f(that)f(w)o(as)h(previously)h(up)g(is)f(no)o(w)g
+(do)o(wn.)0 2582 y Fl(Finishing)23 b(with)g(status)g Fp(exit-status)240
+2645 y(Amd)17 b Fo(is)f(ab)q(out)f(to)f(exit)i(with)g(the)f(giv)o(en)h(exit)f
+(status.)p eop
+%%Page: 53 55
+53 54 bop 0 -83 a Fo(Index)1613 b(SMM:13-53)0 158 y Fp(moun)o(t-info)26
+b Fl(mounted)d(fstype)g(${)p Fp(t)o(yp)q(e)s Fl(})g(on)h(${)p
+Fp(fs)r Fl(})240 221 y Fo(A)15 b(new)h(\014le)g(system)f(has)g(b)q(een)h
+(moun)o(ted.)0 283 y Fp(moun)o(t-info)26 b Fl(restarted)d(fstype)g(${)p
+Fp(t)o(yp)q(e)s Fl(})g(on)h(${)p Fp(fs)r Fl(})240 345 y Fp(Amd)17
+b Fo(is)f(using)g(a)f(pre-moun)o(ted)g(\014lesystem)h(to)f(satisfy)g(a)f
+(moun)o(t)h(request.)0 407 y Fp(moun)o(t-info)26 b Fl(unmounted)d(fstype)g
+(${)p Fp(t)o(yp)q(e)s Fl(})g(from)g(${)p Fp(fs)r Fl(})240 470
+y Fo(A)15 b(\014le)h(system)f(has)g(b)q(een)i(unmoun)o(ted.)0
+532 y Fp(moun)o(t-info)26 b Fl(unmounted)d(fstype)g(${)p Fp(t)o(yp)q(e)s
+Fl(})g(from)g(${)p Fp(fs)r Fl(})h(link)f(${)p Fp(fs)r Fl(}/${)p
+Fp(sublink)s Fl(})240 594 y Fo(A)15 b(\014le)h(system)f(of)g(whic)o(h)h(only)
+g(a)f(sub-directory)h(w)o(as)e(in)i(use)g(has)f(b)q(een)h(unmoun)o(ted.)0
+784 y Fm(Ac)n(kno)n(wledgemen)n(ts)e(&)h(T)-7 b(rademarks)62
+904 y Fo(Thanks)19 b(to)g(the)g(F)l(ormal)f(Metho)q(ds)h(Group)g(at)f(Imp)q
+(erial)j(College)f(for)e(su\013ering)i(patien)o(tly)f(while)i
+Fp(Amd)0 954 y Fo(w)o(as)14 b(b)q(eing)j(dev)o(elop)q(ed)g(on)e(their)h(mac)o
+(hines.)62 1024 y(Thanks)j(to)f(the)h(man)o(y)f(p)q(eople)i(who)e(ha)o(v)o(e)
+h(help)q(ed)h(with)f(the)g(dev)o(elopmen)o(t)h(of)e Fp(Amd)p
+Fo(,)h(esp)q(ecially)i(Piete)0 1074 y(Bro)q(oks)c(at)g(the)h(Cam)o(bridge)g
+(Univ)o(ersit)o(y)g(Computing)g(Lab)g(for)f(man)o(y)g(hours)h(of)f(testing,)h
+(exp)q(erimen)o(tation)0 1124 y(and)d(discussion.)37 1195 y
+Fn(\017)30 b Fk(DEC)p Fo(,)14 b Fk(V)-5 b(AX)16 b Fo(and)g
+Fk(Ultrix)g Fo(are)f(registered)h(trademarks)e(of)h(Digital)h(Equipmen)o(t)g
+(Corp)q(oration.)37 1257 y Fn(\017)30 b Fk(AIX)16 b Fo(and)f
+Fk(IBM)h Fo(are)f(registered)g(trademarks)g(of)f(In)o(ternational)i(Business)
+h(Mac)o(hines)e(Corp)q(oration.)37 1319 y Fn(\017)30 b Fk(Sun)p
+Fo(,)16 b Fk(NFS)e Fo(and)h Fk(SunOS)i Fo(are)e(registered)g(trademarks)f(of)
+h(Sun)h(Microsystems,)e(Inc.)37 1381 y Fn(\017)30 b Fk(Unix)20
+b Fo(is)f(a)g(registered)g(trademark)f(of)h(A)l(T&T)g(Unix)h(Systems)f(Lab)q
+(oratories)g(in)h(the)f(USA)g(and)g(other)90 1431 y(coun)o(tries.)0
+1606 y Fm(Index)0 1826 y Fc(/etc/amd.start)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(33)0 1871
+y(/etc/passwd)d(maps)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)22 b Fc(13)0 1917 y(/etc/rc.lo)q(cal)15 b(additions)e
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(33)0 1963
+y(/v)o(ol)11 b Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22 b
+Fc(56)0 2008 y(Additions)15 b(to)e(/etc/rc.lo)q(cal)7 b Fb(:)h(:)f(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)20 b Fc(33)0 2054 y(Aliased)15 b(hostnames)8 b Fb(:)f(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fc(22)0 2100 y(Alternate)14
+b(lo)q(cations)t Fb(:)8 b(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)17 b Fc(6)0 2145 y(Amd)c(command)h(line)g(options)8 b Fb(:)g(:)e(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)21 b Fc(21)0 2191 y(Amq)13 b(command)d Fb(:)d(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22 b Fc(33)0 2236 y(arc)o(h,)13
+b(FSinfo)h(host)g(attribute)6 b Fb(:)h(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)19
+b Fc(41)0 2282 y(arc)o(h,)13 b(moun)o(t)h(selector)c Fb(:)c(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(16)0 2328 y(Arc)o(hitecture)14
+b(dep)q(enden)o(t)h(v)o(olumes)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)24 b Fc(55)0 2373 y(Arc)o(hitecture)14
+b(sharing)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(55)0 2419 y(Arc)o(hitecture)14 b(sp)q(eci\014c)h(moun)o(ts)9
+b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)22 b Fc(56)0 2465 y(A)o(tomic)13 b(NFS)g(moun)o(ts)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 b Fc(27)0
+2510 y(auto,)13 b(\014lesystem)i(t)o(yp)q(e)6 b Fb(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)19 b Fc(29)0 2556 y(auto)q(dir,)14 b(moun)o(t)g(selector)c
+Fb(:)c(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(16)0 2602 y(Automatic)14
+b(generation)h(of)d(user)i(maps)t Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(13)1015 1826 y(Automoun)o(t)d(directory)f
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)24 b Fc(21)1015
+1871 y(Automoun)o(t)14 b(\014lesystem)t Fb(:)8 b(:)f(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)18 b Fc(29)1015 1917 y(Automoun)o(ter)c(con\014guration)i(maps)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)17 b Fc(11)1015 1963 y(Automoun)o(ter)d(fundamen)o(tals)f
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)23 b Fc(5)1015 2008 y(Bac)o(kground)15
+b(moun)o(ts)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(6)1015 2054 y(Binding)e(names)e(to)f(\014lesystems)6 b
+Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)19 b Fc(6)1015 2100 y(b)q(o)q(otparams,)c(FSinfo)f
+(pre\014x)s Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)16 b Fc(47)1015
+2145 y(Bug)e(rep)q(orts)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(3)1015 2191
+y(b)o(yte,)c(moun)o(t)f(selector)c Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)22 b Fc(16)1015 2236 y(Cac)o(he)14 b(in)o(terv)n(al)9
+b Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22
+b Fc(21)1015 2282 y(cac)o(he,)14 b(moun)o(t)f(option)e Fb(:)6
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(29)1015
+2328 y(Catc)o(h-all)15 b(moun)o(t)e(p)q(oin)o(t)f Fb(:)6 b(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)24 b Fc(56)1015 2373 y(Changing)15 b(the)e(in)o(terv)n(al)i(b)
+q(efore)e(a)g(\014lesystem)i(times)f(out)1098 2419 y Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)18 b Fc(21)1015 2465 y(Cluster)c(names)9
+b Fb(:)e(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)22
+b Fc(24)1015 2510 y(cluster,)14 b(FSinfo)g(host)g(attribute)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)17 b Fc(41)1015 2556 y(cluster,)d(moun)o(t)g(selector)6
+b Fb(:)h(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(17)1015
+2602 y(Command)14 b(line)h(options,)f(Amd)6 b Fb(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(21)p eop
+%%Page: 54 56
+54 55 bop 15 -83 a Fo(SMM:13-54)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fc(Command)d(line)g(options,)g(FSinfo)9
+b Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)22 b Fc(47)0 204 y(con\014g,)14 b(FSinfo)g(host)f(attribute)f
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)23 b Fc(40)0 250 y(Con\014guration)15 b(map)f(t)o(yp)q(es)
+6 b Fb(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fc(11)0 295 y(Con)o(trolling)e(Amd)t
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(34)0 341 y(Creating)d(a)f(pid)h(\014le)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)23 b Fc(22)0 387 y(Debug)14 b(options)8
+b Fb(:)f(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20
+b Fc(24)0 432 y(De\014ning)15 b(a)e(host,)g(FSinfo)g Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)24 b Fc(39)0 478 y(De\014ning)15
+b(an)e(Amd)g(moun)o(t)h(map,)f(FSinfo)s Fb(:)7 b(:)f(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)16 b Fc(45)0 524 y(De\014ning)f(host)e
+(attributes,)i(FSinfo)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(39)0 569 y(dela)o(y)m(,)14
+b(moun)o(t)f(option)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+17 b Fc(18)0 615 y(Dela)o(ying)e(moun)o(ts)f(from)f(sp)q(eci\014c)h(lo)q
+(cations)8 b Fb(:)h(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(18)0 661 y(Determining)15 b(the)f(map)f(t)o(yp)q(e)8 b
+Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(11)0 706 y(dev,)13 b(moun)o(t)h(option)8
+b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21
+b Fc(28)0 752 y(Direct)14 b(automoun)o(t)g(\014lesystem)e Fb(:)6
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)23 b Fc(30)0 798 y(direct,)14 b(\014lesystem)g(t)o(yp)q(e)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(30)0
+843 y(Disco)o(v)o(ering)f(v)o(ersion)e(information)8 b Fb(:)h(:)d(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(23)0 889 y(Disco)o(v)o(ering)16 b(what)d(is)g(going)i(on)e(at)g
+(run-time)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(34)0 935 y(Disk)14 b(\014lesystems)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(28)0 980 y(Displa)o(yin)q(g)f(the)
+d(pro)q(cess)h(id)t Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)16 b
+Fc(22)0 1026 y(Domain)f(name)s Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)16 b Fc(21)0 1072 y(Domain)f(stripping)7
+b Fb(:)i(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20
+b Fc(15)0 1117 y(domain,)14 b(moun)o(t)g(selector)9 b Fb(:)e(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)22 b Fc(17)0 1163 y(Domainname)15 b(op)q(erators)c
+Fb(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(15)0 1209 y(dumpset,)14
+b(FSinfo)g(\014lesystems)g(option)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(44)0 1254 y(dumpset,)14
+b(FSinfo)g(pre\014x)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(48)0 1300 y(Duplicated)e(v)o(olumes)7 b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(5)0 1346 y(En)o(vironmen)o(t)15
+b(v)n(ariables)9 b Fb(:)f(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(15)0 1391 y(Error)13 b(\014lesystem)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(31)0 1437 y(error,)c
+(\014lesystem)h(t)o(yp)q(e)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(31)0 1483 y(Example)14 b(of)f(arc)o(hitecture)i(sp)q(eci\014c)f(moun)o
+(ts)6 b Fb(:)h(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(56)0 1528 y(Example)14 b(of)f(moun)o(ting)i(home)e(directories)8
+b Fb(:)h(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b
+Fc(54)0 1574 y(exp)q(ort,)13 b(FSinfo)h(sp)q(ecial)i(fst)o(yp)q(e)8
+b Fb(:)e(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)21 b Fc(43)0 1620 y(exp)q(ortfs,)13 b(FSinfo)h(moun)o(t)g
+(option)f Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)24 b Fc(44)0 1665 y(exp)q(orts,)14 b(FSinfo)g(pre\014x)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(48)0
+1711 y(File)14 b(map)g(syn)o(tactic)g(con)o(v)o(en)o(tions)6
+b Fb(:)j(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)19 b Fc(11)0 1757 y(File)14 b(maps)t Fb(:)7 b(:)f(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(11)0 1802 y(Fileserv)o(er)6 b Fb(:)i(:)e(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b
+Fc(5)0 1848 y(Filesystem)c(info)f(pac)o(k)n(age)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)20 b Fc(38)0 1893 y(Filesystem)15 b(t)o(yp)q(e;)e(auto)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)20 b Fc(29)0
+1939 y(Filesystem)15 b(t)o(yp)q(e;)e(direct)5 b Fb(:)i(:)f(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)18 b Fc(30)0 1985 y(Filesystem)d(t)o(yp)q(e;)e(error)t
+Fb(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(31)0
+2030 y(Filesystem)e(t)o(yp)q(e;)e(host)d Fb(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)22 b Fc(26)0 2076 y(Filesystem)15 b(t)o(yp)q(e;)e(inherit)6
+b Fb(:)i(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(32)0 2122 y(Filesystem)c(t)o
+(yp)q(e;)e(linkx)s Fb(:)8 b(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16
+b Fc(29)0 2167 y(Filesystem)f(t)o(yp)q(e;)e(link)5 b Fb(:)j(:)e(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)17 b Fc(29)0 2213 y(Filesystem)e(t)o(yp)q(e;)e
+(nfsx)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 b
+Fc(27)0 2259 y(Filesystem)15 b(t)o(yp)q(e;)e(nfs)t Fb(:)6 b(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)16 b Fc(26)0 2304 y(Filesystem)f(t)o(yp)q(e;)e
+(program)8 b Fb(:)f(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21 b Fc(28)0 2350
+y(Filesystem)15 b(t)o(yp)q(e;)e(ro)q(ot)d Fb(:)c(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)23 b Fc(31)0 2396 y(Filesystem)15 b(t)o(yp)q(e;)e(toplvl)5
+b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)17 b Fc(31)0 2441
+y(Filesystem)e(t)o(yp)q(e;)e(ufs)t Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)16 b Fc(28)0 2487 y(Filesystem)f(t)o(yp)q(e;)e(union)6
+b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(31)0 2533
+y(Filesystem)c(t)o(yp)q(es)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)19 b Fc(26)0 2578 y(Filesystem)7 b Fb(:)h(:)e(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19
+b Fc(5)0 2624 y(Flat)14 b(\014le)g(maps)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(11)1015
+158 y(Flushing)f(the)d(map)h(cac)o(he)6 b Fb(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)19 b Fc(35)1015 204 y(F)m(orcing)c(\014lesystem)f(to)f(time)g(out)5
+b Fb(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)18 b Fc(37)1015 250 y(freq,)13 b(FSinfo)h(\014lesystems)h
+(option)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)25 b Fc(43)1015 295 y(fs,)13 b(moun)o(t)g(option)7
+b Fb(:)h(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(18)1015 341 y(FSinfo)15 b(arc)o(h)e(host)g(attribute)s
+Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)16 b Fc(41)1015 387 y(FSinfo)f(automoun)o(t)f
+(de\014nitions)s Fb(:)9 b(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16 b Fc(45)1015 432 y(FSinfo)f(cluster)f
+(host)f(attribute)c Fb(:)e(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22 b Fc(41)1015 478 y(FSinfo)15
+b(command)f(line)g(options)f Fb(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)24 b Fc(47)1015
+524 y(FSinfo)15 b(con\014g)f(host)f(attribute)7 b Fb(:)g(:)f(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20
+b Fc(40)1015 569 y(FSinfo)15 b(dumpset)f(\014lesystems)g(option)f
+Fb(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25
+b Fc(44)1015 615 y(FSinfo)15 b(error)e(messages)6 b Fb(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)19 b Fc(49)1015 661 y(FSinfo)c(\014lesystems)t
+Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)17
+b Fc(41)1015 706 y(FSinfo)e(freq)e(\014lesystems)h(option)8
+b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)22 b Fc(43)1015 752 y(FSinfo)15 b(fst)o(yp)q(e)e
+(\014lesystems)h(option)7 b Fb(:)h(:)e(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fc(43)1015 798 y(FSinfo)15
+b(grammar)9 b Fb(:)d(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)22 b Fc(39)1015 843 y(FSinfo)15 b(host)e(attributes)t Fb(:)7
+b(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(39)1015 889
+y(FSinfo)e(host)e(de\014nitions)8 b Fb(:)h(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+21 b Fc(39)1015 935 y(FSinfo)15 b(log)e(\014lesystems)i(option)7
+b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)21 b Fc(45)1015 980 y(FSinfo)15 b(moun)o(t)e
+(\014lesystems)i(option)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(44)1015 1026 y(FSinfo)e(opts)e
+(\014lesystems)i(option)5 b Fb(:)i(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fc(43)1015 1072
+y(FSinfo)d(os)e(host)g(attribute)5 b Fb(:)i(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(41)1015 1117 y(FSinfo)d(o)o(v)o(erview)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(38)1015 1163
+y(FSinfo)e(passno)f(\014lesystems)g(option)e Fb(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(43)1015
+1209 y(FSinfo)15 b(static)e(moun)o(ts)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)19 b Fc(45)1015 1254 y(FSinfo)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)19 b Fc(38)1015 1300 y(fstab,)13 b(FSinfo)h(pre\014x)e Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)23 b Fc(48)1015
+1346 y(fst)o(yp)q(e,)13 b(FSinfo)i(\014lesystems)f(option)e
+Fb(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)24 b Fc(43)1015 1391 y(Generic)15 b(v)o(olume)f(name)7 b
+Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fc(56)1015
+1437 y(Global)15 b(statistics)d Fb(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)23 b Fc(36)1015 1483 y(Grammar,)14 b(FSinfo)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)20
+b Fc(39)1015 1528 y(Hesio)q(d)15 b(maps)5 b Fb(:)h(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)18 b Fc(13)1015
+1574 y(Home)13 b(directories)t Fb(:)c(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)18 b Fc(54)1015 1620 y(host,)c(\014lesystem)g(t)o(yp)q(e)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)21 b Fc(26)1015
+1665 y(host,)14 b(moun)o(t)f(selector)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)23 b Fc(17)1015 1711 y(hostd,)14 b(moun)o(t)f(selector)8
+b Fb(:)f(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(17)1015
+1757 y(Hostname)14 b(normalisation)f Fb(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(22)1015 1802 y(hostname,)14 b(FSinfo)g(command)g(line)h(option)t
+Fb(:)7 b(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b
+Fc(48)1015 1848 y(Ho)o(w)c(k)o(eys)g(are)h(lo)q(ok)o(ed)g(up)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19 b Fc(14)1015 1893
+y(Ho)o(w)13 b(lo)q(cations)i(are)e(parsed)s Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)17 b Fc(14)1015 1939 y(Ho)o(w)c(to)g(access)g(en)o(vironmen)o(t)i(v)n
+(ariables)h(in)d(maps)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)18 b
+Fc(15)1015 1985 y(Ho)o(w)13 b(to)g(disco)o(v)o(er)h(y)o(our)g(v)o(ersion)g
+(of)f(Amd)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(23)1015 2030 y(Ho)o(w)13 b(to)g(moun)o(t)g(a)g(lo)q(cal)i(disk)9
+b Fb(:)e(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)22 b Fc(28)1015 2076 y(Ho)o(w)13
+b(to)g(moun)o(t)g(a)g(UFS)g(\014lesystems)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(28)1015
+2122 y(Ho)o(w)13 b(to)g(moun)o(t)g(all)i(NFS)e(exp)q(orted)h(\014lesystems)9
+b Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(26)1015 2167 y(Ho)o(w)12
+b(to)g(moun)o(t)h(an)f(atomic)h(group)g(of)f(NFS)g(\014lesystems)5
+b Fb(:)j(:)17 b Fc(27)1015 2213 y(Ho)o(w)c(to)g(moun)o(t)g(and)h(NFS)f
+(\014lesystem)c Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)22 b Fc(26)1015 2259 y(Ho)o(w)13 b(to)g(reference)g(an)g(existing)j
+(part)d(of)g(the)g(lo)q(cal)h(name)1092 2304 y(space)f Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)25 b Fc(29)1015 2350 y(Ho)o(w)13 b(to)g(reference)g(part)g(of)g(the)g
+(lo)q(cal)i(name)e(space)8 b Fb(:)f(:)f(:)g(:)g(:)g(:)21 b
+Fc(29)1015 2396 y(Ho)o(w)13 b(to)g(select)h(log)g(messages)6
+b Fb(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(23)1015 2441 y(Ho)o(w)13
+b(to)g(set)g(default)h(map)f(parameters)f Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(15)1015 2487 y(Ho)o(w)13
+b(to)g(set)g(map)g(cac)o(he)h(parameters)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(29)1015
+2533 y(Ho)o(w)13 b(to)g(start)g(a)g(direct)h(automoun)o(t)g(p)q(oin)o(t)9
+b Fb(:)e(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b
+Fc(30)1015 2578 y(Ho)o(w)13 b(to)g(start)g(an)g(indirect)i(automoun)o(t)f(p)q
+(oin)o(t)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b
+Fc(29)1015 2624 y(Ho)o(w)13 b(v)n(ariables)i(are)e(expanded)5
+b Fb(:)j(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)18 b Fc(15)p eop
+%%Page: 55 57
+55 56 bop 0 -83 a Fo(Index)1613 b(SMM:13-55)0 158 y Fc(inherit,)14
+b(\014lesystem)h(t)o(yp)q(e)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(32)0 204 y(Inheritance)d(\014lesystem)6 b Fb(:)h(:)f(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)19 b Fc(32)0 250 y(In)o(terv)n(al)14 b(b)q(efore)f(a)g
+(\014lesystem)i(times)e(out)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)18 b Fc(21)0 295 y(In)o(tro)q(duction)8 b Fb(:)g(:)e(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20
+b Fc(4)0 341 y(k)n(arc)o(h,)13 b(moun)o(t)h(selector)9 b Fb(:)e(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)21 b Fc(17)0 387 y(Keep-aliv)o(es)11
+b Fb(:)c(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)22 b Fc(7)0 432 y(Key)13 b(lo)q(okup)7 b Fb(:)h(:)e(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(14)0 478 y(k)o(ey)m(,)13 b(moun)o(t)g(selector)e Fb(:)6
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(17)0
+524 y(License)14 b(Information)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)18 b Fc(2)0 569 y(link,)c(\014lesystem)h(t)o(yp)q(e)s
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)16 b
+Fc(29)0 615 y(linkx,)f(\014lesystem)f(t)o(yp)q(e)d Fb(:)6 b(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(29)0 661 y(Listing)15 b(curren)o(tly)f(moun)o
+(ted)g(\014lesystems)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)23 b Fc(34)0 706 y(Lo)q(cation)14 b(format)d Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(14)0 752 y(Lo)q(cation)14 b(lists)8 b Fb(:)h(:)d(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(6)0
+798 y(Log)13 b(\014lename)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(22)0 843 y(Log)13
+b(message)h(selection)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)18
+b Fc(23)0 889 y(log,)c(FSinfo)g(\014lesystems)g(option)e Fb(:)6
+b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)23 b Fc(45)0 935 y(Lo)q(oking)15 b(up)e(k)o(eys)c Fb(:)e(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)21 b Fc(14)0
+980 y(Mac)o(hine)15 b(arc)o(hitecture)f(names)6 b Fb(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(9)0 1026 y(Mac)o(hine)d(arc)o(hitectures)f(supp)q(orted)h(b)o(y)e(Amd)s
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16 b Fc(9)0
+1072 y(Mailing)g(list)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)21 b Fc(3)0 1117 y(Map)14
+b(cac)o(he)f(options)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)19 b Fc(29)0 1163 y(Map)14 b(cac)o(he)f(sync)o(hronising)6
+b Fb(:)j(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(29)0 1209 y(Map)c(cac)o(he)f(t)o
+(yp)q(es)6 b Fb(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)18 b Fc(29)0 1254 y(Map)c(cac)o(he,)f(\015ushing)5 b Fb(:)j(:)e(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(35)0 1300 y(Map)c(defaults)d
+Fb(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)23 b Fc(15)0 1346 y(Map)14 b(en)o(try)f(format)t Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b
+Fc(14)0 1391 y(Map)d(lo)q(okup)f Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(14)0 1437 y(Map)14
+b(options)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)19 b Fc(17)0 1483 y(Map)14 b(t)o(yp)q(es)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)19 b Fc(11)0 1528 y(map,)13 b(moun)o(t)h(selector)9
+b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(17)0
+1574 y(maps,)13 b(FSinfo)h(command)g(line)h(option)6 b Fb(:)h(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(48)0
+1620 y(Moun)o(t)14 b(a)f(\014lesystem)h(under)g(program)g(con)o(trol)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(28)0 1665
+y(Moun)o(t)d(home)f(directories)6 b Fb(:)i(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(54)0 1711 y(Moun)o(t)14 b(information)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)16 b Fc(11)0 1757 y(Moun)o(t)e(map)f(t)o(yp)q(es)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)18
+b Fc(11)0 1802 y(Moun)o(t)c(maps)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(11)0 1848
+y(Moun)o(t)14 b(option;)g(cac)o(he)8 b Fb(:)e(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)21 b Fc(29)0 1893 y(Moun)o(t)14 b(option;)g(dela)o(y)d
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)22 b Fc(18)0
+1939 y(Moun)o(t)14 b(option;)g(dev)7 b Fb(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)20 b Fc(28)0 1985 y(Moun)o(t)14 b(option;)g(fs)6
+b Fb(:)f(:)h(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)18
+b Fc(18)0 2030 y(Moun)o(t)c(option;)g(moun)o(t)8 b Fb(:)f(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)21 b Fc(28)0 2076 y(Moun)o(t)14 b(option;)g(opts)c
+Fb(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22 b Fc(18)0
+2122 y(Moun)o(t)14 b(option;)g(remopts)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)24 b Fc(19)0 2167 y(Moun)o(t)14 b(option;)g(rfs)7 b Fb(:)e(:)i(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19 b Fc(26)0 2213 y(Moun)o(t)14
+b(option;)g(rhost)d Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)23
+b Fc(26)0 2259 y(Moun)o(t)14 b(option;)g(sublink)e Fb(:)7 b(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)23 b Fc(20)0 2304 y(Moun)o(t)14 b(option;)g(t)o(yp)q(e)8
+b Fb(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b
+Fc(20)0 2350 y(Moun)o(t)14 b(option;)g(unmoun)o(t)t Fb(:)7
+b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)16 b Fc(28)0 2396 y(Moun)o(t)e(retries)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)20 b Fc(6)0 2441 y(Moun)o(t)14 b(selector;)f(arc)o(h)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)20 b Fc(16)0
+2487 y(Moun)o(t)14 b(selector;)f(auto)q(dir)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)20 b Fc(16)0 2533 y(Moun)o(t)14 b(selector;)f(b)o(yte)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(16)0
+2578 y(Moun)o(t)14 b(selector;)f(cluster)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)18 b Fc(17)0 2624 y(Moun)o(t)c(selector;)f(domain)7
+b Fb(:)h(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(17)1015 158
+y(Moun)o(t)14 b(selector;)g(hostd)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)19 b Fc(17)1015 204 y(Moun)o(t)14 b(selector;)g(host)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)21 b Fc(17)1015
+250 y(Moun)o(t)14 b(selector;)g(k)n(arc)o(h)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)20 b Fc(17)1015 295 y(Moun)o(t)14 b(selector;)g(k)o(ey)7
+b Fb(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b
+Fc(17)1015 341 y(Moun)o(t)14 b(selector;)g(map)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)20 b Fc(17)1015 387 y(Moun)o(t)14 b(selector;)g(os)9
+b Fb(:)d(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)22
+b Fc(17)1015 432 y(Moun)o(t)14 b(selector;)g(path)5 b Fb(:)i(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fc(17)1015 478 y(Moun)o(t)c(selector;)g(wire)
+8 b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21 b Fc(17)1015
+524 y(moun)o(t)14 b(system)f(call)i(\015ags)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)22 b Fc(18)1015 569 y(moun)o(t)14 b(system)f(call)f
+Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(18)1015 615 y(Moun)o(t)14 b(t)o(yp)q(es)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b
+Fc(26)1015 661 y(moun)o(t,)14 b(FSinfo)g(\014lesystems)g(option)7
+b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)20 b Fc(44)1015 706 y(moun)o(t,)14 b(moun)o(t)f(option)e
+Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(28)1015
+752 y(Moun)o(ting)15 b(a)e(lo)q(cal)i(disk)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)19 b Fc(28)1015 798 y(Moun)o(ting)c(a)e(UFS)g(\014lesystem)g
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(28)1015 843 y(Moun)o(ting)15
+b(a)e(v)o(olume)e Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+23 b Fc(6)1015 889 y(Moun)o(ting)15 b(an)f(atomic)g(group)f(of)g(NFS)g
+(\014lesystems)7 b Fb(:)h(:)e(:)g(:)g(:)g(:)20 b Fc(27)1015
+935 y(Moun)o(ting)15 b(an)e(existing)i(part)e(of)g(the)g(lo)q(cal)i(name)e
+(space)5 b Fb(:)i(:)18 b Fc(29)1015 980 y(Moun)o(ting)d(an)f(NFS)f
+(\014lesystem)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(26)1015 1026 y(Moun)o(ting)15
+b(en)o(tire)f(exp)q(ort)g(trees)7 b Fb(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(26)1015
+1072 y(Moun)o(ting)15 b(part)f(of)e(the)i(lo)q(cal)g(name)g(space)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b
+Fc(29)1015 1117 y(Moun)o(ting)15 b(user)f(\014lesystems)5 b
+Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(53)1015 1163 y(Multiple-thre)q(aded)d
+(serv)o(er)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(8)1015
+1209 y(Namespace)12 b Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(6)1015 1254 y(ndbm)14
+b(maps)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)18 b Fc(12)1015 1300 y(Net)o(w)o(ork)13
+b(\014lesystem)i(group)10 b Fb(:)c(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(27)1015 1346 y(Net)o(w)o(ork)13 b(host)h(\014lesystem)5
+b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(26)1015 1391
+y(Net)o(w)o(ork-wide)14 b(naming)6 b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)19 b Fc(5)1015 1437 y(NFS)13 b(ping)7 b Fb(:)h(:)e(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)20
+b Fc(7)1015 1483 y(nfs,)13 b(\014lesystem)i(t)o(yp)q(e)c Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(26)1015
+1528 y(nfsx,)13 b(\014lesystem)i(t)o(yp)q(e)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)22 b Fc(27)1015 1574 y(NFS)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)19 b Fc(26)1015 1620 y(NIS)13 b(\(YP\))g(domain)h(name)5
+b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(24)1015 1665
+y(NIS)13 b(\(YP\))g(maps)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(12)1015 1711 y(No)q(des)14 b(generated)g(on)f
+(a)g(restart)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(32)1015 1757 y(Non-blo)q(c)o(king)
+e(op)q(eration)c Fb(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(8)1015 1802 y(Normalising)16 b(hostnames)c Fb(:)6 b(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)24 b Fc(22)1015 1848 y(Obtaining)16 b(the)d(source)h(co)q(de)s
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(3)1015 1893 y(Op)q(erating)e
+(system)e(names)8 b Fb(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(9)1015 1939 y(Op)q(erating)15 b(systems)e(supp)q(orted)i(b)o(y)e(Amd)6
+b Fb(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(9)1015 1985 y(Op)q(erational)d(principles)t Fb(:)9 b(:)d(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)16 b Fc(6)1015 2030 y(opts,)e(FSinfo)g(\014lesystems)g
+(option)8 b Fb(:)g(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)22 b Fc(43)1015 2076 y(opts,)14 b(moun)o(t)f(option)g
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)24 b
+Fc(18)1015 2122 y(os,)13 b(FSinfo)h(host)g(attribute)8 b Fb(:)f(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)21 b Fc(41)1015 2167 y(os,)13 b(moun)o(t)h(selector)e
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(17)1015 2213 y(Ov)o(erriding)16 b(defaults)e(on)f(the)g(command)h(line)6
+b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(21)1015
+2259 y(Ov)o(erriding)d(the)d(default)h(moun)o(t)f(p)q(oin)o(t)f
+Fb(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(18)1015 2304 y(Ov)o(erriding)16 b(the)d(lo)q(cal)h(domain)h(name)t
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(21)1015 2350 y(Ov)o(erriding)f(the)d(NIS)g(\(YP\))f(domain)j(name)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b
+Fc(24)1015 2396 y(P)o(assing)d(parameters)f(to)f(the)g(moun)o(t)g(system)h
+(call)7 b Fb(:)g(:)g(:)f(:)g(:)g(:)g(:)20 b Fc(18)1015 2441
+y(passno,)14 b(FSinfo)g(\014lesystems)h(option)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)18 b Fc(43)1015
+2487 y(P)o(assw)o(ord)c(\014le)g(maps)t Fb(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(13)1015 2533 y(path,)d(moun)o(t)f(selector)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(17)1015
+2578 y(P)o(athname)14 b(op)q(erators)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)23 b Fc(15)1015 2624 y(Pic)o(king)16 b(up)d(existing)i(moun)o
+(ts)d Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)24 b Fc(23)p eop
+%%Page: 56 58
+56 57 bop 15 -83 a Fo(SMM:13-56)889 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 158 y Fc(pid)d(\014le,)g(creating)g(with)f(-p)g
+(option)g Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)23 b Fc(22)0 204 y(Primary)14 b(serv)o(er)t
+Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(18)0 250 y(pro)q(cess)d(id)g(of)e(Amd)h(daemon)8 b Fb(:)f(:)f(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)20 b Fc(22)0 295 y(Pro)q(cess)14 b(id)c Fb(:)c(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22 b
+Fc(22)0 341 y(Program)14 b(\014lesystem)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)23 b Fc(28)0 387 y(program,)13 b(\014lesystem)i(t)o(yp)q
+(e)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(28)0 432 y(Querying)15
+b(an)e(alternate)h(host)t Fb(:)7 b(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)17 b Fc(35)0
+478 y(quiet,)d(FSinfo)g(command)g(line)g(option)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fc(49)0 524
+y(Referencing)15 b(an)e(existing)i(part)e(of)g(the)g(lo)q(cal)i(name)e(space)
+82 569 y Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(29)0
+615 y(Referencing)d(part)e(of)g(the)g(lo)q(cal)h(name)g(space)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b Fc(29)0
+661 y(Regular)15 b(expressions)g(in)f(maps)d Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(29)0 706 y(remopts,)13 b(moun)o(t)h(option)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)17 b Fc(19)0 752 y(Replacemen)o(t)e(v)o(olumes)9
+b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21 b Fc(5)0
+798 y(Replicated)15 b(v)o(olumes)d Fb(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)23 b Fc(5)0 843 y(Resolving)16 b(aliased)f(hostnames)c
+Fb(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)23 b Fc(22)0 889 y(Restarting)15 b(existing)g(moun)o(ts)5
+b Fb(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)17 b Fc(23)0 935 y(rfs,)12 b(moun)o(t)i(option)8
+b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(26)0 980 y(rhost,)13 b(moun)o(t)h(option)s Fb(:)8 b(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)16 b Fc(26)0 1026 y(Ro)q(ot)d(\014lesystem)8
+b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(31)0 1072 y(ro)q(ot,)13 b(\014lesystem)h(t)o(yp)q(e)9
+b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)21 b Fc(31)0
+1117 y(RPC)13 b(retries)t Fb(:)7 b(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(8)0 1163 y(Run-time)d
+(administration)7 b Fb(:)i(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(33)0
+1209 y(rwho)13 b(serv)o(ers)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(56)0 1254 y(Secondary)15
+b(serv)o(er)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)17 b Fc(18)0 1300 y(sel,)c(FSinfo)h(moun)o(t)g(option)6
+b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)19 b Fc(44)0 1346 y(Selecting)c(sp)q
+(eci\014c)g(log)f(messages)s Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16 b Fc(23)0 1391
+y(Selector;)e(arc)o(h)7 b Fb(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)19 b Fc(16)0 1437 y(Selector;)14
+b(auto)q(dir)7 b Fb(:)g(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)19 b Fc(16)0 1483 y(Selector;)14 b(b)o(yte)6 b Fb(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b
+Fc(16)0 1528 y(Selector;)14 b(cluster)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(17)0 1574 y(Selector;)d(domain)6
+b Fb(:)i(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(17)0 1620 y(Selector;)14 b(hostd)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(17)0 1665 y(Selector;)c(host)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)20 b Fc(17)0 1711 y(Selector;)14 b(k)n(arc)o(h)6 b Fb(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(17)0
+1757 y(Selector;)14 b(k)o(ey)6 b Fb(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)18 b Fc(17)0 1802 y(Selector;)c(map)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)19 b Fc(17)0 1848 y(Selector;)14 b(os)8 b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b
+Fc(17)0 1893 y(Selector;)14 b(path)t Fb(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(17)0 1939 y(Selector;)d(wire)7
+b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)20 b Fc(17)0 1985 y(Selectors)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(16)0 2030 y(Serv)o(er)d(crashes)e Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(7)0 2076
+y(Setting)14 b(a)f(dela)o(y)i(on)e(a)g(moun)o(t)g(lo)q(cation)6
+b Fb(:)j(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(18)0 2122 y(Setting)14 b(Amd's)f(RPC)g(parameters)7 b
+Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)20 b Fc(23)0 2167 y(Setting)14 b(debug)g(\015ags)f Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)24 b Fc(24)0
+2213 y(Setting)14 b(default)g(map)g(parameters)8 b Fb(:)e(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b
+Fc(15)0 2259 y(Setting)14 b(map)g(cac)o(he)f(parameters)s Fb(:)8
+b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)16 b Fc(29)0 2304 y(Setting)e(map)g(options)e Fb(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 b Fc(17)0 2350
+y(Setting)14 b(system)g(moun)o(t)f(options)i(for)e(non-lo)q(cal)i(net)o(w)o
+(orks)82 2396 y Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b
+Fc(19)0 2441 y(Setting)c(system)g(moun)o(t)f(options)6 b Fb(:)i(:)e(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(18)0 2487 y(Setting)14 b(the)f(cluster)h(name)8 b Fb(:)f(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)21 b Fc(24)0 2533 y(Setting)14 b(the)f(default)h(moun)o(t)g
+(directory)9 b Fb(:)e(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)22 b Fc(21)0 2578 y(Setting)14 b(the)f(\014lesystem)i(t)o(yp)q(e)e(option)
+7 b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+20 b Fc(20)0 2624 y(Setting)14 b(the)f(in)o(terv)n(al)i(b)q(efore)e(a)g
+(\014lesystem)i(times)f(out)c Fb(:)c(:)g(:)22 b Fc(21)1015
+158 y(Setting)15 b(the)e(in)o(terv)n(al)i(b)q(et)o(w)o(een)e(unmoun)o(t)h
+(attempts)e Fb(:)6 b(:)g(:)g(:)25 b Fc(23)1015 204 y(Setting)15
+b(the)e(Kernel)h(arc)o(hitecture)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(22)1015
+250 y(Setting)d(the)e(lo)q(cal)i(domain)f(name)8 b Fb(:)f(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21
+b Fc(21)1015 295 y(Setting)15 b(the)e(lo)q(cal)i(moun)o(t)e(p)q(oin)o(t)8
+b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)22 b Fc(18)1015 341 y(Setting)15 b(the)e(log)h(\014le)8
+b Fb(:)f(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(22)1015 387 y(Setting)15 b(the)e(NIS)g(\(YP\))f(domain)j(name)9
+b Fb(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(24)1015 432 y(Setting)15 b(the)e(sublink)i(option)s Fb(:)9
+b(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(20)1015 478 y(Sharing)e(a)e(\014leserv)o(er)i
+(b)q(et)o(w)o(een)e(arc)o(hitectures)g Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)24 b Fc(55)1015 524 y(SIGHUP)13 b(signal)8 b Fb(:)h(:)d(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(29)1015
+569 y(SIGINT)13 b(signal)7 b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(34)1015 615 y(SIGTERM)14
+b(signal)9 b Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(34)1015 661 y(Source)14 b(co)q(de)g(distribution)g Fb(:)6
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(3)1015 706 y(Starting)15
+b(Amd)5 b Fb(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)18 b Fc(33)1015 752 y(Statically)e(moun)o(ts)e(\014lesystems,)g
+(FSinfo)7 b Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)20
+b Fc(45)1015 798 y(Statistics)12 b Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b
+Fc(36)1015 843 y(Stopping)16 b(Amd)7 b Fb(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(34)1015 889 y(Stripping)c(the)d
+(lo)q(cal)i(domain)f(name)7 b Fb(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(15)1015 935 y(sublink,)c(moun)o(t)d
+(option)g Fb(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25 b Fc(20)1015
+980 y(sublink)13 b Fb(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(5)1015
+1026 y(Supp)q(orted)15 b(mac)o(hine)g(arc)o(hitectures)8 b
+Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)21 b Fc(9)1015 1072 y(Supp)q(orted)15 b(op)q(erating)g(systems)5
+b Fb(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)18 b Fc(9)1015 1117 y(Sym)o(b)q(olic)e(link)f
+(\014lesystem)f(I)q(I)8 b Fb(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21 b Fc(29)1015
+1163 y(Sym)o(b)q(olic)16 b(link)f(\014lesystem)s Fb(:)8 b(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)17 b Fc(29)1015 1209 y(symlink,)e(link)g(\014lesystem)f(t)o(yp)q
+(e)9 b Fb(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(29)1015 1254 y(symlink,)15 b(linkx)g
+(\014lesystem)g(t)o(yp)q(e)7 b Fb(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 b Fc(29)1015
+1300 y(Sync)o(hronisi)q(ng)c(the)d(map)h(cac)o(he)5 b Fb(:)h(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(29)1015 1346 y(syslog)d(priorities)6 b Fb(:)j(:)d(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(23)1015 1391 y(syslog)13
+b Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)24 b Fc(22)1015 1437 y(The)13
+b(moun)o(t)h(system)f(call)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)18
+b Fc(18)1015 1483 y(T)m(op)13 b(lev)o(el)i(\014lesystem)7 b
+Fb(:)h(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fc(31)1015
+1528 y(toplvl,)15 b(\014lesystem)f(t)o(yp)q(e)s Fb(:)8 b(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)17 b Fc(31)1015 1574 y(t)o(yp)q(e,)d(moun)o(t)f(option)e
+Fb(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b
+Fc(20)1015 1620 y(T)o(yp)q(es)14 b(of)f(con\014guration)i(map)8
+b Fb(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(11)1015 1665 y(T)o(yp)q(es)14
+b(of)f(\014lesystem)f Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+24 b Fc(26)1015 1711 y(T)o(yp)q(es)14 b(of)f(moun)o(t)g(map)5
+b Fb(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(11)1015
+1757 y(ufs,)13 b(\014lesystem)i(t)o(yp)q(e)c Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(28)1015 1802 y(UFS)6 b Fb(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)19 b Fc(28)1015 1848 y(Union)c(\014le)e(maps)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(13)1015 1893 y(Union)c(\014lesystem)7 b Fb(:)g(:)g(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fc(31)1015 1939 y(union,)15
+b(\014lesystem)f(t)o(yp)q(e)5 b Fb(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+18 b Fc(31)1015 1985 y(Unix)c(\014lesystem)9 b Fb(:)f(:)e(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(28)1015 2030
+y(Unix)14 b(namespace)e Fb(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)23 b Fc(6)1015 2076 y(unmoun)o(t)15 b(attempt)e(bac)o(k)o
+(o\013)h(in)o(terv)n(al)8 b Fb(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(23)1015 2122 y(unmoun)o(t,)14
+b(moun)o(t)g(option)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)18
+b Fc(28)1015 2167 y(Unmoun)o(ting)d(a)e(\014lesystem)6 b Fb(:)i(:)e(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)19 b Fc(37)1015 2213 y(User)13 b(\014lesystems)t
+Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(53)1015 2259 y(User)c(maps,)g(automatic)i(generation)t
+Fb(:)8 b(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)18 b Fc(13)1015 2304 y(Using)c(FSinfo)s Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(38)1015
+2350 y(Using)d(syslog)h(to)e(log)h(errors)c Fb(:)c(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)23
+b Fc(22)1015 2396 y(Using)14 b(the)g(passw)o(ord)f(\014le)h(as)f(a)g(map)6
+b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)19 b Fc(13)1015 2441 y(V)m(ariable)c(expansion)5 b Fb(:)j(:)e(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(15)1015 2487 y(v)o(erb)q(ose,)c
+(FSinfo)g(command)g(line)h(option)t Fb(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(49)1015 2533 y(V)m(ersion)c(information)h(at)e
+(run-time)6 b Fb(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)19 b Fc(37)1015 2578 y(V)m(ersion)14 b(information)6
+b Fb(:)i(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b
+Fc(23)1015 2624 y(v)o(olname,)c(FSinfo)f(moun)o(t)f(option)f
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)23 b Fc(44)p eop
+%%Page: 57 59
+57 58 bop 0 -83 a Fo(Index)1613 b(SMM:13-57)0 158 y Fc(V)m(olume)14
+b(binding)6 b Fb(:)j(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)19 b Fc(6)0 204 y(V)m(olume)14 b(names)8 b Fb(:)f(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b
+Fc(5)0 250 y(V)m(olume)7 b Fb(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b
+Fc(5)0 295 y(Wildcards)c(in)d(maps)5 b Fb(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)18 b Fc(14)1015 158 y(wire,)13 b(moun)o(t)h(selector)d
+Fb(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(17)1015
+204 y(YP)13 b(domain)i(name)8 b Fb(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)21 b Fc(24)p eop
+%%Page: -1 60
+-1 59 bop 1756 -83 a Fo(SMM:13-i)0 158 y Fm(T)-7 b(able)15
+b(of)g(Con)n(ten)n(ts)0 308 y Fq(Preface)c Fa(:)e(:)i(:)f(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)34 b Fq(1)0 420 y(License)13 b Fa(:)e(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)35 b Fq(1)0 532 y(Source)23
+b(Distribution)15 b Fa(:)d(:)e(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)37 b Fq(1)149 594 y Fo(Bug)16 b(Rep)q(orts)e
+Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)28 b Fo(1)149 644 y(Mailing)17 b(List)8 b Fj(:)g(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)22
+b Fo(2)0 750 y Fq(In)n(tro)r(duction)14 b Fa(:)e(:)e(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)36
+b Fq(2)0 862 y(1)67 b(Ov)n(erview)11 b Fa(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)33
+b Fq(2)149 925 y Fo(1.1)45 b(F)l(undamen)o(tals)10 b Fj(:)d(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)24 b Fo(2)149 975 y(1.2)45
+b(Filesystems)16 b(and)f(V)l(olumes)10 b Fj(:)e(:)f(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)24
+b Fo(3)149 1024 y(1.3)45 b(V)l(olume)16 b(Naming)9 b Fj(:)e(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)23 b Fo(3)149 1074 y(1.4)45
+b(V)l(olume)16 b(Binding)8 b Fj(:)i(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)22 b Fo(3)149 1124 y(1.5)45 b(Op)q(erational)16 b(Principles)6
+b Fj(:)k(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20 b Fo(3)149 1174 y(1.6)45
+b(Moun)o(ting)15 b(a)g(V)l(olume)e Fj(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)26
+b Fo(4)149 1224 y(1.7)45 b(Automatic)15 b(Unmoun)o(ting)e Fj(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)27 b Fo(4)149 1273 y(1.8)45 b(Keep-aliv)o(es)5
+b Fj(:)10 b(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)20 b Fo(5)149 1323 y(1.9)45 b(Non-blo)q(c)o(king)17 b(Op)q(eration)10
+b Fj(:)e(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)24 b Fo(5)0 1430 y Fq(2)67 b(Supp)r(orted)24
+b(Platforms)11 b Fa(:)e(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)33
+b Fq(6)149 1492 y Fo(2.1)45 b(Supp)q(orted)16 b(Op)q(erating)g(Systems)11
+b Fj(:)c(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)25
+b Fo(6)149 1542 y(2.2)45 b(Supp)q(orted)16 b(Mac)o(hine)g(Arc)o(hitectures)6
+b Fj(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20
+b Fo(7)0 1648 y Fq(3)67 b(Moun)n(t)23 b(Maps)11 b Fa(:)f(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)34
+b Fq(7)149 1710 y Fo(3.1)45 b(Map)15 b(T)o(yp)q(es)5 b Fj(:)j(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20 b Fo(7)299
+1760 y(3.1.1)44 b(File)16 b(maps)9 b Fj(:)e(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)23 b Fo(8)299 1810 y(3.1.2)44 b(ndbm)16 b(maps)10 b Fj(:)d(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)24 b Fo(8)299 1859 y(3.1.3)44 b(NIS)16 b(maps)9
+b Fj(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)23 b Fo(9)299 1909
+y(3.1.4)44 b(Hesio)q(d)16 b(maps)10 b Fj(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)24
+b Fo(9)299 1959 y(3.1.5)44 b(P)o(assw)o(ord)14 b(maps)f Fj(:)7
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)28 b Fo(10)299 2009 y(3.1.6)44 b(Union)16 b(maps)6 b
+Fj(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b Fo(10)149 2059 y(3.2)45 b(Ho)o(w)15
+b(k)o(eys)g(are)f(lo)q(ok)o(ed)i(up)c Fj(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26 b
+Fo(10)149 2108 y(3.3)45 b(Lo)q(cation)16 b(F)l(ormat)11 b Fj(:)5
+b(:)i(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(11)299 2158
+y(3.3.1)44 b(Map)15 b(Defaults)c Fj(:)6 b(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)25 b
+Fo(12)299 2208 y(3.3.2)44 b(V)l(ariable)16 b(Expansion)e Fj(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)28
+b Fo(12)299 2258 y(3.3.3)44 b(Selectors)8 b Fj(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)22 b Fo(13)299 2308 y(3.3.4)44 b(Map)15 b(Options)5
+b Fj(:)i(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)19 b Fo(14)448 2357 y(3.3.4.1)44
+b(dela)o(y)15 b(Option)5 b Fj(:)j(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)20 b Fo(14)448 2407 y(3.3.4.2)44 b(fs)15 b(Option)c
+Fj(:)c(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+25 b Fo(14)448 2457 y(3.3.4.3)44 b(opts)14 b(Option)5 b Fj(:)j(:)g(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 b Fo(15)448
+2507 y(3.3.4.4)44 b(remopts)14 b(Option)7 b Fj(:)i(:)e(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)22 b Fo(16)448 2557 y(3.3.4.5)44 b(sublink)17
+b(Option)6 b Fj(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)20
+b Fo(16)448 2607 y(3.3.4.6)44 b(t)o(yp)q(e)15 b(Option)f Fj(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)28
+b Fo(16)p eop
+%%Page: -2 61
+-2 60 bop 15 -83 a Fo(SMM:13-ii)911 b(4.4)15 b(BSD)g(Automoun)o(ter)f
+(Reference)j(Man)o(ual)0 17 y Fq(4)67 b Ff(Amd)24 b Fq(Command)e(Line)h
+(Options)6 b Fa(:)11 b(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)29 b Fq(16)149 79 y Fo(4.1)45
+b Fl(-a)15 b Fp(directory)8 b Fj(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)19 b Fo(17)149 129 y(4.2)45 b Fl(-c)15 b
+Fp(cac)o(he-in)o(terv)m(al)c Fj(:)e(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)24
+b Fo(17)149 178 y(4.3)45 b Fl(-d)15 b Fp(domain)d Fj(:)c(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27 b Fo(17)149 228
+y(4.4)45 b Fl(-k)15 b Fp(k)o(ernel-arc)o(hitecture)f Fj(:)7
+b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)25 b Fo(17)149 278 y(4.5)45 b Fl(-l)15 b
+Fp(log-option)6 b Fj(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)20 b Fo(18)149 328 y(4.6)45 b Fl(-n)12 b Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27
+b Fo(18)149 378 y(4.7)45 b Fl(-p)12 b Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27
+b Fo(18)149 428 y(4.8)45 b Fl(-r)12 b Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27
+b Fo(18)149 477 y(4.9)45 b Fl(-t)15 b Fp(timeout.retransmit)10
+b Fj(:)c(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)24 b Fo(18)149 527 y(4.10)45 b Fl(-v)11
+b Fj(:)6 b(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)26 b Fo(19)149 577 y(4.11)45 b Fl(-w)15
+b Fp(w)o(ait-timeout)8 b Fj(:)f(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22
+b Fo(19)149 627 y(4.12)45 b Fl(-x)15 b Fp(opts)d Fj(:)7 b(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)26 b Fo(19)149
+677 y(4.13)45 b Fl(-y)15 b Fp(NIS-domain)6 b Fj(:)i(:)f(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)20 b Fo(20)149 726 y(4.14)45 b Fl(-C)15
+b Fp(cluster-name)9 b Fj(:)f(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)22
+b Fo(20)149 776 y(4.15)45 b Fl(-D)15 b Fp(opts)d Fj(:)7 b(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)26 b Fo(20)0
+883 y Fq(5)67 b(Filesystem)23 b(T)n(yp)r(es)7 b Fa(:)j(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)30 b Fq(20)149 945 y
+Fo(5.1)45 b(Net)o(w)o(ork)14 b(Filesystem)i(\(`)p Fl(type:=nfs)p
+Fo('\))7 b Fj(:)e(:)i(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)22
+b Fo(21)149 995 y(5.2)45 b(Net)o(w)o(ork)14 b(Host)g(Filesystem)i(\(`)p
+Fl(type:=host)p Fo('\))10 b Fj(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)27 b Fo(21)149
+1045 y(5.3)45 b(Net)o(w)o(ork)14 b(Filesystem)i(Group)f(\(`)p
+Fl(type:=nfsx)p Fo('\))5 b Fj(:)t(:)j(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)20 b Fo(22)149
+1094 y(5.4)45 b(Unix)16 b(Filesystem)g(\(`)p Fl(type:=ufs)p
+Fo('\))10 b Fj(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+27 b Fo(22)149 1144 y(5.5)45 b(Program)14 b(Filesystem)i(\(`)p
+Fl(type:=program)p Fo('\))6 b Fj(:)f(:)i(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)22
+b Fo(23)149 1194 y(5.6)45 b(Sym)o(b)q(olic)17 b(Link)f(Filesystem)g(\(`)p
+Fl(type:=link)p Fo('\))7 b Fj(:)t(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)21 b Fo(23)149
+1244 y(5.7)45 b(Sym)o(b)q(olic)17 b(Link)f(Filesystem)g(I)q(I)g(\(`)p
+Fl(type:=link)p Fo('\))10 b Fj(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27 b Fo(24)149 1294
+y(5.8)45 b(Automoun)o(t)14 b(Filesystem)i(\(`)p Fl(type:=auto)p
+Fo('\))6 b Fj(:)t(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)20 b Fo(24)149
+1343 y(5.9)45 b(Direct)15 b(Automoun)o(t)g(Filesystem)h(\(`)p
+Fl(type:=direct)p Fo('\))10 b Fj(:)d(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)28 b Fo(25)149 1393 y(5.10)45 b(Union)16
+b(Filesystem)g(\(`)p Fl(type:=union)p Fo('\))5 b Fj(:)g(:)i(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)20 b Fo(25)149 1443 y(5.11)45 b(Error)14
+b(Filesystem)i(\(`)p Fl(type:=error)p Fo('\))9 b Fj(:)e(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)27 b Fo(26)149 1493 y(5.12)45 b(T)l(op-lev)o(el)16
+b(Filesystem)g(\(`)p Fl(type:=toplvl)p Fo('\))11 b Fj(:)c(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)29 b Fo(26)149 1543 y(5.13)45 b(Ro)q(ot)15 b(Filesystem)t
+Fj(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)19 b Fo(26)149
+1592 y(5.14)45 b(Inheritance)16 b(Filesystem)d Fj(:)7 b(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)27
+b Fo(26)0 1699 y Fq(6)67 b(Run-time)24 b(Administration)6 b
+Fa(:)13 b(:)d(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)29 b Fq(27)149 1761 y Fo(6.1)45
+b(Starting)15 b Fp(Amd)c Fj(:)c(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)24 b Fo(27)149 1811 y(6.2)45 b(Stopping)16 b Fp(Amd)e
+Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26 b
+Fo(28)149 1861 y(6.3)45 b(Con)o(trolling)16 b Fp(Amd)10 b Fj(:)d(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)23 b Fo(28)299 1911 y(6.3.1)44 b
+Fp(Amq)16 b Fo(default)g(information)9 b Fj(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)23 b Fo(28)299 1960 y(6.3.2)44 b Fp(Amq)16
+b Fo(-f)f(option)t Fj(:)8 b(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)19 b Fo(29)299 2010
+y(6.3.3)44 b Fp(Amq)16 b Fo(-h)f(option)9 b Fj(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)23
+b Fo(29)299 2060 y(6.3.4)44 b Fp(Amq)16 b Fo(-m)f(option)e
+Fj(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)27 b Fo(29)299 2110 y(6.3.5)44 b Fp(Amq)16 b
+Fo(-M)f(option)10 b Fj(:)e(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fo(30)299 2160 y(6.3.6)44
+b Fp(Amq)16 b Fo(-s)f(option)e Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27 b Fo(30)299
+2209 y(6.3.7)44 b Fp(Amq)16 b Fo(-u)f(option)9 b Fj(:)f(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)23
+b Fo(31)299 2259 y(6.3.8)44 b Fp(Amq)16 b Fo(-v)f(option)9
+b Fj(:)f(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)24 b Fo(31)299 2309 y(6.3.9)44 b(Other)15
+b Fp(Amq)h Fo(options)d Fj(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)27 b Fo(31)p eop
+%%Page: -3 62
+-3 61 bop 1730 -83 a Fo(SMM:13-iii)0 17 y Fq(7)67 b(FSinfo)11
+b Fa(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)33 b Fq(31)149 79
+y Fo(7.1)45 b Fp(FSinfo)18 b Fo(o)o(v)o(erview)8 b Fj(:)f(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)23 b Fo(31)149 129 y(7.2)45 b(Using)16
+b Fp(FSinfo)9 b Fj(:)f(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)22
+b Fo(32)149 178 y(7.3)45 b Fp(FSinfo)18 b Fo(grammar)12 b Fj(:)c(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)29 b Fo(32)149 228 y(7.4)45 b Fp(FSinfo)18
+b Fo(host)d(de\014nitions)f Fj(:)7 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)27 b Fo(33)149
+278 y(7.5)45 b Fp(FSinfo)18 b Fo(host)d(attributes)8 b Fj(:)e(:)h(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)22 b Fo(33)299 328 y(7.5.1)44 b(netif)16 b(Option)e Fj(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)28 b Fo(34)299 378 y(7.5.2)44 b(con\014g)15
+b(Option)10 b Fj(:)f(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fo(34)299 428 y(7.5.3)44
+b(arc)o(h)15 b(Option)6 b Fj(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)21 b
+Fo(34)299 477 y(7.5.4)44 b(os)15 b(Option)8 b Fj(:)f(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)23 b Fo(34)299 527 y(7.5.5)44 b(cluster)16 b(Option)d
+Fj(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)28 b Fo(35)149 577 y(7.6)45 b Fp(FSinfo)18
+b Fo(\014lesystems)8 b Fj(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)23
+b Fo(35)299 627 y(7.6.1)44 b(fst)o(yp)q(e)15 b(Option)9 b Fj(:)f(:)f(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)24 b Fo(36)299 677 y(7.6.2)44 b(opts)15 b(Option)6 b Fj(:)i(:)f(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)21 b Fo(37)299 726 y(7.6.3)44 b(passno)15 b(Option)e
+Fj(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)27 b Fo(37)299 776 y(7.6.4)44 b(freq)15
+b(Option)10 b Fj(:)e(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fo(37)299 826
+y(7.6.5)44 b(moun)o(t)14 b(Option)5 b Fj(:)j(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)19
+b Fo(37)299 876 y(7.6.6)44 b(dumpset)15 b(Option)g Fj(:)7 b(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)29
+b Fo(38)299 926 y(7.6.7)44 b(log)15 b(Option)9 b Fj(:)f(:)f(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)24 b Fo(38)149 976 y(7.7)45 b Fp(FSinfo)18 b Fo(static)d(moun)o(ts)10
+b Fj(:)c(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)24 b Fo(38)149 1025 y(7.8)45
+b(De\014ning)16 b(an)f Fp(Amd)i Fo(Moun)o(t)e(Map)g(in)h Fp(FSinfo)f
+Fj(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)27 b Fo(39)149 1075 y(7.9)45
+b Fp(FSinfo)18 b Fo(Command)d(Line)h(Options)6 b Fj(:)i(:)g(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)21 b Fo(40)299 1125
+y(7.9.1)44 b Fl(-a)15 b Fp(auto)q(dir)e Fj(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)24
+b Fo(41)299 1175 y(7.9.2)44 b Fl(-b)15 b Fp(b)q(o)q(otparams)7
+b Fj(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)20 b Fo(41)299 1225 y(7.9.3)44 b Fl(-d)15
+b Fp(dumpsets)c Fj(:)c(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)24 b Fo(41)299 1274
+y(7.9.4)44 b Fl(-e)15 b Fp(exp)q(ortfs)f Fj(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)27
+b Fo(41)299 1324 y(7.9.5)44 b Fl(-f)15 b Fp(fstab)5 b Fj(:)i(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)19 b Fo(42)299 1374 y(7.9.6)44 b Fl(-h)15
+b Fp(hostname)10 b Fj(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 b Fo(42)299 1424
+y(7.9.7)44 b Fl(-m)15 b Fp(moun)o(t-maps)c Fj(:)c(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)25 b
+Fo(42)299 1474 y(7.9.8)44 b Fl(-q)11 b Fj(:)6 b(:)h(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(42)299 1523 y(7.9.9)44
+b Fl(-v)11 b Fj(:)6 b(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)25 b Fo(42)299 1573 y(7.9.10)43 b Fl(-D)15 b Fp(name[=defn])8
+b Fj(:)g(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)21 b Fo(42)299 1623 y(7.9.11)43 b Fl(-I)15 b Fp(directory)h
+Fj(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)26 b Fo(42)299 1673 y(7.9.12)43 b Fl(-U)15
+b Fp(name)c Fj(:)c(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)23 b Fo(43)149
+1723 y(7.10)45 b(Errors)14 b(pro)q(duced)i(b)o(y)f Fp(FSinfo)e
+Fj(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)25 b Fo(43)0 1829 y Fq(8)67 b(Examples)18 b Fa(:)10 b(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)40
+b Fq(45)149 1891 y Fo(8.1)45 b(User)15 b(Filesystems)10 b Fj(:)e(:)g(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fo(45)149 1941 y(8.2)45 b(Home)15
+b(Directories)5 b Fj(:)j(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20
+b Fo(47)149 1991 y(8.3)45 b(Arc)o(hitecture)16 b(Sharing)10
+b Fj(:)e(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fo(48)149 2041 y(8.4)45
+b(Wildcard)16 b(names)f(&)h(Replicated)h(Serv)o(ers)12 b Fj(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)27 b Fo(48)149 2091 y(8.5)45
+b(`)p Fl(rwho)p Fo(')14 b(serv)o(ers)d Fj(:)c(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)27 b Fo(49)149 2140 y(8.6)45 b(`)p Fl(/vol)p
+Fo(')6 b Fj(:)g(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)21 b Fo(49)0 2240 y Fq(9)67 b(In)n(ternals)15
+b Fa(:)c(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)38 b Fq(50)149 2302 y Fo(9.1)45
+b(Log)15 b(Messages)c Fj(:)c(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)27 b Fo(50)299 2352 y(9.1.1)44 b(F)l(atal)15 b(errors)10
+b Fj(:)c(:)h(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)25 b Fo(50)299 2402 y(9.1.2)44
+b(Info)15 b(messages)10 b Fj(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)25 b Fo(52)0
+2508 y Fq(Ac)n(kno)n(wledgemen)n(ts)d(&)h(T)-6 b(rademarks)9
+b Fa(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)h(:)31 b Fq(53)0 2630 y(Index)7 b Fa(:)12 b(:)e(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)30 b Fq(53)p eop
+%%Trailer
+end
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/usr.sbin/amd/doc/amdref.texinfo b/usr.sbin/amd/doc/amdref.texinfo
new file mode 100644
index 0000000..4a6d8e9
--- /dev/null
+++ b/usr.sbin/amd/doc/amdref.texinfo
@@ -0,0 +1,4554 @@
+\input texinfo @c -*-texinfo-*-
+@c
+@c Copyright (c) 1989 Jan-Simon Pendry
+@c Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+@c Copyright (c) 1989 The Regents of the University of California.
+@c All rights reserved.
+@c
+@c This code is derived from software contributed to Berkeley by
+@c Jan-Simon Pendry at Imperial College, London.
+@c
+@c Redistribution and use in source and binary forms, with or without
+@c modification, are permitted provided that the following conditions
+@c are met:
+@c 1. Redistributions of source code must retain the above copyright
+@c notice, this list of conditions and the following disclaimer.
+@c 2. Redistributions in binary form must reproduce the above copyright
+@c notice, this list of conditions and the following disclaimer in the
+@c documentation and/or other materials provided with the distribution.
+@c 3. All advertising materials mentioning features or use of this software
+@c must display the following acknowledgement:
+@c This product includes software developed by the University of
+@c California, Berkeley and its contributors.
+@c 4. Neither the name of the University nor the names of its contributors
+@c may be used to endorse or promote products derived from this software
+@c without specific prior written permission.
+@c
+@c THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+@c ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+@c IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@c ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+@c FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+@c DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+@c OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+@c HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+@c LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+@c OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+@c
+@c @(#)amdref.texinfo 8.1 (Berkeley) 6/6/93
+@c
+@c $Id: amdref.texinfo,v 5.2.2.1 1992/02/09 15:11:50 jsp beta $
+@c
+@setfilename amdref.info
+@c @setfilename /usr/local/emacs/info/amd
+@tex
+\overfullrule=0pt
+@end tex
+
+@settitle 4.4 BSD Automounter Reference Manual
+@titlepage
+@sp 6
+@center @titlefont{Amd}
+@sp 2
+@center @titlefont{The 4.4 BSD Automounter}
+@sp 2
+@center @titlefont{Reference Manual}
+@sp 2
+@center @authorfont{Jan-Simon Pendry}
+@sp
+@center @i{and}
+@sp
+@center @authorfont{Nick Williams}
+@sp 4
+@center Last updated March 1991
+@center Documentation for software revision 5.3 Alpha
+@page
+Copyright @copyright{} 1989 Jan-Simon Pendry
+@sp -1
+Copyright @copyright{} 1989 Imperial College of Science, Technology & Medicine
+@sp -1
+Copyright @copyright{} 1989 The Regents of the University of California.
+@sp 0
+All Rights Reserved.
+@vskip 1ex
+Permission to copy this document, or any portion of it, as
+necessary for use of this software is granted provided this
+copyright notice and statement of permission are included.
+@end titlepage
+@page
+@ifinfo
+@node Top, License, , (DIR)
+
+Amd - The 4.4 BSD Automounter
+*****************************
+
+Amd is the 4.4 BSD Automounter. This Info file describes how
+to use and understand Amd.
+@end ifinfo
+
+@menu
+* License:: Explains the terms and conditions for using
+ and distributing Amd.
+* Distrib:: How to get the latest Amd distribution.
+* Intro:: An introduction to Automounting concepts.
+* Overview:: An overview of Amd.
+* Supported Platforms:: Machines and Systems supported by Amd.
+* Mount Maps:: Details of mount maps
+* Amd Command Line Options:: All the Amd command line options explained.
+* Filesystem Types:: The different mount types supported by Amd.
+* Run-time Administration:: How to start, stop and control Amd.
+* FSinfo:: The FSinfo filesystem management tool.
+* Internals:: Internals.
+* Acknowledgements & Trademarks:: Legal notes.
+* Examples:: Some examples showing how Amd might be used.
+* Internals:: Implementation details.
+* Acknowledgements & Trademarks::
+
+Indexes
+* Index:: An item for each concept.
+@end menu
+
+@iftex
+@unnumbered Preface
+
+This manual documents the use of the 4.4 BSD automounter---@i{Amd}.
+This is primarily a reference manual. Unfortunately, no tutorial
+exists.
+
+This manual comes in two forms: the published form and the Info form.
+The Info form is for on-line perusal with the INFO program which is
+distributed along with GNU Emacs. Both forms contain substantially the
+same text and are generated from a common source file, which is
+distributed with the @i{Amd} source.
+@end iftex
+
+@node License, Distrib, Top, Top
+@unnumbered License
+@cindex License Information
+
+@i{Amd} is not in the public domain; it is copyrighted and there are
+restrictions on its distribution.
+
+Redistribution and use in source and binary forms are permitted provided
+that: (1) source distributions retain this entire copyright notice and
+comment, and (2) distributions including binaries display the following
+acknowledgement: ``This product includes software developed by The
+University of California, Berkeley and its Contributors'' in the
+documentation or other materials provided with the distribution and in
+all advertising materials mentioning features or use of this software.
+neither the name of the University nor the names of its Contributors may
+be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+@node Distrib, Intro, License, Top
+@unnumbered Source Distribution
+@cindex Source code distribution
+@cindex Obtaining the source code
+
+If you have access to the Internet, you can get the latest distribution
+version of @i{Amd} from host @file{usc.edu} using anonymous FTP. Move to
+the directory @file{/pub/amd} on that host and fetch the file @file{amd.tar.Z}.
+
+If you are in the UK, you can get the latest distribution version of
+@i{Amd} from the UKnet info-server. Start by sending email to
+@file{info-server@@doc.ic.ac.uk}.
+
+Sites on the UK JANET network can get the latest distribution by using
+anonymous NIFTP to fetch the file @samp{<AMD>amd.tar.Z} from host
+@samp{uk.ac.imperial.doc.src}.
+
+Revision 5.2 was part of the 4.3 BSD Reno distribution.
+
+Revision 5.3bsdnet, a late alpha version of 5.3, was part
+of the BSD network version 2 distribution
+
+@unnumberedsec Bug Reports
+@cindex Bug reports
+
+Send all bug reports to @file{jsp@@doc.ic.ac.uk} quoting the details of
+the release and your configuration. These can be obtained by running
+the command @samp{amd -v}.
+
+@unnumberedsec Mailing List
+@cindex Mailing list
+
+There is a mailing list for people interested in keeping uptodate with
+developments. To subscribe, send a note to @file{amd-workers-request@@acl.lanl.gov}.
+
+@node Intro, Overview, Distrib, Top
+@unnumbered Introduction
+@cindex Introduction
+
+An @dfn{automounter} maintains a cache of mounted filesystems.
+Filesystems are mounted on demand when they are first referenced,
+and unmounted after a period of inactivity.
+
+@i{Amd} may be used as a replacement for Sun's automounter. The choice
+of which filesystem to mount can be controlled dynamically with
+@dfn{selectors}. Selectors allow decisions of the form ``hostname is
+@var{this},'' or ``architecture is not @var{that}.'' Selectors may be
+combined arbitrarily. @i{Amd} also supports a variety of filesystem
+types, including NFS, UFS and the novel @dfn{program} filesystem. The
+combination of selectors and multiple filesystem types allows identical
+configuration files to be used on all machines so reducing the
+administrative overhead.
+
+@i{Amd} ensures that it will not hang if a remote server goes down.
+Moreover, @i{Amd} can determine when a remote server has become
+inaccessible and then mount replacement filesystems as and when they
+become available.
+
+@i{Amd} contains no proprietary source code and has been ported to
+numerous flavours of Unix.
+
+@node Overview, Supported Platforms, Intro, Top
+@chapter Overview
+
+@i{Amd} maintains a cache of mounted filesystems. Filesystems are
+@dfn{demand-mounted} when they are first referenced, and unmounted after
+a period of inactivity. @i{Amd} may be used as a replacement for Sun's
+@b{automount}(8) program. It contains no proprietary source code and
+has been ported to numerous flavours of Unix. @xref{Supported Operating
+Systems}.@refill
+
+@i{Amd} was designed as the basis for experimenting with filesystem
+layout and management. Although @i{Amd} has many direct applications it
+is loaded with additional features which have little practical use. At
+some point the infrequently used components may be removed to streamline
+the production system.
+
+@c @i{Amd} supports the notion of @dfn{replicated} filesystems by evaluating
+@c each member of a list of possible filesystem locations in parallel.
+@c @i{Amd} checks that each cached mapping remains valid. Should a mapping be
+@c lost -- such as happens when a fileserver goes down -- @i{Amd} automatically
+@c selects a replacement should one be available.
+@c
+@menu
+* Fundamentals::
+* Filesystems and Volumes::
+* Volume Naming::
+* Volume Binding::
+* Operational Principles::
+* Mounting a Volume::
+* Automatic Unmounting::
+* Keep-alives::
+* Non-blocking Operation::
+@end menu
+
+@node Fundamentals, Filesystems and Volumes, Overview, Overview
+@comment node-name, next, previous, up
+@section Fundamentals
+@cindex Automounter fundamentals
+
+The fundamental concept behind @i{Amd} is the ability to separate the
+name used to refer to a file from the name used to refer to its physical
+storage location. This allows the same files to be accessed with the
+same name regardless of where in the network the name is used. This is
+very different from placing @file{/n/hostname} in front of the pathname
+since that includes location dependent information which may change if
+files are moved to another machine.
+
+By placing the required mappings in a centrally administered database,
+filesystems can be re-organised without requiring changes to
+configuration files, shell scripts and so on.
+
+@node Filesystems and Volumes, Volume Naming, Fundamentals, Overview
+@comment node-name, next, previous, up
+@section Filesystems and Volumes
+@cindex Filesystem
+@cindex Volume
+@cindex Fileserver
+@cindex sublink
+
+@i{Amd} views the world as a set of fileservers, each containg one or
+more filesystems where each filesystem contains one or more
+@dfn{volumes}. Here the term @dfn{volume} is used to refer to a
+coherent set of files such as a user's home directory or a @TeX{}
+distribution.@refill
+
+In order to access the contents of a volume, @i{Amd} must be told in
+which filesystem the volume resides and which host owns the filesystem.
+By default the host is assumed to be local and the volume is assumed to
+be the entire filesystem. If a filesystem contains more than one
+volume, then a @dfn{sublink} is used to refer to the sub-directory
+within the filesystem where the volume can be found.
+
+@node Volume Naming, Volume Binding, Filesystems and Volumes, Overview
+@comment node-name, next, previous, up
+@section Volume Naming
+@cindex Volume names
+@cindex Network-wide naming
+@cindex Replicated volumes
+@cindex Duplicated volumes
+@cindex Replacement volumes
+
+Volume names are defined to be unique across the entire network. A
+volume name is the pathname to the volume's root as known by the users
+of that volume. Since this name uniquely identifies the volume
+contents, all volumes can be named and accessed from each host, subject
+to administrative controls.
+
+Volumes may be replicated or duplicated. Replicated volumes contain
+identical copies of the same data and reside at two or more locations in
+the network. Each of the replicated volumes can be used
+interchangeably. Duplicated volumes each have the same name but contain
+different, though functionally identical, data. For example,
+@samp{/vol/tex} might be the name of a @TeX{} distribution which varied
+for each machine architecture.@refill
+
+@i{Amd} provides facilities to take advantage of both replicated and
+duplicated volumes. Configuration options allow a single set of
+configuration data to be shared across an entire network by taking
+advantage of replicated and duplicated volumes.
+
+@i{Amd} can take advantage of replacement volumes by mounting them as
+required should an active fileserver become unavailable.
+
+@node Volume Binding, Operational Principles, Volume Naming, Overview
+@comment node-name, next, previous, up
+@section Volume Binding
+@cindex Volume binding
+@cindex Unix namespace
+@cindex Namespace
+@cindex Binding names to filesystems
+
+Unix implements a namespace of hierarchically mounted filesystems. Two
+forms of binding between names and files are provided. A @dfn{hard
+link} completes the binding when the name is added to the filesystem. A
+@dfn{soft link} delays the binding until the name is accessed. An
+@dfn{automounter} adds a further form in which the binding of name to
+filesystem is delayed until the name is accessed.@refill
+
+The target volume, in its general form, is a tuple (host, filesystem,
+sublink) which can be used to name the physical location of any volume
+in the network.
+
+When a target is referenced, @i{Amd} ignores the sublink element and
+determines whether the required filesystem is already mounted. This is
+done by computing the local mount point for the filesystem and checking
+for an existing filesystem mounted at the same place. If such a
+filesystem already exists then it is assumed to be functionally
+identical to the target filesystem. By default there is a one-to-one
+mapping between the pair (host, filesystem) and the local mount point so
+this assumption is valid.
+
+@node Operational Principles, Mounting a Volume, Volume Binding, Overview
+@comment node-name, next, previous, up
+@section Operational Principles
+@cindex Operational principles
+
+@i{Amd} operates by introducing new mount points into the namespace.
+These are called @dfn{automount} points. The kernel sees these
+automount points as NFS filesystems being served by @i{Amd}. Having
+attached itself to the namespace, @i{Amd} is now able to control the
+view the rest of the system has of those mount points. RPC calls are
+received from the kernel one at a time.
+
+When a @dfn{lookup} call is received @i{Amd} checks whether the name is
+already known. If it is not, the required volume is mounted. A
+symbolic link pointing to the volume root is then returned. Once the
+symbolic link is returned, the kernel will send all other requests
+direct to the mounted filesystem.
+
+If a volume is not yet mounted, @i{Amd} consults a configuration
+@dfn{mount-map} corresponding to the automount point. @i{Amd} then
+makes a runtime decision on what and where to mount a filesystem based
+on the information obtained from the map.
+
+@i{Amd} does not implement all the NFS requests; only those relevant
+to name binding such as @dfn{lookup}, @dfn{readlink} and @dfn{readdir}.
+Some other calls are also implemented but most simply return an error
+code; for example @dfn{mkdir} always returns ``read-only filesystem''.
+
+@node Mounting a Volume, Automatic Unmounting, Operational Principles, Overview
+@comment node-name, next, previous, up
+@section Mounting a Volume
+@cindex Mounting a volume
+@cindex Location lists
+@cindex Alternate locations
+@cindex Mount retries
+@cindex Background mounts
+
+Each automount point has a corresponding mount map. The mount map
+contains a list of key--value pairs. The key is the name of the volume
+to be mounted. The value is a list of locations describing where the
+filesystem is stored in the network. In the source for the map the
+value would look like
+
+@display
+location1 location2 @dots{} locationN
+@end display
+
+@i{Amd} examines each location in turn. Each location may contain
+@dfn{selectors} which control whether @i{Amd} can use that location.
+For example, the location may be restricted to use by certain hosts.
+Those locations which cannot be used are ignored.
+
+@i{Amd} attempts to mount the filesystem described by each remaining
+location until a mount succeeds or @i{Amd} can no longer proceed. The
+latter can occur in three ways:
+
+@itemize @bullet
+@item
+If none of the locations could be used, or if all of the locations
+caused an error, then the last error is returned.
+
+@item
+If a location could be used but was being mounted in the background then
+@i{Amd} marks that mount as being ``in progress'' and continues with
+the next request; no reply is sent to the kernel.
+
+@item
+Lastly, one or more of the mounts may have been @dfn{deferred}. A mount
+is deferred if extra information is required before the mount can
+proceed. When the information becomes available the mount will take
+place, but in the mean time no reply is sent to the kernel. If the
+mount is deferred, @i{Amd} continues to try any remaining locations.
+@end itemize
+
+Once a volume has been mounted, @i{Amd} establishes a @dfn{volume
+mapping} which is used to satisfy subsequent requests.@refill
+
+@node Automatic Unmounting, Keep-alives, Mounting a Volume, Overview
+@comment node-name, next, previous, up
+@section Automatic Unmounting
+
+To avoid an ever increasing number of filesystem mounts, @i{Amd} removes
+volume mappings which have not been used recently. A time-to-live
+interval is associated with each mapping and when that expires the
+mapping is removed. When the last reference to a filesystem is removed,
+that filesystem is unmounted. If the unmount fails, for example the
+filesystem is still busy, the mapping is re-instated and its
+time-to-live interval is extended. The global default for this grace
+period is controlled by the ``-w'' command-line option (@pxref{-w
+Option, -w}). It is also possible to set this value on a per-mount
+basis (@pxref{opts Option, opts, opts}).@refill
+
+Filesystems can be forcefully timed out using the @i{Amq} command.
+@xref{Run-time Administration}.
+
+@node Keep-alives, Non-blocking Operation, Automatic Unmounting, Overview
+@comment node-name, next, previous, up
+@section Keep-alives
+@cindex Keep-alives
+@cindex Server crashes
+@cindex NFS ping
+
+Use of some filesystem types requires the presence of a server on
+another machine. If a machine crashes then it is of no concern to
+processes on that machine that the filesystem is unavailable. However,
+to processes on a remote host using that machine as a fileserver this
+event is important. This situation is most widely recognised when an
+NFS server crashes and the behaviour observed on client machines is that
+more and more processes hang. In order to provide the possibility of
+recovery, @i{Amd} implements a @dfn{keep-alive} interval timer for some
+filesystem types. Currently only NFS makes use of this service.
+
+The basis of the NFS keep-alive implementation is the observation that
+most sites maintain replicated copies of common system data such as
+manual pages, most or all programs, system source code and so on. If
+one of those servers goes down it would be reasonable to mount one of
+the others as a replacement.
+
+The first part of the process is to keep track of which fileservers are
+up and which are down. @i{Amd} does this by sending RPC requests to the
+servers' NFS @code{NullProc} and checking whether a reply is returned.
+While the server state is uncertain the requests are re-transmitted at
+three second intervals and if no reply is received after four attempts
+the server is marked down. If a reply is received the fileserver is
+marked up and stays in that state for 30 seconds at which time another
+NFS ping is sent.
+
+Once a fileserver is marked down, requests continue to be sent every 30
+seconds in order to determine when the fileserver comes back up. During
+this time any reference through @i{Amd} to the filesystems on that
+server fail with the error ``Operation would block''. If a replacement
+volume is available then it will be mounted, otherwise the error is
+returned to the user.
+
+@c @i{Amd} keeps track of which servers are up and which are down.
+@c It does this by sending RPC requests to the servers' NFS {\sc NullProc} and
+@c checking whether a reply is returned. If no replies are received after a
+@c short period, @i{Amd} marks the fileserver @dfn{down}.
+@c RPC requests continue to be sent so that it will notice when a fileserver
+@c comes back up.
+@c ICMP echo packets \cite{rfc:icmp} are not used because it is the availability
+@c of the NFS service that is important, not the existence of a base kernel.
+@c Whenever a reference to a fileserver which is down is made via @i{Amd}, an alternate
+@c filesystem is mounted if one is available.
+@c
+Although this action does not protect user files, which are unique on
+the network, or processes which do not access files via @i{Amd} or
+already have open files on the hung filesystem, it can prevent most new
+processes from hanging.
+
+By default, fileserver state is not maintained for NFS/TCP mounts. The
+remote fileserver is always assumed to be up.
+@c
+@c With a suitable combination of filesystem management and mount-maps,
+@c machines can be protected against most server downtime. This can be
+@c enhanced by allocating boot-servers dynamically which allows a diskless
+@c workstation to be quickly restarted if necessary. Once the root filesystem
+@c is mounted, @i{Amd} can be started and allowed to mount the remainder of
+@c the filesystem from whichever fileservers are available.
+
+@node Non-blocking Operation, , Keep-alives, Overview
+@comment node-name, next, previous, up
+@section Non-blocking Operation
+@cindex Non-blocking operation
+@cindex Multiple-threaded server
+@cindex RPC retries
+
+Since there is only one instance of @i{Amd} for each automount point,
+and usually only one instance on each machine, it is important that it
+is always available to service kernel calls. @i{Amd} goes to great
+lengths to ensure that it does not block in a system call. As a last
+resort @i{Amd} will fork before it attempts a system call that may block
+indefinitely, such as mounting an NFS filesystem. Other tasks such as
+obtaining filehandle information for an NFS filesystem, are done using a
+purpose built non-blocking RPC library which is integrated with
+@i{Amd}'s task scheduler. This library is also used to implement NFS
+keep-alives (@pxref{Keep-alives}).
+
+Whenever a mount is deferred or backgrounded, @i{Amd} must wait for it
+to complete before replying to the kernel. However, this would cause
+@i{Amd} to block waiting for a reply to be constructed. Rather than do
+this, @i{Amd} simply @dfn{drops} the call under the assumption that the
+kernel RPC mechanism will automatically retry the request.
+
+@node Supported Platforms, Mount Maps, Overview, Top
+@comment node-name, next, previous, up
+@chapter Supported Platforms
+
+@i{Amd} has been ported to a wide variety of machines and operating systems.
+The table below lists those platforms supported by the current release.
+
+@menu
+* Supported Operating Systems::
+* Supported Machine Architectures::
+@end menu
+
+@node Supported Operating Systems, Supported Machine Architectures, Supported Platforms, Supported Platforms
+@comment node-name, next, previous, up
+@section Supported Operating Systems
+@cindex Operating system names
+@cindex Operating systems supported by Amd
+@cindex Supported operating systems
+
+The following operating systems are currently supported by @i{Amd}.
+@i{Amd}'s conventional name for each system is given.
+
+@table @code
+@item acis43
+4.3 BSD for IBM RT. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item aix3
+AIX 3.1. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item aux
+System V for Mac-II. Contributed by Julian Onions @t{<jpo@@cs.nott.ac.uk>}
+@item bsd44
+4.4 BSD. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item concentrix
+Concentrix 5.0. Contributed by Sjoerd Mullender @t{<sjoerd@@cwi.nl>}
+@item convex
+Convex OS 7.1. Contributed by Eitan Mizrotsky @t{<eitan@@shumuji.ac.il>}
+@item dgux
+Data General DG/UX. Contributed by Mark Davies @t{<mark@@comp.vuw.ac.nz>}
+@item fpx4
+Celerity FPX 4.1/2. Contributed by Stephen Pope @t{<scp@@grizzly.acl.lanl.gov>}
+@item hcx
+Harris HCX/UX. Contributed by Chris Metcalf @t{<metcalf@@masala.lcs.mit.edu>}
+@item hlh42
+HLH OTS 1.@i{x} (4.2 BSD). Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item hpux
+HP-UX 6.@i{x} or 7.0. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item irix
+SGI Irix. Contributed by Scott R. Presnell @t{<srp@@cgl.ucsf.edu>}
+@item next
+Mach for NeXT. Contributed by Bill Trost @t{<trost%reed@@cse.ogi.edu>}
+@item pyrOSx
+Pyramid OSx. Contributed by Stefan Petri @t{<petri@@tubsibr.UUCP>}
+@item riscix
+Acorn RISC iX. Contributed by Piete Brooks @t{<pb@@cam.cl.ac.uk>}
+@item sos3
+SunOS 3.4 & 3.5. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item sos4
+SunOS 4.@i{x}. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@item u2_2
+Ultrix 2.2. Contributed by Piete Brooks @t{<pb@@cam.cl.ac.uk>}
+@item u3_0
+Ultrix 3. Contributed by Piete Brooks @t{<pb@@cam.cl.ac.uk>}
+@item u4_0
+Ultrix 4.0. Contributed by Chris Lindblad @t{<cjl@@ai.mit.edu>}
+@item umax43
+Umax 4.3 BSD. Contributed by Sjoerd Mullender @t{<sjoerd@@cwi.nl>}
+@item utek
+Utek 4.0. Contributed by Bill Trost @t{<trost%reed@@cse.ogi.edu>}
+@item xinu43
+mt Xinu MORE/bsd. Contributed by Jan-Simon Pendry @t{<jsp@@doc.ic.ac.uk>}
+@end table
+
+@node Supported Machine Architectures, , Supported Operating Systems, Supported Platforms
+@comment node-name, next, previous, up
+@section Supported Machine Architectures
+@cindex Supported machine architectures
+@cindex Machine architecture names
+@cindex Machine architectures supported by Amd
+
+@table @code
+@item alliant
+Alliant FX/4
+@item arm
+Acorn ARM
+@item aviion
+Data General AViiON
+@item encore
+Encore
+@item fps500
+FPS Model 500
+@item hp9000
+HP 9000/300 family
+@item hp9k8
+HP 9000/800 family
+@item ibm032
+IBM RT
+@item ibm6000
+IBM RISC System/6000
+@item iris4d
+SGI Iris 4D
+@item macII
+Apple Mac II
+@item mips
+MIPS RISC
+@item multimax
+Encore Multimax
+@item orion105
+HLH Orion 1/05
+@item sun3
+Sun-3 family
+@item sun4
+Sun-4 family
+@item tahoe
+Tahoe family
+@item vax
+DEC Vax
+@end table
+
+@node Mount Maps, Amd Command Line Options, Supported Platforms, Top
+@comment node-name, next, previous, up
+@chapter Mount Maps
+@cindex Mount maps
+@cindex Automounter configuration maps
+@cindex Mount information
+
+@i{Amd} has no built-in knowledge of machines or filesystems.
+External @dfn{mount-maps} are used to provide the required information.
+Specifically, @i{Amd} needs to know when and under what conditions it
+should mount filesystems.
+
+The map entry corresponding to the requested name contains a list of
+possible locations from which to resolve the request. Each location
+specifies filesystem type, information required by that filesystem (for
+example the block special device in the case of UFS), and some
+information describing where to mount the filesystem (@pxref{fs Option}). A
+location may also contain @dfn{selectors} (@pxref{Selectors}).@refill
+
+@menu
+* Map Types::
+* Key Lookup::
+* Location Format::
+@end menu
+
+@node Map Types, Key Lookup, Mount Maps, Mount Maps
+@comment node-name, next, previous, up
+@section Map Types
+@cindex Mount map types
+@cindex Map types
+@cindex Configuration map types
+@cindex Types of mount map
+@cindex Types of configuration map
+@cindex Determining the map type
+
+A mount-map provides the run-time configuration information to @i{Amd}.
+Maps can be implemented in many ways. Some of the forms supported by
+@i{Amd} are regular files, ndbm databases, NIS maps the @dfn{Hesiod}
+name server and even the password file.
+
+A mount-map @dfn{name} is a sequence of characters. When an automount
+point is created a handle on the mount-map is obtained. For each map
+type configured @i{Amd} attempts to reference the a map of the
+appropriate type. If a map is found, @i{Amd} notes the type for future
+use and deletes the reference, for example closing any open file
+descriptors. The available maps are configure when @i{Amd} is built and
+can be displayed by running the command @samp{amd -v}.
+
+By default, @i{Amd} caches data in a mode dependent on the type of map.
+This is the same as specifying @samp{cache:=mapdefault} and selects a
+suitable default cache mode depending on the map type. The individual
+defaults are described below. The @var{cache} option can be specified
+on automount points to alter the caching behaviour (@pxref{Automount
+Filesystem}).@refill
+
+The following map types have been implemented, though some are not
+available on all machines. Run the command @samp{amd -v} to obtain a
+list of map types configured on your machine.
+
+@menu
+* File maps::
+* ndbm maps::
+* NIS maps::
+* Hesiod maps::
+* Password maps::
+* Union maps::
+@end menu
+
+@node File maps, ndbm maps, Map Types, Map Types
+@comment node-name, next, previous, up
+@subsection File maps
+@cindex File maps
+@cindex Flat file maps
+@cindex File map syntactic conventions
+
+When @i{Amd} searches a file for a map entry it does a simple scan of
+the file and supports both comments and continuation lines.
+
+Continuation lines are indicated by a backslash character (@samp{\}) as
+the last character of a line in the file. The backslash, newline character
+@emph{and any leading white space on the following line} are discarded. A maximum
+line length of 2047 characters is enforced after continuation lines are read
+but before comments are stripped. Each line must end with
+a newline character; that is newlines are terminators, not separators.
+The following examples illustrate this:
+
+@example
+key valA valB; \
+ valC
+@end example
+
+specifies @emph{three} locations, and is identical to
+
+@example
+key valA valB; valC
+@end example
+
+However,
+
+@example
+key valA valB;\
+ valC
+@end example
+
+specifies only @emph{two} locations, and is identical to
+
+@example
+key valA valB;valC
+@end example
+
+After a complete line has been read from the file, including
+continuations, @i{Amd} determines whether there is a comment on the
+line. A comment begins with a hash (``@samp{#}'') character and
+continues to the end of the line. There is no way to escape or change
+the comment lead-in character.
+
+Note that continuation lines and comment support @dfn{only} apply to
+file maps, or ndbm maps built with the @code{mk-amd-map} program.
+
+When caching is enabled, file maps have a default cache mode of
+@code{all} (@pxref{Automount Filesystem}).
+
+@node ndbm maps, NIS maps, File maps, Map Types
+@comment node-name, next, previous, up
+@subsection ndbm maps
+@cindex ndbm maps
+
+An ndbm map may be used as a fast access form of a file map. The program,
+@code{mk-amd-map}, converts a normal map file into an ndbm database.
+This program supports the same continuation and comment conventions that
+are provided for file maps. Note that ndbm format files may @emph{not}
+be sharable across machine architectures. The notion of speed generally
+only applies to large maps; a small map, less than a single disk block,
+is almost certainly better implemented as a file map.
+
+ndbm maps do not support cache mode @samp{all} and, when caching is
+enabled, have a default cache mode of @samp{inc} (@pxref{Automount Filesystem}).
+
+@node NIS maps, Hesiod maps, ndbm maps, Map Types
+@comment node-name, next, previous, up
+@subsection NIS maps
+@cindex NIS (YP) maps
+
+When using NIS (formerly YP), an @i{Amd} map is implemented directly
+by the underlying NIS map. Comments and continuation lines are
+@emph{not} supported in the automounter and must be stripped when
+constructing the NIS server's database.
+
+NIS maps do not support cache mode @code{all} and, when caching is
+enabled, have a default cache mode of @code{inc} (@pxref{Automount Filesystem}).
+
+The following rule illustrates what could be added to your NIS @file{Makefile},
+in this case causing the @file{amd.home} map to be rebuilt:
+@example
+$(YPTSDIR)/amd.home.time: $(ETCDIR)/amd.home
+ -@@sed -e "s/#.*$$//" -e "/^$$/d" $(ETCDIR)/amd.home | \
+ awk '@{ \
+ for (i = 1; i <= NF; i++) \
+ if (i == NF) @{ \
+ if (substr($$i, length($$i), 1) == "\\") \
+ printf("%s", substr($$i, 1, length($$i) - 1)); \
+ else \
+ printf("%s\n", $$i); \
+ @} \
+ else \
+ printf("%s ", $$i); \
+ @}' | \
+ $(MAKEDBM) - $(YPDBDIR)/amd.home; \
+ touch $(YPTSDIR)/amd.home.time; \
+ echo "updated amd.home"; \
+ if [ ! $(NOPUSH) ]; then \
+ $(YPPUSH) amd.home; \
+ echo "pushed amd.home"; \
+ else \
+ : ; \
+ fi
+@end example
+
+Here @code{$(YPTSDIR)} contains the time stamp files, and @code{$(YPDBDIR)} contains
+the dbm format NIS files.
+
+@node Hesiod maps, Password maps, NIS maps, Map Types
+@comment node-name, next, previous, up
+@subsection Hesiod maps
+@cindex Hesiod maps
+
+When the map name begins with the string @samp{hesiod.} lookups are made
+using the @dfn{Hesiod} name server. The string following the dot is
+used as a name qualifier and is prepended with the key being located.
+The entire string is then resolved in the @code{automount} context. For
+example, if the the key is @samp{jsp} and map name is
+@samp{hesiod.homes} then @dfn{Hesiod} is asked to resolve
+@samp{jsp.homes.automount}.
+
+Hesiod maps do not support cache mode @samp{all} and, when caching is
+enabled, have a default cache mode of @samp{inc} (@pxref{Automount Filesystem}).
+
+The following is an example of a @dfn{Hesiod} map entry:
+
+@example
+jsp.homes.automount HS TXT "rfs:=/home/charm;rhost:=charm;sublink:=jsp"
+njw.homes.automount HS TXT "rfs:=/home/dylan/dk2;rhost:=dylan;sublink:=njw"
+@end example
+
+@node Password maps, Union maps, Hesiod maps, Map Types
+@comment node-name, next, previous, up
+@subsection Password maps
+@cindex Password file maps
+@cindex /etc/passwd maps
+@cindex User maps, automatic generation
+@cindex Automatic generation of user maps
+@cindex Using the password file as a map
+
+The password map support is unlike the four previous map types. When
+the map name is the string @file{/etc/passwd} @i{Amd} can lookup a user
+name in the password file and re-arrange the home directory field to
+produce a usable map entry.
+
+@i{Amd} assumes the home directory has the format
+`@t{/}@i{anydir}@t{/}@i{dom1}@t{/../}@i{domN}@t{/}@i{login}'.
+@c @footnote{This interpretation is not necessarily exactly what you want.}
+It breaks this string into a map entry where @code{$@{rfs@}} has the
+value `@t{/}@i{anydir}@t{/}@i{domN}', @code{$@{rhost@}} has the value
+`@i{domN}@t{.}@i{...}@t{.}@i{dom1}', and @code{$@{sublink@}} has the
+value @samp{login}.@refill
+
+Thus if the password file entry was
+
+@example
+/home/achilles/jsp
+@end example
+
+the map entry used by @i{Amd} would be
+
+@example
+rfs:=/home/achilles;rhost:=achilles;sublink:=jsp
+@end example
+
+Similarly, if the password file entry was
+
+@example
+/home/cc/sugar/mjh
+@end example
+
+the map entry used by @i{Amd} would be
+
+@example
+rfs:=/home/sugar;rhost:=sugar.cc;sublink:=jsp
+@end example
+
+@node Union maps, , Password maps, Map Types
+@comment node-name, next, previous, up
+@subsection Union maps
+@cindex Union file maps
+
+The union map support is provided specifically for use with the union
+filesystem, @pxref{Union Filesystem}.
+
+It is identified by the string @samp{union:} which is followed by a
+colon separated list of directories. The directories are read in order,
+and the names of all entries are recorded in the map cache. Later
+directories take precedence over earlier ones. The union filesystem
+type then uses the map cache to determine the union of the names in all
+the directories.
+
+@c subsection Gdbm
+
+@node Key Lookup, Location Format, Map Types, Mount Maps
+@comment node-name, next, previous, up
+@section How keys are looked up
+@cindex Key lookup
+@cindex Map lookup
+@cindex Looking up keys
+@cindex How keys are looked up
+@cindex Wildcards in maps
+
+The key is located in the map whose type was determined when the
+automount point was first created. In general the key is a pathname
+component. In some circumstances this may be modified by variable
+expansion (@pxref{Variable Expansion}) and prefixing. If the automount
+point has a prefix, specified by the @var{pref} option, then that is
+prepended to the search key before the map is searched.
+
+If the map cache is a @samp{regexp} cache then the key is treated as an
+egrep-style regular expression, otherwise a normal string comparison is
+made.
+
+If the key cannot be found then a @dfn{wildcard} match is attempted.
+@i{Amd} repeatedly strips the basename from the key, appends @samp{/*} and
+attempts a lookup. Finally, @i{Amd} attempts to locate the special key @samp{*}.
+
+@group
+For example, the following sequence would be checked if @file{home/dylan/dk2} was
+being located:
+
+@example
+ home/dylan/dk2
+ home/dylan/*
+ home/*
+ *
+@end example
+@end group
+
+At any point when a wildcard is found, @i{Amd} proceeds as if an exact
+match had been found and the value field is then used to resolve the
+mount request, otherwise an error code is propagated back to the kernel.
+(@pxref{Filesystem Types}).@refill
+
+@node Location Format, , Key Lookup, Mount Maps
+@comment node-name, next, previous, up
+@section Location Format
+@cindex Location format
+@cindex Map entry format
+@cindex How locations are parsed
+
+The value field from the lookup provides the information required to
+mount a filesystem. The information is parsed according to the syntax
+shown below.
+
+@display
+@i{location-list}:
+ @i{location-selection}
+ @i{location-list} @i{white-space} @t{||} @i{white-space} @i{location-selection}
+@i{location-selection}:
+ @i{location}
+ @i{location-selection} @i{white-space} @i{location}
+@i{location}:
+ @i{location-info}
+ @t{-}@i{location-info}
+ @t{-}
+@i{location-info}:
+ @i{sel-or-opt}
+ @i{location-info}@t{;}@i{sel-or-opt}
+ @t{;}
+@i{sel-or-opt}:
+ @i{selection}
+ @i{opt-ass}
+@i{selection}:
+ selector@t{==}@i{value}
+ selector@t{!=}@i{value}
+@i{opt-ass}:
+ option@t{:=}@i{value}
+@i{white-space}:
+ space
+ tab
+@end display
+
+Note that unquoted whitespace is not allowed in a location description.
+White space is only allowed, and is mandatory, where shown with non-terminal
+@samp{white-space}.
+
+A @dfn{location-selection} is a list of possible volumes with which to
+satisfy the request. @dfn{location-selection}s are separated by the
+@samp{||} operator. The effect of this operator is to prevent use of
+location-selections to its right if any of the location-selections on
+its left were selected whether or not any of them were successfully
+mounted (@pxref{Selectors}).@refill
+
+The location-selection, and singleton @dfn{location-list},
+@samp{type:=ufs;dev:=/dev/xd1g} would inform @i{Amd} to mount a UFS
+filesystem from the block special device @file{/dev/xd1g}.
+
+The @dfn{sel-or-opt} component is either the name of an option required
+by a specific filesystem, or it is the name of a built-in, predefined
+selector such as the architecture type. The value may be quoted with
+double quotes @samp{"}, for example
+@samp{type:="ufs";dev:="/dev/xd1g"}. These quotes are stripped when the
+value is parsed and there is no way to get a double quote into a value
+field. Double quotes are used to get white space into a value field,
+which is needed for the program filesystem (@pxref{Program Filesystem}).@refill
+
+@menu
+* Map Defaults::
+* Variable Expansion::
+* Selectors::
+* Map Options::
+@end menu
+
+@node Map Defaults, Variable Expansion, Location Format, Location Format
+@comment node-name, next, previous, up
+@subsection Map Defaults
+@cindex Map defaults
+@cindex How to set default map parameters
+@cindex Setting default map parameters
+
+A location beginning with a dash @samp{-} is used to specify default
+values for subsequent locations. Any previously specified defaults in
+the location-list are discarded. The default string can be empty in
+which case no defaults apply.
+
+The location @samp{-fs:=/mnt;opts:=ro} would set the local mount point
+to @file{/mnt} and cause mounts to be read-only by default. Defaults
+specified this way are appended to, and so override, any global map
+defaults given with @samp{/defaults}).
+@c
+@c A @samp{/defaults} value @dfn{gdef} and a location list
+@c \begin{quote}
+@c $@samp{-}@dfn{def}_a $\verb*+ +$ @dfn{loc}_{a_1} $\verb*+ +$ @dfn{loc}_{a_2} $\verb*+ +$ @samp{-}@dfn{def}_b $\verb*+ +$ @dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+@c is equivalent to
+@c \begin{quote}
+@c $@samp{-}@dfn{gdef}@samp{;}@dfn{def}_a $\verb*+ +$ @dfn{loc}_{a_1} $\verb*+ +$ @dfn{loc}_{a_2} $\verb*+ +$ @samp{-}@dfn{gdef}@samp{;}@dfn{def}_b $\verb*+ +$ @dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+@c which is equivalent to
+@c \begin{quote}
+@c $@dfn{gdef}@samp{;}@dfn{def}_a@samp{;}@dfn{loc}_{a_1} $\verb*+ +$@dfn{gdef}@samp{;}@dfn{def}_a@samp{;}@dfn{loc}_{a_2} $\verb*+ +$@dfn{gdef}@samp{;}@dfn{def}_b@samp{;}@dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+
+@node Variable Expansion, Selectors, Map Defaults, Location Format
+@comment node-name, next, previous, up
+@subsection Variable Expansion
+@cindex Variable expansion
+@cindex How variables are expanded
+@cindex Pathname operators
+@cindex Domain stripping
+@cindex Domainname operators
+@cindex Stripping the local domain name
+@cindex Environment variables
+@cindex How to access environment variables in maps
+
+To allow generic location specifications @i{Amd} does variable expansion
+on each location and also on some of the option strings. Any option or
+selector appearing in the form @code{$@dfn{var}} is replaced by the
+current value of that option or selector. For example, if the value of
+@code{$@{key@}} was @samp{bin}, @code{$@{autodir@}} was @samp{/a} and
+@code{$@{fs@}} was `@t{$@{autodir@}}@t{/local/}@t{$@{key@}}' then
+after expansion @code{$@{fs@}} would have the value @samp{/a/local/bin}.
+Any environment variable can be accessed in a similar way.@refill
+
+Two pathname operators are available when expanding a variable. If the
+variable name begins with @samp{/} then only the last component of
+then pathname is substituted. For example, if @code{$@{path@}} was
+@samp{/foo/bar} then @code{$@{/path@}} would be expanded to @samp{bar}.
+Similarly, if the variable name ends with @samp{/} then all but the
+last component of the pathname is substituted. In the previous example,
+@code{$@{path/@}} would be expanded to @samp{/foo}.@refill
+
+Two domain name operators are also provided. If the variable name
+begins with @samp{.} then only the domain part of the name is
+substituted. For example, if @code{$@{rhost@}} was
+@samp{swan.doc.ic.ac.uk} then @code{$@{.rhost@}} would be expanded to
+@samp{doc.ic.ac.uk}. Similarly, if the variable name ends with @samp{.}
+then only the host component is substituted. In the previous example,
+@code{$@{rhost.@}} would be expanded to @samp{swan}.@refill
+
+Variable expansion is a two phase process. Before a location is parsed,
+all references to selectors, @i{eg} @code{$@{path@}}, are expanded. The
+location is then parsed, selections are evaluated and option assignments
+recorded. If there were no selections or they all succeeded the
+location is used and the values of the following options are expanded in
+the order given: @var{sublink}, @var{rfs}, @var{fs}, @var{opts},
+@var{remopts}, @var{mount} and @var{unmount}.
+
+Note that expansion of option values is done after @dfn{all} assignments
+have been completed and not in a purely left to right order as is done
+by the shell. This generally has the desired effect but care must be
+taken if one of the options references another, in which case the
+ordering can become significant.
+
+There are two special cases concerning variable expansion:
+
+@enumerate
+@item
+before a map is consulted, any selectors in the name received
+from the kernel are expanded. For example, if the request from the
+kernel was for `@t{$@{arch@}}@t{.bin}' and the machine architecture
+was @samp{vax}, the value given to @code{$@{key@}} would be
+@samp{vax.bin}.@refill
+
+@item
+the value of @code{$@{rhost@}} is expanded and normalized before the
+other options are expanded. The normalization process strips any local
+sub-domain components. For example, if @code{$@{domain@}} was
+@samp{Berkeley.EDU} and @code{$@{rhost@}} was initially
+@samp{snow.Berkeley.EDU}, after the normalization it would simply be
+@samp{snow}. Hostname normalization is currently done in a
+@emph{case-dependent} manner.@refill
+@end enumerate
+
+@node Selectors, Map Options, Variable Expansion, Location Format
+@comment node-name, next, previous, up
+@subsection Selectors
+@cindex Selectors
+
+Selectors are used to control the use of a location. It is possible to
+share a mount map between many machines in such a way that filesystem
+location, architecture and operating system differences are hidden from
+the users. A selector of the form @samp{arch==sun3;os==sos4} would only
+apply on Sun-3s running SunOS 4.x.
+
+Selectors are evaluated left to right. If a selector fails then that
+location is ignored. Thus the selectors form a conjunction and the
+locations form a disjunction. If all the locations are ignored or
+otherwise fail then @i{Amd} uses the @dfn{error} filesystem
+(@pxref{Error Filesystem}). This is equivalent to having a location
+@samp{type:=error} at the end of each mount-map entry.@refill
+
+The selectors currently implemented are:
+
+@table @samp
+@cindex arch, mount selector
+@cindex Mount selector; arch
+@cindex Selector; arch
+@item arch
+the machine architecture which was automatically determined at compile
+time. The architecture type can be displayed by running the command
+@samp{amd -v}. @xref{Supported Machine Architectures}.@refill
+
+@item autodir
+@cindex autodir, mount selector
+@cindex Mount selector; autodir
+@cindex Selector; autodir
+the default directory under which to mount filesystems. This may be
+changed by the ``-a'' command line option. See the @var{fs} option.
+
+@item byte
+@cindex byte, mount selector
+@cindex Mount selector; byte
+@cindex Selector; byte
+the machine's byte ordering. This is either @samp{little}, indicating
+little-endian, or @samp{big}, indicating big-endian. One possible use
+is to share @samp{rwho} databases (@pxref{rwho servers}). Another is to
+share ndbm databases, however this use can be considered a courageous
+juggling act.
+
+@item cluster
+@cindex cluster, mount selector
+@cindex Mount selector; cluster
+@cindex Selector; cluster
+is provided as a hook for the name of the local cluster. This can be
+used to decide which servers to use for copies of replicated
+filesystems. @code{$@{cluster@}} defaults to the value of
+@code{$@{domain@}} unless a different value is set with the ``-C''
+command line option.
+
+@item domain
+@cindex domain, mount selector
+@cindex Mount selector; domain
+@cindex Selector; domain
+the local domain name as specified by the ``-d'' command line option.
+See @samp{host}.
+
+@item host
+@cindex host, mount selector
+@cindex Mount selector; host
+@cindex Selector; host
+the local hostname as determined by @b{gethostname}(2). If no domain
+name was specified on the command line and the hostname contains a
+period @samp{.} then the string before the period is used as the
+host name, and the string after the period is assigned to
+@code{$@{domain@}}. For example, if the hostname is
+@samp{styx.doc.ic.ac.uk} then @code{host} would be @samp{styx} and
+@code{domain} would be @samp{doc.ic.ac.uk}. @code{hostd} would be
+@samp{styx.doc.ic.ac.uk}.@refill
+
+@item hostd
+@cindex hostd, mount selector
+@cindex Mount selector; hostd
+@cindex Selector; hostd
+is @code{$@{host@}} and @code{$@{domain@}} concatenated with a
+@samp{.} inserted between them if required. If @code{$@{domain@}}
+is an empty string then @code{$@{host@}} and @code{$@{hostd@}} will be
+identical.
+
+@item karch
+@cindex karch, mount selector
+@cindex Mount selector; karch
+@cindex Selector; karch
+is provided as a hook for the kernel architecture. This is used on
+SunOS 4, for example, to distinguish between different @samp{/usr/kvm}
+volumes. @code{$@{karch@}} defaults to the value of @code{$@{arch@}}
+unless a different value is set with the ``-k'' command line option.
+
+@item os
+@cindex os, mount selector
+@cindex Mount selector; os
+@cindex Selector; os
+the operating system. Like the machine architecture, this is
+automatically determined at compile time. The operating system name can
+be displayed by running the command @samp{amd -v}. @xref{Supported
+Operating Systems}.@refill
+
+@end table
+
+The following selectors are also provided. Unlike the other selectors,
+they vary for each lookup. Note that when the name from the kernel is
+expanded prior to a map lookup, these selectors are all defined as empty
+strings.
+
+@table @samp
+@item key
+@cindex key, mount selector
+@cindex Mount selector; key
+@cindex Selector; key
+the name being resolved. For example, if @file{/home} is an automount
+point, then accessing @file{/home/foo} would set @code{$@{key@}} to the
+string @samp{foo}. The key is prefixed by the @var{pref} option set in
+the parent mount point. The default prefix is an empty string. If the
+prefix was @file{blah/} then @code{$@{key@}} would be set to
+@file{blah/foo}.@refill
+
+@item map
+@cindex map, mount selector
+@cindex Mount selector; map
+@cindex Selector; map
+the name of the mount map being used.
+
+@item path
+@cindex path, mount selector
+@cindex Mount selector; path
+@cindex Selector; path
+the full pathname of the name being resolved. For example
+@file{/home/foo} in the example above.
+
+@item wire
+@cindex wire, mount selector
+@cindex Mount selector; wire
+@cindex Selector; wire
+the name of the network to which the primary network interface is
+attached. If a symbolic name cannot be found in the networks or hosts
+database then dotted IP address format is used. This value is also
+output by the ``-v'' option.
+
+@end table
+
+Selectors can be negated by using @samp{!=} instead of @samp{==}. For
+example to select a location on all non-Vax machines the selector
+@samp{arch!=vax} would be used.
+
+@node Map Options, , Selectors, Location Format
+@comment node-name, next, previous, up
+@subsection Map Options
+@cindex Map options
+@cindex Setting map options
+
+Options are parsed concurrently with selectors. The difference is that
+when an option is seen the string following the @samp{:=} is
+recorded for later use. As a minimum the @var{type} option must be
+specified. Each filesystem type has other options which must also be
+specified. @xref{Filesystem Types}, for details on the filesystem
+specific options.@refill
+
+Superfluous option specifications are ignored and are not reported
+as errors.
+
+The following options apply to more than one filesystem type.
+
+@menu
+* delay Option::
+* fs Option::
+* opts Option::
+* remopts Option::
+* sublink Option::
+* type Option::
+@end menu
+
+@node delay Option, fs Option, Map Options, Map Options
+@comment node-name, next, previous, up
+@subsubsection delay Option
+@cindex Setting a delay on a mount location
+@cindex Delaying mounts from specific locations
+@cindex Primary server
+@cindex Secondary server
+@cindex delay, mount option
+@cindex Mount option; delay
+
+The delay, in seconds, before an attempt will be made to mount from the current location.
+Auxilliary data, such as network address, file handles and so on are computed
+regardless of this value.
+
+A delay can be used to implement the notion of primary and secondary file servers.
+The secondary servers would have a delay of a few seconds,
+thus giving the primary servers a chance to respond first.
+
+@node fs Option, opts Option, delay Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection fs Option
+@cindex Setting the local mount point
+@cindex Overriding the default mount point
+@cindex fs, mount option
+@cindex Mount option; fs
+
+The local mount point. The semantics of this option vary between
+filesystems.
+
+For NFS and UFS filesystems the value of @code{$@{fs@}} is used as the
+local mount point. For other filesystem types it has other meanings
+which are described in the section describing the respective filesystem
+type. It is important that this string uniquely identifies the
+filesystem being mounted. To satisfy this requirement, it should
+contain the name of the host on which the filesystem is resident and the
+pathname of the filesystem on the local or remote host.
+
+The reason for requiring the hostname is clear if replicated filesystems
+are considered. If a fileserver goes down and a replacement filesystem
+is mounted then the @dfn{local} mount point @dfn{must} be different from
+that of the filesystem which is hung. Some encoding of the filesystem
+name is required if more than one filesystem is to be mounted from any
+given host.
+
+If the hostname is first in the path then all mounts from a particular
+host will be gathered below a single directory. If that server goes
+down then the hung mount points are less likely to be accidentally
+referenced, for example when @b{getwd}(3) traverses the namespace to
+find the pathname of the current directory.
+
+The @samp{fs} option defaults to
+@code{$@{autodir@}/$@{rhost@}$@{rfs@}}. In addition,
+@samp{rhost} defaults to the local host name (@code{$@{host@}}) and
+@samp{rfs} defaults to the value of @code{$@{path@}}, which is the full
+path of the requested file; @samp{/home/foo} in the example above
+(@pxref{Selectors}). @code{$@{autodir@}} defaults to @samp{/a} but may
+be changed with the ``-a'' command line option. Sun's automounter
+defaults to @samp{/tmp_mnt}. Note that there is no @samp{/} between
+the @code{$@{rhost@}} and @code{$@{rfs@}} since @code{$@{rfs@}} begins
+with a @samp{/}.@refill
+
+@node opts Option, remopts Option, fs Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection opts Option
+@cindex Setting system mount options
+@cindex Passing parameters to the mount system call
+@cindex mount system call
+@cindex mount system call flags
+@cindex The mount system call
+@cindex opts, mount option
+@cindex Mount option; opts
+
+The options to pass to the mount system call. A leading @samp{-} is
+silently ignored. The mount options supported generally correspond to
+those used by @b{mount}(8) and are listed below. Some additional
+pseudo-options are interpreted by @i{Amd} and are also listed.
+
+Unless specifically overridden, each of the system default mount options
+applies. Any options not recognised are ignored. If no options list is
+supplied the string @samp{rw,defaults} is used and all the system
+default mount options apply. Options which are not applicable for a
+particular operating system are silently ignored. For example, only 4.4
+BSD is known to implement the @code{compress} and @code{spongy} options.
+
+@table @code
+@item compress
+Use NFS compression protocol.
+@item grpid
+Use BSD directory group-id semantics.
+@item intr
+Allow keyboard interrupts on hard mounts.
+@item noconn
+Don't make a connection on datagram transports.
+@item nocto
+No close-to-open consistency.
+@item nodevs
+Don't allow local special devices on this filesystem.
+@item nosuid
+Don't allow set-uid or set-gid executables on this filesystem.
+@item quota
+Enable quota checking on this mount.
+@item retrans=@i{n}
+The number of NFS retransmits made before a user error is generated by a
+@samp{soft} mounted filesystem, and before a @samp{hard} mounted
+filesystem reports @samp{NFS server @dfn{yoyo} not responding still
+trying}.
+@item ro
+Mount this filesystem readonly.
+@item rsize=@var{n}
+The NFS read packet size. You may need to set this if you are using
+NFS/UDP through a gateway.
+@item soft
+Give up after @dfn{retrans} retransmissions.
+@item spongy
+Like @samp{soft} for status requests, and @samp{hard} for data transfers.
+@item tcp
+Use TCP/IP instead of UDP/IP, ignored if the NFS implementation does not
+support TCP/IP mounts.
+@item timeo=@var{n}
+The NFS timeout, in tenth-seconds, before a request is retransmitted.
+@item wsize=@var{n}
+The NFS write packet size. You may need to set this if you are using
+NFS/UDP through a gateway.
+@end table
+
+The following options are implemented by @i{Amd}, rather than being
+passed to the kernel.
+
+@table @code
+@item nounmount
+Configures the mount so that its time-to-live will
+never expire. This is also the default for some filesystem types.
+@c
+@c Implementation broken:
+@item ping=@var{n}
+The interval, in seconds, between keep-alive pings. When four
+consecutive pings have failed the mount point is marked as hung. This
+interval defaults to 30 seconds. If the ping interval is less than zero,
+no pings are sent and the host is assumed to be always
+up. By default, pings are not sent for an NFS/TCP mount.
+@item retry=@var{n}
+The number of times to retry the mount system call.
+@item utimeout=@var{n}
+The interval, in seconds, by which the mount's
+time-to-live is extended after an unmount attempt
+has failed. In fact the interval is extended before the unmount is
+attempted to avoid thrashing. The default value is 120 seconds (two
+minutes) or as set by the ``-w'' command line option.
+@end table
+
+@node remopts Option, sublink Option, opts Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection remopts Option
+@cindex Setting system mount options for non-local networks
+@cindex remopts, mount option
+@cindex Mount option; remopts
+
+This option has the same use as @code{$@{opts@}} but applies only when
+the remote host is on a non-local network. For example, when using NFS
+across a gateway it is often necessary to use smaller values for the
+data read and write sizes. This can simply be done by specifying the
+small values in @var{remopts}. When a non-local host is accessed, the
+smaller sizes will automatically be used.
+
+@i{Amd} determines whether a host is local by examining the network
+interface configuration at startup. Any interface changes made after
+@i{Amd} has been started will not be noticed. The likely effect will
+be that a host may incorrectly be declared non-local.
+
+Unless otherwise set, the value of @code{$@{rem@}} is the same as the
+value of @code{$@{opts@}}.
+
+@node sublink Option, type Option, remopts Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection sublink Option
+@cindex Setting the sublink option
+@cindex sublink, mount option
+@cindex Mount option; sublink
+
+The subdirectory within the mounted filesystem to which the reference
+should point. This can be used to prevent duplicate mounts in cases
+where multiple directories in the same mounted filesystem are used.
+
+@node type Option, , sublink Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection type Option
+@cindex Setting the filesystem type option
+@cindex type, mount option
+@cindex Mount option; type
+
+The filesystem type to be used. @xref{Filesystem Types}, for a full
+description of each type.@refill
+
+@node Amd Command Line Options, Filesystem Types, Mount Maps, Top
+@comment node-name, next, previous, up
+@chapter @i{Amd} Command Line Options
+@cindex Command line options, Amd
+@cindex Amd command line options
+@cindex Overriding defaults on the command line
+
+Many of @i{Amd}'s parameters can be set from the command line. The
+command line is also used to specify automount points and maps.
+
+The general format of a command line is
+
+@example
+amd [@i{options}] @{ @i{directory} @i{map-name} [-@i{map-options}] @} ...
+@end example
+
+For each directory and map-name given, @i{Amd} establishes an
+automount point. The @dfn{map-options} may be any sequence of options
+or selectors---@pxref{Location Format}. The @dfn{map-options}
+apply only to @i{Amd}'s mount point.
+
+@samp{type:=toplvl;cache:=mapdefault;fs:=$@{map@}} is the default value for the
+map options. Default options for a map are read from a special entry in
+the map whose key is the string @samp{/defaults}. When default options
+are given they are prepended to any options specified in the mount-map
+locations as explained in. @xref{Map Defaults}, for more details.
+
+The @dfn{options} are any combination of those listed below.
+
+Once the command line has been parsed, the automount points are mounted.
+The mount points are created if they do not already exist, in which case they
+will be removed when @i{Amd} exits.
+Finally, @i{Amd} disassociates itself from its controlling terminal and
+forks into the background.
+
+Note: Even if @i{Amd} has been built with @samp{-DDEBUG} it will still
+background itself and disassociate itself from the controlling terminal.
+To use a debugger it is necessary to specify @samp{-D nodaemon} on the
+command line.
+
+@menu
+* -a Option:: Automount directory.
+* -c Option:: Cache timeout interval.
+* -d Option:: Domain name.
+* -k Option:: Kernel architecture.
+* -l Option:: Log file.
+* -n Option:: Hostname normalisation.
+* -p Option:: Output process id.
+* -r Option:: Restart existing mounts.
+* -t Option:: Kernel RPC timeout.
+* -v Option:: Version information.
+* -w Option:: Wait interval after failed unmount.
+* -x Option:: Log options.
+* -y Option:: NIS domain.
+* -C-Option:: Cluster name.
+* -D-Option:: Debug flags.
+@end menu
+
+@node -a Option, -c Option, Amd Command Line Options, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-a} @var{directory}
+@cindex Automount directory
+@cindex Setting the default mount directory
+
+Specifies the default mount directory. This option changes the variable
+@code{$@{autodir@}} which otherwise defaults to @file{/a}. For example,
+some sites prefer @file{/amd}.
+
+@example
+amd -a /amd ...
+@end example
+
+@node -c Option, -d Option, -a Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-c} @var{cache-interval}
+@cindex Cache interval
+@cindex Interval before a filesystem times out
+@cindex Setting the interval before a filesystem times out
+@cindex Changing the interval before a filesystem times out
+
+Selects the period, in seconds, for which a name is cached by @i{Amd}.
+If no reference is made to the volume in this period, @i{Amd} discards
+the volume name to filesystem mapping.
+
+Once the last reference to a filesystem has been removed, @i{Amd}
+attempts to unmount the filesystem. If the unmount fails the interval
+is extended by a further period as specified by the @samp{-w} command
+line option or by the @samp{utimeout} mount option.
+
+The default @dfn{cache-interval} is 300 seconds (five minutes).
+
+@node -d Option, -k Option, -c Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-d} @var{domain}
+@cindex Domain name
+@cindex Setting the local domain name
+@cindex Overriding the local domain name
+
+Specifies the host's domain. This sets the internal variable
+@code{$@{domain@}} and affects the @code{$@{hostd@}} variable.
+
+If this option is not specified and the hostname already contains the
+local domain then that is used, otherwise the default value of
+@code{$@{domain@}} is @samp{unknown.domain}.
+
+For example, if the local domain was @samp{doc.ic.ac.uk}, @i{Amd} could
+be started as follows:
+
+@example
+amd -d doc.ic.ac.uk ...
+@end example
+
+@node -k Option, -l Option, -d Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-k} @var{kernel-architecture}
+@cindex Setting the Kernel architecture
+
+Specifies the kernel architecture of the system. This is usually the
+output of @samp{arch -k} and its only effect is to set the variable
+@code{$@{karch@}}. If this option is not given, @code{$@{karch@}} has
+the same value as @code{$@{arch@}}.
+
+This would be used as follows:
+
+@example
+amd -k `arch -k` ...
+@end example
+
+@node -l Option, -n Option, -k Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-l} @var{log-option}
+@cindex Log filename
+@cindex Setting the log file
+@cindex Using syslog to log errors
+@cindex syslog
+
+Selects the form of logging to be made. Two special @dfn{log-options}
+are recognised.
+
+@enumerate
+@item
+If @dfn{log-option} is the string @samp{syslog}, @i{Amd} will use the
+@b{syslog}(3) mechanism.@refill
+
+@item
+If @dfn{log-option} is the string @samp{/dev/stderr}, @i{Amd} will use
+standard error, which is also the default target for log messages. To
+implement this, @i{Amd} simulates the effect of the @samp{/dev/fd}
+driver.
+@end enumerate
+
+Any other string is taken as a filename to use for logging. Log
+messages are appended to the file if it already exists, otherwise a new
+file is created. The file is opened once and then held open, rather
+than being re-opened for each message.
+
+If the @samp{syslog} option is specified but the system does not support
+syslog or if the named file cannot be opened or created, @i{Amd} will
+use standard error. Error messages generated before @i{Amd} has
+finished parsing the command line are printed on standard error.
+
+Using @samp{syslog} is usually best, in which case @i{Amd} would be
+started as follows:
+
+@example
+amd -l syslog ...
+@end example
+
+@node -n Option, -p Option, -l Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-n}
+@cindex Hostname normalisation
+@cindex Aliased hostnames
+@cindex Resolving aliased hostnames
+@cindex Normalising hostnames
+
+Normalises the remote hostname before using it. Normalisation is done
+by replacing the value of @code{$@{rhost@}} with the primary name
+returned by a hostname lookup.
+
+This option should be used if several names are used to refer to a
+single host in a mount map.
+
+@node -p Option, -r Option, -n Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-p}
+@cindex Process id
+@cindex Displaying the process id
+@cindex process id of Amd daemon
+@cindex pid file, creating with -p option
+@cindex Creating a pid file
+
+Causes @i{Amd}'s process id to be printed on standard output.
+This can be redirected to a suitable file for use with kill:
+
+@example
+amd -p > /var/run/amd.pid ...
+@end example
+
+This option only has an affect if @i{Amd} is running in daemon mode.
+If @i{Amd} is started with the @code{-D nodaemon} debug flag, this
+option is ignored.
+
+@node -r Option, -t Option, -p Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-r}
+@cindex Restarting existing mounts
+@cindex Picking up existing mounts
+
+Tells @i{Amd} to restart existing mounts (@pxref{Inheritance Filesystem}).
+@c @dfn{This option will be made the default in the next release.}
+
+@node -t Option, -v Option, -r Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-t} @var{timeout.retransmit}
+@cindex Setting Amd's RPC parameters
+
+Specifies the RPC @dfn{timeout} and @dfn{retransmit} intervals used by
+the kernel to communicate to @i{Amd}. These are used to set the
+@samp{timeo} and @samp{retrans} mount options.
+
+@i{Amd} relies on the kernel RPC retransmit mechanism to trigger mount
+retries. The value of this parameter changes the retry interval. Too
+long an interval gives poor interactive response, too short an interval
+causes excessive retries.
+
+@node -v Option, -w Option, -t Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-v}
+@cindex Version information
+@cindex Discovering version information
+@cindex How to discover your version of Amd
+
+Print version information on standard error and then exit. The output
+is of the form:
+
+@example
+amd 5.2.1.11 of 91/03/17 18:04:05 5.3Alpha11 #0: Sun Mar 17 18:07:28 GMT 1991
+Built by pendry@@vangogh.Berkeley.EDU for a hp300 running bsd44 (big-endian).
+Map support for: root, passwd, union, file, error.
+FS: ufs, nfs, nfsx, host, link, program, union, auto, direct, toplvl, error.
+Primary network is 128.32.130.0.
+@end example
+
+The information includes the version number, release date and name of
+the release. The architecture (@pxref{Supported Machine Architectures}),
+operating system (@pxref{Supported Operating Systems})
+and byte ordering are also printed as they appear in the @code{$@{os@}},
+@code{$@{arch@}} and @code{$@{byte@}} variables.@refill
+
+@node -w Option, -x Option, -v Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-w} @var{wait-timeout}
+@cindex Setting the interval between unmount attempts
+@cindex unmount attempt backoff interval
+
+Selects the interval in seconds between unmount attempts after the
+initial time-to-live has expired.
+
+This defaults to 120 seconds (two minutes).
+
+@node -x Option, -y Option, -w Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-x} @var{opts}
+@cindex Log message selection
+@cindex Selecting specific log messages
+@cindex How to select log messages
+@cindex syslog priorities
+
+Specifies the type and verbosity of log messages. @dfn{opts} is
+a comma separated list selected from the following options:
+
+@table @code
+@item fatal
+Fatal errors
+@item error
+Non-fatal errors
+@item user
+Non-fatal user errors
+@item warn
+Recoverable errors
+@item warning
+Alias for @code{warn}
+@item info
+Information messages
+@item map
+Mount map usage
+@item stats
+Additional statistics
+@item all
+All of the above
+@end table
+
+Initially a set of default logging flags is enabled. This is as if
+@samp{-x all,nomap,nostats} had been selected. The command line is
+parsed and logging is controlled by the ``-x'' option. The very first
+set of logging flags is saved and can not be subsequently disabled using
+@i{Amq}. This default set of options is useful for general production
+use.@refill
+
+The @samp{info} messages include details of what is mounted and
+unmounted and when filesystems have timed out. If you want to have the
+default set of messages without the @samp{info} messages then you simply
+need @samp{-x noinfo}. The messages given by @samp{user} relate to
+errors in the mount maps, so these are useful when new maps are
+installed. The following table lists the syslog priorites used for each
+of the message types.@refill
+
+@table @code
+@item fatal
+LOG_CRIT
+@item error
+LOG_ERR
+@item user
+LOG_WARNING
+@item warning
+LOG_WARNING
+@item info
+LOG_INFO
+@item debug
+LOG_DEBUG
+@item map
+LOG_DEBUG
+@item stats
+LOG_INFO
+@end table
+
+
+The options can be prefixed by the string @samp{no} to indicate
+that this option should be turned off. For example, to obtain all
+but @samp{info} messages the option @samp{-x all,noinfo} would be used.
+
+If @i{Amd} was built with debugging enabled the @code{debug} option is
+automatically enabled regardless of the command line options.
+
+@node -y Option, -C-Option, -x Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-y} @var{NIS-domain}
+@cindex NIS (YP) domain name
+@cindex Overriding the NIS (YP) domain name
+@cindex Setting the NIS (YP) domain name
+@cindex YP domain name
+
+Selects an alternate NIS domain. This is useful for debugging and
+cross-domain shared mounting. If this flag is specified, @i{Amd}
+immediately attempts to bind to a server for this domain.
+@c @i{Amd} refers to NIS maps when it starts, unless the ``-m'' option
+@c is specified, and whenever required in a mount map.
+
+@node -C-Option, -D-Option, -y Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-C} @var{cluster-name}
+@cindex Cluster names
+@cindex Setting the cluster name
+
+Specifies the name of the cluster of which the local machine is a member.
+The only effect is to set the variable @code{$@{cluster@}}.
+The @dfn{cluster-name} is will usually obtained by running another command which uses
+a database to map the local hostname into a cluster name.
+@code{$@{cluster@}} can then be used as a selector to restrict mounting of
+replicated data.
+If this option is not given, @code{$@{cluster@}} has the same value as @code{$@{domain@}}.
+This would be used as follows:
+
+@example
+amd -C `clustername` ...
+@end example
+
+@node -D-Option, , -C-Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-D} @var{opts}
+@cindex Debug options
+@cindex Setting debug flags
+
+Controls the verbosity and coverage of the debugging trace; @dfn{opts}
+is a comma separated list of debugging options. The ``-D'' option is
+only available if @i{Amd} was compiled with @samp{-DDEBUG}. The memory
+debugging facilities are only available if @i{Amd} was compiled with
+@samp{-DDEBUG_MEM} (in addition to @samp{-DDEBUG}).
+
+The most common options to use are @samp{-D trace} and @samp{-D test}
+(which turns on all the useful debug options). See the program source
+for a more detailed explanation of the available options.
+
+@node Filesystem Types, Run-time Administration, Amd Command Line Options, Top
+@comment node-name, next, previous, up
+@chapter Filesystem Types
+@cindex Filesystem types
+@cindex Mount types
+@cindex Types of filesystem
+
+To mount a volume, @i{Amd} must be told the type of filesystem to be
+used. Each filesystem type typically requires additional information
+such as the fileserver name for NFS.
+
+From the point of view of @i{Amd}, a @dfn{filesystem} is anything that
+can resolve an incoming name lookup. An important feature is support
+for multiple filesystem types. Some of these filesystems are
+implemented in the local kernel and some on remote fileservers, whilst
+the others are implemented internally by @i{Amd}.@refill
+
+The two common filesystem types are UFS and NFS. Four other user
+accessible filesystems (@samp{link}, @samp{program}, @samp{auto} and
+@samp{direct}) are also implemented internally by @i{Amd} and these are
+described below. There are two additional filesystem types internal to
+@i{Amd} which are not directly accessible to the user (@samp{inherit}
+and @samp{error}). Their use is described since they may still have an
+effect visible to the user.@refill
+
+@menu
+* Network Filesystem:: A single NFS filesystem.
+* Network Host Filesystem:: NFS mount a host's entire export tree.
+* Network Filesystem Group:: An atomic group of NFS filesystems.
+* Unix Filesystem:: Native disk filesystem.
+* Program Filesystem:: Generic Program mounts.
+* Symbolic Link Filesystem:: Local link referencing existing filesystem.
+* Automount Filesystem::
+* Direct Automount Filesystem::
+* Union Filesystem::
+* Error Filesystem::
+* Top-level Filesystem::
+* Root Filesystem::
+* Inheritance Filesystem::
+@end menu
+
+@node Network Filesystem, Network Host Filesystem, Filesystem Types, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Filesystem (@samp{type:=nfs})
+@cindex NFS
+@cindex Mounting an NFS filesystem
+@cindex How to mount and NFS filesystem
+@cindex nfs, filesystem type
+@cindex Filesystem type; nfs
+
+The @dfn{nfs} filesystem type provides access to Sun's NFS.
+
+@noindent
+The following options must be specified:
+
+@table @code
+@cindex rhost, mount option
+@cindex Mount option; rhost
+@item rhost
+the remote fileserver. This must be an entry in the hosts database. IP
+addresses are not accepted. The default value is taken
+from the local host name (@code{$@{host@}}) if no other value is
+specified.
+
+@cindex rfs, mount option
+@cindex Mount option; rfs
+@item rfs
+the remote filesystem.
+If no value is specified for this option, an internal default of
+@code{$@{path@}} is used.
+@end table
+
+NFS mounts require a two stage process. First, the @dfn{file handle} of
+the remote file system must be obtained from the server. Then a mount
+system call must be done on the local system. @i{Amd} keeps a cache
+of file handles for remote file systems. The cache entries have a
+lifetime of a few minutes.
+
+If a required file handle is not in the cache, @i{Amd} sends a request
+to the remote server to obtain it. @i{Amd} @dfn{does not} wait for
+a response; it notes that one of the locations needs retrying, but
+continues with any remaining locations. When the file handle becomes
+available, and assuming none of the other locations was successfully
+mounted, @i{Amd} will retry the mount. This mechanism allows several
+NFS filesystems to be mounted in parallel.
+@c @footnote{The mechanism
+@c is general, however NFS is the only filesystem
+@c for which the required hooks have been written.}
+The first one which responds with a valid file handle will be used.
+
+@noindent
+An NFS entry might be:
+
+@example
+jsp host!=charm;type:=nfs;rhost:=charm;rfs:=/home/charm;sublink:=jsp
+@end example
+
+The mount system call and any unmount attempts are always done
+in a new task to avoid the possibilty of blocking @i{Amd}.
+
+@node Network Host Filesystem, Network Filesystem Group, Network Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Host Filesystem (@samp{type:=host})
+@cindex Network host filesystem
+@cindex Mounting entire export trees
+@cindex How to mount all NFS exported filesystems
+@cindex host, filesystem type
+@cindex Filesystem type; host
+
+@c NOTE: the current implementation of the @dfn{host} filesystem type
+@c sometimes fails to maintain a consistent view of the remote mount tree.
+@c This happens when the mount times out and only some of the remote mounts
+@c are successfully unmounted. To prevent this from occuring, use the
+@c @samp{nounmount} mount option.
+
+The @dfn{host} filesystem allows access to the entire export tree of an
+NFS server. The implementation is layered above the @samp{nfs}
+implementation so keep-alives work in the same way. The only option
+which needs to specified is @samp{rhost} which is the name of the
+fileserver to mount.
+
+The @samp{host} filesystem type works by querying the mount daemon on
+the given fileserver to obtain its export list. @i{Amd} then obtains
+filehandles for each of the exported filesystems. Any errors at this
+stage cause that particular filesystem to be ignored. Finally each
+filesystem is mounted. Again, errors are logged but ignored. One
+common reason for mounts to fail is that the mount point does not exist.
+Although @i{Amd} attempts to automatically create the mount point, it
+may be on a remote filesystem to which @i{Amd} does not have write
+permission.
+
+When an attempt to unmount a @samp{host} filesystem mount fails, @i{Amd}
+remounts any filesystems which had succesfully been unmounted. To do
+this @i{Amd} queries the mount daemon again and obtains a fresh copy of
+the export list. @i{Amd} then tries to mount any exported filesystems
+which are not currently mounted.
+
+Sun's automounter provides a special @samp{-hosts} map. To achieve the
+same effect with @i{Amd} requires two steps. First a mount map must
+be created as follows:
+
+@example
+/defaults type:=host;fs:=$@{autodir@}/$@{rhost@}/root;rhost:=$@{key@}
+* opts:=rw,nosuid,grpid
+@end example
+
+@noindent
+and then start @i{Amd} with the following command
+
+@example
+amd /n net.map
+@end example
+
+@noindent
+where @samp{net.map} is the name of map described above. Note that the
+value of @code{$@{fs@}} is overridden in the map. This is done to avoid
+a clash between the mount tree and any other filesystem already mounted
+from the same fileserver.
+
+If different mount options are needed for different hosts then
+additional entries can be added to the map, for example
+
+@example
+host2 opts:=ro,nosuid,soft
+@end example
+
+@noindent
+would soft mount @samp{host2} read-only.
+
+@node Network Filesystem Group, Unix Filesystem, Network Host Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Filesystem Group (@samp{type:=nfsx})
+@cindex Network filesystem group
+@cindex Atomic NFS mounts
+@cindex Mounting an atomic group of NFS filesystems
+@cindex How to mount an atomic group of NFS filesystems
+@cindex nfsx, filesystem type
+@cindex Filesystem type; nfsx
+
+The @dfn{nfsx} filesystem allows a group of filesystems to be mounted
+from a single NFS server. The implementation is layered above the
+@samp{nfs} implementation so keep-alives work in the same way.
+
+The options are the same as for the @samp{nfs} filesystem with one
+difference.
+
+@noindent
+The following options must be specified:
+
+@table @code
+@item rhost
+the remote fileserver. This must be an entry in the hosts database. IP
+addresses are not accepted. The default value is taken from the local
+host name (@code{$@{host@}}) if no other value is specified.
+
+@item rfs
+as a list of filesystems to mount. The list is in the form of a comma
+separated strings.
+@end table
+
+@noindent
+For example:
+
+@example
+pub type:=nfsx;rhost:=gould;\
+ rfs:=/public,/,graphics,usenet;fs:=$@{autodir@}/$@{rhost@}/root
+@end example
+
+The first string defines the root of the tree, and is applied as a
+prefix to the remaining members of the list which define the individual
+filesystems. The first string is @emph{not} used as a filesystem name.
+A parallel operation is used to determine the local mount points to
+ensure a consistent layout of a tree of mounts.
+
+Here, the @emph{three} filesystems, @samp{/public},
+@samp{/public/graphics} and @samp{/public/usenet}, would be mounted.@refill
+
+A local mount point, @code{$@{fs@}}, @emph{must} be specified. The
+default local mount point will not work correctly in the general case.
+A suggestion is to use @samp{fs:=$@{autodir@}/$@{rhost@}/root}.@refill
+
+@node Unix Filesystem, Program Filesystem, Network Filesystem Group, Filesystem Types
+@comment node-name, next, previous, up
+@section Unix Filesystem (@samp{type:=ufs})
+@cindex Unix filesystem
+@cindex UFS
+@cindex Mounting a UFS filesystem
+@cindex Mounting a local disk
+@cindex How to mount a UFS filesystems
+@cindex How to mount a local disk
+@cindex Disk filesystems
+@cindex ufs, filesystem type
+@cindex Filesystem type; ufs
+
+The @dfn{ufs} filesystem type provides access to the system's
+standard disk filesystem---usually a derivative of the Berkeley Fast Filesystem.
+
+@noindent
+The following option must be specified:
+
+@table @code
+@cindex dev, mount option
+@cindex Mount option; dev
+@item dev
+the block special device to be mounted.
+@end table
+
+A UFS entry might be:
+
+@example
+jsp host==charm;type:=ufs;dev:=/dev/xd0g;sublink:=jsp
+@end example
+
+@node Program Filesystem, Symbolic Link Filesystem, Unix Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Program Filesystem (@samp{type:=program})
+@cindex Program filesystem
+@cindex Mount a filesystem under program control
+@cindex program, filesystem type
+@cindex Filesystem type; program
+
+The @dfn{program} filesystem type allows a program to be run whenever a
+mount or unmount is required. This allows easy addition of support for
+other filesystem types, such as MIT's Remote Virtual Disk (RVD)
+which has a programmatic interface via the commands
+@samp{rvdmount} and @samp{rvdunmount}.
+
+@noindent
+The following options must be specified:
+
+@table @code
+@cindex mount, mount option
+@cindex Mount option; mount
+@item mount
+the program which will perform the mount.
+
+@cindex unmount, mount option
+@cindex Mount option; unmount
+@item unmount
+the program which will perform the unmount.
+@end table
+
+The exit code from these two programs is interpreted as a Unix error
+code. As usual, exit code zero indicates success. To execute the
+program @i{Amd} splits the string on whitespace to create an array of
+substrings. Single quotes @samp{'} can be used to quote whitespace
+if that is required in an argument. There is no way to escape or change
+the quote character.
+
+To run the program @samp{rvdmount} with a host name and filesystem as
+arguments would be specified by @samp{mount:="/etc/rvdmount rvdmount
+fserver $@{path@}"}.
+
+The first element in the array is taken as the pathname of the program
+to execute. The other members of the array form the argument vector to
+be passed to the program, @dfn{including argument zero}. This means
+that the split string must have at least two elements. The program is
+directly executed by @i{Amd}, not via a shell. This means that scripts
+must begin with a @code{#!} interpreter specification.
+
+If a filesystem type is to be heavily used, it may be worthwhile adding
+a new filesystem type into @i{Amd}, but for most uses the program
+filesystem should suffice.
+
+When the program is run, standard input and standard error are inherited
+from the current values used by @i{Amd}. Standard output is a
+duplicate of standard error. The value specified with the ``-l''
+command line option has no effect on standard error.
+
+@node Symbolic Link Filesystem, Symbolic Link Filesystem II, Program Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Symbolic Link Filesystem (@samp{type:=link})
+@cindex Symbolic link filesystem
+@cindex Referencing part of the local name space
+@cindex Mounting part of the local name space
+@cindex How to reference part of the local name space
+@cindex link, filesystem type
+@cindex symlink, link filesystem type
+@cindex Filesystem type; link
+
+Each filesystem type creates a symbolic link to point from the volume
+name to the physical mount point. The @samp{link} filesystem does the
+same without any other side effects. This allows any part of the
+machines name space to be accessed via @i{Amd}.
+
+One common use for the symlink filesystem is @file{/homes} which can be
+made to contain an entry for each user which points to their
+(auto-mounted) home directory. Although this may seem rather expensive,
+it provides a great deal of administrative flexibility.
+
+@noindent
+The following option must be defined:
+
+@table @code
+@item fs
+The value of @var{fs} option specifies the destination of the link, as
+modified by the @var{sublink} option. If @var{sublink} is non-null, it
+is appended to @code{$@{fs@}}@code{/} and the resulting string is used
+as the target.
+@end table
+
+The @samp{link} filesystem can be though of as identical to the
+@samp{ufs} filesystem but without actually mounting anything.
+
+An example entry might be:
+
+@example
+jsp host==charm;type:=link;fs:=/home/charm;sublink:=jsp
+@end example
+which would return a symbolic link pointing to @file{/home/charm/jsp}.
+
+@node Symbolic Link Filesystem II, Automount Filesystem, Program Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Symbolic Link Filesystem II (@samp{type:=link})
+@cindex Symbolic link filesystem II
+@cindex Referencing an existing part of the local name space
+@cindex Mounting an existing part of the local name space
+@cindex How to reference an existing part of the local name space
+@cindex linkx, filesystem type
+@cindex symlink, linkx filesystem type
+@cindex Filesystem type; linkx
+
+The @samp{linkx} filesystem type is identical to @samp{link} with the
+exception that the target of the link must exist. Existence is checked
+with the @samp{lstat} system call.
+
+The @samp{linkx} filesystem type is particularly useful for wildcard map
+entries. In this case, a list of possible targets can be give and
+@i{Amd} will choose the first one which exists on the local machine.
+
+@node Automount Filesystem, Direct Automount Filesystem, Symbolic Link Filesystem II, Filesystem Types
+@comment node-name, next, previous, up
+@section Automount Filesystem (@samp{type:=auto})
+@cindex Automount filesystem
+@cindex Map cache types
+@cindex Setting map cache parameters
+@cindex How to set map cache parameters
+@cindex How to start an indirect automount point
+@cindex auto, filesystem type
+@cindex Filesystem type; auto
+@cindex SIGHUP signal
+@cindex Map cache synchronising
+@cindex Synchronising the map cache
+@cindex Map cache options
+@cindex Regular expressions in maps
+
+The @dfn{auto} filesystem type creates a new automount point below an
+existing automount point. Top-level automount points appear as system
+mount points. An automount mount point can also appear as a
+sub-directory of an existing automount point. This allows some
+additional structure to be added, for example to mimic the mount tree of
+another machine.
+
+The following options may be specified:
+
+@table @code
+@cindex cache, mount option
+@cindex Mount option; cache
+@item cache
+specifies whether the data in this mount-map should be
+cached. The default value is @samp{none}, in which case
+no caching is done in order to conserve memory.
+However, better performance and reliability can be obtained by caching
+some or all of a mount-map.
+
+If the cache option specifies @samp{all},
+the entire map is enumerated when the mount point is created.
+
+If the cache option specifies @samp{inc}, caching is done incrementally
+as and when data is required.
+Some map types do not support cache mode @samp{all}, in which case @samp{inc}
+is used whenever @samp{all} is requested.
+
+Caching can be entirely disabled by using cache mode @samp{none}.
+
+If the cache option specifies @samp{regexp} then the entire map will be
+enumerated and each key will be treated as an egrep-style regular
+expression. The order in which a cached map is searched does not
+correspond to the ordering in the source map so the regular expressions
+should be mutually exclusive to avoid confusion.
+
+Each mount map type has a default cache type, usually @samp{inc}, which
+can be selected by specifying @samp{mapdefault}.
+
+The cache mode for a mount map can only be selected on the command line.
+Starting @i{Amd} with the command:
+
+@example
+amd /homes hesiod.homes -cache:=inc
+@end example
+
+will cause @samp{/homes} to be automounted using the @dfn{Hesiod} name
+server with local incremental caching of all succesfully resolved names.
+
+All cached data is forgotten whenever @i{Amd} receives a @samp{SIGHUP}
+signal and, if cache @samp{all} mode was selected, the cache will be
+reloaded. This can be used to inform @i{Amd} that a map has been
+updated. In addition, whenever a cache lookup fails and @i{Amd} needs
+to examine a map, the map's modify time is examined. If the cache is
+out of date with respect to the map then it is flushed as if a
+@samp{SIGHUP} had been received.
+
+An additional option (@samp{sync}) may be specified to force @i{Amd} to
+check the map's modify time whenever a cached entry is being used. For
+example, an incremental, synchronised cache would be created by the
+following command:
+
+@example
+amd /homes hesiod.homes -cache:=inc,sync
+@end example
+
+@item fs
+specifies the name of the mount map to use for the new mount point.
+
+Arguably this should have been specified with the @code{$@{rfs@}} option but
+we are now stuck with it due to historical accident.
+
+@c %If the string @samp{.} is used then the same map is used;
+@c %in addition the lookup prefix is set to the name of the mount point followed
+@c %by a slash @samp{/}.
+@c %This is the same as specifying @samp{fs:=\$@{map@};pref:=\$@{key@}/}.
+@c
+
+@item pref
+alters the name that is looked up in the mount map. If
+@code{$@{pref@}}, the @dfn{prefix}, is non-null then it is prepended to
+the name requested by the kernel @dfn{before} the map is searched.
+@end table
+
+The server @samp{dylan.doc.ic.ac.uk} has two user disks:
+@samp{/dev/dsk/2s0} and @samp{/dev/dsk/5s0}. These are accessed as
+@samp{/home/dylan/dk2} and @samp{/home/dylan/dk5} respectively. Since
+@samp{/home} is already an automount point, this naming is achieved with
+the following map entries:@refill
+
+@example
+dylan type:=auto;fs:=$@{map@};pref:=$@{key@}/
+dylan/dk2 type:=ufs;dev:=/dev/dsk/2s0
+dylan/dk5 type:=ufs;dev:=/dev/dsk/5s0
+@end example
+
+@node Direct Automount Filesystem, Union Filesystem, Automount Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Direct Automount Filesystem (@samp{type:=direct})
+@cindex Direct automount filesystem
+@cindex How to start a direct automount point
+@cindex direct, filesystem type
+@cindex Filesystem type; direct
+
+The @dfn{direct} filesystem is almost identical to the automount
+filesystem. Instead of appearing to be a directory of mount points, it
+appears as a symbolic link to a mounted filesystem. The mount is done
+at the time the link is accessed. @xref{Automount Filesystem} for a
+list of required options.
+
+Direct automount points are created by specifying the @samp{direct}
+filesystem type on the command line:
+
+@example
+amd ... /usr/man auto.direct -type:=direct
+@end example
+
+where @samp{auto.direct} would contain an entry such as:
+
+@example
+usr/man -type:=nfs;rfs:=/usr/man \
+ rhost:=man-server1 rhost:=man-server2
+@end example
+
+In this example, @samp{man-server1} and @samp{man-server2} are file
+servers which export copies of the manual pages. Note that the key
+which is looked up is the name of the automount point without the
+leading @samp{/}.
+
+@node Union Filesystem, Error Filesystem, Direct Automount Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Union Filesystem (@samp{type:=union})
+@cindex Union filesystem
+@cindex union, filesystem type
+@cindex Filesystem type; union
+
+The @dfn{union} filesystem type allows the contents of several
+directories to be merged and made visible in a single directory. This
+can be used to overcome one of the major limitations of the Unix mount
+mechanism which only allows complete directories to be mounted.
+
+For example, supposing @file{/tmp} and @file{/var/tmp} were to be merged
+into a new directory called @file{/mtmp}, with files in @file{/var/tmp}
+taking precedence. The following command could be used to achieve this
+effect:
+
+@example
+amd ... /mtmp union:/tmp:/var/tmp -type:=union
+@end example
+
+Currently, the unioned directories must @emph{not} be automounted. That
+would cause a deadlock. This seriously limits the current usefulness of
+this filesystem type and the problem will be addressed in a future
+release of @i{Amd}.
+
+Files created in the union directory are actually created in the last
+named directory. This is done by creating a wildcard entry which points
+to the correct directory. The wildcard entry is visible if the union
+directory is listed, so allowing you to see which directory has
+priority.
+
+The files visible in the union directory are computed at the time
+@i{Amd} is started, and are not kept uptodate with respect to the
+underlying directories. Similarly, if a link is removed, for example
+with the @samp{rm} command, it will be lost forever.
+
+@node Error Filesystem, Top-level Filesystem, Union Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Error Filesystem (@samp{type:=error})
+@cindex Error filesystem
+@cindex error, filesystem type
+@cindex Filesystem type; error
+
+The @dfn{error} filesystem type is used internally as a catch-all in
+the case where none of the other filesystems was selected, or some other
+error occurred.
+Lookups and mounts always fail with ``No such file or directory''.
+All other operations trivially succeed.
+
+The error filesystem is not directly accessible.
+
+@node Top-level Filesystem, Root Filesystem, Error Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Top-level Filesystem (@samp{type:=toplvl})
+@cindex Top level filesystem
+@cindex toplvl, filesystem type
+@cindex Filesystem type; toplvl
+
+The @dfn{toplvl} filesystems is derived from the @samp{auto} filesystem
+and is used to mount the top-level automount nodes. Requests of this
+type are automatically generated from the command line arguments and
+can also be passed in by using the ``-M'' option of the @dfn{Amq} command.
+
+@node Root Filesystem, Inheritance Filesystem, Top-level Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Root Filesystem
+@cindex Root filesystem
+@cindex root, filesystem type
+@cindex Filesystem type; root
+
+The @dfn{root} (@samp{type:=root}) filesystem type acts as an internal
+placeholder onto which @i{Amd} can pin @samp{toplvl} mounts. Only one
+node of this type need ever exist and one is created automatically
+during startup. The effect of creating a second root node is undefined.
+
+@node Inheritance Filesystem, , Root Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Inheritance Filesystem
+@cindex Inheritance filesystem
+@cindex Nodes generated on a restart
+@cindex inherit, filesystem type
+@cindex Filesystem type; inherit
+
+The @dfn{inheritance} (@samp{type:=inherit}) filesystem is not directly
+accessible. Instead, internal mount nodes of this type are
+automatically generated when @i{Amd} is started with the ``-r'' option.
+At this time the system mount table is scanned to locate any filesystems
+which are already mounted. If any reference to these filesystems is
+made through @i{Amd} then instead of attempting to mount it, @i{Amd}
+simulates the mount and @dfn{inherits} the filesystem. This allows a
+new version of @i{Amd} to be installed on a live system simply by
+killing the old daemon with @code{SIGTERM} and starting the new one.@refill
+
+This filesystem type is not generally visible externally, but it is
+possible that the output from @samp{amq -m} may list @samp{inherit} as
+the filesystem type. This happens when an inherit operation cannot
+be completed for some reason, usually because a fileserver is down.
+
+@node Run-time Administration, FSinfo, Filesystem Types, Top
+@comment node-name, next, previous, up
+@chapter Run-time Administration
+@cindex Run-time administration
+@cindex Amq command
+
+@menu
+* Starting Amd::
+* Stopping Amd::
+* Controlling Amd::
+@end menu
+
+@node Starting Amd, Stopping Amd, Run-time Administration, Run-time Administration
+@comment node-name, next, previous, up
+@section Starting @i{Amd}
+@cindex Starting Amd
+@cindex Additions to /etc/rc.local
+@cindex /etc/rc.local additions
+@cindex /etc/amd.start
+
+@i{Amd} is best started from @samp{/etc/rc.local}:
+
+@example
+if [ -f /etc/amd.start ]; then
+ sh /etc/amd.start; (echo -n ' amd') >/dev/console
+fi
+@end example
+
+@noindent
+The shell script, @samp{amd.start}, contains:
+
+@example
+#!/bin/sh -
+PATH=/etc:/bin:/usr/bin:/usr/ucb:$PATH export PATH
+
+#
+# Either name of logfile or "syslog"
+#
+LOGFILE=syslog
+#LOGFILE=/var/log/amd
+
+#
+# Figure out whether domain name is in host name
+# If the hostname is just the machine name then
+# pass in the name of the local domain so that the
+# hostnames in the map are domain stripped correctly.
+#
+case `hostname` in
+*.*) dmn= ;;
+*) dmn='-d doc.ic.ac.uk'
+esac
+
+#
+# Zap earlier log file
+#
+case "$LOGFILE" in
+*/*)
+ mv "$LOGFILE" "$LOGFILE"-
+ > "$LOGFILE"
+ ;;
+syslog)
+ : nothing
+ ;;
+esac
+
+cd /usr/sbin
+#
+# -r restart
+# -d dmn local domain
+# -w wait wait between unmount attempts
+# -l log logfile or "syslog"
+#
+eval ./amd -r $dmn -w 240 -l "$LOGFILE" \
+ /homes amd.homes -cache:=inc \
+ /home amd.home -cache:=inc \
+ /vol amd.vol -cache:=inc \
+ /n amd.net -cache:=inc
+@end example
+
+If the list of automount points and maps is contained in a file or NIS map
+it is easily incorporated onto the command line:
+
+@example
+...
+eval ./amd -r $dmn -w 240 -l "$LOGFILE" `ypcat -k auto.master`
+@end example
+
+@node Stopping Amd, Controlling Amd, Starting Amd, Run-time Administration
+@comment node-name, next, previous, up
+@section Stopping @i{Amd}
+@cindex Stopping Amd
+@cindex SIGTERM signal
+@cindex SIGINT signal
+
+@i{Amd} stops in response to two signals.
+
+@table @samp
+@item SIGTERM
+causes the top-level automount points to be unmounted and then @i{Amd}
+to exit. Any automounted filesystems are left mounted. They can be
+recovered by restarting @i{Amd} with the ``-r'' command line option.@refill
+
+@item SIGINT
+causes @i{Amd} to attempt to unmount any filesystems which it has
+automounted, in addition to the actions of @samp{SIGTERM}. This signal
+is primarly used for debugging.@refill
+@end table
+
+Actions taken for other signals are undefined.
+
+@node Controlling Amd, , Stopping Amd, Run-time Administration
+@comment node-name, next, previous, up
+@section Controlling @i{Amd}
+@cindex Controlling Amd
+@cindex Discovering what is going on at run-time
+@cindex Listing currently mounted filesystems
+
+It is sometimes desirable or necessary to exercise external control
+over some of @i{Amd}'s internal state. To support this requirement,
+@i{Amd} implements an RPC interface which is used by the @dfn{Amq} program.
+A variety of information is available.
+
+@i{Amq} generally applies an operation, specified by a single letter option,
+to a list of mount points. The default operation is to obtain statistics
+about each mount point. This is similar to the output shown above
+but includes information about the number and type of accesses to each
+mount point.
+
+@menu
+* Amq default:: Default command behaviour.
+* Amq -f option:: Flushing the map cache.
+* Amq -h option:: Controlling a non-local host.
+* Amq -m option:: Obtaining mount statistics.
+* Amq -M-option:: Mounting a volume.
+* Amq -s option:: Obtaining global statistics.
+* Amq -u option:: Forcing volumes to time out.
+* Amq -v option:: Version information.
+* Other Amq options:: Three other special options.
+@end menu
+
+@node Amq default, Amq -f option, Controlling Amd, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} default information
+
+With no arguments, @dfn{Amq} obtains a brief list of all existing
+mounts created by @i{Amd}. This is different from the list displayed by
+@b{df}(1) since the latter only includes system mount points.
+
+@noindent
+The output from this option includes the following information:
+
+@itemize @bullet
+@item
+the automount point,
+@item
+the filesystem type,
+@item
+the mount map or mount information,
+@item
+the internal, or system mount point.
+@end itemize
+
+@noindent
+For example:
+
+@example
+/ root "root" sky:(pid75)
+/homes toplvl /usr/local/etc/amd.homes /homes
+/home toplvl /usr/local/etc/amd.home /home
+/homes/jsp nfs charm:/home/charm /a/charm/home/charm/jsp
+/homes/phjk nfs toytown:/home/toytown /a/toytown/home/toytown/ai/phjk
+@end example
+
+@noindent
+If an argument is given then statistics for that volume name will
+be output. For example:
+
+@example
+What Uid Getattr Lookup RdDir RdLnk Statfs Mounted@@
+/homes 0 1196 512 22 0 30 90/09/14 12:32:55
+/homes/jsp 0 0 0 0 1180 0 90/10/13 12:56:58
+@end example
+
+@table @code
+@item What
+the volume name.
+
+@item Uid
+ignored.
+
+@item Getattr
+the count of NFS @dfn{getattr} requests on this node. This should only be
+non-zero for directory nodes.
+
+@item Lookup
+the count of NFS @dfn{lookup} requests on this node. This should only be
+non-zero for directory nodes.
+
+@item RdDir
+the count of NFS @dfn{readdir} requests on this node. This should only
+be non-zero for directory nodes.
+
+@item RdLnk
+the count of NFS @dfn{readlink} requests on this node. This should be
+zero for directory nodes.
+
+@item Statfs
+the could of NFS @dfn{statfs} requests on this node. This should only
+be non-zero for top-level automount points.
+
+@item Mounted@@
+the date and time the volume name was first referenced.
+@end table
+
+@node Amq -f option, Amq -h option, Amq default, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -f option
+@cindex Flushing the map cache
+@cindex Map cache, flushing
+
+The ``-f'' option causes @i{Amd} to flush the internal mount map cache.
+This is useful for Hesiod maps since @i{Amd} will not automatically
+notice when they have been updated. The map cache can also be
+synchronised with the map source by using the @samp{sync} option
+(@pxref{Automount Filesystem}).@refill
+
+@node Amq -h option, Amq -m option, Amq -f option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -h option
+@cindex Querying an alternate host
+
+By default the local host is used. In an HP-UX cluster the root server
+is used since that is the only place in the cluster where @i{Amd} will
+be running. To query @i{Amd} on another host the ``-h'' option should
+be used.
+
+@node Amq -m option, Amq -M-option, Amq -h option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -m option
+
+The ``-m'' option displays similar information about mounted
+filesystems, rather than automount points. The output includes the
+following information:
+
+@itemize @bullet
+@item
+the mount information,
+@item
+the mount point,
+@item
+the filesystem type,
+@item
+the number of references to this filesystem,
+@item
+the server hostname,
+@item
+the state of the file server,
+@item
+any error which has occured.
+@end itemize
+
+For example:
+
+@example
+"root" truth:(pid602) root 1 localhost is up
+hesiod.home /home toplvl 1 localhost is up
+hesiod.vol /vol toplvl 1 localhost is up
+hesiod.homes /homes toplvl 1 localhost is up
+amy:/home/amy /a/amy/home/amy nfs 5 amy is up
+swan:/home/swan /a/swan/home/swan nfs 0 swan is up (Permission denied)
+ex:/home/ex /a/ex/home/ex nfs 0 ex is down
+@end example
+
+When the reference count is zero the filesystem is not mounted but
+the mount point and server information is still being maintained
+by @i{Amd}.
+
+@node Amq -M-option, Amq -s option, Amq -m option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -M option
+
+The ``-M'' option passes a new map entry to @i{Amd} and waits for it to
+be evaluated, possibly causing a mount. For example, the following
+command would cause @samp{/home/toytown} on host @samp{toytown} to be
+mounted locally on @samp{/mnt/toytown}.
+
+@example
+amq -M '/mnt/toytown type:=nfs;rfs:=/home/toytown;rhost:=toytown;fs:=$@{key@}'
+@end example
+
+@i{Amd} applies some simple security checks before allowing this
+operation. The check tests whether the incoming request is from a
+privileged UDP port on the local machine. ``Permission denied'' is
+returned if the check fails.
+
+A future release of @i{Amd} will include code to allow the @b{mount}(8)
+command to mount automount points:
+
+@example
+mount -t amd /vol hesiod.vol
+@end example
+
+This will then allow @i{Amd} to be controlled from the standard system
+filesystem mount list.
+
+@node Amq -s option, Amq -u option, Amq -M-option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -s option
+@cindex Global statistics
+@cindex Statistics
+
+The ``-s'' option displays global statistics. If any other options are specified
+or any filesystems named then this option is ignored. For example:
+
+@example
+requests stale mount mount unmount
+deferred fhandles ok failed failed
+1054 1 487 290 7017
+@end example
+
+@table @samp
+@item Deferred requests
+are those for which an immediate reply could not be constructed. For
+example, this would happen if a background mount was required.
+
+@item Stale filehandles
+counts the number of times the kernel passes a stale filehandle to @i{Amd}.
+Large numbers indicate problems.
+
+@item Mount ok
+counts the number of automounts which were successful.
+
+@item Mount failed
+counts the number of automounts which failed.
+
+@item Unmount failed
+counts the number of times a filesystem could not be unmounted. Very
+large numbers here indicate that the time between unmount attempts
+should be increased.
+@end table
+
+@node Amq -u option, Amq -v option, Amq -s option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -u option
+@cindex Forcing filesystem to time out
+@cindex Unmounting a filesystem
+
+The ``-u'' option causes the time-to-live interval of the named mount
+points to be expired, thus causing an unmount attempt. This is the only
+safe way to unmount an automounted filesystem. It is not possible to
+unmount a filesystem which has been mounted with the @samp{nounmount}
+flag.
+
+@c The ``-H'' option informs @i{Amd} that the specified mount point has hung -
+@c as if its keepalive timer had expired.
+
+@node Amq -v option, Other Amq options, Amq -u option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} -v option
+@cindex Version information at run-time
+
+The ``-v'' option displays the version of @i{Amd} in a similar way to
+@i{Amd}'s ``-v'' option.
+
+@node Other Amq options, , Amq -v option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection Other @i{Amq} options
+
+Three other operations are implemented. These modify the state of
+@i{Amd} as a whole, rather than any particular filesystem. The ``-l'',
+``-x'' and ``-D'' options have exactly the same effect as @i{Amd}'s
+corresponding command line options. The ``-l'' option is rejected by
+@i{Amd} in the current version for obvious security reasons. When
+@i{Amd} receives a ``-x''flag it limits the log options being modified
+to those which were not enabled at startup. This prevents a user
+turning @emph{off} any logging option which was specified at startup,
+though any which have been turned off since then can still be turned
+off. The ``-D'' option has a similar behaviour.
+
+@node FSinfo, Examples, Run-time Administration, Top
+@comment node-name, next, previous, up
+@chapter FSinfo
+@cindex FSinfo
+@cindex Filesystem info package
+
+@menu
+* FSinfo Overview:: Introduction to FSinfo.
+* Using FSinfo:: Basic concepts.
+* FSinfo Grammar:: Language syntax, semantics and examples.
+* FSinfo host definitions:: Defining a new host.
+* FSinfo host attributes:: Definable host attributes.
+* FSinfo filesystems:: Defining locally attached filesystems.
+* FSinfo static mounts:: Defining additional static mounts.
+* FSinfo automount definitions::
+* FSinfo command line options::
+* FSinfo errors::
+@end menu
+
+@node FSinfo Overview, Using FSinfo, FSinfo, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} overview
+@cindex FSinfo overview
+
+@i{FSinfo} is a filesystem management tool. It has been designed to
+work with @i{Amd} to help system administrators keep track of the ever
+increasing filesystem namespace under their control.
+
+The purpose of @i{FSinfo} is to generate all the important standard
+filesystem data files from a single set of input data. Starting with a
+single data source guarantees that all the generated files are
+self-consistent. One of the possible output data formats is a set of
+@i{Amd} maps which can be used amongst the set of hosts described in the
+input data.
+
+@i{FSinfo} implements a declarative language. This language is
+specifically designed for describing filesystem namespace and physical
+layouts. The basic declaration defines a mounted filesystem including
+its device name, mount point, and all the volumes and access
+permissions. @i{FSinfo} reads this information and builds an internal
+map of the entire network of hosts. Using this map, many different data
+formats can be produced including @file{/etc/fstab},
+@file{/etc/exports}, @i{Amd} mount maps and
+@file{/etc/bootparams}.@refill
+
+@node Using FSinfo, FSinfo Grammar, FSinfo Overview, FSinfo
+@comment node-name, next, previous, up
+@section Using @i{FSinfo}
+@cindex Using FSinfo
+
+The basic strategy when using @i{FSinfo} is to gather all the
+information about all disks on all machines into one set of
+declarations. For each machine being managed, the following data is
+required:
+
+@itemize @bullet
+@item
+Hostname
+@item
+List of all filesystems and, optionally, their mount points.
+@item
+Names of volumes stored on each filesystem.
+@item
+NFS export information for each volume.
+@item
+The list of static filesystem mounts.
+@end itemize
+
+The following information can also be entered into the same
+configuration files so that all data can be kept in one place.
+
+@itemize @bullet
+@item
+List of network interfaces
+@item
+IP address of each interface
+@item
+Hardware address of each interface
+@item
+Dumpset to which each filesystem belongs
+@item
+and more @dots{}
+@end itemize
+
+To generate @i{Amd} mount maps, the automount tree must also be defined
+(@pxref{FSinfo automount definitions}). This will have been designed at
+the time the volume names were allocated. Some volume names will not be
+automounted, so @i{FSinfo} needs an explicit list of which volumes
+should be automounted.@refill
+
+Hostnames are required at several places in the @i{FSinfo} language. It
+is important to stick to either fully qualified names or unqualified
+names. Using a mixture of the two will inevitably result in confusion.
+
+Sometimes volumes need to be referenced which are not defined in the set
+of hosts being managed with @i{FSinfo}. The required action is to add a
+dummy set of definitions for the host and volume names required. Since
+the files generated for those particular hosts will not be used on them,
+the exact values used is not critical.
+
+@node FSinfo Grammar, FSinfo host definitions, Using FSinfo, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} grammar
+@cindex FSinfo grammar
+@cindex Grammar, FSinfo
+
+@i{FSinfo} has a relatively simple grammar. Distinct syntactic
+constructs exist for each of the different types of data, though they
+share a common flavour. Several conventions are used in the grammar
+fragments below.
+
+The notation, @i{list(}@t{xxx}@i{)}, indicates a list of zero or more
+@t{xxx}'s. The notation, @i{opt(}@t{xxx}@i{)}, indicates zero or one
+@t{xxx}. Items in double quotes, @i{eg} @t{"host"}, represent input
+tokens. Items in angle brackets, @i{eg} @var{<hostname>}, represent
+strings in the input. Strings need not be in double quotes, except to
+differentiate them from reserved words. Quoted strings may include the
+usual set of C ``@t{\}'' escape sequences with one exception: a
+backslash-newline-whitespace sequence is squashed into a single space
+character. To defeat this feature, put a further backslash at the start
+of the second line.
+
+At the outermost level of the grammar, the input consists of a
+sequence of host and automount declarations. These declarations are
+all parsed before they are analyzed. This means they can appear in
+any order and cyclic host references are possible.
+
+@example
+fsinfo : @i{list(}fsinfo_attr@i{)} ;
+
+fsinfo_attr : host | automount ;
+@end example
+
+@menu
+* FSinfo host definitions::
+* FSinfo automount definitions::
+@end menu
+
+@node FSinfo host definitions, FSinfo host attributes, FSinfo grammar, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} host definitions
+@cindex FSinfo host definitions
+@cindex Defining a host, FSinfo
+
+A host declaration consists of three parts: a set of machine attribute
+data, a list of filesystems physically attached to the machine, and a
+list of additional statically mounted filesystems.
+
+@example
+host : "host" host_data @i{list(}filesystem@i{@i{)}} @i{list(}mount@i{@i{)}} ;
+@end example
+
+Each host must be declared in this way exactly once. Such things as the
+hardware address, the architecture and operating system types and the
+cluster name are all specified within the @dfn{host data}.
+
+All the disks the machine has should then be described in the @dfn{list
+of filesystems}. When describing disks, you can specify what
+@dfn{volname} the disk/partition should have and all such entries are
+built up into a dictionary which can then be used for building the
+automounter maps.
+
+The @dfn{list of mounts} specifies all the filesystems that should be
+statically mounted on the machine.
+
+@menu
+* FSinfo host attributes::
+* FSinfo filesystems::
+* FSinfo static mounts::
+@end menu
+
+@node FSinfo host attributes, FSinfo filesystems, FSinfo host definitions , FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} host attributes
+@cindex FSinfo host attributes
+@cindex Defining host attributes, FSinfo
+
+The host data, @dfn{host_data}, always includes the @dfn{hostname}. In
+addition, several other host attributes can be given.
+
+@example
+host_data : @var{<hostname>}
+ | "@{" @i{list(}host_attrs@i{)} "@}" @var{<hostname>}
+ ;
+
+host_attrs : host_attr "=" @var{<string>}
+ | netif
+ ;
+
+host_attr : "config"
+ | "arch"
+ | "os"
+ | "cluster"
+ ;
+@end example
+
+The @dfn{hostname} is, typically, the fully qualified hostname of the
+machine.
+
+Examples:
+
+@example
+host dylan.doc.ic.ac.uk
+
+host @{
+ os = hpux
+ arch = hp300
+@} dougal.doc.ic.ac.uk
+@end example
+
+The options that can be given as host attributes are shown below.
+
+@menu
+* netif Option: FSinfo host netif:
+* config Option: FSinfo host config:
+* arch Option: FSinfo host arch:
+* os Option: FSinfo host os:
+* cluster Option: FSinfo host cluster:
+@end menu
+
+@node FSinfo host netif, FSinfo host config, , FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection netif Option
+
+This defines the set of network interfaces configured on the machine.
+The interface attributes collected by @i{FSinfo} are the IP address,
+subnet mask and hardware address. Multiple interfaces may be defined
+for hosts with several interfaces by an entry for each interface. The
+values given are sanity checked, but are currently unused for anything
+else.
+
+@example
+netif : "netif" @var{<string>} "@{" @i{list(}netif_attrs@i{)} "@}" ;
+
+netif_attrs : netif_attr "=" @var{<string>} ;
+
+netif_attr : "inaddr" | "netmask" | "hwaddr" ;
+@end example
+
+Examples:
+
+@example
+netif ie0 @{
+ inaddr = 129.31.81.37
+ netmask = 0xfffffe00
+ hwaddr = "08:00:20:01:a6:a5"
+@}
+
+netif ec0 @{ @}
+@end example
+
+@node FSinfo host config, FSinfo host arch, FSinfo host netif, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection config Option
+@cindex FSinfo config host attribute
+@cindex config, FSinfo host attribute
+
+This option allows you to specify configuration variables for the
+startup scripts (@file{rc} scripts). A simple string should immediately
+follow the keyword.
+
+Example:
+
+@example
+config "NFS_SERVER=true"
+config "ZEPHYR=true"
+@end example
+
+This option is currently unsupported.
+
+@node FSinfo host arch, FSinfo host os, FSinfo host config, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection arch Option
+@cindex FSinfo arch host attribute
+@cindex arch, FSinfo host attribute
+
+This defines the architecture of the machine. For example:
+
+@example
+arch = hp300
+@end example
+
+This is intended to be of use when building architecture specific
+mountmaps, however, the option is currently unsupported.
+
+@node FSinfo host os, FSinfo host cluster, FSinfo host arch, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection os Option
+@cindex FSinfo os host attribute
+@cindex os, FSinfo host attribute
+
+This defines the operating system type of the host. For example:
+
+@example
+os = hpux
+@end example
+
+This information is used when creating the @file{fstab} files, for
+example in choosing which format to use for the @file{fstab} entries
+within the file.
+
+@node FSinfo host cluster, , FSinfo host os, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection cluster Option
+@cindex FSinfo cluster host attribute
+@cindex cluster, FSinfo host attribute
+
+This is used for specifying in which cluster the machine belongs. For
+example:
+
+@example
+cluster = "theory"
+@end example
+
+The cluster is intended to be used when generating the automount maps,
+although it is currently unsupported.
+
+@node FSinfo filesystems, FSinfo static mounts, FSinfo host attributes, FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} filesystems
+@cindex FSinfo filesystems
+
+The list of physically attached filesystems follows the machine
+attributes. These should define all the filesystems available from this
+machine, whether exported or not. In addition to the device name,
+filesystems have several attributes, such as filesystem type, mount
+options, and @samp{fsck} pass number which are needed to generate
+@file{fstab} entries.
+
+@example
+filesystem : "fs" @var{<device>} "@{" @i{list(}fs_data@i{)} "@}" ;
+
+fs_data : fs_data_attr "=" @var{<string>}
+ | mount
+ ;
+
+fs_data_attr
+ : "fstype" | "opts" | "passno"
+ | "freq" | "dumpset" | "log"
+ ;
+@end example
+
+Here, @var{<device>} is the device name of the disk (for example,
+@file{/dev/dsk/2s0}). The device name is used for building the mount
+maps and for the @file{fstab} file. The attributes that can be
+specified are shown in the following section.
+
+The @i{FSinfo} configuration file for @code{dylan.doc.ic.ac.uk} is listed below.
+
+@example
+host dylan.doc.ic.ac.uk
+
+fs /dev/dsk/0s0 @{
+ fstype = swap
+@}
+
+fs /dev/dsk/0s0 @{
+ fstype = hfs
+ opts = rw,noquota,grpid
+ passno = 0;
+ freq = 1;
+ mount / @{ @}
+@}
+
+fs /dev/dsk/1s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount /usr @{
+ local @{
+ exportfs "dougal eden dylan zebedee brian"
+ volname /nfs/hp300/local
+ @}
+ @}
+@}
+
+fs /dev/dsk/2s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk2
+ @}
+@}
+
+fs /dev/dsk/3s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk3
+ @}
+@}
+
+fs /dev/dsk/5s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk5
+ @}
+@}
+@end example
+
+@menu
+* fstype Option: FSinfo filesystems fstype:
+* opts Option: FSinfo filesystems opts:
+* passno Option: FSinfo filesystems passno:
+* freq Option: FSinfo filesystems freq:
+* mount Option: FSinfo filesystems mount:
+* dumpset Option: FSinfo filesystems dumpset:
+* log Option: FSinfo filesystems log:
+@end menu
+
+@node FSinfo filesystems fstype, FSinfo filesystems opts, , FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection fstype Option
+@cindex FSinfo fstype filesystems option
+@cindex fstype, FSinfo filesystems option
+@cindex export, FSinfo special fstype
+
+This specifies the type of filesystem being declared and will be placed
+into the @file{fstab} file as is. The value of this option will be
+handed to @code{mount} as the filesystem type---it should have such
+values as @code{4.2}, @code{nfs} or @code{swap}. The value is not
+examined for correctness.
+
+There is one special case. If the filesystem type is specified as
+@samp{export} then the filesystem information will not be added to the
+host's @file{fstab} information, but it will still be visible on the
+network. This is useful for defining hosts which contain referenced
+volumes but which are not under full control of @i{FSinfo}.
+
+Example:
+
+@example
+fstype = swap
+@end example
+
+@node FSinfo filesystems opts, FSinfo filesystems passno,FSinfo filesystems fstype, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection opts Option
+@cindex FSinfo opts filesystems option
+@cindex opts, FSinfo filesystems option
+
+This defines any options that should be given to @b{mount}(8) in the
+@file{fstab} file. For example:
+
+@example
+opts = rw,nosuid,grpid
+@end example
+
+@node FSinfo filesystems passno, FSinfo filesystems freq, FSinfo filesystems opts, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection passno Option
+@cindex FSinfo passno filesystems option
+@cindex passno, FSinfo filesystems option
+
+This defines the @b{fsck}(8) pass number in which to check the
+filesystem. This value will be placed into the @file{fstab} file.
+
+Example:
+
+@example
+passno = 1
+@end example
+
+@node FSinfo filesystems freq, FSinfo filesystems mount, FSinfo filesystems passno, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection freq Option
+@cindex FSinfo freq filesystems option
+@cindex freq, FSinfo filesystems option
+
+This defines the interval (in days) between dumps. The value is placed
+as is into the @file{fstab} file.
+
+Example:
+
+@example
+freq = 3
+@end example
+
+@node FSinfo filesystems mount, FSinfo filesystems dumpset, FSinfo filesystems freq, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection mount Option
+@cindex FSinfo mount filesystems option
+@cindex mount, FSinfo filesystems option
+@cindex exportfs, FSinfo mount option
+@cindex volname, FSinfo mount option
+@cindex sel, FSinfo mount option
+
+This defines the mountpoint at which to place the filesystem. If the
+mountpoint of the filesystem is specified as @code{default}, then the
+filesystem will be mounted in the automounter's tree under its volume
+name and the mount will automatically be inherited by the automounter.
+
+Following the mountpoint, namespace information for the filesystem may
+be described. The options that can be given here are @code{exportfs},
+@code{volname} and @code{sel}.
+
+The format is:
+
+@example
+mount : "mount" vol_tree ;
+
+vol_tree : @i{list(}vol_tree_attr@i{)} ;
+
+vol_tree_attr
+ : @var{<string>} "@{" @i{list(}vol_tree_info@i{)} vol_tree "@}" ;
+
+vol_tree_info
+ : "exportfs" @var{<export-data>}
+ | "volname" @var{<volname>}
+ | "sel" @var{<selector-list>}
+ ;
+@end example
+
+Example:
+
+@example
+mount default @{
+ exportfs "dylan dougal florence zebedee"
+ volname /vol/andrew
+@}
+@end example
+
+In the above example, the filesystem currently being declared will have
+an entry placed into the @file{exports} file allowing the filesystem to
+be exported to the machines @code{dylan}, @code{dougal}, @code{florence}
+and @code{zebedee}. The volume name by which the filesystem will be
+referred to remotely, is @file{/vol/andrew}. By declaring the
+mountpoint to be @code{default}, the filesystem will be mounted on the
+local machine in the automounter tree, where @i{Amd} will automatically
+inherit the mount as @file{/vol/andrew}.@refill
+
+@table @samp
+@item exportfs
+a string defining which machines the filesystem may be exported to.
+This is copied, as is, into the @file{exports} file---no sanity checking
+is performed on this string.@refill
+
+@item volname
+a string which declares the remote name by which to reference the
+filesystem. The string is entered into a dictionary and allows you to
+refer to this filesystem in other places by this volume name.@refill
+
+@item sel
+a string which is placed into the automounter maps as a selector for the
+filesystem.@refill
+
+@end table
+
+@node FSinfo filesystems dumpset, FSinfo filesystems log, FSinfo filesystems mount, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection dumpset Option
+@cindex FSinfo dumpset filesystems option
+@cindex dumpset, FSinfo filesystems option
+
+This provides support for Imperial College's local file backup tools and
+is not documented further here.
+
+@node FSinfo filesystems log, , FSinfo filesystems dumpset, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection log Option
+@cindex FSinfo log filesystems option
+@cindex log, FSinfo filesystems option
+
+Specifies the log device for the current filesystem. This is ignored if
+not required by the particular filesystem type.
+
+@node FSinfo static mounts, FSinfo automount definitions , FSinfo filesystems, FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} static mounts
+@cindex FSinfo static mounts
+@cindex Statically mounts filesystems, FSinfo
+
+Each host may also have a number of statically mounted filesystems. For
+example, the host may be a diskless workstation in which case it will
+have no @code{fs} declarations. In this case the @code{mount}
+declaration is used to determine from where its filesystems will be
+mounted. In addition to being added to the @file{fstab} file, this
+information can also be used to generate a suitable @file{bootparams}
+file.@refill
+
+@example
+mount : "mount" @var{<volname>} @i{list(}localinfo@i{)} ;
+
+localinfo : localinfo_attr @var{<string>} ;
+
+localinfo_attr
+ : "as"
+ | "from"
+ | "fstype"
+ | "opts"
+ ;
+@end example
+
+The filesystem specified to be mounted will be searched for in the
+dictionary of volume names built when scanning the list of hosts'
+definitions.
+
+The attributes have the following semantics:
+@table @samp
+@item from @var{machine}
+mount the filesystem from the machine with the hostname of
+@dfn{machine}.@refill
+
+@item as @var{mountpoint}
+mount the filesystem locally as the name given, in case this is
+different from the advertised volume name of the filesystem.
+
+@item opts @var{options}
+native @b{mount}(8) options.
+
+@item fstype @var{type}
+type of filesystem to be mounted.
+@end table
+
+An example:
+
+@example
+mount /export/exec/hp300/local as /usr/local
+@end example
+
+If the mountpoint specified is either @file{/} or @file{swap}, the
+machine will be considered to be booting off the net and this will be
+noted for use in generating a @file{bootparams} file for the host which
+owns the filesystems.
+
+@node FSinfo automount definitions, FSinfo Command Line Options, FSinfo static mounts, FSinfo
+@comment node-name, next, previous, up
+@section Defining an @i{Amd} Mount Map in @i{FSinfo}
+@cindex FSinfo automount definitions
+@cindex Defining an Amd mount map, FSinfo
+
+The maps used by @i{Amd} can be constructed from @i{FSinfo} by defining
+all the automount trees. @i{FSinfo} takes all the definitions found and
+builds one map for each top level tree.
+
+The automount tree is usually defined last. A single automount
+configuration will usually apply to an entire management domain. One
+@code{automount} declaration is needed for each @i{Amd} automount point.
+@i{FSinfo} determines whether the automount point is @dfn{direct}
+(@pxref{Direct Automount Filesystem}) or @dfn{indirect}
+(@pxref{Top-level Filesystem}). Direct automount points are
+distinguished by the fact that there is no underlying
+@dfn{automount_tree}.@refill
+
+@example
+automount : "automount" opt(auto_opts@i{)} automount_tree ;
+
+auto_opts : "opts" @var{<mount-options>} ;
+
+automount_tree
+ : @i{list(}automount_attr@i{)}
+ ;
+
+automount_attr
+ : @var{<string>} "=" @var{<volname>}
+ | @var{<string>} "->" @var{<symlink>}
+ | @var{<string>} "@{" automount_tree "@}"
+ ;
+@end example
+
+If @var{<mount-options>} is given, then it is the string to be placed in
+the maps for @i{Amd} for the @code{opts} option.
+
+A @dfn{map} is typically a tree of filesystems, for example @file{home}
+normally contains a tree of filesystems representing other machines in
+the network.
+
+A map can either be given as a name representing an already defined
+volume name, or it can be a tree. A tree is represented by placing
+braces after the name. For example, to define a tree @file{/vol}, the
+following map would be defined:
+
+@example
+automount /vol @{ @}
+@end example
+
+Within a tree, the only items that can appear are more maps.
+For example:
+
+@example
+automount /vol @{
+ andrew @{ @}
+ X11 @{ @}
+@}
+@end example
+
+In this case, @i{FSinfo} will look for volumes named @file{/vol/andrew}
+and @file{/vol/X11} and a map entry will be generated for each. If the
+volumes are defined more than once, then @i{FSinfo} will generate
+a series of alternate entries for them in the maps.@refill
+
+Instead of a tree, either a link (@var{name} @code{->}
+@var{destination}) or a reference can be specified (@var{name} @code{=}
+@var{destination}). A link creates a symbolic link to the string
+specified, without further processing the entry. A reference will
+examine the destination filesystem and optimise the reference. For
+example, to create an entry for @code{njw} in the @file{/homes} map,
+either of the two forms can be used:@refill
+
+@example
+automount /homes @{
+ njw -> /home/dylan/njw
+@}
+@end example
+
+or
+
+@example
+automount /homes @{
+ njw = /home/dylan/njw
+@}
+@end example
+
+In the first example, when @file{/homes/njw} is referenced from @i{Amd},
+a link will be created leading to @file{/home/dylan/njw} and the
+automounter will be referenced a second time to resolve this filename.
+The map entry would be:
+
+@example
+njw type:=link;fs:=/home/dylan/njw
+@end example
+
+In the second example, the destination directory is analysed and found
+to be in the filesystem @file{/home/dylan} which has previously been
+defined in the maps. Hence the map entry will look like:
+
+@example
+njw rhost:=dylan;rfs:=/home/dylan;sublink:=njw
+@end example
+
+Creating only one symbolic link, and one access to @i{Amd}.
+
+@c ---------------------------------------------
+@node FSinfo Command Line Options, FSinfo errors, FSinfo automount definitions, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} Command Line Options
+@cindex FSinfo command line options
+@cindex Command line options, FSinfo
+
+@i{FSinfo} is started from the command line by using the command:
+
+@example
+fsinfo [@i{options}] files ...
+@end example
+
+The input to @i{FSinfo} is a single set of definitions of machines and
+automount maps. If multiple files are given on the command-line, then
+the files are concatenated together to form the input source. The files
+are passed individually through the C pre-processor before being parsed.
+
+Several options define a prefix for the name of an output file. If the
+prefix is not specified no output of that type is produced. The suffix
+used will correspond either to the hostname to which a file belongs, or
+to the type of output if only one file is produced. Dumpsets and the
+@file{bootparams} file are in the latter class. To put the output into
+a subdirectory simply put a @file{/} at the end of the prefix, making
+sure that the directory has already been made before running
+@samp{fsinfo}.
+
+@menu
+* -a FSinfo Option:: Amd automount directory:
+* -b FSinfo Option:: Prefix for bootparams files.
+* -d FSinfo Option:: Prefix for dumpset data files.
+* -e FSinfo Option:: Prefix for exports files.
+* -f FSinfo Option:: Prefix for fstab files.
+* -h FSinfo Option:: Local hostname.
+* -m FSinfo Option:: Prefix for automount maps.
+* -q FSinfo Option:: Ultra quiet mode.
+* -v FSinfo Option:: Verbose mode.
+* -I FSinfo Option:: Define new #include directory.
+* -D-FSinfo Option:: Define macro.
+* -U FSinfo Option:: Undefine macro.
+@end menu
+
+@node -a FSinfo Option, -b FSinfo Option, FSinfo Command Line Options, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-a} @var{autodir}
+
+Specifies the directory name in which to place the automounter's
+mountpoints. This defaults to @file{/a}. Some sites have the autodir set
+to be @file{/amd}, and this would be achieved by:
+
+@example
+fsinfo -a /amd ...
+@end example
+
+@node -b FSinfo Option, -d FSinfo Option, -a FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-b} @var{bootparams}
+@cindex bootparams, FSinfo prefix
+
+This specifies the prefix for the @file{bootparams} filename. If it is
+not given, then the file will not be generated. The @file{bootparams}
+file will be constructed for the destination machine and will be placed
+into a file named @file{bootparams} and prefixed by this string. The
+file generated contains a list of entries describing each diskless
+client that can boot from the destination machine.
+
+As an example, to create a @file{bootparams} file in the directory
+@file{generic}, the following would be used:
+
+@example
+fsinfo -b generic/ ...
+@end example
+
+@node -d FSinfo Option, -e FSinfo Option, -b FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-d} @var{dumpsets}
+@cindex dumpset, FSinfo prefix
+
+This specifies the prefix for the @file{dumpsets} file. If it is not
+specified, then the file will not be generated. The file will be for
+the destination machine and will be placed into a filename
+@file{dumpsets}, prefixed by this string. The @file{dumpsets} file is
+for use by Imperial College's local backup system.
+
+For example, to create a dumpsets file in the directory @file{generic},
+then you would use the following:
+
+@example
+fsinfo -d generic/ ...
+@end example
+
+@node -e FSinfo Option, -f FSinfo Option, -d FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-e} @var{exportfs}
+@cindex exports, FSinfo prefix
+
+Defines the prefix for the @file{exports} files. If it is not given,
+then the file will not be generated. For each machine defined in the
+configuration files as having disks, an @file{exports} file is
+constructed and given a filename determined by the name of the machine,
+prefixed with this string. If a machine is defined as diskless, then no
+@file{exports} file will be created for it. The files contain entries
+for directories on the machine that may be exported to clients.
+
+Example: To create the @file{exports} files for each diskful machine
+and place them into the directory @file{exports}:
+
+@example
+fsinfo -e exports/ ...
+@end example
+
+@node -f FSinfo Option, -h FSinfo Option, -e FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-f} @var{fstab}
+@cindex fstab, FSinfo prefix
+
+This defines the prefix for the @file{fstab} files. The files will only
+be created if this prefix is defined. For each machine defined in the
+configuration files, a @file{fstab} file is created with the filename
+determined by prefixing this string with the name of the machine. These
+files contain entries for filesystems and partitions to mount at boot
+time.
+
+Example, to create the files in the directory @file{fstabs}:
+
+@example
+fsinfo -f fstabs/ ...
+@end example
+
+@node -h FSinfo Option, -m FSinfo Option, -f FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-h} @var{hostname}
+@cindex hostname, FSinfo command line option
+
+Defines the hostname of the destination machine to process for. If this
+is not specified, it defaults to the local machine name, as returned by
+@b{gethostname}(2).
+
+Example:
+
+@example
+fsinfo -h dylan.doc.ic.ac.uk ...
+@end example
+
+@node -m FSinfo Option, -q FSinfo Option, -h FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-m} @var{mount-maps}
+@cindex maps, FSinfo command line option
+
+Defines the prefix for the automounter files. The maps will only be
+produced if this prefix is defined. The mount maps suitable for the
+network defined by the configuration files will be placed into files
+with names calculated by prefixing this string to the name of each map.
+
+For example, to create the automounter maps and place them in the
+directory @file{automaps}:
+
+@example
+fsinfo -m automaps/ ...
+@end example
+
+@node -q FSinfo Option, -v FSinfo Option, -m FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-q}
+@cindex quiet, FSinfo command line option
+
+Selects quiet mode. @i{FSinfo} suppress the ``running commentary'' and
+only outputs any error messages which are generated.
+
+@node -v FSinfo Option, -D-FSinfo Option, -q FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-v}
+@cindex verbose, FSinfo command line option
+
+Selects verbose mode. When this is activated, the program will display
+more messages, and display all the information discovered when
+performing the semantic analysis phase. Each verbose message is output
+to @file{stdout} on a line starting with a @samp{#} character.
+
+@node -D-FSinfo Option, -I FSinfo Option, -v FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-D} @var{name[=defn]}
+
+Defines a symbol @dfn{name} for the preprocessor when reading the
+configuration files. Equivalent to @code{#define} directive.
+
+@node -I FSinfo Option, -U FSinfo Option, -D-FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-I} @var{directory}
+
+This option is passed into the preprocessor for the configuration files.
+It specifies directories in which to find include files
+
+@node -U FSinfo Option, , -I FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-U} @var{name}
+
+Removes any initial definition of the symbol @dfn{name}. Inverse of the
+@code{-D} option.
+
+@node FSinfo errors, , FSinfo command line options, FSinfo
+@comment node-name, next, previous, up
+@section Errors produced by @i{FSinfo}
+@cindex FSinfo error messages
+
+The following table documents the errors and warnings which @i{FSinfo} may produce.
+
+@table @t
+
+@item can't open @var{filename} for writing
+Occurs if any errors are encountered when opening an output file.@refill
+
+@item unknown host attribute
+Occurs if an unrecognised keyword is used when defining a host.@refill
+
+@item unknown filesystem attribute
+Occurs if an unrecognised keyword is used when defining a host's
+filesystems.@refill
+
+@item not allowed '/' in a directory name
+When reading the configuration input, if there is a filesystem
+definition which contains a pathname with multiple directories for any
+part of the mountpoint element, and it is not a single absolute path,
+then this message will be produced by the parser.@refill
+
+@item unknown directory attribute
+If an unknown keyword is found while reading the definition of a hosts's
+filesystem mount option.
+
+@item unknown mount attribute
+Occurs if an unrecognised keyword is found while parsing the list of
+static mounts.@refill
+
+@item " expected
+Occurs if an unescaped newline is found in a quoted string.
+
+@item unknown \ sequence
+Occurs if an unknown escape sequence is found inside a string. Within a
+string, you can give the standard C escape sequences for strings, such
+as newlines and tab characters.@refill
+
+@item @var{filename}: cannot open for reading
+If a file specified on the command line as containing configuration data
+could not be opened.@refill
+
+@item end of file within comment
+A comment was unterminated before the end of one of the configuration
+files.
+
+@item host field "@var{field-name}" already set
+If duplicate definitions are given for any of the fields with a host
+definition.
+
+@item duplicate host @var{hostname}!
+If a host has more than one definition.
+
+@item netif field @var{field-name} already set
+Occurs if you attempt to define an attribute of an interface more than
+once.
+
+@item malformed IP dotted quad: @var{address}
+If the Internet address of an interface is incorrectly specified. An
+Internet address definition is handled to @b{inet_addr}(3N) to see if it
+can cope. If not, then this message will be displayed.
+
+@item malformed netmask: @var{netmask}
+If the netmask cannot be decoded as though it were a hexadecimal number,
+then this message will be displayed. It will typically be caused by
+incorrect characters in the @var{netmask} value.@refill
+
+@item fs field "@var{field-name}" already set
+Occurs when multiple definitions are given for one of the attributes of a
+host's filesystem.
+
+@item mount tree field "@var{field-name}" already set
+Occurs when the @var{field-name} is defined more than once during the
+definition of a filesystems mountpoint.
+
+@item mount field "@var{field-name}" already set
+Occurs when a static mount has multiple definitions of the same field.
+
+@item no disk mounts on @var{hostname}
+If there are no static mounts, nor local disk mounts specified for a
+machine, this message will be displayed.
+
+@item @var{host}:@var{device} needs field "@var{field-name}"
+Occurs when a filesystem is missing a required field. @var{field-name} could
+be one of @code{fstype}, @code{opts}, @code{passno} or
+@code{mount}.@refill
+
+@item @var{filesystem} has a volname but no exportfs data
+Occurs when a volume name is declared for a file system, but the string
+specifying what machines the filesystem can be exported to is
+missing.
+
+@item sub-directory @var{directory} of @var{directory-tree} starts with '/'
+Within the filesystem specification for a host, if an element
+@var{directory} of the mountpoint begins with a @samp{/} and it is not
+the start of the tree.@refill
+
+@item @var{host}:@var{device} has no mount point
+Occurs if the @samp{mount} option is not specified for a host's
+filesystem.@refill
+
+@item @var{host}:@var{device} has more than one mount point
+Occurs if the mount option for a host's filesystem specifies multiple
+trees at which to place the mountpoint.@refill
+
+@item no volname given for @var{host}:@var{device}
+Occurs when a filesystem is defined to be mounted on @file{default}, but
+no volume name is given for the file system, then the mountpoint cannot
+be determined.@refill
+
+@item @var{host}:mount field specified for swap partition
+Occurs if a mountpoint is given for a filesystem whose type is declared
+to be @code{swap}.@refill
+
+@item ambiguous mount: @var{volume} is a replicated filesystem
+If several filesystems are declared as having the same volume name, they
+will be considered replicated filesystems. To mount a replicated
+filesystem statically, a specific host will need to be named, to say
+which particular copy to try and mount, else this error will
+result.@refill
+
+@item cannot determine localname since volname @var{volume} is not uniquely defined
+If a volume is replicated and an attempt is made to mount the filesystem
+statically without specifying a local mountpoint, @i{FSinfo} cannot
+calculate a mountpoint, as the desired pathname would be
+ambiguous.@refill
+
+@item volname @var{volume} is unknown
+Occurs if an attempt is made to mount or reference a volume name which
+has not been declared during the host filesystem definitions.@refill
+
+@item volname @var{volume} not exported from @var{machine}
+Occurs if you attempt to mount the volume @var{volume} from a machine
+which has not declared itself to have such a filesystem
+available.@refill
+
+@item network booting requires both root and swap areas
+Occurs if a machine has mount declarations for either the root partition
+or the swap area, but not both. You cannot define a machine to only
+partially boot via the network.@refill
+
+@item unknown volname @var{volume} automounted @i{[} on <name> @i{]}
+Occurs if @var{volume} is used in a definition of an automount map but the volume
+name has not been declared during the host filesystem definitions.@refill
+
+@item not allowed '/' in a directory name
+Occurs when a pathname with multiple directory elements is specified as
+the name for an automounter tree. A tree should only have one name at
+each level.
+
+@item @var{device} has duplicate exportfs data
+Produced if the @samp{exportfs} option is used multiple times within the
+same branch of a filesytem definition. For example, if you attempt to
+set the @samp{exportfs} data at different levels of the mountpoint
+directory tree.@refill
+
+@item sub-directory of @var{directory-tree} is named "default"
+@samp{default} is a keyword used to specify if a mountpoint should be
+automatically calculated by @i{FSinfo}. If you attempt to specify a
+directory name as this, it will use the filename of @file{default} but
+will produce this warning.@refill
+
+@item pass number for @var{host}:@var{device} is non-zero
+Occurs if @var{device} has its @samp{fstype} declared to be @samp{swap}
+or @samp{export} and the @b{fsck}(8) pass number is set. Swap devices should not be
+fsck'd. @xref{FSinfo filesystems fstype}@refill
+
+@item dump frequency for @var{host}:@var{device} is non-zero
+Occurs if @var{device} has its @samp{fstype} declared to be @samp{swap}
+or @samp{export} and the @samp{dump} option is set to a value greater
+than zero. Swap devices should not be dumped.@refill
+
+@end table
+
+@node Examples, Internals, FSinfo, Top
+@comment node-name, next, previous, up
+@chapter Examples
+
+@menu
+* User Filesystems::
+* Home Directories::
+* Architecture Sharing::
+* Wildcard names::
+* rwho servers::
+* /vol::
+@end menu
+
+@node User Filesystems, Home Directories, Examples, Examples
+@comment node-name, next, previous, up
+@section User Filesystems
+@cindex User filesystems
+@cindex Mounting user filesystems
+
+With more than one fileserver, the directories most frequently
+cross-mounted are those containing user home directories. A common
+convention used at Imperial College is to mount the user disks under
+@t{/home/}@i{machine}.
+
+Typically, the @samp{/etc/fstab} file contained a long list of entries
+such as:
+
+@example
+@i{machine}:/home/@i{machine} /home/@i{machine} nfs ...
+@end example
+
+for each fileserver on the network.
+
+There are numerous problems with this system. The mount list can become
+quite large and some of the machines may be down when a system is
+booted. When a new fileserver is installed, @samp{/etc/fstab} must be
+updated on every machine, the mount directory created and the filesystem
+mounted.
+
+In many environments most people use the same few workstations, but
+it is convenient to go to a colleague's machine and access your own
+files. When a server goes down, it can cause a process on a client
+machine to hang. By minimising the mounted filesystems to only include
+those actively being used, there is less chance that a filesystem will
+be mounted when a server goes down.
+
+The following is a short extract from a map taken from a research fileserver
+at Imperial College.
+
+Note the entry for @samp{localhost} which is used for users such as
+the operator (@samp{opr}) who have a home directory on most machine as
+@samp{/home/localhost/opr}.
+
+@example
+/defaults opts:=rw,intr,grpid,nosuid
+charm host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/xd0g
+#
+...
+
+#
+localhost type:=link;fs:=$@{host@}
+...
+#
+# dylan has two user disks so have a
+# top directory in which to mount them.
+#
+dylan type:=auto;fs:=$@{map@};pref:=$@{key@}/
+#
+dylan/dk2 host!=dylan;type:=nfs;rhost:=dylan;rfs:=/home/$@{key@} \
+ host==dylan;type:=ufs;dev:=/dev/dsk/2s0
+#
+dylan/dk5 host!=dylan;type:=nfs;rhost:=dylan;rfs:=/home/$@{key@} \
+ host==dylan;type:=ufs;dev:=/dev/dsk/5s0
+...
+#
+toytown host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/xy1g
+...
+#
+zebedee host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/dsk/1s0
+#
+# Just for access...
+#
+gould type:=auto;fs:=$@{map@};pref:=$@{key@}/
+gould/staff host!=gould;type:=nfs;rhost:=gould;rfs:=/home/$@{key@}
+#
+gummo host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@}
+...
+@end example
+
+This map is shared by most of the machines listed so on those
+systems any of the user disks is accessible via a consistent name.
+@i{Amd} is started with the following command
+
+@example
+amd /home amd.home
+@end example
+
+Note that when mounting a remote filesystem, the @dfn{automounted}
+mount point is referenced, so that the filesystem will be mounted if
+it is not yet (at the time the remote @samp{mountd} obtains the file handle).
+
+@node Home Directories, Architecture Sharing, User Filesystems, Examples
+@comment node-name, next, previous, up
+@section Home Directories
+@cindex Home directories
+@cindex Example of mounting home directories
+@cindex Mount home directories
+
+One convention for home directories is to locate them in @samp{/homes}
+so user @samp{jsp}'s home directory is @samp{/homes/jsp}. With more
+than a single fileserver it is convenient to spread user files across
+several machines. All that is required is a mount-map which converts
+login names to an automounted directory.
+
+Such a map might be started by the command:
+
+@example
+amd /homes amd.homes
+@end example
+
+where the map @samp{amd.homes} contained the entries:
+
+@example
+/defaults type:=link # All the entries are of type:=link
+jsp fs:=/home/charm/jsp
+njw fs:=/home/dylan/dk5/njw
+...
+phjk fs:=/home/toytown/ai/phjk
+sjv fs:=/home/ganymede/sjv
+@end example
+
+Whenever a login name is accessed in @samp{/homes} a symbolic link
+appears pointing to the real location of that user's home directory. In
+this example, @samp{/homes/jsp} would appear to be a symbolic link
+pointing to @samp{/home/charm/jsp}. Of course, @samp{/home} would also
+be an automount point.
+
+This system causes an extra level of symbolic links to be used.
+Although that turns out to be relatively inexpensive, an alternative is
+to directly mount the required filesystems in the @samp{/homes}
+map. The required map is simple, but long, and its creation is best automated.
+The entry for @samp{jsp} could be:
+
+@example
+jsp -sublink:=$@{key@};rfs:=/home/charm \
+ host==charm;type:=ufs;dev:=/dev/xd0g \
+ host!=charm;type:=nfs;rhost:=charm
+@end example
+
+This map can become quite big if it contains a large number of entries.
+By combining two other features of @i{Amd} it can be greatly simplified.
+
+First the UFS partitions should be mounted under the control of
+@samp{/etc/fstab}, taking care that they are mounted in the same place
+that @i{Amd} would have automounted them. In most cases this would be
+something like @samp{/a/@dfn{host}/home/@dfn{host}} and
+@samp{/etc/fstab} on host @samp{charm} would have a line:@refill
+
+@example
+/dev/xy0g /a/charm/home/charm 4.2 rw,nosuid,grpid 1 5
+@end example
+
+The map can then be changed to:
+
+@example
+/defaults type:=nfs;sublink:=$@{key@};opts:=rw,intr,nosuid,grpid
+jsp rhost:=charm;rfs:=/home/charm
+njw rhost:=dylan;rfs:=/home/dylan/dk5
+...
+phjk rhost:=toytown;rfs:=/home/toytown;sublink:=ai/$@{key@}
+sjv rhost:=ganymede;rfs:=/home/ganymede
+@end example
+
+This map operates as usual on a remote machine (@i{ie} @code{$@{host@}}
+not equal to @code{$@{rhost@}}). On the machine where the filesystem is
+stored (@i{ie} @code{$@{host@}} equal to @code{$@{rhost@}}), @i{Amd}
+will construct a local filesystem mount point which corresponds to the
+name of the locally mounted UFS partition. If @i{Amd} is started with
+the ``-r'' option then instead of attempting an NFS mount, @i{Amd} will
+simply inherit the UFS mount (@pxref{Inheritance Filesystem}). If
+``-r'' is not used then a loopback NFS mount will be made. This type of
+mount is known to cause a deadlock on many systems.
+
+@node Architecture Sharing, Wildcard Names, Home Directories, Examples
+@comment node-name, next, previous, up
+@section Architecture Sharing
+@cindex Architecture sharing
+@cindex Sharing a fileserver between architectures
+@cindex Architecture dependent volumes
+
+@c %At the moment some of the research machines have sets of software
+@c %mounted in @samp{/vol}. This contains subdirectories for \TeX,
+@c %system sources, local sources, prolog libraries and so on.
+Often a filesystem will be shared by machines of different architectures.
+Separate trees can be maintained for the executable images for each
+architecture, but it may be more convenient to have a shared tree,
+with distinct subdirectories.
+
+A shared tree might have the following structure on the fileserver (called
+@samp{fserver} in the example):
+
+@example
+local/tex
+local/tex/fonts
+local/tex/lib
+local/tex/bin
+local/tex/bin/sun3
+local/tex/bin/sun4
+local/tex/bin/hp9000
+...
+@end example
+
+In this example, the subdirectories of @samp{local/tex/bin} should be
+hidden when accessed via the automount point (conventionally @samp{/vol}).
+A mount-map for @samp{/vol} to achieve this would look like:
+
+@example
+/defaults sublink:=$@{/key@};rhost:=fserver;type:=link
+tex type:=auto;fs:=$@{map@};pref:=$@{key@}/
+tex/fonts host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host==fserver;fs:=/usr/local/tex
+tex/lib host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host==fserver;fs:=/usr/local/tex
+tex/bin -sublink:=$@{/key@}/$@{arch@} host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host:=fserver;fs:=/usr/local/tex
+@end example
+
+When @samp{/vol/tex/bin} is referenced, the current machine architecture
+is automatically appended to the path by the @code{$@{sublink@}}
+variable. This means that users can have @samp{/vol/tex/bin} in their
+@samp{PATH} without concern for architecture dependencies.
+
+@node Wildcard Names, rwho servers, Architecture Sharing, Examples
+@comment node-name, next, previous, up
+@section Wildcard names & Replicated Servers
+
+By using the wildcard facility, @i{Amd} can @dfn{overlay} an existing
+directory with additional entries.
+The system files are usually mounted under @samp{/usr}. If instead
+@i{Amd} is mounted on @samp{/usr}, additional
+names can be overlayed to augment or replace names in the ``master'' @samp{/usr}.
+A map to do this would have the form:
+
+@example
+local type:=auto;fs:=local-map
+share type:=auto;fs:=share-map
+* -type:=nfs;rfs:=/export/exec/$@{arch@};sublink:="$@{key@}" \
+ rhost:=fserv1 rhost:=fserv2 rhost:=fserv3
+@end example
+
+Note that the assignment to @code{$@{sublink@}} is surrounded by double
+quotes to prevent the incoming key from causing the map to be
+misinterpreted. This map has the effect of directing any access to
+@samp{/usr/local} or @samp{/usr/share} to another automount point.
+
+In this example, it is assumed that the @samp{/usr} files are replicated
+on three fileservers: @samp{fserv1}, @samp{fserv2} and @samp{fserv3}.
+For any references other than to @samp{local} and @samp{share} one of
+the servers is used and a symbolic link to
+@t{$@{autodir@}/$@{rhost@}/export/exec/$@{arch@}/@i{whatever}} is
+returned once an appropriate filesystem has been mounted.@refill
+
+@node rwho servers, /vol, Wildcard Names, Examples
+@comment node-name, next, previous, up
+@section @samp{rwho} servers
+@cindex rwho servers
+@cindex Architecture specific mounts
+@cindex Example of architecture specific mounts
+
+The @samp{/usr/spool/rwho} directory is a good candidate for automounting.
+For efficiency reasons it is best to capture the rwho data on a small
+number of machines and then mount that information onto a large number
+of clients. The data written into the rwho files is byte order dependent
+so only servers with the correct byte ordering can be used by a client:
+
+@example
+/defaults type:=nfs
+usr/spool/rwho -byte==little;rfs:=/usr/spool/rwho \
+ rhost:=vaxA rhost:=vaxB \
+ || -rfs:=/usr/spool/rwho \
+ rhost:=sun4 rhost:=hp300
+@end example
+
+@node /vol, , rwho servers, Examples
+@comment node-name, next, previous, up
+@section @samp{/vol}
+@cindex /vol
+@cindex Catch-all mount point
+@cindex Generic volume name
+
+@samp{/vol} is used as a catch-all for volumes which do not have other
+conventional names.
+
+Below is part of the @samp{/vol} map for the domain @samp{doc.ic.ac.uk}.
+The @samp{r+d} tree is used for new or experimental software that needs
+to be available everywhere without installing it on all the fileservers.
+Users wishing to try out the new software then simply include
+@samp{/vol/r+d/@{bin,ucb@}} in their path.@refill
+
+The main tree resides on one host @samp{gould.doc.ic.ac.uk}, which has
+different @samp{bin}, @samp{etc}, @samp{lib} and @samp{ucb}
+sub-directories for each machine architecture. For example,
+@samp{/vol/r+d/bin} for a Sun-4 would be stored in the sub-directory
+@samp{bin/sun4} of the filesystem @samp{/usr/r+d}. When it was accessed
+a symbolic link pointing to @samp{/a/gould/usr/r+d/bin/sun4} would be
+returned.@refill
+
+@example
+/defaults type:=nfs;opts:=rw,grpid,nosuid,intr,soft
+wp -opts:=rw,grpid,nosuid;rhost:=charm \
+ host==charm;type:=link;fs:=/usr/local/wp \
+ host!=charm;type:=nfs;rfs:=/vol/wp
+...
+#
+src -opts:=rw,grpid,nosuid;rhost:=charm \
+ host==charm;type:=link;fs:=/usr/src \
+ host!=charm;type:=nfs;rfs:=/vol/src
+#
+r+d type:=auto;fs:=$@{map@};pref:=r+d/
+# per architecture bin,etc,lib&ucb...
+r+d/bin rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/etc rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/include rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/lib rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/man rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/src rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/ucb rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+# hades pictures
+pictures -opts:=rw,grpid,nosuid;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/pictures \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=pictures
+# hades tools
+hades -opts:=rw,grpid,nosuid;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/hades \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=hades
+# bsd tools for hp.
+bsd -opts:=rw,grpid,nosuid;arch==hp9000;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/bsd \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=bsd
+@end example
+
+@node Internals, Acknowledgements & Trademarks, Examples, Top
+@comment node-name, next, previous, up
+@chapter Internals
+
+@menu
+* Log Messages::
+@end menu
+
+@node Log Messages, , Internals, Internals
+@comment node-name, next, previous, up
+@section Log Messages
+
+In the following sections a brief explanation is given of some of the
+log messages made by @i{Amd}. Where the message is in @samp{typewriter}
+font, it corresponds exactly to the message produced by @i{Amd}. Words
+in @dfn{italic} are replaced by an appropriate string. Variables,
+@code{$@{var@}}, indicate that the value of the appropriate variable is
+output.
+
+Log messages are either sent direct to a file,
+or logged via the @b{syslog}(3) mechanism.
+Messages are logged with facility @samp{LOG_DAEMON} when using @b{syslog}(3).
+In either case, entries in the file are of the form:
+@example
+@i{date-string} @i{hostname} @t{amd[}@i{pid}@t{]} @i{message}
+@end example
+
+@menu
+* Fatal errors::
+* Info messages::
+@end menu
+
+@node Fatal errors, Info messages, Log Messages, Log Messages
+@comment node-name, next, previous, up
+@subsection Fatal errors
+
+@i{Amd} attempts to deal with unusual events. Whenever it is not
+possible to deal with such an error, @i{Amd} will log an appropriate
+message and, if it cannot possibly continue, will either exit or abort.
+These messages are selected by @samp{-x fatal} on the command line.
+When @b{syslog}(3) is being used, they are logged with level
+@samp{LOG_FATAL}. Even if @i{Amd} continues to operate it is likely to
+remain in a precarious state and should be restarted at the earliest
+opportunity.
+
+@table @asis
+@item @t{Attempting to inherit not-a-filesystem}
+The prototype mount point created during a filesystem restart did not
+contain a reference to the restarted filesystem. This erorr ``should
+never happen''.
+
+@item @t{Can't bind to domain "@i{NIS-domain}"}
+A specific NIS domain was requested on the command line, but no server
+for that domain is available on the local net.
+
+@item @t{Can't determine IP address of this host (@i{hostname})}
+When @i{Amd} starts it determines its own IP address. If this lookup
+fails then @i{Amd} cannot continue. The hostname it looks up is that
+obtained returned by @b{gethostname}(2) system call.
+
+@item @t{Can't find root file handle for @i{automount point}}
+@i{Amd} creates its own file handles for the automount points. When it
+mounts itself as a server, it must pass these file handles to the local
+kernel. If the filehandle is not obtainable the mount point is ignored.
+This error ``should never happen''.
+
+@item @t{Must be root to mount filesystems (euid = @i{euid})}
+To prevent embarrassment, @i{Amd} makes sure it has appropriate system
+privileges. This amounts to having an euid of 0. The check is made
+after argument processing complete to give non-root users a chance to
+access the ``-v'' option.
+
+@item @t{No work to do - quitting}
+No automount points were given on the command line and so there is no
+work to do.
+
+@item @t{Out of memory in realloc}
+While attempting to realloc some memory, the memory space available to
+@i{Amd} was exhausted. This is an unrecoverable error.
+
+@item @t{Out of memory}
+While attempting to malloc some memory, the memory space available to
+@i{Amd} was exhausted. This is an unrecoverable error.
+
+@item @t{cannot create rpc/udp service}
+Either the NFS or AMQ endpoint could not be created.
+
+@item @t{gethostname:} @i{description}
+The @b{gethostname}(2) system call failed during startup.
+
+@item @t{host name is not set}
+The @b{gethostname}(2) system call returned a zero length host name.
+This can happen if @i{Amd} is started in single user mode just after
+booting the system.
+
+@item @t{ifs_match called!}
+An internal error occurred while restarting a pre-mounted filesystem.
+This error ``should never happen''.
+
+@item @t{mount_afs:} @i{description}
+An error occured while @i{Amd} was mounting itself.
+
+@item @t{run_rpc failed}
+Somehow the main NFS server loop failed. This error ``should never
+happen''.
+
+@item @t{unable to free rpc arguments in amqprog_1}
+The incoming arguments to the AMQ server could not be free'ed.
+
+@item @t{unable to free rpc arguments in nfs_program_1}
+The incoming arguments to the NFS server could not be free'ed.
+
+@item @t{unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)}
+The AMQ server could not be registered with the local portmapper or the
+internal RPC dispatcher.
+
+@item @t{unable to register (NFS_PROGRAM, NFS_VERSION, 0)}
+The NFS server could not be registered with the internal RPC dispatcher.
+
+@end table
+
+@node Info messages, , Fatal errors, Log Messages
+@comment node-name, next, previous, up
+@subsection Info messages
+
+@i{Amd} generates information messages to record state changes. These
+messages are selected by @samp{-x info} on the command line. When
+@b{syslog}(3) is being used, they are logged with level @samp{LOG_INFO}.
+
+The messages listed below can be generated and are in a format suitable
+for simple statistical analysis. @dfn{mount-info} is the string
+that is displayed by @dfn{Amq} in its mount information column and
+placed in the system mount table.
+
+@table @asis
+@item @t{mount of "@t{$@{@i{path}@}}" on @t{$@{@i{fs}@}} timed out}
+Attempts to mount a filesystem for the given automount point have failed
+to complete within 30 seconds.
+
+@item @t{"@t{$@{@i{path}@}}" forcibly timed out}
+An automount point has been timed out by the @i{Amq} command.
+
+@item @t{restarting @i{mount-info} on @t{$@{@i{fs}@}}}
+A pre-mounted file system has been noted.
+
+@item @t{"@t{$@{@i{path}@}}" has timed out}
+No access to the automount point has been made within the timeout
+period.
+
+@item @t{file server @t{$@{@i{rhost}@}} is down - timeout of "@t{$@{@i{path}@}}" ignored}
+An automount point has timed out, but the corresponding file server is
+known to be down. This message is only produced once for each mount
+point for which the server is down.
+
+@item @t{Re-synchronizing cache for map @t{$@{@i{map}@}}}
+The named map has been modified and the internal cache is being re-synchronized.
+
+@item @t{Filehandle denied for "@t{$@{@i{rhost}@}}:@t{$@{@i{rfs}@}}"}
+The mount daemon refused to return a file handle for the requested filesystem.
+
+@item @t{Filehandle error for "$@{@i{rhost}@}:$@{@i{rfs}@}":} @i{description}
+The mount daemon gave some other error for the requested filesystem.
+
+@item @t{file server @t{$@{@i{rhost}@}} type nfs starts up}
+A new NFS file server has been referenced and is known to be up.
+
+@item @t{file server @t{$@{@i{rhost}@}} type nfs starts down}
+A new NFS file server has been referenced and is known to be down.
+
+@item @t{file server @t{$@{@i{rhost}@}} type nfs is up}
+An NFS file server that was previously down is now up.
+
+@item @t{file server @t{$@{@i{rhost}@}} type nfs is down}
+An NFS file server that was previously up is now down.
+
+@item @t{Finishing with status @i{exit-status}}
+@i{Amd} is about to exit with the given exit status.
+
+@item @t{@i{mount-info} mounted fstype @t{$@{@i{type}@}} on @t{$@{@i{fs}@}}}
+A new file system has been mounted.
+
+@item @t{@i{mount-info} restarted fstype @t{$@{@i{type}@}} on @t{$@{@i{fs}@}}}
+@i{Amd} is using a pre-mounted filesystem to satisfy a mount request.
+
+@item @t{@i{mount-info} unmounted fstype @t{$@{@i{type}@}} from @t{$@{@i{fs}@}}}
+A file system has been unmounted.
+
+@item @t{@i{mount-info} unmounted fstype @t{$@{@i{type}@}} from @t{$@{@i{fs}@}} link @t{$@{@i{fs}@}}/@t{$@{@i{sublink}@}}}
+A file system of which only a sub-directory was in use has been unmounted.
+
+@end table
+
+@node Acknowledgements & Trademarks, Index, Internals, Top
+@comment node-name, next, previous, up
+@unnumbered Acknowledgements & Trademarks
+
+Thanks to the Formal Methods Group at Imperial College for
+suffering patiently while @i{Amd} was being developed on their machines.
+
+Thanks to the many people who have helped with the development of
+@i{Amd}, especially Piete Brooks at the Cambridge University Computing
+Lab for many hours of testing, experimentation and discussion.
+
+@itemize @bullet
+@item
+@b{DEC}, @b{VAX} and @b{Ultrix} are registered trademarks of Digital
+Equipment Corporation.
+@item
+@b{AIX} and @b{IBM} are registered trademarks of International Business
+Machines Corporation.
+@item
+@b{Sun}, @b{NFS} and @b{SunOS} are registered trademarks of Sun
+Microsystems, Inc.
+@item
+@b{Unix} is a registered trademark of AT&T Unix Systems Laboratories
+in the USA and other countries.
+@end itemize
+
+@node Index, Intro, Acknowledgements & Trademarks, Top
+@comment node-name, next, previous, up
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/usr.sbin/amd/doc/texinfo.tex b/usr.sbin/amd/doc/texinfo.tex
new file mode 100644
index 0000000..73528ed
--- /dev/null
+++ b/usr.sbin/amd/doc/texinfo.tex
@@ -0,0 +1,2192 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
+
+%GNU CC is free software; you can redistribute it and/or modify
+%it under the terms of the GNU General Public License as published by
+%the Free Software Foundation; either version 1, or (at your option)
+%any later version.
+
+%GNU CC is distributed in the hope that it will be useful,
+%but WITHOUT ANY WARRANTY; without even the implied warranty of
+%MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+%GNU General Public License for more details.
+
+%You should have received a copy of the GNU General Public License
+%along with GNU CC; see the file COPYING. If not, write to
+%the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{1.26}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+%---------------------Begin change-----------------------
+%
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+\outervsize=9.5in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+ {\let\hsize=\pagewidth \makefootline}}
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.
+% The argument can be delimited with [...] or with "..." or braces
+% or it can be a whole line.
+% #1 should be a macro which expects
+% an ordinary undelimited TeX argument.
+
+\def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx}
+
+\def\parseargx{%
+\ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else%
+\aftergroup \parseargline %
+\fi \endgroup}
+
+{\obeyspaces %
+\gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}}
+
+\gdef\obeyedspace{\ }
+
+\def\parseargline{\begingroup \obeylines \parsearglinex}
+{\obeylines %
+\gdef\parsearglinex #1^^M{\endgroup \next {#1}}}
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+%% @end foo executes the definition of \Efoo.
+%% foo can be delimited by doublequotes or brackets.
+
+\def\end{\parsearg\endxxx}
+
+\def\endxxx #1{%
+\expandafter\ifx\csname E#1\endcsname\relax
+\expandafter\ifx\csname #1\endcsname\relax
+\errmessage{Undefined command @end #1}\else
+\errorE{#1}\fi\fi
+\csname E#1\endcsname}
+\def\errorE#1{
+{\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}}
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\sf \char '100}}
+
+% Define @` and @' to be the same as ` and '
+% but suppressing ligatures.
+\def\`{{`}}
+\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break
+\def\w #1{\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page.
+
+\def\group{\begingroup% \inENV ???
+\def \Egroup{\egroup\endgroup}
+\vbox\bgroup}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+\def\exdent{\errmessage{@exdent in filled text}}
+ % @lisp, etc, define \exdent locally from \internalexdent
+
+{\obeyspaces
+\gdef\internalexdent{\parsearg\exdentzzz}}
+
+\def\exdentzzz #1{{\advance \leftskip by -\lispnarrowing
+\advance \hsize by -\leftskip
+\advance \hsize by -\rightskip
+\leftline{{\rm#1}}}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+\def\includezzz #1{{\def\thisfile{#1}\input #1
+}}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\parsearg \commentxxx}
+
+\def\commentxxx #1{}
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+}
+
+\def\ignore{\begingroup\ignoresections\ignorexxx}
+\long\def\ignorexxx #1\end ignore{\endgroup}
+
+% Conditionals to test whether a flag is set.
+
+\outer\def\ifset{\begingroup\ignoresections\parsearg\ifsetxxx}
+
+\def\ifsetxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\ifsetfail
+\else \let\temp=\relax \fi
+\temp}
+\def\Eifset{}
+\def\ifsetfail{\begingroup\ignoresections\ifsetfailxxx}
+\long\def\ifsetfailxxx #1\end ifset{\endgroup}
+
+\outer\def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx}
+
+\def\ifclearxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\relax
+\else \let\temp=\ifclearfail \fi
+\temp}
+\def\Eifclear{}
+\def\ifclearfail{\begingroup\ignoresections\ifclearfailxxx}
+\long\def\ifclearfailxxx #1\end ifclear{\endgroup}
+
+% Some texinfo constructs that are trivial in tex
+
+\def\iftex{}
+\def\Eiftex{}
+\def\ifinfo{\begingroup\ignoresections\ifinfoxxx}
+\long\def\ifinfoxxx #1\end ifinfo{\endgroup}
+\long\def\menu #1\end menu{}
+\def\asis#1{#1}
+
+\def\node{\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\losespace#3{}}, node `\losespace#1{}'}
+\def\losespace #1{#1}
+
+\message{fonts,}
+
+% Font-change commands.
+
+%% Try out Computer Modern fonts at \magstephalf
+\font\tenrm=cmr10 scaled \magstephalf
+\font\tentt=cmtt10 scaled \magstephalf
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\tenbf=cmb10 scaled \magstephalf
+\font\tenit=cmti10 scaled \magstephalf
+\font\tensl=cmsl10 scaled \magstephalf
+\font\tensf=cmss10 scaled \magstephalf
+\def\li{\sf}
+\font\tensc=cmcsc10 scaled \magstephalf
+
+% Fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\let\deftt=\tentt
+\def\df{\let\tt=\deftt \defbf}
+
+% Font for title
+\font\titlerm = cmbx10 scaled \magstep5
+
+% Fonts for indices
+\font\indit=cmti9 \font\indrm=cmr9
+\def\indbf{\indrm} \def\indsl{\indit}
+\def\indexfonts{\let\it=\indit \let\sl=\indsl \let\bf=\indbf \let\rm=\indrm}
+
+% Fonts for headings
+\font\chaprm=cmbx10 scaled \magstep3
+\font\chapit=cmti10 scaled \magstep3
+\font\chapsl=cmsl10 scaled \magstep3
+\font\chaptt=cmtt10 scaled \magstep3
+\font\chapsf=cmss10 scaled \magstep3
+\let\chapbf=\chaprm
+
+\font\secrm=cmbx10 scaled \magstep2
+\font\secit=cmti10 scaled \magstep2
+\font\secsl=cmsl10 scaled \magstep2
+\font\sectt=cmtt10 scaled \magstep2
+\font\secsf=cmss10 scaled \magstep2
+\let\secbf=\secrm
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an fontlooked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+\font\ssecrm=cmb10 at 13pt % Note the use of cmb rather than cmbx.
+\font\ssecit=cmti10 at 13pt % Also, the size is a little larger than
+\font\ssecsl=cmsl10 at 13pt % being scaled magstep1.
+\font\ssectt=cmtt10 at 13pt
+\font\ssecsf=cmss10 at 13pt
+
+\let\ssecbf=\ssecrm
+
+\def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf%
+\let\smallcaps=\tensc\let\sf=\tensf}
+\def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf}
+\def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf}
+\def\subsecfonts{\let\rm=\ssecrm\let\it=\ssecit\let\sl=\ssecsl\let\bf=\ssecbf\let\tt=\ssectt\let\sf=\ssecsf}
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Font for table of contents.
+\font\truesecrm=cmr12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+\def\i#1{{\sl #1}}
+\let\var=\i
+\let\dfn=\i
+\let\emph=\i
+\let\cite=\i
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+\def\t#1{{\tt \rawbackslash \frenchspacing #1}\null}
+\let\ttfont = \t
+\let\kbd=\t
+\let\code=\t
+\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\key #1{{\tt \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+\def\sc#1{{\\smallcaps #1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\def\titlefont#1{{\titlerm #1}}
+
+% Make altmode in file print out right
+
+\catcode `\^^[=\active \def^^[{$\diamondsuit$}
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\font\titlerm = cmbx12 scaled \magstep2
+\def\titlefont#1{{\titlerm #1}}
+
+\newtoks\realeverypar
+\newif\ifseenauthor
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \font\subtitlerm = cmr10 scaled \magstephalf
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 12pt \normalbaselines}%
+ %
+ \font\authorrm = cmbx12 scaled \magstep1
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % The first subtitle should have some space before it, but not the
+ % others. They all should be ragged left.
+% ??? This code turned off because (1) it is wrong for all old title
+% pages, and (2) it makes an extra group which never is ended.
+% \begingroup \realeverypar = {\leftskip = 2in plus 3em minus 1em
+% \parfillskip = 0pt}%
+% \everypar = {\vglue \baselineskip \the\realeverypar
+% \everypar={\the\realeverypar}}%
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ \vglue\titlepagetopglue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+% \def\page{\vskip4pt \hrule height 2pt \vskip\titlepagebottomglue
+% \oldpage \endgroup\hrule height0pt\relax}%
+ \def\page{\oldpage \hbox{}}}
+}
+
+\def\Etitlepage{\endgroup\page\HEADINGSon}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}}
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% Tables -- @table, @ftable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table and @ftable define @item, @itemx, etc., with these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}\itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}\itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+\advance \hsize by -\rightskip %
+\advance \hsize by -\leftskip %
+\setbox0=\hbox{\itemfont{#1}}%
+\itemindex{#1}%
+\parskip=0in %
+\noindent %
+\ifdim \wd0>\itemmax %
+\vadjust{\penalty 10000}%
+\hbox to \hsize{\hskip -\tableindent\box0\hss}\ %
+\else %
+\hbox to 0pt{\hskip -\tableindent\box0\hss}%
+\fi %
+\endgroup %
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{\itemizey {#1}{\Eitemize}}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\begingroup %
+\itemno = 0 %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+\def\enumerate{\itemizey{\the\itemno.}\Eenumerate\flushcr}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 300}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexnofonts{%
+\let\code=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{\tex %
+\catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+\catcode`\$=\other\catcode`\_=\other
+\catcode`\~=\other
+\def\indexbackslash{\rawbackslashxx}
+\indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+\begindoublecolumns
+\openin 1 \jobname.#1s
+\ifeof 1 \else \closein 1 \input \jobname.#1s
+\fi
+\enddoublecolumns
+\Etex}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\outer\def\initial #1{%
+{\let\tentt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty3000}}
+
+\outer\def\entry #1#2{
+{\parfillskip=0in \parskip=0in \parindent=0in
+\hangindent=1in \hangafter=1%
+\noindent\hbox{#1}\dotfill #2\par
+}}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\dotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXBook, page 416
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize \doublecolumnhsize = 3.11in
+\newdimen\doublecolumnvsize \doublecolumnvsize = 19.1in
+
+\def\begindoublecolumns{\begingroup
+ \output={\global\setbox\partialpage=\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject
+ \output={\doublecolumnout} \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize}
+\def\enddoublecolumns{\output={\balancecolumns}\eject
+ \endgroup \pagegoal=\vsize}
+
+\def\doublecolumnout{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+% changes it to set cropmarks (P. A. MacKay, 12 Nov. 1986)
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\balancecolumns{\setbox0=\vbox{\unvbox255} \dimen@=\ht0
+ \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip
+ {\vbadness=10000 \loop \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}
+ \setbox0=\vbox to\dimen@{\unvbox1} \setbox2=\vbox to\dimen@{\unvbox3}
+ \pagesofar}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno
+\newcount \subsecno
+\newcount \subsubsecno
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\outer\def\chapter{\parsearg\chapterzzz}
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}\gdef\thischapter{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+}
+
+\outer\def\appendix{\parsearg\appendixzzz}
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash chapentry {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+}
+
+\outer\def\unnumbered{\parsearg\unnumberedzzz}
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)}
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+}
+
+\outer\def\section{\parsearg\sectionzzz}
+\def\sectionzzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsection{\parsearg\appendixsectionzzz}
+\outer\def\appendixsec{\parsearg\appendixsectionzzz}
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedseczzz}
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\subsection{\parsearg\subsectionzzz}
+\def\subsectionzzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubseczzz}
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\subsubsection{\parsearg\subsubsectionzzz}
+\def\subsubsectionzzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsubsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubseczzz}
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% Define @majorheading, @heading and @subheading
+
+\def\majorheading #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading #1{\chapbreak %
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+\pchapsepmacro %
+{\chapfonts \line{\rm #2.\enspace #1\hfill}}\bigskip \par\penalty 5000 %
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \line{\rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \line{\rm#2.#3.#4\enspace #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \line{\rm#2.#3.#4.#5\enspace #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\def\startcontents#1{%
+ \ifnum \pageno>0
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ \unnumbchapmacro{#1}\def\thischapter{#1}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -1in % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts \let\rm = \truesecrm \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+\def\shortchapentry#1#2#3{%
+ \line{{#2\labelspace #1}\dotfill\doshortpageno{#3}}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{%
+ \line{#1\dotfill\doshortpageno{#2}}%
+}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \line{\chapentryfonts #1\dotfill \dopageno{#2}}%
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{%
+ \line{\secentryfonts \hskip\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsecentry#1#2{%
+ \line{\subsecentryfonts \hskip2\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsubsecentry#1#2{%
+ \line{\subsubsecentryfonts \hskip3\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \let\rm = \sf \sf}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode`\"=12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\def\@={@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Cause \obeyspaces to make each Space cause a word-separation
+% rather than the default which is that it acts punctuation.
+% This is because space in tt font looks funny.
+{\obeyspaces %
+\gdef\sepspaces{\def {\ }}}
+
+\newskip\aboveenvskipamount \aboveenvskipamount= 0pt
+\def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip
+\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}}
+
+\def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}
+
+\def\lisp{\aboveenvbreak\begingroup\inENV %This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Elisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \tt \rawbackslash
+\def\next##1{}\next}
+
+
+\let\example=\lisp
+\def\Eexample{\Elisp}
+
+\let\smallexample=\lisp
+\def\Esmallexample{\Elisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.
+% From Pavel@xerox. This is not really used unless the
+% @smallbook command is given.
+
+\def\smalllispx{\aboveenvbreak\begingroup\inENV
+% This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Esmalllisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \ninett \rawbackslash
+\def\next##1{}\next}
+
+% This is @display; same as @lisp except use roman font.
+
+\def\display{\begingroup\inENV %This group ends at the end of the @display body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Edisplay{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% This is @format; same as @lisp except use roman font and don't narrow margins
+
+\def\format{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Eformat{\endgroup\afterenvbreak}
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @flushleft and @flushright
+
+\def\flushleft{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushleft{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+\def\flushright{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushright{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\advance \leftskip by 0pt plus 1fill
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @quotation - narrow the margins.
+
+\def\quotation{\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+\advance \rightskip by \lispnarrowing
+\advance \leftskip by \lispnarrowing}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=36pt
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\tt\char`\[}} \def\rbrb{{\tt\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+\leftskip = 0in %
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}%
+\tolerance=10000 \hbadness=10000 % Make all lines underfull and no complaints
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl #1%
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\endgraf\vskip -\parskip \penalty 10000}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special form}%
+\defunargs {#2}\endgroup %
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Operation on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopparsebody\Edefcv\defcvx\defcvheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defmethparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\vskip -\parskip \penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defmethparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\defmethparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+% \xref and \pxref generate cross references to specified points.
+
+\def\pxref #1{see \xrefX [#1,,,,,,,]}
+\def\xref #1{See \xrefX [#1,,,,,,,]}
+\def\xrefX [#1,#2,#3,#4,#5,#6]{%
+\setbox1=\hbox{\i{\losespace#5{}}}%
+\setbox0=\hbox{\losespace#3{}}%
+\ifdim \wd0 =0pt \setbox0=\hbox{\losespace#1{}}\fi%
+\ifdim \wd1 >0pt%
+section \unhbox0{} in \unhbox1%
+\else%
+\refx{#1-snt} [\unhbox0], page\tie \refx{#1-pg}%
+\fi }
+
+% \dosetq is the interface for calls from other macros
+
+\def\dosetq #1#2{{\let\folio=0%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Define @refx to reference a specific cross-reference string.
+
+\def\refx#1{%
+{%
+\expandafter\ifx\csname X#1\endcsname\relax
+% If not defined, say something at least.
+\expandafter\gdef\csname X#1\endcsname {$<$undefined$>$}%
+\message {WARNING: Cross-reference "#1" used but not yet defined}%
+\message {}%
+\fi %
+\csname X#1\endcsname %It's defined, so just use it.
+}}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+\gdef\footnote{\global\advance \footnoteno by \@ne
+\edef\thisfootno{$^{\the\footnoteno}$}%
+\let\@sf\empty
+\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+\thisfootno\@sf\parsearg\footnotezzz}
+
+\gdef\footnotezzz #1{\insert\footins{
+\interlinepenalty\interfootnotelinepenalty
+\splittopskip\ht\strutbox % top baseline for broken footnotes
+\splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+\footstrut\hang\textindent{\thisfootno}#1\strut}}
+
+}%end \catcode `\@=11
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+\hsize = 6.5in
+\parindent 15pt
+\parskip 18pt plus 1pt
+\baselineskip 15pt
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Use @smallbook to reset parameters for 7x9.5 format
+\def\smallbook{
+\global\lispnarrowing = 0.3in
+\global\baselineskip 12pt
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+\global\font\ninett=cmtt9
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+%% For a final copy, take out the rectangles
+%% that mark overfull boxes (in case you have decided
+%% that the text looks ok even though it passes the margin).
+\def\finalout{\overfullrule=0pt}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary)
+% Define certain chars to be always in tt font.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+\catcode`\_=\active
+\def_{{\tt \char '137}}
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+{\catcode`\\=\other
+@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+@c \catcode 17=0 @c Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
diff --git a/usr.sbin/amd/fsinfo/Makefile b/usr.sbin/amd/fsinfo/Makefile
new file mode 100644
index 0000000..50f4642
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/Makefile
@@ -0,0 +1,30 @@
+# @(#)Makefile 8.1 (Berkeley) 6/28/93
+
+PROG= fsinfo
+MAN8= fsinfo.0
+SRCS= fsinfo.c fsi_gram.c fsi_lex.c \
+ fsi_util.c fsi_analyze.c fsi_dict.c \
+ wr_atab.c wr_bparam.c wr_dumpset.c \
+ wr_exportfs.c wr_fstab.c
+CLEANFILES= \
+ fsi_gram.c y.tab.c fsi_gram.h y.tab.h \
+ fsi_lex.c lex.yy.c y.output
+CFLAGS+=-I.
+CFLAGS+=-I${.CURDIR}/../include
+CFLAGS+=-I${.CURDIR}/../config
+CFLAGS+=-DOS_HDR=\"os-bsd44.h\"
+
+fsi_lex.o fsinfo.o: fsi_gram.h
+fsi_gram.c fsi_gram.h: ../fsinfo/fsi_gram.y
+ @echo "# expect 2 shift/reduce conflicts"
+ ${YACC} -d ${.CURDIR}/fsi_gram.y
+ mv y.tab.c fsi_gram.c
+ mv y.tab.h fsi_gram.h
+
+fsi_lex.c: ../fsinfo/fsi_lex.l
+ ${LEX} ${.CURDIR}/fsi_lex.l
+ mv lex.yy.c fsi_lex.c
+
+.PATH: ${.CURDIR}/../config
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/amd/fsinfo/conf/automounts b/usr.sbin/amd/fsinfo/conf/automounts
new file mode 100644
index 0000000..ee4b4ee
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/automounts
@@ -0,0 +1,48 @@
+host localhost.doc.ic.ac.uk
+
+fs localhost:/localhost {
+ fstype = export
+ mount default {
+ exportfs ""
+ volname /home/localhost
+ }
+}
+
+automount opts "opts:=rw,nosuid,grpid" /vol {
+ rwho {}
+ r+d {}
+ public {}
+ src { gnu{} athena{} gould{} utx{} sos4{} xinu43{} }
+ export {
+ exec {
+ sun3 {}
+ sun4 {}
+ }
+ roots {}
+ swaps {
+ tsun1 {} tsun2 {} tsun3 {} tsun4 {} tsun5 {} tsun6 {}
+ tsun7 {} tsun8 {} tsun9 {} tsun10 {} tsun11 {} tsun12 {}
+ tsun13 {} tsun14 {} tsun15 {} tsun16 {} tsun17 {} tsun18 {}
+ tsun19 {}
+ tcsun1 {} tcsun2 {} tcsun3 {} tcsun4 {} tcsun5 {}
+ }
+ misc {}
+ }
+}
+
+automount opts "opts:=rw,nosuid,grpid" /home {
+ achilles {}
+ toytown {}
+ gummo {}
+ dylan { dk2{} dk5 {} }
+ ganymede {}
+ gould { staff{} teach{} }
+ "localhost" -> localhost
+}
+
+automount opts "opts:=rw,nosuid,grpid" /homes {
+ opr -> /home/localhost/opr
+#include "users"
+}
+
+automount /usr/achilles = /home/achilles
diff --git a/usr.sbin/amd/fsinfo/conf/csg_sun3 b/usr.sbin/amd/fsinfo/conf/csg_sun3
new file mode 100644
index 0000000..7d75db2
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/csg_sun3
@@ -0,0 +1,18 @@
+// $Id$
+// standard setups for DoC tsuns.
+// note that no /var/spool/rwho is mounted as we now expect amd to do this as /vol/rwho
+
+// a sun3
+#ifndef SOS4_SYS_OPTS
+#define SOS4_SYS_OPTS grpid,hard,intr
+#endif
+#define CSG_SUN3(HOST,DOMAIN,BOOT,EXEC) \
+host HOST.DOMAIN \
+\
+mount /vol/export/roots/HOST as / from BOOT opts rw,SOS4_SYS_OPTS \
+mount /vol/export/swaps/HOST fstype swap as swap from BOOT opts swap \
+mount /vol/export/exec/sun3 as /usr from EXEC opts ro,SOS4_SYS_OPTS \
+mount /vol/export/misc/crash/HOST as /var/crash/HOST from EXEC opts rw,nosuid,SOS4_SYS_OPTS \
+mount /vol/export/misc/tmp/HOST as /tmp from EXEC opts rw,nosuid,SOS4_SYS_OPTS \
+mount /vol/export/misc/usr.tmp/HOST as /var/tmp from EXEC opts rw,nosuid,SOS4_SYS_OPTS \
+mount /var/mmdf from BOOT opts rw,nosuid,SOS4_SYS_OPTS
diff --git a/usr.sbin/amd/fsinfo/conf/csg_vax b/usr.sbin/amd/fsinfo/conf/csg_vax
new file mode 100644
index 0000000..0ef23a5
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/csg_vax
@@ -0,0 +1,67 @@
+// $Id$
+// csg vax config - really just for {s,r}vax
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw
+
+#define CSG_VAX(HOST,DOMAIN) \
+host HOST.DOMAIN\
+\
+/*\
+arch vax\
+os xinu43\
+cluster csg\
+dumphost flamingo.doc.ic.ac.uk\
+*/\
+\
+// root\
+fs /dev/hp0a {\
+ fstype = FSTYPE_UFS\
+ opts = DEFAULT_OPTS\
+ freq = 1\
+ passno = 1\
+ mount / {}\
+}\
+\
+// swap\
+fs /dev/hp0b {\
+ fstype = swap\
+}\
+\
+// usr\
+fs /dev/hp0e {\
+ fstype = FSTYPE_UFS\
+ opts = DEFAULT_OPTS\
+ freq = 1\
+ passno = 2\
+ mount /usr {\
+ exportfs "\\\
+ sky.doc.ic.ac.uk\\\
+ svax.doc.ic.ac.uk\\\
+ rvax.doc.ic.ac.uk\\\
+ ivax.doc.ic.ac.uk\\\
+ "\
+ }\
+}\
+\
+// var\
+fs /dev/hp0d {\
+ fstype = FSTYPE_UFS\
+ opts = DEFAULT_OPTS\
+ freq = 1\
+ passno = 3\
+ mount /var {}\
+}\
+\
+// home directories\
+fs /dev/hp0f {\
+ fstype = FSTYPE_UFS\
+ opts = DEFAULT_OPTS\
+ freq = 1\
+ passno = 3\
+ mount /a/HOST/home/HOST {\
+ exportfs "\\\
+ teach_hosts\\\
+ "\
+ }\
+} \ No newline at end of file
diff --git a/usr.sbin/amd/fsinfo/conf/diskless_sun3_sos4 b/usr.sbin/amd/fsinfo/conf/diskless_sun3_sos4
new file mode 100644
index 0000000..0cacb20
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/diskless_sun3_sos4
@@ -0,0 +1,9 @@
+#define DISKLESS_SUN3_SOS4(HOST,DOMAIN,BOOTSERVER) \
+host HOST.DOMAIN \
+\
+mount /export/root/HOST as / from BOOTSERVER opts rw,grpid,intr \
+mount /export/swap/HOST as swap fstype swap from BOOTSERVER opts swap \
+mount /export/exec/sun3 as /usr from BOOTSERVER opts rw,grpid,intr \
+mount /var/clients/HOST as /var from BOOTSERVER opts rw,grpid,intr,nosuid \
+mount /var/clients/HOST.tmp as /tmp from BOOTSERVER opts rw,grpid,intr,nosuid \
+mount /var/spool/mail from BOOTSERVER opts rw,grpid,intr,nosuid
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/achilles.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/achilles.doc.ic.ac.uk
new file mode 100644
index 0000000..6a46ce8
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/achilles.doc.ic.ac.uk
@@ -0,0 +1,116 @@
+// mkfsinfo
+
+host achilles.doc.ic.ac.uk
+
+/*
+arch sun4
+os sos4
+cluster theory
+dumphost achilles.doc.ic.ac.uk
+*/
+
+// SWAP Partitions
+fs /dev/xd0b {
+ fstype = swap
+}
+
+fs /dev/xd1b {
+ fstype = swap
+}
+
+// ROOT
+fs /dev/xd0a {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ passno = 1;
+ freq = 1;
+ mount / { }
+}
+
+// ROOT Backup
+fs /dev/xd1a {
+ fstype = ignore
+ opts = rw,noquota,grpid
+ passno = 1;
+ freq = 1;
+ mount /backup { }
+}
+
+fs /dev/xd1d {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ passno = 1;
+ freq = 1;
+ mount /export {
+ root {
+ truth { exportfs "-root=truth,access=truth" }
+ }
+ swap {
+ truth { exportfs "-root=truth,access=truth" }
+ }
+ exec {
+ sun4 { exportfs "-access=toytown_clients:hangers_on:gummo:harpo:opus,rw=dylan:truth:florence:toytown" }
+ }
+ }
+}
+
+fs /dev/xd1f {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ passno = 1;
+ freq = 1;
+ mount /var {
+ clients {
+ truth { exportfs "-root=truth,access=truth" }
+ truth.tmp { exportfs "-root=truth,access=truth" }
+ }
+ spool {
+ mail { exportfs "-root=truth,access=truth" }
+ rwho { exportfs "ro" volname /vol/rwho sel "byte==big" }
+ }
+ }
+}
+
+fs /dev/xd0d {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ passno = 1;
+ freq = 1;
+ mount /tmp {
+ X11NeWS { exportfs "-ro" }
+ }
+}
+
+fs /dev/xd0g {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ passno = 1
+ freq = 1
+ mount default {
+ exportfs "-access=toytown_clients:hangers_on"
+ volname /home/achilles
+ }
+}
+
+fs /dev/xd1g {
+ fstype = 4.2
+ opts = rw,noquota
+ passno = 1
+ freq = 1
+ mount /usr {
+ exportfs "-access=toytown_clients:hangers_on:gummo:harpo:opus,rw=dylan:truth:florence:toytown"
+ share {
+ volname "/usr/share"
+ //exportfs "blah"
+ }
+ src {
+ local {
+ //exportfs "-access=toytown:zebedee:dougal:dylan:florence:opus,rw=dylan:florence,root=dylan:florence"
+ bits { gnu { volname "/vol/src/gnu" } }
+ athena { volname "/vol/src/athena" }
+ }
+ }
+ }
+}
+
+/*mount /export/exec/sun3 fstype nfs from gould.doc.ic.ac.uk as /usr opts "rw"*/
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/bigears.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/bigears.doc.ic.ac.uk
new file mode 100644
index 0000000..bda2fd8
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/bigears.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../diskless_sun3_sos4"
+
+DISKLESS_SUN3_SOS4(bigears,doc.ic.ac.uk,toytown.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/dylan.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/dylan.doc.ic.ac.uk
new file mode 100644
index 0000000..5284147
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/dylan.doc.ic.ac.uk
@@ -0,0 +1,68 @@
+// mkfsinfo
+
+host dylan.doc.ic.ac.uk
+
+// SWAP
+fs /dev/dsk/0s0 {
+ fstype = swap
+}
+
+// SWAP
+fs /dev/dsk/1s0 {
+ fstype = swap
+}
+
+// ROOT
+fs /dev/dsk/0s0 {
+ fstype = hfs
+ opts = rw,noquota,grpid
+ passno = 0;
+ freq = 1;
+ mount / { }
+}
+
+fs /dev/dsk/1s0 {
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount /usr {
+ local {
+ exportfs "dougal eden dylan zebedee brian"
+ volname /nfs/hp300/local
+ }
+ }
+}
+
+fs /dev/dsk/2s0 {
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default {
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk2
+ }
+}
+
+fs /dev/dsk/3s0 {
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default {
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk3
+ }
+}
+
+fs /dev/dsk/5s0 {
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default {
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk5
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/flamingo.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/flamingo.doc.ic.ac.uk
new file mode 100644
index 0000000..31f1be0
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/flamingo.doc.ic.ac.uk
@@ -0,0 +1,104 @@
+// mkfsinfo for flamingo
+// $Id$
+
+host flamingo.doc.ic.ac.uk
+
+/*
+arch sun3
+os sos4
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw,noquota,nosuid,grpid
+
+// swap
+fs /dev/xy0b {
+ fstype = swap
+}
+
+// root
+fs /dev/xy0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ passno = 1
+ freq = 1
+ dumpset = csg_sun3_vax
+ mount / {}
+}
+
+// usr
+fs /dev/xy0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ dumpset = csg_sun3_vax
+ mount /usr {
+ volname /vol/export/exec/sun3
+ exportfs "-ro,access=teach_hosts:ssun2.doc.ic.ac.uk:pelican:gould,\
+ root=gould:pelican:ssun2.doc.ic.ac.uk"
+ }
+}
+
+// tmp
+fs /dev/xy0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS,nosuid
+ freq = 1
+ passno = 3
+ mount /tmp {
+ exportfs "-access=ssun1:tsunfs,root=tsunfs"
+ }
+}
+
+// var
+fs /dev/xy0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ dumpset = csg_sun3_vax
+ mount /var {
+ tmp {
+ exportfs "-access=ssun1:sky.doc.ic.ac.uk"
+ }
+ crash {
+ exportfs "-access=ssun1"
+ }
+ misc {
+ exportfs "-access=teach_hosts"
+ }
+ spool {
+ rwho {
+ volname /vol/rwho
+ exportfs "-ro,access=teach_hosts"
+ sel "byte==big"
+ }
+ }
+ }
+}
+
+// source - sos4
+fs /dev/xy0h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 6
+ mount /usr/src {
+ volname /vol/src/sos4
+ exportfs "-access=svax:pelican:gould,root=pelican:svax"
+ }
+}
+
+// home directories
+fs /dev/xy0g {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 5
+ mount /a/flamingo/home/flamingo {
+ exportfs "-access=teach_hosts:thp_hosts:ssun2:obsidian:truth,root=gould"
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/ganymede.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/ganymede.doc.ic.ac.uk
new file mode 100644
index 0000000..e847c85
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/ganymede.doc.ic.ac.uk
@@ -0,0 +1,33 @@
+host ganymede.doc.ic.ac.uk
+
+fs /dev/xy0a {
+ fstype = 4.2
+ opts = rw
+ freq = 1
+ passno = 1
+ mount / {
+ }
+}
+
+fs /dev/xy0g {
+ fstype = 4.2
+ opts = rw
+ freq = 1
+ passno = 2
+ mount /usr {
+ exportfs "-access=toytown:toytown_clients"
+ }
+}
+
+fs /dev/xy0h {
+ fstype = 4.2
+ opts = rw
+ freq = 1
+ passno = 3
+ mount /home/ganymede {
+ exportfs "-access=toytown_clients:samson:hangers_on"
+ }
+}
+
+mount /home/toytown opts rw,bg,nosuid
+mount /usr/local from toytown.doc.ic.ac.uk opts ro,bg
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/gould.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/gould.doc.ic.ac.uk
new file mode 100644
index 0000000..8804c8e
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/gould.doc.ic.ac.uk
@@ -0,0 +1,477 @@
+// mkfsinfo for gould
+// $Id$
+
+host gould.doc.ic.ac.uk
+
+/*
+arch powernode
+os utx21
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+#define FSTYPE_UFS 4.3
+#define DEFAULT_OPTS rw,noquota
+
+// swap
+fs /dev/dk0b {
+ fstype = swap
+}
+
+fs /dev/dk1b {
+ fstype = swap
+}
+
+fs /dev/dk4b {
+ fstype = swap
+}
+
+// root
+fs /dev/dk0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ passno = 1
+ freq = 1
+ dumpset = csg_nightly
+ mount / {}
+}
+
+// root backup
+fs /dev/dk4a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ mount /backup {}
+}
+
+// usr
+fs /dev/dk4d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ dumpset = csg_nightly
+ mount /usr {}
+}
+
+// tmp
+fs /dev/dk1a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS,nosuid
+ freq = 0
+ passno = 2
+ mount /tmp {}
+}
+
+// var
+fs /dev/dk4g {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ dumpset = csg_nightly
+ mount /var {}
+}
+
+// shared stuff - usually for Suns
+fs /dev/dk5f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 6
+ mount /usr/share {
+ exportfs "-rdonly=1 \
+ ivax.doc.ic.ac.uk \
+ rvax.doc.ic.ac.uk \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ svax.doc.ic.ac.uk \
+ tsun1.doc.ic.ac.uk \
+ tsun10.doc.ic.ac.uk \
+ tsun11.doc.ic.ac.uk \
+ tsun12.doc.ic.ac.uk \
+ tsun13.doc.ic.ac.uk \
+ tsun14.doc.ic.ac.uk \
+ tsun15.doc.ic.ac.uk \
+ tsun16.doc.ic.ac.uk \
+ tsun17.doc.ic.ac.uk \
+ tsun18.doc.ic.ac.uk \
+ tsun19.doc.ic.ac.uk \
+ tsun2.doc.ic.ac.uk \
+ tsun3.doc.ic.ac.uk \
+ tsun4.doc.ic.ac.uk \
+ tsun5.doc.ic.ac.uk \
+ tsun6.doc.ic.ac.uk \
+ tsun7.doc.ic.ac.uk \
+ tsun8.doc.ic.ac.uk \
+ tsun9.doc.ic.ac.uk \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ oriona \
+ sky.doc.ic.ac.uk \
+ whoops.doc.ic.ac.uk \
+ whoops \
+ "
+ }
+}
+
+// spool stuff, including the news
+fs /dev/dk4f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 5
+ mount /var/spool {
+ exportfs "\
+ oriona \
+ rpcsfg \
+ "
+ }
+}
+
+fs /dev/dk3h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /var/spool/News {}
+}
+
+// this is the public ftp area
+fs /dev/dk3f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ mount /usr/reserve {
+ PUBLIC {
+ volname /vol/public
+ exportfs "\
+ oriona \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ obsidian \
+ gummo \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ "
+ }
+ }
+}
+
+// sources - local and public
+fs /dev/dk7c {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ dumpset = csg_nightly
+ mount /usr/src {
+ volname /vol/src/gould
+ exportfs "\
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ oriona \
+ ssun1.doc.ic.ac.uk \
+ svax.doc.ic.ac.uk \
+ rvax.doc.ic.ac.uk \
+ obsidian \
+ tsunfs \
+ "
+ }
+}
+
+// sources - utx
+fs /dev/dk4e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 6
+ dumpset = csg_nightly
+ mount /usr/src/utx {
+ volname /vol/src/utx
+ exportfs "-rdonly=1 \
+ flamingo.doc.ic.ac.uk \
+ "
+ }
+}
+
+// home directories
+fs /dev/dk1h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ dumpset = csg_nightly
+ mount /home/gould/teach {
+ exportfs "\
+ thp1 \
+ thp2 \
+ thp3 \
+ thp4 \
+ thp5 \
+ thp6 \
+ thp7 \
+ thp8 \
+ thp9 \
+ thp10 \
+ thpfs \
+ ivax.doc.ic.ac.uk \
+ rvax.doc.ic.ac.uk \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ svax.doc.ic.ac.uk \
+ tsun1.doc.ic.ac.uk \
+ tsun10.doc.ic.ac.uk \
+ tsun11.doc.ic.ac.uk \
+ tsun12.doc.ic.ac.uk \
+ tsun13.doc.ic.ac.uk \
+ tsun14.doc.ic.ac.uk \
+ tsun15.doc.ic.ac.uk \
+ tsun16.doc.ic.ac.uk \
+ tsun17.doc.ic.ac.uk \
+ tsun18.doc.ic.ac.uk \
+ tsun19.doc.ic.ac.uk \
+ tsun2.doc.ic.ac.uk \
+ tsun3.doc.ic.ac.uk \
+ tsun4.doc.ic.ac.uk \
+ tsun5.doc.ic.ac.uk \
+ tsun6.doc.ic.ac.uk \
+ tsun7.doc.ic.ac.uk \
+ tsun8.doc.ic.ac.uk \
+ tsun9.doc.ic.ac.uk \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ oriona \
+ sky.doc.ic.ac.uk \
+ whoops.doc.ic.ac.uk \
+ whoops \
+ vlsi.doc.ic.ac.uk \
+ vlsi \
+ "
+ }
+}
+
+fs /dev/dk0h {
+ fstype = FSTYPE_UFS
+ opts = rw,quota
+ freq = 1
+ passno = 2
+ dumpset = csg_nightly
+ mount /home/gould/staff {
+ exportfs "\
+ achilles \
+ thp1 \
+ thp2 \
+ thp3 \
+ thp4 \
+ thp5 \
+ thp6 \
+ thp7 \
+ thp8 \
+ thp9 \
+ thp10 \
+ thpfs \
+ ivax.doc.ic.ac.uk \
+ rvax.doc.ic.ac.uk \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ svax.doc.ic.ac.uk \
+ tsun1.doc.ic.ac.uk \
+ tsun10.doc.ic.ac.uk \
+ tsun11.doc.ic.ac.uk \
+ tsun12.doc.ic.ac.uk \
+ tsun13.doc.ic.ac.uk \
+ tsun14.doc.ic.ac.uk \
+ tsun15.doc.ic.ac.uk \
+ tsun16.doc.ic.ac.uk \
+ tsun17.doc.ic.ac.uk \
+ tsun18.doc.ic.ac.uk \
+ tsun19.doc.ic.ac.uk \
+ tsun2.doc.ic.ac.uk \
+ tsun3.doc.ic.ac.uk \
+ tsun4.doc.ic.ac.uk \
+ tsun5.doc.ic.ac.uk \
+ tsun6.doc.ic.ac.uk \
+ tsun7.doc.ic.ac.uk \
+ tsun8.doc.ic.ac.uk \
+ tsun9.doc.ic.ac.uk \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ oriona \
+ sky.doc.ic.ac.uk \
+ whoops.doc.ic.ac.uk \
+ whoops \
+ vlsi.doc.ic.ac.uk \
+ vlsi \
+ vlsi02 \
+ "
+ }
+}
+
+// booting diskless suns
+fs /dev/dk5e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ dumpset = csg_nightly
+ mount /export {
+#ifndef ok
+ volname /vol/export
+#endif
+ exportfs "\
+ -rootid=0 \
+ whoops \
+ whoops.doc.ic.ac.uk \
+ "
+ misc {
+ volname /vol/export/misc
+ }
+ }
+}
+
+fs /dev/dk5a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ dumpset = csg_nightly
+ mount /export/roots {
+ volname /vol/export/roots
+ exportfs "\
+ -rootid=0 \
+ whoops \
+ whoops.doc.ic.ac.uk \
+ "
+ }
+}
+
+fs /dev/dk5d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 5
+ dumpset = csg_nightly
+ mount /export/exec/sun3 {
+ volname /vol/export/exec/sun3
+ exportfs "\
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ tsun1.doc.ic.ac.uk \
+ tsun10.doc.ic.ac.uk \
+ tsun11.doc.ic.ac.uk \
+ tsun12.doc.ic.ac.uk \
+ tsun13.doc.ic.ac.uk \
+ tsun14.doc.ic.ac.uk \
+ tsun15.doc.ic.ac.uk \
+ tsun16.doc.ic.ac.uk \
+ tsun17.doc.ic.ac.uk \
+ tsun18.doc.ic.ac.uk \
+ tsun19.doc.ic.ac.uk \
+ tsun2.doc.ic.ac.uk \
+ tsun3.doc.ic.ac.uk \
+ tsun4.doc.ic.ac.uk \
+ tsun5.doc.ic.ac.uk \
+ tsun6.doc.ic.ac.uk \
+ tsun7.doc.ic.ac.uk \
+ tsun8.doc.ic.ac.uk \
+ tsun9.doc.ic.ac.uk \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ whoops.doc.ic.ac.uk \
+ whoops \
+ "
+ }
+}
+
+// various r+d things - used for athena, etc
+fs /dev/dk5g {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr/r+d {
+ volname /vol/r+d
+ exportfs "\
+ ivax.doc.ic.ac.uk \
+ rvax.doc.ic.ac.uk \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ svax.doc.ic.ac.uk \
+ tsun1.doc.ic.ac.uk \
+ tsun10.doc.ic.ac.uk \
+ tsun11.doc.ic.ac.uk \
+ tsun12.doc.ic.ac.uk \
+ tsun13.doc.ic.ac.uk \
+ tsun14.doc.ic.ac.uk \
+ tsun15.doc.ic.ac.uk \
+ tsun16.doc.ic.ac.uk \
+ tsun17.doc.ic.ac.uk \
+ tsun18.doc.ic.ac.uk \
+ tsun19.doc.ic.ac.uk \
+ tsun2.doc.ic.ac.uk \
+ tsun3.doc.ic.ac.uk \
+ tsun4.doc.ic.ac.uk \
+ tsun5.doc.ic.ac.uk \
+ tsun6.doc.ic.ac.uk \
+ tsun7.doc.ic.ac.uk \
+ tsun8.doc.ic.ac.uk \
+ tsun9.doc.ic.ac.uk \
+ tsunfs.doc.ic.ac.uk \
+ flamingo.doc.ic.ac.uk \
+ pelican.doc.ic.ac.uk \
+ oriona \
+ sky.doc.ic.ac.uk \
+ whoops.doc.ic.ac.uk \
+ whoops \
+ "
+ }
+}
+
+fs /dev/dk3d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /usr/r+d/r1 {
+ exportfs "\
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ "
+ }
+}
+
+fs /dev/dk4h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 7
+ mount /usr/r+d/r2 {
+ exportfs "\
+ achilles \
+ gummo \
+ harpo \
+ oriona \
+ ssun1.doc.ic.ac.uk \
+ ssun2.doc.ic.ac.uk \
+ thpfs \
+ toytown \
+ obsidian \
+ "
+ }
+}
+
+// this bit of disc needs a name !
+fs /dev/dk5h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 7
+ mount /mnt2 {}
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/gummo.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/gummo.doc.ic.ac.uk
new file mode 100644
index 0000000..aae6a5d
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/gummo.doc.ic.ac.uk
@@ -0,0 +1,12 @@
+// mkfsinfo
+
+host gummo.doc.ic.ac.uk
+
+// ROOT
+fs /dev/xxx1 {
+ fstype = export
+ mount default {
+ exportfs ""
+ volname /home/gummo
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/ivax.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/ivax.doc.ic.ac.uk
new file mode 100644
index 0000000..c8fcb5d
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/ivax.doc.ic.ac.uk
@@ -0,0 +1,84 @@
+// $Id$
+// ivax
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw
+
+host {
+ config "NFS_SERVER=true"
+ config "NFS_CLIENT=true"
+ config "YP_SERVER=false"
+ config "YP_CLIENT=false"
+
+ arch = vax
+ os = xinu43
+ cluster = teach.doc.ic.ac.uk
+ netif il0 { hwaddr = "08:08:08:08:08:08" netmask = 0xfffffe00 inaddr = 129.31.80.36 }
+
+} ivax.doc.ic.ac.uk
+
+// root
+fs /dev/hp0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount / {}
+}
+
+// swap
+fs /dev/hp0b {
+ fstype = swap
+}
+
+// usr
+fs /dev/hp0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr {
+ exportfs "\
+ sky.doc.ic.ac.uk\
+ svax.doc.ic.ac.uk\
+ rvax.doc.ic.ac.uk\
+ ivax.doc.ic.ac.uk\
+ "
+ }
+}
+
+// var
+fs /dev/hp0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /var {}
+}
+
+// home directories
+fs /dev/hp0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount default {
+ volname /home/ivax
+ exportfs "\
+ sky.doc.ic.ac.uk\
+ "
+ }
+}
+
+// sources which are used by the gould for the infoserver
+fs /dev/hp2c {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /public {
+ exportfs "\
+ gould\
+ "
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/obsidian.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/obsidian.doc.ic.ac.uk
new file mode 100644
index 0000000..dd9f0f7
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/obsidian.doc.ic.ac.uk
@@ -0,0 +1,28 @@
+// $Id$
+// conf for obsidian
+
+#define FSTYPE_UFS hfs
+#define DEFAULT_OPTS rw
+
+host obsidian.doc.ic.ac.uk
+
+fs /dev/dsk/0s0 {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount / {}
+}
+
+fs /dev/dsk/1s0 {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount default {
+ volname /home/obsidian
+ exportfs "\
+ gould\
+ "
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/pelican.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/pelican.doc.ic.ac.uk
new file mode 100644
index 0000000..1ffd8d7
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/pelican.doc.ic.ac.uk
@@ -0,0 +1,208 @@
+// mkfsinfo for pelican
+// $Id$
+
+host pelican.doc.ic.ac.uk
+
+/*
+arch sun3
+os sos4
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw,noquota,nosuid,grpid
+
+// swap
+fs /dev/xd0b {
+ fstype = swap
+}
+
+// root
+fs /dev/xd0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ passno = 1
+ freq = 1
+ dumpset = csg_sun3_vax
+ mount / {
+ exportfs "-ro,access=tsunfs,root=tsunfs"
+ }
+}
+
+// usr
+fs /dev/xd0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ dumpset = csg_sun3_vax
+ mount /usr {
+ volname /vol/export/exec/sun3
+ exportfs "-ro,access=teach_hosts,root=gould:flamingo:tsunfs"
+ }
+}
+
+// tmp
+fs /dev/xd0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS,nosuid
+ freq = 1
+ passno = 3
+ mount /tmp {
+ exportfs "\
+ -access=\
+ flamingo:\
+ tsun16.doc.ic.ac.uk:\
+ tsun17.doc.ic.ac.uk:\
+ tsun18.doc.ic.ac.uk:\
+ tsun19.doc.ic.ac.uk"
+ }
+}
+
+// var
+fs /dev/xd0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ dumpset = csg_sun3_vax
+ mount /var {
+ misc {
+ // this is due to differences between tsunfs and pelican
+ volname /vol/export/misc
+ exportfs "\
+ -access=teach_hosts,\
+ root=\
+ tcsun1.doc.ic.ac.uk:\
+ tcsun2.doc.ic.ac.uk:\
+ tcsun3.doc.ic.ac.uk:\
+ tcsun4.doc.ic.ac.uk:\
+ tcsun5.doc.ic.ac.uk:\
+ tsun16.doc.ic.ac.uk:\
+ tsun17.doc.ic.ac.uk:\
+ tsun18.doc.ic.ac.uk:\
+ tsun19.doc.ic.ac.uk"
+ }
+ mmdf {
+ exportfs "\
+ -access=teach_hosts,\
+ root=\
+ tcsun1.doc.ic.ac.uk:\
+ tcsun2.doc.ic.ac.uk:\
+ tcsun3.doc.ic.ac.uk:\
+ tcsun4.doc.ic.ac.uk:\
+ tcsun5.doc.ic.ac.uk:\
+ tsun16.doc.ic.ac.uk:\
+ tsun17.doc.ic.ac.uk:\
+ tsun18.doc.ic.ac.uk:\
+ tsun19.doc.ic.ac.uk"
+ }
+ spool {
+ rwho {
+ volname /vol/rwho
+ exportfs "-ro,access=teach_hosts"
+ sel "byte==big"
+ }
+ }
+ }
+}
+
+// export for diskless clients
+fs /dev/xd0h {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 6
+ mount /export {
+ roots {
+ tcsun1 {
+ volname /vol/export/roots/tcsun1
+ exportfs "-root=tcsun1.doc.ic.ac.uk,access=tcsun1.doc.ic.ac.uk"
+ }
+ tcsun2 {
+ volname /vol/export/roots/tcsun2
+ exportfs "-root=tcsun2.doc.ic.ac.uk,access=tcsun2.doc.ic.ac.uk"
+ }
+ tcsun3 {
+ volname /vol/export/roots/tcsun3
+ exportfs "-root=tcsun3.doc.ic.ac.uk,access=tcsun3.doc.ic.ac.uk"
+ }
+ tcsun4 {
+ volname /vol/export/roots/tcsun4
+ exportfs "-root=tcsun4.doc.ic.ac.uk,access=tcsun4.doc.ic.ac.uk"
+ }
+ tcsun5 {
+ volname /vol/export/roots/tcsun5
+ exportfs "-root=tcsun5.doc.ic.ac.uk,access=tcsun5.doc.ic.ac.uk"
+ }
+
+ tsun16 {
+ volname /vol/export/roots/tsun16
+ exportfs "-root=tsun16.doc.ic.ac.uk,access=tsun16.doc.ic.ac.uk"
+ }
+ tsun17 {
+ volname /vol/export/roots/tsun17
+ exportfs "-root=tsun17.doc.ic.ac.uk,access=tsun17.doc.ic.ac.uk"
+ }
+ tsun18 {
+ volname /vol/export/roots/tsun18
+ exportfs "-root=tsun18.doc.ic.ac.uk,access=tsun18.doc.ic.ac.uk"
+ }
+ tsun19 {
+ volname /vol/export/roots/tsun19
+ exportfs "-root=tsun19.doc.ic.ac.uk,access=tsun19.doc.ic.ac.uk"
+ }
+ }
+ swaps {
+ tcsun1 {
+ volname /vol/export/swaps/tcsun1
+ exportfs "-root=tcsun1.doc.ic.ac.uk,access=tcsun1.doc.ic.ac.uk"
+ }
+ tcsun2 {
+ volname /vol/export/swaps/tcsun2
+ exportfs "-root=tcsun2.doc.ic.ac.uk,access=tcsun2.doc.ic.ac.uk"
+ }
+ tcsun3 {
+ volname /vol/export/swaps/tcsun3
+ exportfs "-root=tcsun3.doc.ic.ac.uk,access=tcsun3.doc.ic.ac.uk"
+ }
+ tcsun4 {
+ volname /vol/export/swaps/tcsun4
+ exportfs "-root=tcsun4.doc.ic.ac.uk,access=tcsun4.doc.ic.ac.uk"
+ }
+ tcsun5 {
+ volname /vol/export/swaps/tcsun5
+ exportfs "-root=tcsun5.doc.ic.ac.uk,access=tcsun5.doc.ic.ac.uk"
+ }
+ tsun16 {
+ volname /vol/export/swaps/tsun16
+ exportfs "-root=tsun16.doc.ic.ac.uk,access=tsun16.doc.ic.ac.uk"
+ }
+ tsun17 {
+ volname /vol/export/swaps/tsun17
+ exportfs "-root=tsun17.doc.ic.ac.uk,access=tsun17.doc.ic.ac.uk"
+ }
+ tsun18 {
+ volname /vol/export/swaps/tsun18
+ exportfs "-root=tsun18.doc.ic.ac.uk,access=tsun18.doc.ic.ac.uk"
+ }
+ tsun19 {
+ volname /vol/export/swaps/tsun19
+ exportfs "-root=tsun19.doc.ic.ac.uk,access=tsun19.doc.ic.ac.uk"
+ }
+ }
+ }
+}
+
+// home directories
+fs /dev/xd0g {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 5
+ mount default {
+ volname /home/pelican
+ exportfs "-access=teach_hosts:thp_hosts:ssun2:obsidian:truth,root=gould"
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/rvax.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/rvax.doc.ic.ac.uk
new file mode 100644
index 0000000..303d552
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/rvax.doc.ic.ac.uk
@@ -0,0 +1,66 @@
+// $Id$
+// rvax
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw
+
+host rvax.doc.ic.ac.uk
+
+/*
+arch vax
+os xinu43
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+// root
+fs /dev/hp0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount / {}
+}
+
+// swap
+fs /dev/hp0b {
+ fstype = swap
+}
+
+// usr
+fs /dev/hp0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr {
+ exportfs "\
+ sky.doc.ic.ac.uk\
+ svax.doc.ic.ac.uk\
+ rvax.doc.ic.ac.uk\
+ ivax.doc.ic.ac.uk\
+ "
+ }
+}
+
+// var
+fs /dev/hp0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /var {}
+}
+
+// home directories
+fs /dev/hp0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /a/rvax/home/rvax {
+ exportfs "\
+ teach_hosts\
+ "
+ }
+} \ No newline at end of file
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/sky.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/sky.doc.ic.ac.uk
new file mode 100644
index 0000000..7877659
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/sky.doc.ic.ac.uk
@@ -0,0 +1,79 @@
+// $Id$
+// sky
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw
+
+host sky.doc.ic.ac.uk
+
+/*
+arch vax
+os xinu43
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+// root
+fs /dev/hp0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount / {}
+}
+
+// swap
+fs /dev/hp0b {
+ fstype = swap
+}
+
+// usr
+fs /dev/hp0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr {
+ exportfs "\
+ sky.doc.ic.ac.uk\
+ svax.doc.ic.ac.uk\
+ rvax.doc.ic.ac.uk\
+ ivax.doc.ic.ac.uk\
+ "
+ }
+}
+
+// var
+fs /dev/hp0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /var {}
+}
+
+// home directories
+fs /dev/hp0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /a/sky/home/sky {}
+}
+
+// 4.3 sources
+fs /dev/hp1g {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr/src {
+ volname /vol/src/xinu43
+ exportfs "\
+ svax.doc.ic.ac.uk\
+ rvax.doc.ic.ac.uk\
+ sky.doc.ic.ac.uk\
+ ivax.doc.ic.ac.uk\
+ "
+ }
+} \ No newline at end of file
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/svax.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/svax.doc.ic.ac.uk
new file mode 100644
index 0000000..aa99fbf
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/svax.doc.ic.ac.uk
@@ -0,0 +1,66 @@
+// $Id$
+// svax
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw
+
+host svax.doc.ic.ac.uk
+
+/*
+arch vax
+os xinu43
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+// root
+fs /dev/hp0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 1
+ mount / {}
+}
+
+// swap
+fs /dev/hp0b {
+ fstype = swap
+}
+
+// usr
+fs /dev/hp0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 2
+ mount /usr {
+ exportfs "\
+ sky.doc.ic.ac.uk\
+ svax.doc.ic.ac.uk\
+ rvax.doc.ic.ac.uk\
+ ivax.doc.ic.ac.uk\
+ "
+ }
+}
+
+// var
+fs /dev/hp0d {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /var {}
+}
+
+// home directories
+fs /dev/hp0f {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 3
+ mount /a/svax/home/svax {
+ exportfs "\
+ teach_hosts\
+ "
+ }
+} \ No newline at end of file
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tcsun1.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tcsun1.doc.ic.ac.uk
new file mode 100644
index 0000000..1b10d84
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tcsun1.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tcsun1,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tcsun2.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tcsun2.doc.ic.ac.uk
new file mode 100644
index 0000000..933d2f4
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tcsun2.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tcsun2,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tcsun3.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tcsun3.doc.ic.ac.uk
new file mode 100644
index 0000000..ccef4d4
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tcsun3.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tcsun3,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tcsun4.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tcsun4.doc.ic.ac.uk
new file mode 100644
index 0000000..9de9a9a
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tcsun4.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tcsun4,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tcsun5.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tcsun5.doc.ic.ac.uk
new file mode 100644
index 0000000..7f268a0
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tcsun5.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tcsun5,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/toytown.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/toytown.doc.ic.ac.uk
new file mode 100644
index 0000000..7b27f16
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/toytown.doc.ic.ac.uk
@@ -0,0 +1,116 @@
+host toytown.doc.ic.ac.uk
+
+fs /dev/xy0a {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ freq = 25
+ passno = 1
+ mount / {
+ }
+}
+
+fs /dev/xy0g {
+ fstype = 4.2
+ opts = rw,noquota,grpid
+ freq = 25
+ passno = 2
+ mount /usr {
+ exportfs "-access=toytown_clients:hangers_on:pythagoras,ro"
+ sun3 { }
+ local { }
+ }
+}
+
+fs /dev/xy1g {
+ fstype = 4.2
+ opts = rw,grpid,nosuid
+ freq = 6
+ passno = 2
+ mount /home/toytown {
+ exportfs "-access=toytown_clients:hangers_on,root=achilles"
+ }
+}
+
+fs /dev/xy0f {
+ fstype = 4.2
+ opts = rw,noquota,grpid,nosuid
+ freq = 25
+ passno = 4
+ mount /var {
+ spool {
+ exportfs "-access=toytown_clients:hangers_on"
+ mail { }
+ rwho { volname /vol/rwho sel "byte==big" }
+/*
+ mail { exportfs "-access=toytown_clients:hangers_on" }
+ rwho { exportfs "ro" volname /vol/rwho sel "byte==big" }
+*/
+ }
+ clients {
+ archimedes { exportfs "-access=archimedes,root=archimedes" }
+ archimedes.tmp { exportfs "-access=archimedes,root=archimedes" }
+ aver { exportfs "-access=aver,root=aver" }
+ aver.tmp { exportfs "-access=aver,root=aver" }
+ bigears { exportfs "-access=bigears,root=bigears" }
+ bigears.tmp { exportfs "-access=bigears,root=bigears" }
+ diadem { exportfs "-access=diadem,root=diadem" }
+ diadem.tmp { exportfs "-access=diadem,root=diadem" }
+ montague { exportfs "-access=montague,root=montague" }
+ montague.tmp { exportfs "-access=montague,root=montague" }
+ noddy { exportfs "-access=noddy,root=noddy" }
+ noddy.tmp { exportfs "-access=noddy,root=noddy" }
+ pcplod { exportfs "-access=pcplod,root=pcplod" }
+ pcplod.tmp { exportfs "-access=pcplod,root=pcplod" }
+ samson { exportfs "-access=samson,root=samson" }
+ samson.tmp { exportfs "-access=samson,root=samson" }
+ turing { exportfs "-access=turing,root=turing" }
+ turing.tmp { exportfs "-access=turing,root=turing" }
+ }
+ }
+}
+
+fs /dev/xy0d {
+ fstype = 4.2
+ opts = rw,noquota,grpid,nosuid
+ freq = 25
+ passno = 3
+ mount /export {
+ exec {
+ sun3 { exportfs "-access=toytown_clients:hangers_on:pythagoras" }
+ }
+ root {
+ archimedes { exportfs "-access=archimedes,root=archimedes" }
+ aver { exportfs "-access=aver,root=aver" }
+ bigears { exportfs "-access=bigears,root=bigears" }
+ diadem { exportfs "-access=diadem,root=diadem" }
+ montague { exportfs "-access=montague,root=montague" }
+ noddy { exportfs "-access=noddy,root=noddy" }
+ pcplod { exportfs "-access=pcplod,root=pcplod" }
+ samson { exportfs "-access=samson,root=samson" }
+ turing { exportfs "-access=turing,root=turing" }
+ }
+ swap {
+ archimedes { exportfs "-access=archimedes,root=archimedes" }
+ aver { exportfs "-access=aver,root=aver" }
+ bigears { exportfs "-access=bigears,root=bigears" }
+ diadem { exportfs "-access=diadem,root=diadem" }
+ montague { exportfs "-access=montague,root=montague" }
+ noddy { exportfs "-access=noddy,root=noddy" }
+ pcplod { exportfs "-access=pcplod,root=pcplod" }
+ samson { exportfs "-access=samson,root=samson" }
+ turing { exportfs "-access=turing,root=turing" }
+ }
+ }
+}
+
+fs /dev/xy0b {
+ fstype = swap
+}
+
+fs /dev/xy1b {
+ fstype = swap
+}
+
+mount /home/ganymede opts rw,grpid,nosuid,bg,intr
+mount /home/achilles opts rw,grpid,nosuid,bg,intr
+mount /usr/src from achilles.doc.ic.ac.uk opts rw,grpid,nosuid,bg,intr
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/truth.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/truth.doc.ic.ac.uk
new file mode 100644
index 0000000..0139279
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/truth.doc.ic.ac.uk
@@ -0,0 +1,9 @@
+host truth.doc.ic.ac.uk
+
+mount /export/exec/sun4 from achilles.doc.ic.ac.uk as /usr opts "rw,grpid,intr"
+mount /export/root/truth from achilles.doc.ic.ac.uk as / opts "rw,grpid,intr"
+mount /export/swap/truth from achilles.doc.ic.ac.uk fstype swap as swap opts swap
+mount /var/clients/truth.tmp from achilles.doc.ic.ac.uk as /tmp opts "rw,nosuid,grpid,intr"
+mount /var/clients/truth from achilles.doc.ic.ac.uk as /var opts "rw,nosuid,grpid,intr"
+mount /var/spool/mail from achilles.doc.ic.ac.uk as /var/spool/mail opts "rw,nosuid,grpid,intr"
+mount /usr/src from achilles.doc.ic.ac.uk as /usr/src opts "rw,nosuid,grpid,intr,bg"
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun1.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun1.doc.ic.ac.uk
new file mode 100644
index 0000000..ff5016c
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun1.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun1,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun10.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun10.doc.ic.ac.uk
new file mode 100644
index 0000000..2496cdb
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun10.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun10,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun11.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun11.doc.ic.ac.uk
new file mode 100644
index 0000000..d6e7b9d
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun11.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun11,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun12.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun12.doc.ic.ac.uk
new file mode 100644
index 0000000..a8439bb
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun12.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun12,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun13.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun13.doc.ic.ac.uk
new file mode 100644
index 0000000..44e4956
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun13.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun13,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun14.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun14.doc.ic.ac.uk
new file mode 100644
index 0000000..66a5051
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun14.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun14,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun15.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun15.doc.ic.ac.uk
new file mode 100644
index 0000000..3246df3
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun15.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun15,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun16.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun16.doc.ic.ac.uk
new file mode 100644
index 0000000..4ab7bd0
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun16.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun16,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun17.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun17.doc.ic.ac.uk
new file mode 100644
index 0000000..11ef757
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun17.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun17,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun18.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun18.doc.ic.ac.uk
new file mode 100644
index 0000000..fbdf879
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun18.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun18,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun19.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun19.doc.ic.ac.uk
new file mode 100644
index 0000000..da9aba8
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun19.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun19,doc.ic.ac.uk,pelican.doc.ic.ac.uk,pelican.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun2.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun2.doc.ic.ac.uk
new file mode 100644
index 0000000..b6fca77
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun2.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun2,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun3.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun3.doc.ic.ac.uk
new file mode 100644
index 0000000..e40bd16
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun3.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun3,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun4.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun4.doc.ic.ac.uk
new file mode 100644
index 0000000..cd97358
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun4.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun4,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun5.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun5.doc.ic.ac.uk
new file mode 100644
index 0000000..3a8c7e2
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun5.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun5,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun6.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun6.doc.ic.ac.uk
new file mode 100644
index 0000000..4c6ea76
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun6.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun6,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun7.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun7.doc.ic.ac.uk
new file mode 100644
index 0000000..9df32a9
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun7.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun7,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun8.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun8.doc.ic.ac.uk
new file mode 100644
index 0000000..e2b5e1f
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun8.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun8,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsun9.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsun9.doc.ic.ac.uk
new file mode 100644
index 0000000..e82e815
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsun9.doc.ic.ac.uk
@@ -0,0 +1,3 @@
+#include "../csg_sun3"
+
+CSG_SUN3(tsun9,doc.ic.ac.uk,tsunfs.doc.ic.ac.uk,gould.doc.ic.ac.uk)
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/tsunfs.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/tsunfs.doc.ic.ac.uk
new file mode 100644
index 0000000..b09db9d
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/tsunfs.doc.ic.ac.uk
@@ -0,0 +1,211 @@
+// mkfsinfo for tsunfs
+// $Id$
+
+host tsunfs.doc.ic.ac.uk
+
+/*
+arch sun3
+os sos4
+cluster csg
+dumphost flamingo.doc.ic.ac.uk
+*/
+
+#define FSTYPE_UFS 4.2
+#define DEFAULT_OPTS rw,noquota,nosuid,grpid
+
+// swap
+fs /dev/xy0b {
+ fstype = swap
+}
+
+// root
+fs /dev/xy0a {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ passno = 1
+ freq = 1
+ dumpset = csg_sun3_vax
+ mount / {}
+}
+
+// usr
+fs /dev/xy0f {
+ fstype = FSTYPE_UFS
+ opts = rw,grpid
+ freq = 1
+ passno = 2
+ dumpset = csg_sun3_vax
+ mount /usr {}
+}
+
+// var
+fs /dev/xy0e {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 4
+ dumpset = csg_sun3_vax
+ mount /var {
+ mmdf {
+ exportfs "-access=teach_hosts,root=\
+ tsun1.doc.ic.ac.uk:\
+ tsun2.doc.ic.ac.uk:\
+ tsun3.doc.ic.ac.uk:\
+ tsun4.doc.ic.ac.uk:\
+ tsun5.doc.ic.ac.uk:\
+ tsun6.doc.ic.ac.uk:\
+ tsun7.doc.ic.ac.uk:\
+ tsun8.doc.ic.ac.uk:\
+ tsun9.doc.ic.ac.uk:\
+ tsun10.doc.ic.ac.uk:\
+ tsun11.doc.ic.ac.uk:\
+ tsun12.doc.ic.ac.uk:\
+ tsun13.doc.ic.ac.uk:\
+ tsun14.doc.ic.ac.uk:\
+ tsun15.doc.ic.ac.uk:\
+ ssun1.doc.ic.ac.uk:\
+ whoops.doc.ic.ac.uk:\
+ "
+ }
+ }
+}
+
+// root filesystems for diskless clients
+fs /dev/xy0d {
+ fstype = FSTYPE_UFS
+ opts = rw,grpid
+ freq = 1
+ passno = 3
+ mount /export/roots {
+ tsun1 {
+ volname /vol/export/roots/tsun1
+ exportfs "-root=tsun1.doc.ic.ac.uk,-access=tsun1.doc.ic.ac.uk"
+ }
+ tsun2 {
+ volname /vol/export/roots/tsun2
+ exportfs "-root=tsun2.doc.ic.ac.uk,-access=tsun2.doc.ic.ac.uk"
+ }
+ tsun3 {
+ volname /vol/export/roots/tsun3
+ exportfs "-root=tsun3.doc.ic.ac.uk,-access=tsun3.doc.ic.ac.uk"
+ }
+ tsun4 {
+ volname /vol/export/roots/tsun4
+ exportfs "-root=tsun4.doc.ic.ac.uk,-access=tsun4.doc.ic.ac.uk"
+ }
+ tsun5 {
+ volname /vol/export/roots/tsun5
+ exportfs "-root=tsun5.doc.ic.ac.uk,-access=tsun5.doc.ic.ac.uk"
+ }
+ tsun6 {
+ volname /vol/export/roots/tsun6
+ exportfs "-root=tsun6.doc.ic.ac.uk,-access=tsun6.doc.ic.ac.uk"
+ }
+ tsun7 {
+ volname /vol/export/roots/tsun7
+ exportfs "-root=tsun7.doc.ic.ac.uk,-access=tsun7.doc.ic.ac.uk"
+ }
+ tsun8 {
+ volname /vol/export/roots/tsun8
+ exportfs "-root=tsun8.doc.ic.ac.uk,-access=tsun8.doc.ic.ac.uk"
+ }
+ tsun9 {
+ volname /vol/export/roots/tsun9
+ exportfs "-root=tsun9.doc.ic.ac.uk,-access=tsun9.doc.ic.ac.uk"
+ }
+ tsun10 {
+ volname /vol/export/roots/tsun10
+ exportfs "-root=tsun10.doc.ic.ac.uk,-access=tsun10.doc.ic.ac.uk"
+ }
+ tsun11 {
+ volname /vol/export/roots/tsun11
+ exportfs "-root=tsun11.doc.ic.ac.uk,-access=tsun11.doc.ic.ac.uk"
+ }
+ tsun12 {
+ volname /vol/export/roots/tsun12
+ exportfs "-root=tsun12.doc.ic.ac.uk,-access=tsun12.doc.ic.ac.uk"
+ }
+ tsun13 {
+ volname /vol/export/roots/tsun13
+ exportfs "-root=tsun13.doc.ic.ac.uk,-access=tsun13.doc.ic.ac.uk"
+ }
+ tsun14 {
+ volname /vol/export/roots/tsun14
+ exportfs "-root=tsun14.doc.ic.ac.uk,-access=tsun14.doc.ic.ac.uk"
+ }
+ tsun15 {
+ volname /vol/export/roots/tsun15
+ exportfs "-root=tsun15.doc.ic.ac.uk,-access=tsun15.doc.ic.ac.uk"
+ }
+ }
+}
+
+// swap for diskless clients
+fs /dev/xy1c {
+ fstype = FSTYPE_UFS
+ opts = DEFAULT_OPTS
+ freq = 1
+ passno = 5
+ mount /export/swaps {
+ tsun1 {
+ volname /vol/export/swaps/tsun1
+ exportfs "-root=tsun1.doc.ic.ac.uk,-access=tsun1.doc.ic.ac.uk"
+ }
+ tsun2 {
+ volname /vol/export/swaps/tsun2
+ exportfs "-root=tsun2.doc.ic.ac.uk,-access=tsun2.doc.ic.ac.uk"
+ }
+ tsun3 {
+ volname /vol/export/swaps/tsun3
+ exportfs "-root=tsun3.doc.ic.ac.uk,-access=tsun3.doc.ic.ac.uk"
+ }
+ tsun4 {
+ volname /vol/export/swaps/tsun4
+ exportfs "-root=tsun4.doc.ic.ac.uk,-access=tsun4.doc.ic.ac.uk"
+ }
+ tsun5 {
+ volname /vol/export/swaps/tsun5
+ exportfs "-root=tsun5.doc.ic.ac.uk,-access=tsun5.doc.ic.ac.uk"
+ }
+ tsun6 {
+ volname /vol/export/swaps/tsun6
+ exportfs "-root=tsun6.doc.ic.ac.uk,-access=tsun6.doc.ic.ac.uk"
+ }
+ tsun7 {
+ volname /vol/export/swaps/tsun7
+ exportfs "-root=tsun7.doc.ic.ac.uk,-access=tsun7.doc.ic.ac.uk"
+ }
+ tsun8 {
+ volname /vol/export/swaps/tsun8
+ exportfs "-root=tsun8.doc.ic.ac.uk,-access=tsun8.doc.ic.ac.uk"
+ }
+ tsun9 {
+ volname /vol/export/swaps/tsun9
+ exportfs "-root=tsun9.doc.ic.ac.uk,-access=tsun9.doc.ic.ac.uk"
+ }
+ tsun10 {
+ volname /vol/export/swaps/tsun10
+ exportfs "-root=tsun10.doc.ic.ac.uk,-access=tsun10.doc.ic.ac.uk"
+ }
+ tsun11 {
+ volname /vol/export/swaps/tsun11
+ exportfs "-root=tsun11.doc.ic.ac.uk,-access=tsun11.doc.ic.ac.uk"
+ }
+ tsun12 {
+ volname /vol/export/swaps/tsun12
+ exportfs "-root=tsun12.doc.ic.ac.uk,-access=tsun12.doc.ic.ac.uk"
+ }
+ tsun13 {
+ volname /vol/export/swaps/tsun13
+ exportfs "-root=tsun13.doc.ic.ac.uk,-access=tsun13.doc.ic.ac.uk"
+ }
+ tsun14 {
+ volname /vol/export/swaps/tsun14
+ exportfs "-root=tsun14.doc.ic.ac.uk,-access=tsun14.doc.ic.ac.uk"
+ }
+ tsun15 {
+ volname /vol/export/swaps/tsun15
+ exportfs "-root=tsun15.doc.ic.ac.uk,-access=tsun15.doc.ic.ac.uk"
+ }
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/conf/hosts/whoops.doc.ic.ac.uk b/usr.sbin/amd/fsinfo/conf/hosts/whoops.doc.ic.ac.uk
new file mode 100644
index 0000000..831053b
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/hosts/whoops.doc.ic.ac.uk
@@ -0,0 +1,21 @@
+// $Id$
+// sm's bastardised csg_sun3
+// note that no /var/spool/rwho is mounted as we now expect amd to do this as /vol/rwho
+
+#define HOST whoops
+#define DOMAIN doc.ic.ac.uk
+#define BOOT gould.doc.ic.ac.uk
+#define EXEC gould.doc.ic.ac.uk
+#define MAIL tsunfs.doc.ic.ac.uk
+
+// a sun3
+host HOST.DOMAIN
+
+mount /vol/export/roots/HOST as / from BOOT opts rw,grpid,hard,intr
+mount /vol/export/swaps/HOST fstype swap as swap from BOOT opts swap
+mount /vol/export/exec/sun3 as /usr from EXEC opts ro,grpid,hard,intr
+mount /vol/export/misc/crash/HOST as /var/crash/HOST from EXEC opts rw,nosuid,grpid,hard,intr
+mount /vol/export/misc/tmp/HOST as /tmp from EXEC opts rw,nosuid,grpid,hard,intr
+mount /vol/export/misc/usr.tmp/HOST as /var/tmp from EXEC opts rw,nosuid,grpid,hard,intr
+mount /var/mmdf from MAIL opts rw,nosuid,grpid,hard,intr
+
diff --git a/usr.sbin/amd/fsinfo/conf/users b/usr.sbin/amd/fsinfo/conf/users
new file mode 100644
index 0000000..9dc83d9
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/conf/users
@@ -0,0 +1,106 @@
+audit -> /etc/security/audit
+bin -> /bin
+daemon -> /
+games -> /usr/games
+ingres -> /usr/ingres
+news -> /var/spool/news
+nobody -> /nonexistent
+root -> /
+sync -> /
+sys -> /
+sysdiag -> /usr/diag/sysdiag
+uucp -> /var/spool/uucppublic
+acwf = /home/toytown/others/acwf
+adh = /home/dylan/dk2/adh
+ae = /home/toytown/samson/ae
+aj = /home/toytown/samson/aj
+athena = /vol/src/athena
+bh = /home/toytown/jim/bh
+bp = /home/toytown/others/bp
+brg = /home/gummo/users/brg
+bt = /home/toytown/samson/bt
+ca = /home/toytown/diadem/ca
+ccm = /home/toytown/ai/ccm
+chlo = /home/toytown/samson/chlo
+clh = /home/toytown/ai/clh
+cr = /home/toytown/samson/cr
+cw = /home/toytown/genesis/cw
+dds = /home/toytown/genesis/dds
+dg = /home/toytown/dov/dg
+dgb = /home/dylan/dk2/dgb
+dme = /home/achilles/dme
+dp = /home/gummo/usersdiana
+ds = /home/toytown/ai/ds
+dwj = /home/achilles/dwj
+eaa = /home/toytown/dov/eaa
+esh = /home/toytown/ai/esh
+fcs = /home/ganymede/fcs
+fst = /home/dylan/dk2/fst
+glb = /home/toytown/ai/glb
+grace = /home/toytown/others/grace
+guest = /home/toytown/others/guest
+hd = /home/toytown/others/hd
+hf = /home/toytown/genesis/hf
+iccp = /home/toytown/samson/iccp
+ids = /home/toytown/samson/ids
+ih = /home/toytown/others/ih
+ja = /home/toytown/ai/ja
+jfc = /home/toytown/jim/jfc
+jg = /home/toytown/genesis/jg
+jjc = /home/toytown/genesis/jjc
+js = /home/toytown/samson/js
+jsp = /home/achilles/jsp
+jvp = /home/toytown/jim/jvp
+kdr = /home/dylan/dk2/kdr
+kevin = /home/toytown/others/kpt
+kpt = /home/toytown/others/kpt
+ksa = /home/toytown/ai/ksa
+lkcl = /home/dylan/dk2/lkcl
+ll = /home/toytown/dov/ll
+ll1 = /home/toytown/others/ll1
+lmjm = /home/toytown/others/lmjm
+lsh = /home/toytown/ai/lsh
+mb = /home/toytown/jim/mb
+md = /home/achilles/md
+mdr = /home/achilles/mdr
+mg = /home/ganymede/mg
+mjh = /home/toytown/others/mjh
+mrs = /home/achilles/mrs
+mwg = /home/achilles/mwg
+mwt = /home/achilles/mwt
+nd = /home/gummo/users/nd
+njw = /home/dylan/dk2/njw
+ok = /home/ganymede/ok
+pah = /home/toytown/jim/pah
+pdg = /home/toytown/samson/pdg
+phjk = /home/toytown/ai/phjk
+pm = /home/achilles/pm
+pm2 = /home/dylan/dk2/pm2
+ps = /home/toytown/genesis/ps
+pt = /home/toytown/dov/pt
+pvr = /home/toytown/jim/pvr
+rgc = /home/toytown/jim/rgc
+rjc = /home/toytown/jim/rjc
+rjq = /home/achilles/rjq
+sa = /home/toytown/samson/sa
+shb = /home/toytown/others/shb
+shc = /home/dylan/dk2/shc
+sjk = /home/toytown/jim/sjk
+sjl2 = /home/achilles/sjl2
+sjv = /home/ganymede/sjv
+sm = /home/toytown/others/sm
+sme = /home/ganymede/sme
+sph = /home/toytown/ai/sph
+ssp = /home/toytown/others/ssp
+sw = /home/toytown/others/sw
+sza = /home/ganymede/sza
+teb = /home/dylan/dk2/teb
+thp = /home/achilles/thp
+tm = /home/toytown/ai/tm
+tsem = /home/toytown/genesis/tsem
+umacd20 = /home/ganymede/umacd20
+wmvh = /home/dylan/dk2/wmvh
+wrdo = /home/ganymede/wrdo
+ygal = /home/toytown/samson/ygal
+zmact03 = /home/toytown/jim/zmact03
+zmacy26 = /home/toytown/jim/zmacy26
diff --git a/usr.sbin/amd/fsinfo/fsi_analyze.c b/usr.sbin/amd/fsinfo/fsi_analyze.c
new file mode 100644
index 0000000..d436a49
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_analyze.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsi_analyze.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsi_analyze.c,v 5.2.2.1 1992/02/09 15:09:41 jsp beta $
+ *
+ */
+
+/*
+ * Analyze filesystem declarations
+ *
+ * Note: most of this is magic!
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+char *disk_fs_strings[] = {
+ "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", 0,
+};
+
+char *mount_strings[] = {
+ "volname", "exportfs", 0,
+};
+
+char *fsmount_strings[] = {
+ "as", "volname", "fstype", "opts", "from", 0,
+};
+
+char *host_strings[] = {
+ "host", "netif", "config", "arch", "cluster", "os", 0,
+};
+
+char *ether_if_strings[] = {
+ "inaddr", "netmask", "hwaddr", 0,
+};
+
+/*
+ * Strip off the trailing part of a domain
+ * to produce a short-form domain relative
+ * to the local host domain.
+ * Note that this has no effect if the domain
+ * names do not have the same number of
+ * components. If that restriction proves
+ * to be a problem then the loop needs recoding
+ * to skip from right to left and do partial
+ * matches along the way -- ie more expensive.
+ */
+void domain_strip(otherdom, localdom)
+char *otherdom, *localdom;
+{
+#ifdef PARTIAL_DOMAINS
+ char *p1 = otherdom-1;
+ char *p2 = localdom-1;
+
+ do {
+ if (p1 = strchr(p1+1, '.'))
+ if (p2 = strchr(p2+1, '.'))
+ if (STREQ(p1+1, p2+1)) {
+ *p1 = '\0';
+ break;
+ }
+ } while (p1 && p2);
+#else
+ char *p1, *p2;
+
+ if ((p1 = strchr(otherdom, '.')) &&
+ (p2 = strchr(localdom, '.')) &&
+ (strcmp(p1+1, p2+1) == 0))
+ *p1 = '\0';
+#endif /* PARTIAL_DOMAINS */
+}
+
+/*
+ * Take a little-endian domain name and
+ * transform into a big-endian Un*x pathname.
+ * For example: kiska.doc.ic -> ic/doc/kiska
+ */
+static char *compute_hostpath(hn)
+char *hn;
+{
+ char *p = strdup(hn);
+ char *d;
+ char path[MAXPATHLEN];
+
+ domain_strip(p, hostname);
+ path[0] = '\0';
+
+ do {
+ d = strrchr(p, '.');
+ if (d) {
+ *d = 0;
+ strcat(path, d+1);
+ strcat(path, "/");
+ } else {
+ strcat(path, p);
+ }
+ } while (d);
+
+ log("hostpath of '%s' is '%s'", hn, path);
+
+ strcpy(p, path);
+ return p;
+}
+
+static dict_ent *find_volname(nn)
+char *nn;
+{
+ dict_ent *de;
+ char *p = strdup(nn);
+ char *q;
+
+ do {
+ log("Searching for volname %s", p);
+ de = dict_locate(dict_of_volnames, p);
+ q = strrchr(p, '/');
+ if (q) *q = '\0';
+ } while (!de && q);
+
+ free(p);
+ return de;
+}
+
+static show_required(l, mask, info, hostname, strings)
+ioloc *l;
+int mask;
+char *info;
+char *hostname;
+char *strings[];
+{
+ int i;
+ log("mask left for %s:%s is %#x", hostname, info, mask);
+
+ for (i = 0; strings[i]; i++)
+ if (ISSET(mask, i))
+ lerror(l, "%s:%s needs field \"%s\"", hostname, info, strings[i]);
+}
+
+/*
+ * Check and fill in "exportfs" details.
+ * Make sure the m_exported field references
+ * the most local node with an "exportfs" entry.
+ */
+static int check_exportfs(q, e)
+qelem *q;
+mount *e;
+{
+ mount *mp;
+ int errors = 0;
+
+ ITER(mp, mount, q) {
+ if (ISSET(mp->m_mask, DM_EXPORTFS)) {
+ if (e)
+ lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name);
+ mp->m_exported = mp;
+ if (!ISSET(mp->m_mask, DM_VOLNAME))
+ set_mount(mp, DM_VOLNAME, strdup(mp->m_name));
+ } else {
+ mp->m_exported = e;
+ }
+
+ /*
+ * Recursively descend the mount tree
+ */
+ if (mp->m_mount)
+ errors += check_exportfs(mp->m_mount, mp->m_exported);
+
+ /*
+ * If a volume name has been specified, but this node and none
+ * of its parents has been exported, report an error.
+ */
+ if (ISSET(mp->m_mask, DM_VOLNAME) && !mp->m_exported) {
+ lerror(mp->m_ioloc, "%s has a volname but no exportfs data", mp->m_name);
+ errors++;
+ }
+ }
+
+ return errors;
+}
+
+static int analyze_dkmount_tree(q, parent, dk)
+qelem *q;
+mount *parent;
+disk_fs *dk;
+{
+ mount *mp;
+ int errors = 0;
+
+ ITER(mp, mount, q) {
+ log("Mount %s:", mp->m_name);
+ if (parent) {
+ char n[MAXPATHLEN];
+ sprintf(n, "%s/%s", parent->m_name, mp->m_name);
+ if (*mp->m_name == '/')
+ lerror(mp->m_ioloc, "sub-directory %s of %s starts with '/'", mp->m_name, parent->m_name);
+ else if (STREQ(mp->m_name, "default"))
+ lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name);
+ log("Changing name %s to %s", mp->m_name, n);
+ free(mp->m_name);
+ mp->m_name = strdup(n);
+ }
+ mp->m_name_len = strlen(mp->m_name);
+ mp->m_parent = parent;
+ mp->m_dk = dk;
+ if (mp->m_mount)
+ analyze_dkmount_tree(mp->m_mount, mp, dk);
+ }
+
+ return errors;
+}
+
+/*
+ * The mount tree is a singleton list
+ * containing the top-level mount
+ * point for a disk.
+ */
+static int analyze_dkmounts(dk, q)
+disk_fs *dk;
+qelem *q;
+{
+ int errors = 0;
+ mount *mp, *mp2 = 0;
+ int i = 0;
+
+ /*
+ * First scan the list of subdirs to make
+ * sure there is only one - and remember it
+ */
+ if (q) {
+ ITER(mp, mount, q) {
+ mp2 = mp;
+ i++;
+ }
+ }
+
+ /*
+ * Check...
+ */
+ if (i < 1) {
+ lerror(dk->d_ioloc, "%s:%s has no mount point", dk->d_host->h_hostname, dk->d_dev);
+ return 1;
+ }
+ if (i > 1) {
+ lerror(dk->d_ioloc, "%s:%s has more than one mount point", dk->d_host->h_hostname, dk->d_dev);
+ errors++;
+ }
+ /*
+ * Now see if a default mount point is required
+ */
+ if (STREQ(mp2->m_name, "default")) {
+ if (ISSET(mp2->m_mask, DM_VOLNAME)) {
+ char nbuf[1024];
+ compute_automount_point(nbuf, dk->d_host, mp2->m_volname);
+ free(mp2->m_name);
+ mp2->m_name = strdup(nbuf);
+ log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
+ } else {
+ lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev);
+ errors++;
+ }
+ }
+ /*
+ * Fill in the disk mount point
+ */
+ if (!errors && mp2 && mp2->m_name)
+ dk->d_mountpt = strdup(mp2->m_name);
+ else
+ dk->d_mountpt = strdup("error");
+
+ /*
+ * Analyze the mount tree
+ */
+ errors += analyze_dkmount_tree(q, 0, dk);
+
+ /*
+ * Analyze the export tree
+ */
+ errors += check_exportfs(q, 0);
+
+ return errors;
+}
+
+static void fixup_required_disk_info(dp)
+disk_fs *dp;
+{
+ /*
+ * "fstype"
+ */
+ if (ISSET(dp->d_mask, DF_FSTYPE)) {
+ if (STREQ(dp->d_fstype, "swap")) {
+ /*
+ * Fixup for a swap device
+ */
+ if (!ISSET(dp->d_mask, DF_PASSNO)) {
+ dp->d_passno = 0;
+ BITSET(dp->d_mask, DF_PASSNO);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "Pass number for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "freq"
+ */
+ if (!ISSET(dp->d_mask, DF_FREQ)) {
+ dp->d_freq = 0;
+ BITSET(dp->d_mask, DF_FREQ);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "dump frequency for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "opts"
+ */
+ if (!ISSET(dp->d_mask, DF_OPTS))
+ set_disk_fs(dp, DF_OPTS, strdup("swap"));
+
+ /*
+ * "mount"
+ */
+ if (!ISSET(dp->d_mask, DF_MOUNT)) {
+ qelem *q = new_que();
+ mount *m = new_mount();
+ m->m_name = strdup("swap");
+ m->m_mount = new_que();
+ ins_que(&m->m_q, q->q_back);
+ dp->d_mount = q;
+ BITSET(dp->d_mask, DF_MOUNT);
+ } else {
+ lerror(dp->d_ioloc, "%s: mount field specified for swap partition", dp->d_host->h_hostname);
+ }
+ } else if (STREQ(dp->d_fstype, "export")) {
+ /*
+ * "passno"
+ */
+ if (!ISSET(dp->d_mask, DF_PASSNO)) {
+ dp->d_passno = 0;
+ BITSET(dp->d_mask, DF_PASSNO);
+ } else if (dp->d_passno != 0) {
+ lwarning(dp->d_ioloc,
+ "pass number for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "freq"
+ */
+ if (!ISSET(dp->d_mask, DF_FREQ)) {
+ dp->d_freq = 0;
+ BITSET(dp->d_mask, DF_FREQ);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "dump frequency for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "opts"
+ */
+ if (!ISSET(dp->d_mask, DF_OPTS))
+ set_disk_fs(dp, DF_OPTS, strdup("rw,defaults"));
+
+ }
+ }
+}
+
+static void fixup_required_mount_info(fp, de)
+fsmount *fp;
+dict_ent *de;
+{
+ if (!ISSET(fp->f_mask, FM_FROM)) {
+ if (de->de_count != 1) {
+ lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname);
+ } else {
+ dict_data *dd;
+ mount *mp = 0;
+ ITER(dd, dict_data, &de->de_q) {
+ mp = (mount *) dd->dd_data;
+ break;
+ }
+ if (!mp)
+ abort();
+ fp->f_ref = mp;
+ set_fsmount(fp, FM_FROM, mp->m_dk->d_host->h_hostname);
+ log("set: %s comes from %s", fp->f_volname, fp->f_from);
+ }
+ }
+
+ if (!ISSET(fp->f_mask, FM_FSTYPE)) {
+ set_fsmount(fp, FM_FSTYPE, strdup("nfs"));
+ log("set: fstype is %s", fp->f_fstype);
+ }
+
+ if (!ISSET(fp->f_mask, FM_OPTS)) {
+ set_fsmount(fp, FM_OPTS, strdup("rw,nosuid,grpid,defaults"));
+ log("set: opts are %s", fp->f_opts);
+ }
+
+ if (!ISSET(fp->f_mask, FM_LOCALNAME)) {
+ if (fp->f_ref) {
+ set_fsmount(fp, FM_LOCALNAME, strdup(fp->f_volname));
+ log("set: localname is %s", fp->f_localname);
+ } else {
+ lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname);
+ }
+ }
+}
+
+/*
+ * For each disk on a host
+ * analyze the mount information
+ * and fill in any derivable
+ * details.
+ */
+static void analyze_drives(hp)
+host *hp;
+{
+ qelem *q = hp->h_disk_fs;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ int req;
+ log("Disk %s:", dp->d_dev);
+ dp->d_host = hp;
+ fixup_required_disk_info(dp);
+ req = ~dp->d_mask & DF_REQUIRED;
+ if (req)
+ show_required(dp->d_ioloc, req, dp->d_dev, hp->h_hostname, disk_fs_strings);
+ analyze_dkmounts(dp, dp->d_mount);
+ }
+}
+
+/*
+ * Check that all static mounts make sense and
+ * that the source volumes exist.
+ */
+static void analyze_mounts(hp)
+host *hp;
+{
+ qelem *q = hp->h_mount;
+ fsmount *fp;
+ int netbootp = 0;
+
+ ITER(fp, fsmount, q) {
+ char *p;
+ char *nn = strdup(fp->f_volname);
+ int req;
+ dict_ent *de;
+ int found = 0;
+ int matched = 0;
+ do {
+ p = 0;
+ de = find_volname(nn);
+ log("Mount: %s (trying %s)", fp->f_volname, nn);
+
+ if (de) {
+ found = 1;
+ /*
+ * Check that the from field is really exporting
+ * the filesystem requested.
+ */
+ if (ISSET(fp->f_mask, FM_FROM)) {
+ dict_data *dd;
+ mount *mp2 = 0;
+ ITER(dd, dict_data, &de->de_q) {
+ mount *mp = (mount *) dd->dd_data;
+ if (STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
+ mp2 = mp;
+ break;
+ }
+ }
+
+ if (mp2) {
+ fp->f_ref = mp2;
+ matched = 1;
+ break;
+ }
+ } else {
+ matched = 1;
+ break;
+ }
+ }
+ p = strrchr(nn, '/');
+ if (p)
+ *p = 0;
+ } while (de && p);
+ free(nn);
+
+ if (!found) {
+ lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname);
+ } else if (matched) {
+ fixup_required_mount_info(fp, de);
+ req = ~fp->f_mask & FM_REQUIRED;
+ if (req) {
+ show_required(fp->f_ioloc, req, fp->f_volname, hp->h_hostname,
+ fsmount_strings);
+ } else if (strcmp(fp->f_localname, "/") == 0) {
+ hp->h_netroot = fp;
+ netbootp |= FM_NETROOT;
+ } else if (strcmp(fp->f_localname, "swap") == 0) {
+ hp->h_netswap = fp;
+ netbootp |= FM_NETSWAP;
+ }
+ } else {
+ lerror(fp->f_ioloc, "volname %s not exported from %s", fp->f_volname,
+ fp->f_from ? fp->f_from : "anywhere");
+ }
+ }
+
+ if (netbootp && (netbootp != FM_NETBOOT))
+ lerror(hp->h_ioloc, "network booting requires both root and swap areas");
+}
+
+void analyze_hosts(q)
+qelem *q;
+{
+ host *hp;
+
+ show_area_being_processed("analyze hosts", 5);
+
+ /*
+ * Check all drives
+ */
+ ITER(hp, host, q) {
+ log("disks on host %s", hp->h_hostname);
+ show_new("ana-host");
+ hp->h_hostpath = compute_hostpath(hp->h_hostname);
+
+ if (hp->h_disk_fs)
+ analyze_drives(hp);
+
+ }
+
+ show_area_being_processed("analyze mounts", 5);
+
+ /*
+ * Check static mounts
+ */
+ ITER(hp, host, q) {
+ log("mounts on host %s", hp->h_hostname);
+ show_new("ana-mount");
+ if (hp->h_mount)
+ analyze_mounts(hp);
+
+ }
+}
+
+/*
+ * Check an automount request
+ */
+static void analyze_automount(ap)
+automount *ap;
+{
+ dict_ent *de = find_volname(ap->a_volname);
+ if (de) {
+ ap->a_mounted = de;
+ } else {
+ if (STREQ(ap->a_volname, ap->a_name))
+ lerror(ap->a_ioloc, "unknown volname %s automounted", ap->a_volname);
+ else
+ lerror(ap->a_ioloc, "unknown volname %s automounted on %s", ap->a_volname, ap->a_name);
+ }
+}
+
+static void analyze_automount_tree(q, pref, lvl)
+qelem *q;
+char *pref;
+int lvl;
+{
+ automount *ap;
+
+ ITER(ap, automount, q) {
+ char nname[1024];
+ if (lvl > 0 || ap->a_mount)
+ if (ap->a_name[1] && strchr(ap->a_name+1, '/'))
+ lerror(ap->a_ioloc, "not allowed '/' in a directory name");
+ sprintf(nname, "%s/%s", pref, ap->a_name);
+ free(ap->a_name);
+ ap->a_name = strdup(nname[1] == '/' ? nname+1 : nname);
+ log("automount point %s:", ap->a_name);
+ show_new("ana-automount");
+ if (ap->a_mount) {
+ analyze_automount_tree(ap->a_mount, ap->a_name, lvl+1);
+ } else if (ap->a_volname) {
+ log("\tautomount from %s", ap->a_volname);
+ analyze_automount(ap);
+ } else if (ap->a_symlink) {
+ log("\tsymlink to %s", ap->a_symlink);
+ } else {
+ ap->a_volname = strdup(ap->a_name);
+ log("\timplicit automount from %s", ap->a_volname);
+ analyze_automount(ap);
+ }
+ }
+}
+
+void analyze_automounts(q)
+qelem *q;
+{
+ auto_tree *tp;
+
+ show_area_being_processed("analyze automount", 5);
+ /*
+ * q is a list of automounts
+ */
+ ITER(tp, auto_tree, q)
+ analyze_automount_tree(tp->t_mount, "", 0);
+}
diff --git a/usr.sbin/amd/fsinfo/fsi_data.h b/usr.sbin/amd/fsinfo/fsi_data.h
new file mode 100644
index 0000000..3fc10c4
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_data.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsi_data.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsi_data.h,v 5.2.2.1 1992/02/09 15:09:53 jsp beta $
+ *
+ */
+
+typedef struct auto_tree auto_tree;
+typedef struct automount automount;
+typedef struct dict dict;
+typedef struct dict_data dict_data;
+typedef struct dict_ent dict_ent;
+typedef struct disk_fs disk_fs;
+typedef struct ether_if ether_if;
+typedef struct fsmount fsmount;
+typedef struct host host;
+typedef struct ioloc ioloc;
+typedef struct mount mount;
+typedef struct qelem qelem;
+
+/*
+ * Linked lists...
+ */
+struct qelem {
+ qelem *q_forw;
+ qelem *q_back;
+};
+
+/*
+ * Automount tree
+ */
+struct automount {
+ qelem a_q;
+ ioloc *a_ioloc;
+ char *a_name; /* Automount key */
+ char *a_volname; /* Equivalent volume to be referenced */
+ char *a_symlink; /* Symlink representation */
+ qelem *a_mount; /* Tree representation */
+ dict_ent *a_mounted;
+};
+
+/*
+ * List of automount trees
+ */
+struct auto_tree {
+ qelem t_q;
+ ioloc *t_ioloc;
+ char *t_defaults;
+ qelem *t_mount;
+};
+
+/*
+ * A host
+ */
+struct host {
+ qelem q;
+ int h_mask;
+ ioloc *h_ioloc;
+ fsmount *h_netroot, *h_netswap;
+#define HF_HOST 0
+ char *h_hostname; /* The full name of the host */
+ char *h_lochost; /* The name of the host with local domains stripped */
+ char *h_hostpath; /* The filesystem path to the host (cf compute_hostpath) */
+#define HF_ETHER 1
+ qelem *h_ether;
+#define HF_CONFIG 2
+ qelem *h_config;
+#define HF_ARCH 3
+ char *h_arch;
+#define HF_CLUSTER 4
+ char *h_cluster;
+#define HF_OS 5
+ char *h_os;
+ qelem *h_disk_fs;
+ qelem *h_mount;
+};
+
+/*
+ * An ethernet interface
+ */
+struct ether_if {
+ qelem e_q;
+ int e_mask;
+ ioloc *e_ioloc;
+ char *e_if;
+#define EF_INADDR 0
+ struct in_addr e_inaddr;
+#define EF_NETMASK 1
+ u_long e_netmask;
+#define EF_HWADDR 2
+ char *e_hwaddr;
+};
+
+/*
+ * Disk filesystem structure.
+ *
+ * If the DF_* numbers are changed
+ * disk_fs_strings in analyze.c will
+ * need updating.
+ */
+struct disk_fs {
+ qelem d_q;
+ int d_mask;
+ ioloc *d_ioloc;
+ host *d_host;
+ char *d_mountpt;
+ char *d_dev;
+#define DF_FSTYPE 0
+ char *d_fstype;
+#define DF_OPTS 1
+ char *d_opts;
+#define DF_DUMPSET 2
+ char *d_dumpset;
+#define DF_PASSNO 3
+ int d_passno;
+#define DF_FREQ 4
+ int d_freq;
+#define DF_MOUNT 5
+ qelem *d_mount;
+#define DF_LOG 6
+ char *d_log;
+};
+#define DF_REQUIRED ((1<<DF_FSTYPE)|(1<<DF_OPTS)|(1<<DF_PASSNO)|(1<<DF_MOUNT))
+
+/*
+ * A mount tree
+ */
+struct mount {
+ qelem m_q;
+ ioloc *m_ioloc;
+ int m_mask;
+#define DM_VOLNAME 0
+ char *m_volname;
+#define DM_EXPORTFS 1
+ char *m_exportfs;
+#define DM_SEL 2
+ char *m_sel;
+ char *m_name;
+ int m_name_len;
+ mount *m_parent;
+ disk_fs *m_dk;
+ mount *m_exported;
+ qelem *m_mount;
+};
+
+/*
+ * Additional filesystem mounts
+ *
+ * If the FM_* numbers are changed
+ * disk_fs_strings in analyze.c will
+ * need updating.
+ */
+struct fsmount {
+ qelem f_q;
+ mount *f_ref;
+ ioloc *f_ioloc;
+ int f_mask;
+#define FM_LOCALNAME 0
+ char *f_localname;
+#define FM_VOLNAME 1
+ char *f_volname;
+#define FM_FSTYPE 2
+ char *f_fstype;
+#define FM_OPTS 3
+ char *f_opts;
+#define FM_FROM 4
+ char *f_from;
+};
+#define FM_REQUIRED ((1<<FM_VOLNAME)|(1<<FM_FSTYPE)|(1<<FM_OPTS)|(1<<FM_FROM)|(1<<FM_LOCALNAME))
+#define FM_NETROOT 0x01
+#define FM_NETSWAP 0x02
+#define FM_NETBOOT (FM_NETROOT|FM_NETSWAP)
+
+#define DICTHASH 5
+struct dict_ent {
+ dict_ent *de_next;
+ char *de_key;
+ int de_count;
+ qelem de_q;
+};
+
+/*
+ * Dictionaries ...
+ */
+struct dict_data {
+ qelem dd_q;
+ char *dd_data;
+};
+
+struct dict {
+ dict_ent *de[DICTHASH];
+};
+
+/*
+ * Source text location for error reports
+ */
+struct ioloc {
+ int i_line;
+ char *i_file;
+};
diff --git a/usr.sbin/amd/fsinfo/fsi_dict.c b/usr.sbin/amd/fsinfo/fsi_dict.c
new file mode 100644
index 0000000..5067e79
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_dict.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsi_dict.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsi_dict.c,v 5.2.2.1 1992/02/09 15:09:43 jsp beta $
+ *
+ */
+
+/*
+ * Dictionary support
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+static int dict_hash(k)
+char *k;
+{
+ unsigned int h;
+
+ for (h = 0; *k; h += *k++)
+ ;
+ return h % DICTHASH;
+}
+
+dict *new_dict()
+{
+ dict *dp = ALLOC(dict);
+ return dp;
+}
+
+static void dict_add_data(de, v)
+dict_ent *de;
+char *v;
+{
+ dict_data *dd = ALLOC(dict_data);
+ dd->dd_data = v;
+ ins_que(&dd->dd_q, de->de_q.q_back);
+ de->de_count++;
+}
+
+static dict_ent *new_dict_ent(k)
+char *k;
+{
+ dict_ent *de = ALLOC(dict_ent);
+ de->de_key = k;
+ init_que(&de->de_q);
+ return de;
+}
+
+dict_ent *dict_locate(dp, k)
+dict *dp;
+char *k;
+{
+ dict_ent *de = dp->de[dict_hash(k)];
+ while (de && !STREQ(de->de_key, k))
+ de = de->de_next;
+
+ return de;
+}
+
+void dict_add(dp, k, v)
+dict *dp;
+char *k, *v;
+{
+ dict_ent *de = dict_locate(dp, k);
+ if (!de) {
+ dict_ent **dep = &dp->de[dict_hash(k)];
+ de = new_dict_ent(k);
+ de->de_next = *dep;
+ *dep = de;
+ }
+ dict_add_data(de, v);
+}
+
+int dict_iter(dp, fn)
+dict *dp;
+int (*fn)();
+{
+ int i;
+ int errors = 0;
+
+ for (i = 0; i < DICTHASH; i++) {
+ dict_ent *de = dp->de[i];
+ while (de) {
+ errors += (*fn)(&de->de_q);
+ de = de->de_next;
+ }
+ }
+ return errors;
+}
diff --git a/usr.sbin/amd/fsinfo/fsi_gram.y b/usr.sbin/amd/fsinfo/fsi_gram.y
new file mode 100644
index 0000000..b4aa245
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_gram.y
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsi_gram.y 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsi_gram.y,v 5.2.2.1 1992/02/09 15:09:35 jsp beta $
+ *
+ */
+
+%{
+#include "../fsinfo/fsinfo.h"
+#include <stdio.h>
+
+extern qelem *list_of_hosts, *list_of_automounts;
+%}
+
+%union {
+ auto_tree *a;
+ disk_fs *d;
+ ether_if *e;
+ host *h;
+ qelem *q;
+ char *s;
+ mount *m;
+ fsmount *f;
+}
+
+%token tARCH
+%token tAS
+%token tAUTOMOUNT
+%token tCLUSTER
+%token tCONFIG
+%token tDUMPSET
+%token tEQ
+%token tEXPORTFS
+%token tFREQ
+%token tFROM
+%token tFS
+%token tFSTYPE
+%token tHWADDR
+%token tINADDR
+%token tHOST
+%token tLOCALHOST
+%token tLOG
+%token tMOUNT
+%token tNETMASK
+%token tNETIF
+%token tVOLNAME
+%token tOPTS
+%token tOS
+%token tPASSNO
+%token tSEL
+%token <s> tSTR
+
+%start list_of_hosts
+
+%type <a> automount
+%type <q> automount_tree
+%type <e> ether_attr
+%type <m> dir_tree_info
+%type <d> filesystem fs_info_list
+%type <h> host host_attr host_attr_list
+%type <q> list_of_hosts list_of_filesystems list_of_mounts dir_tree
+%type <f> localinfo_list
+%type <s> opt_auto_opts
+
+%%
+
+list_of_hosts :
+ /* empty */
+ { $$ = new_que(); }
+
+ | list_of_hosts host
+ { if ($2) ins_que((qelem *) $2, list_of_hosts->q_back);
+ $$ = $1; }
+
+ | list_of_hosts automount
+ { if ($2) ins_que((qelem *) $2, list_of_automounts->q_back);
+ $$ = $1; }
+ ;
+
+/*
+ * A new host:
+ *
+ * host foo.domain
+ */
+host :
+ tHOST host_attr list_of_filesystems list_of_mounts
+ { $$ = $2; $$->h_disk_fs = $3; $$->h_mount = $4; }
+
+ | error tHOST host_attr list_of_filesystems list_of_mounts
+ { $$ = $3; $$->h_disk_fs = $4; $$->h_mount = $5; }
+
+ ;
+
+host_attr :
+ tSTR
+ { $$ = new_host(); set_host($$, HF_HOST, $1); }
+
+ | '{' host_attr_list '}' tSTR
+ { $$ = $2; set_host($$, HF_HOST, $4); }
+
+ ;
+
+host_attr_list :
+ /* empty */
+ { $$ = new_host(); }
+
+ | host_attr_list tNETIF tSTR '{' ether_attr '}'
+ { if ($5) {
+ $5->e_if = $3;
+ $$ = $1; set_host($$, HF_ETHER, $5); }
+ }
+
+ | host_attr_list tCONFIG tSTR
+ { $$ = $1; set_host($$, HF_CONFIG, $3); }
+
+ | host_attr_list tARCH '=' tSTR
+ { $$ = $1; set_host($$, HF_ARCH, $4); }
+
+ | host_attr_list tOS '=' tSTR
+ { $$ = $1; set_host($$, HF_OS, $4); }
+
+ | host_attr_list tCLUSTER '=' tSTR
+ { $$ = $1; set_host($$, HF_CLUSTER, $4); }
+
+ | host_attr_list error '=' tSTR
+ { yyerror("unknown host attribute"); }
+ ;
+
+ether_attr :
+ /* empty */
+ { $$ = new_ether_if(); }
+
+ | ether_attr tINADDR '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_INADDR, $4); }
+ | ether_attr tNETMASK '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_NETMASK, $4); }
+ | ether_attr tHWADDR '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_HWADDR, $4); }
+ ;
+
+/*
+ * A new automount tree:
+ *
+ * automount /mountpoint { ... }
+ */
+automount :
+ tAUTOMOUNT opt_auto_opts automount_tree
+ { if ($3) {
+ $$ = new_auto_tree($2, $3);
+ } else {
+ $$ = 0;
+ }
+ }
+
+ | tAUTOMOUNT error
+ { $$ = 0; }
+ ;
+
+opt_auto_opts :
+ /* empty */
+ { $$ = strdup(""); }
+
+ | tOPTS tSTR
+ { $$ = $2; }
+ ;
+
+list_of_filesystems :
+ /* empty */
+ { $$ = 0; }
+
+ | list_of_filesystems filesystem
+ { if ($2) {
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$2->d_q, $$->q_back);
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+/*
+ * A new filesystem:
+ *
+ * fs /dev/whatever { ... }
+ */
+filesystem :
+ tFS tSTR '{' fs_info_list '}'
+ { $4->d_dev = $2; $$ = $4; }
+
+ | tFS error '}'
+ { $$ = (disk_fs *) 0; }
+ ;
+
+/*
+ * Per-filesystem information:
+ *
+ * fstype - the type of the filesystem (4.2, nfs, swap, export)
+ * opts - the mount options ("rw,grpid")
+ * passno - fsck pass number
+ * freq - dump frequency
+ * dumpset - tape set for filesystem dumps
+ * mount - where to mount this filesystem
+ * log - log device
+ */
+fs_info_list :
+ /* empty */
+ { $$ = new_disk_fs(); }
+
+ | fs_info_list tFSTYPE '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_FSTYPE, $4); }
+
+ | fs_info_list tOPTS '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_OPTS, $4); }
+
+ | fs_info_list tPASSNO '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_PASSNO, $4); }
+
+ | fs_info_list tFREQ '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_FREQ, $4); }
+
+ | fs_info_list tMOUNT dir_tree
+ { $$ = $1; set_disk_fs($$, DF_MOUNT, (char *) $3); }
+
+ | fs_info_list tDUMPSET '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_DUMPSET, $4); }
+
+ | fs_info_list tLOG '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_LOG, $4); }
+
+ | fs_info_list error '=' tSTR
+ { yyerror("unknown filesystem attribute"); }
+ ;
+
+/*
+ * An automount tree:
+ *
+ * name = "volname" name is a reference to volname
+ * name -> "string" name is a link to "string"
+ * name { ... } name is an automount tree
+ */
+automount_tree :
+ /* empty */
+ { $$ = 0; }
+
+ | automount_tree tSTR '=' tSTR
+ { automount *a = new_automount($2);
+ a->a_volname = $4;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+
+ | automount_tree tSTR tEQ tSTR
+ { automount *a = new_automount($2);
+ a->a_symlink = $4;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+
+ | automount_tree tSTR '{' automount_tree '}'
+ { automount *a = new_automount($2);
+ a->a_mount = $4;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+ ;
+
+dir_tree :
+ /* empty */
+ { $$ = 0; }
+
+ | dir_tree tSTR '{' dir_tree_info dir_tree '}'
+ { $4->m_mount = $5;
+ $4->m_name = $2;
+ if ($2[0] != '/' && $2[1] && strchr($2+1, '/'))
+ yyerror("not allowed '/' in a directory name");
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$4->m_q, $$->q_back);
+ }
+ ;
+
+dir_tree_info :
+ /* empty */
+ { $$ = new_mount(); }
+
+ | dir_tree_info tEXPORTFS tSTR
+ { $$ = $1; set_mount($$, DM_EXPORTFS, $3); }
+
+ | dir_tree_info tVOLNAME tSTR
+ { $$ = $1; set_mount($$, DM_VOLNAME, $3); }
+
+ | dir_tree_info tSEL tSTR
+ { $$ = $1; set_mount($$, DM_SEL, $3); }
+
+ | dir_tree_info error '=' tSTR
+ { yyerror("unknown directory attribute"); }
+ ;
+
+/*
+ * Additional mounts on a host
+ *
+ * mount "volname" ...
+ */
+list_of_mounts :
+ /* empty */
+ { $$ = 0; }
+
+ | list_of_mounts tMOUNT tSTR localinfo_list
+ { set_fsmount($4, FM_VOLNAME, $3);
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$4->f_q, $$->q_back);
+ }
+ ;
+
+/*
+ * Mount info:
+ *
+ * from "hostname" - obtain the object from the named host
+ * as "string" - where to mount, if different from the volname
+ * opts "string" - mount options
+ * fstype "type" - type of filesystem mount, if not nfs
+ */
+localinfo_list :
+ /* empty */
+ { $$ = new_fsmount(); }
+
+ | localinfo_list tAS tSTR
+ { $$ = $1; set_fsmount($$, FM_LOCALNAME, $3); }
+
+ | localinfo_list tFROM tSTR
+ { $$ = $1; set_fsmount($$, FM_FROM, $3); }
+
+ | localinfo_list tFSTYPE tSTR
+ { $$ = $1; set_fsmount($$, FM_FSTYPE, $3); }
+
+ | localinfo_list tOPTS tSTR
+ { $$ = $1; set_fsmount($$, FM_OPTS, $3); }
+
+ | localinfo_list error '=' tSTR
+ { yyerror("unknown mount attribute"); }
+ ;
diff --git a/usr.sbin/amd/fsinfo/fsi_lex.l b/usr.sbin/amd/fsinfo/fsi_lex.l
new file mode 100644
index 0000000..46ec532
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_lex.l
@@ -0,0 +1,403 @@
+%{
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsi_lex.l 8.2 (Berkeley) 2/17/94
+ *
+ * $Id: fsi_lex.l,v 5.2.2.1 1992/02/09 15:09:36 jsp beta $
+ *
+ */
+
+/*
+ * Lexical analyzer for fsinfo.
+ * TODO: Needs rewriting.
+ */
+
+static int xinput();
+static void xunput();
+
+#ifdef FLEX_SCANNER
+static int yylineno;
+/* Flex support with help from Vern Paxson <vern@helios.ee.lbl.gov> */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+{ \
+ int i; \
+ for (i = 0; i < max_size; i++) { \
+ int ch = xinput(i == 0); \
+ if (ch == 0) \
+ break; \
+ buf[i] = ch; \
+ } \
+ result = i; \
+}
+
+#define INIT_STATE { \
+ switch ((yy_start - 1) / 2) { \
+ case 0: \
+ BEGIN F; \
+ break; \
+ } \
+}
+
+
+#else
+/*
+ * Using old lex...
+ */
+#undef unput
+#define unput(ch) xunput(ch)
+#undef input
+#define input() xinput(1)
+
+#define INIT_STATE { \
+ switch (yybgin - yysvec - 1) { \
+ case 0: \
+ BEGIN F; \
+ break; \
+ } \
+}
+
+#endif /* FLEX_SCANNER */
+
+#include "../fsinfo/fsinfo.h"
+#include "fsi_gram.h"
+#include <ctype.h>
+
+static char *filename;
+static char *optr;
+static char ostr[1024];
+static find_resword();
+static unsigned char ibuf[64];
+static unsigned char *iptr = ibuf;
+static int quoted;
+static int lastch, nextch = '\n';
+YYSTYPE yylval;
+
+struct r {
+ char *rw;
+ int tok;
+} rr[] = {
+ { "->", tEQ },
+ { "arch", tARCH },
+ { "as", tAS },
+ { "automount", tAUTOMOUNT },
+ { "cluster", tCLUSTER },
+ { "config", tCONFIG },
+ { "dumpset", tDUMPSET },
+ { "exportfs", tEXPORTFS },
+ { "freq", tFREQ },
+ { "from", tFROM },
+ { "fs", tFS },
+ { "fstype", tFSTYPE },
+ { "host", tHOST },
+ { "hwaddr", tHWADDR },
+ { "inaddr", tINADDR },
+ { "localhost", tLOCALHOST },
+ { "log", tLOG },
+ { "mount", tMOUNT },
+ { "netif", tNETIF },
+ { "netmask", tNETMASK },
+ { "opts", tOPTS },
+ { "os", tOS },
+ { "passno", tPASSNO },
+ { "sel", tSEL },
+ { "volname", tVOLNAME },
+ { 0, 0 },
+};
+#define NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
+
+%}
+
+%start F Q
+
+%%
+ INIT_STATE; /* witchcraft */
+
+<F>[^ \t\n"={}]+ { return find_resword(yytext); }
+<F>[ \t] ;
+<F>"\n" { yylineno++; }
+<F>[={}] { return *yytext; }
+
+<F>\" { BEGIN Q; optr = ostr; quoted = 1; }
+<Q>\n { yylineno++; yyerror("\" expected"); BEGIN F; }
+<Q>\\b { *optr++ = '\b'; /* escape */ }
+<Q>\\t { *optr++ = '\t'; /* escape */ }
+<Q>\\\" { *optr++ = '\"'; /* escape */ }
+<Q>\\\\ { *optr++ = '\\'; /* escape */ }
+<Q>\\\n { yylineno++; /* continue */ }
+<Q>\\r { *optr++ = '\r'; /* escape */ }
+<Q>\\n { *optr++ = '\n'; /* escape */ }
+<Q>\\f { *optr++ = '\f'; /* escape */ }
+<Q>"\\ " { *optr++ = ' '; /* force space */ }
+<Q>\\. { yyerror("Unknown \\ sequence"); }
+<Q>([ \t]|"\\\n"){2,} { char *p = yytext-1; while (p = strchr(p+1, '\n')) yylineno++; }
+<Q>\" { BEGIN F; quoted = 0;
+ *optr = '\0';
+ yylval.s = strdup(ostr);
+ return tSTR;
+ }
+<Q>. { *optr++ = *yytext; }
+
+%%
+
+static int find_resword(s)
+char *s;
+{
+ int tok = 0;
+
+ int l = 0, m = NRES_WORDS/2, h = NRES_WORDS-1;
+ int rc = 0;
+
+ m = NRES_WORDS/2;
+
+#define FSTRCMP(p, q) ((*(p) == *(q)) ? strcmp((p)+1, (q)+1) : *(p) - *(q))
+
+ while ((l <= h) && (rc = FSTRCMP(s, rr[m].rw))) {
+ /*fprintf(stderr, "failed to cmp(%s, %s), %d, %d, %d\n", s, rr[m].rw, l, m, h);*/
+ if (rc < 0)
+ h = m - 1;
+ else
+ l = m + 1;
+ m = (h + l) / 2;
+ }
+
+ if (rc == 0)
+ tok = rr[m].tok;
+
+ switch (tok) {
+ case tLOCALHOST:
+ s = "${host}";
+ /* fall through... */
+ case 0:
+ yylval.s = strdup(s);
+ tok = tSTR;
+ /* fall through... */
+ default:
+ return tok;
+ }
+
+}
+
+int yyerror(s, s1, s2, s3, s4)
+char *s;
+char *s1, *s2, *s3, *s4;
+{
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", filename ? filename : "/dev/stdin", yylineno);
+ fprintf(stderr, s, s1, s2, s3, s4);
+ fputc('\n', stderr);
+ parse_errors++;
+}
+
+ioloc *current_location()
+{
+ ioloc *ip = ALLOC(ioloc);
+ ip->i_line = yylineno;
+ ip->i_file = filename;
+ return ip;
+}
+
+#ifdef FLEX_SCANNER
+#undef yywrap
+#endif
+
+int yywrap()
+{
+static int first = 1;
+ if (first) {
+ char prog[16*1024];
+ strcpy(prog, "for file in ");
+ while (*++g_argv) {
+ if (access(*g_argv, 4) < 0) {
+ error("\"%s\": Cannot open for reading", *g_argv);
+ file_io_errors++;
+ } else {
+ strcat(prog, *g_argv);
+ strcat(prog, " ");
+ }
+ }
+ strcat(prog, "; do /lib/cpp ");
+ strcat(prog, idvbuf);
+ strcat(prog, " -DHOSTNAME=\'");
+ strcat(prog, hostname);
+ strcat(prog, "\' \"$file\"; done");
+ yyin = popen(prog, "r");
+ if (yyin) {
+ /*if (filename) free(filename);*/
+ filename = strdup("unknown");
+ yylineno = 1;
+ first = 0;
+ return 0;
+ } else {
+ perror(prog);
+ }
+ }
+
+ if (!first && yyin && pclose(yyin) != 0)
+ parse_errors++;
+
+ return 1;
+}
+
+#define xgetc(fp) ((iptr > ibuf) ? (*--iptr) : (lastch = nextch, nextch = getc(fp), (nextch == EOF ? nextch = lastch, EOF : nextch)))
+
+static int xinput(need)
+int need;
+{
+static int c_comment = 0;
+ int ch, ch2;
+
+ do {
+ ch = xgetc(yyin);
+ /* fprintf(stderr, "ch = %c, %#x, %d\n", ch, ibuf,iptr-ibuf); */
+ if (ch == EOF) return 0;
+ if (quoted)
+ return ch;
+ if (c_comment) {
+ ch2 = ch;
+ do {
+ if (ch2 == '\n') {
+ nextch = '\n';
+ return ch2;
+ }
+ /* C style comment */
+ do {
+ ch2 = getc(yyin);
+ if (ch2 == '\n') {
+ nextch = '\n';
+ return ch2;
+ }
+ } while (ch2 != '*' && ch2 != EOF);
+
+ while (ch2 == '*')
+ ch2 = getc(yyin);
+ } while (ch2 != '/' && ch2 != EOF);
+ c_comment = 0;
+ if (ch2 == EOF)
+ break;
+ continue;
+ }
+
+ if (ch == '#') {
+ /*log("lastch = '%c' (%#x)", lastch, lastch);*/
+ if (lastch == '\n') {
+ char fname[MAXPATHLEN];
+ char *fptr;
+ if (!need) {
+ xunput('#');
+ nextch = '\n';
+ return 0;
+ }
+ fname[0] = '\0';
+ /* Skip past space */
+ do {
+ ch2 = getc(yyin);
+ } while (ch2 != EOF && ch2 != '\n' && !isdigit(ch2));
+ if (isdigit(ch2)) {
+ /* Read in line number */
+ fptr = fname;
+ do {
+ *fptr++ = ch2;
+ ch2 = getc(yyin);
+ } while (isdigit(ch2));
+ *fptr = '\0';
+ if (fptr != fname)
+ yylineno = atoi(fname) - 1;
+ }
+ /* Skip past space */
+ while (ch2 != EOF && ch2 != '\"' && ch2 != '\n')
+ ch2 = getc(yyin);
+ if (ch2 == '\"') {
+ /* Read file name */
+ fptr = fname;
+ ch2 = getc(yyin);
+ while (ch2 != '\"' && ch2 != EOF && ch2 != EOF) {
+ *fptr++ = ch2;
+ ch2 = getc(yyin);
+ }
+ *fptr = '\0';
+ if (fname[0]) {
+ log("Setting filename to \"%s\"", fname);
+ /*if (filename) free(filename);*/
+ filename = strdup(fname);
+ }
+ }
+ while (ch2 != '\n' && ch2 != EOF)
+ ch2 = getc(yyin);
+ } else do {
+ ch2 = getc(yyin);
+ } while (ch2 != '\n' && ch2 != EOF);
+ if (ch2 == '\n') {
+ nextch = '\n';
+ return ch2;
+ }
+ } else if (ch == '/') {
+ ch2 = getc(yyin);
+ if (ch2 == '/') {
+ /* C++ style comment */
+ do {
+ ch2 = getc(yyin);
+ } while (ch2 != '\n' && ch2 != EOF);
+ if (ch2 == '\n') {
+ nextch = '\n';
+ return ch2;
+ }
+ } else if (ch2 == '*') {
+ c_comment = 1;
+ continue;
+ } else {
+ xunput(ch2);
+ return ch;
+ }
+ } else {
+ return ch;
+ }
+ } while (ch2 != EOF);
+ error("End of file within comment");
+ return 0;
+}
+
+static void xunput(c)
+int c;
+{
+ if (c && c != EOF) {
+ if (iptr == ibuf + sizeof(ibuf) - 1)
+ fatal("Out of space in lexical pushback");
+ *iptr++ = c;
+ }
+}
diff --git a/usr.sbin/amd/fsinfo/fsi_util.c b/usr.sbin/amd/fsinfo/fsi_util.c
new file mode 100644
index 0000000..c0d8088
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsi_util.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * 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.
+ *
+ * @(#)fsi_util.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsi_util.c,v 5.2.2.1 1992/02/09 15:09:39 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+/*
+ * Lots of ways of reporting errors...
+ */
+void error(s, s1, s2, s3, s4)
+char *s, *s1, *s2, *s3, *s4;
+{
+ col_cleanup(0);
+ fprintf(stderr, "%s: Error, ", progname);
+ fprintf(stderr, s, s1, s2, s3, s4);
+ fputc('\n', stderr);
+ errors++;
+}
+
+void lerror(l, s, s1, s2, s3, s4)
+ioloc *l;
+char *s, *s1, *s2, *s3, *s4;
+{
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
+ fprintf(stderr, s, s1, s2, s3, s4);
+ fputc('\n', stderr);
+ errors++;
+}
+
+void lwarning(l, s, s1, s2, s3, s4)
+ioloc *l;
+char *s, *s1, *s2, *s3, *s4;
+{
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
+ fprintf(stderr, s, s1, s2, s3, s4);
+ fputc('\n', stderr);
+
+}
+
+void fatal(s, s1, s2, s3, s4)
+char *s, *s1, *s2, *s3, *s4;
+{
+ col_cleanup(1);
+ fprintf(stderr, "%s: Fatal, ", progname);
+ fprintf(stderr, s, s1, s2, s3, s4);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+/*
+ * Dup a string
+ */
+char *strdup(s)
+char *s;
+{
+ int len = strlen(s);
+ char *sp = (char *) xmalloc(len+1);
+
+ bcopy(s, sp, len);
+ sp[len] = 0;
+
+ return sp;
+}
+
+/*
+ * Debug log
+ */
+void log(s, s1, s2, s3, s4)
+char *s, *s1, *s2, *s3, *s4;
+{
+ if (verbose > 0) {
+ fputc('#', stdout);
+ fprintf(stdout, "%s: ", progname);
+ fprintf(stdout, s, s1, s2, s3, s4);
+ putc('\n', stdout);
+ }
+}
+
+void info_hdr(ef, info)
+FILE *ef;
+char *info;
+{
+ fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
+}
+
+void gen_hdr(ef, hn)
+FILE *ef;
+char *hn;
+{
+ fprintf(ef, "# *** NOTE: Only for use on %s\n", hn);
+}
+
+static void make_banner(fp)
+FILE *fp;
+{
+ time_t t = time((time_t*) 0);
+ char *ctime(), *cp = ctime(&t);
+
+ fprintf(fp,
+"\
+# *** This file was automatically generated -- DO NOT EDIT HERE ***\n\
+# \"%s\" run by %s@%s on %s\
+#\n\
+",
+ progname, username, hostname, cp);
+}
+
+static int show_range = 10;
+static int col = 0;
+static int total_shown = 0;
+static int total_mmm = 8;
+
+static int col_output(len)
+int len;
+{
+ int wrapped = 0;
+ col += len;
+ if (col > 77) {
+ fputc('\n', stdout);
+ col = len;
+ wrapped = 1;
+ }
+ return wrapped;
+}
+
+static void show_total()
+{
+ if (total_mmm != -show_range+1) {
+ char n[8];
+ int len;
+ if (total_mmm < 0)
+ fputc('*', stdout);
+ sprintf(n, "%d", total_shown);
+ len = strlen(n);
+ if (col_output(len))
+ fputc(' ', stdout);
+ fputs(n, stdout); fflush(stdout);
+ total_mmm = -show_range;
+ }
+}
+
+col_cleanup(eoj)
+int eoj;
+{
+ if (verbose < 0) return;
+ if (eoj) {
+ show_total();
+ fputs(")]", stdout);
+ }
+ if (col) {
+ fputc('\n', stdout);
+ col = 0;
+ }
+}
+
+void show_new(msg)
+char *msg;
+{
+ if (verbose < 0) return;
+ total_shown++;
+ if (total_mmm > show_range) {
+ show_total();
+ } else if (total_mmm == 0) {
+ fputc('*', stdout); fflush(stdout);
+ col += 1;
+ }
+ total_mmm++;
+}
+
+void show_area_being_processed(area, n)
+char *area;
+int n;
+{
+static char *last_area = 0;
+ if (verbose < 0) return;
+ if (last_area) {
+ if (total_shown)
+ show_total();
+ fputs(")", stdout);
+ col += 1;
+ }
+ if (!last_area || strcmp(area, last_area) != 0) {
+ if (last_area) {
+ col_cleanup(0);
+ total_shown = 0;
+ total_mmm = show_range+1;
+ }
+ (void) col_output(strlen(area)+2);
+ fprintf(stdout, "[%s", area);
+ last_area = area;
+ }
+
+ fputs(" (", stdout);
+ col += 2;
+ show_range = n;
+ total_mmm = n + 1;
+
+ fflush(stdout);
+}
+
+/*
+ * Open a file with the given prefix and name
+ */
+FILE *pref_open(pref, hn, hdr, arg)
+char *pref;
+char *hn;
+void (*hdr)();
+char *arg;
+{
+ char p[MAXPATHLEN];
+ FILE *ef;
+ sprintf(p, "%s%s", pref, hn);
+ log("Writing %s info for %s to %s", pref, hn, p);
+ ef = fopen(p, "w");
+ if (ef) {
+ (*hdr)(ef, arg);
+ make_banner(ef, hn);
+ } else {
+ error("can't open %s for writing", p);
+ }
+
+ return ef;
+}
+
+int pref_close(fp)
+FILE *fp;
+{
+ return fclose(fp) == 0;
+}
+
+/*
+ * Determine where Amd would automount the host/volname pair
+ */
+void compute_automount_point(buf, hp, vn)
+char *buf;
+host *hp;
+char *vn;
+{
+#ifdef AMD_USES_HOSTPATH
+ sprintf(buf, "%s/%s%s", autodir, hp->h_hostpath, vn);
+#else
+ sprintf(buf, "%s/%s%s", autodir, hp->h_lochost, vn);
+#endif
+}
+
+char *xcalloc(i, s)
+int i;
+int s;
+{
+ char *p = (char *) calloc(i, (unsigned) s);
+ if (!p)
+ fatal("Out of memory");
+ return p;
+}
+
+char *xmalloc(i)
+int i;
+{
+ char *p = (char *) malloc(i);
+ if (!p)
+ fatal("Out of memory");
+ return p;
+}
+
+/*
+ * Data constructors..
+ */
+
+automount *new_automount(name)
+char *name;
+{
+ automount *ap = ALLOC(automount);
+ ap->a_ioloc = current_location();
+ ap->a_name = name;
+ ap->a_volname = 0;
+ ap->a_mount = 0;
+ show_new("automount");
+ return ap;
+}
+
+auto_tree *new_auto_tree(def, ap)
+char *def;
+qelem *ap;
+{
+ auto_tree *tp = ALLOC(auto_tree);
+ tp->t_ioloc = current_location();
+ tp->t_defaults = def;
+ tp->t_mount = ap;
+ show_new("auto_tree");
+ return tp;
+}
+
+host *new_host()
+{
+ host *hp = ALLOC(host);
+ hp->h_ioloc = current_location();
+ hp->h_mask = 0;
+ show_new("host");
+ return hp;
+}
+
+void set_host(hp, k, v)
+host *hp;
+int k;
+char *v;
+{
+ int m = 1 << k;
+ if (hp->h_mask & m) {
+ yyerror("host field \"%s\" already set", host_strings[k]);
+ return;
+ }
+
+ hp->h_mask |= m;
+
+ switch (k) {
+ case HF_HOST: {
+ char *p = strdup(v);
+ dict_ent *de = dict_locate(dict_of_hosts, v);
+ if (de)
+ yyerror("duplicate host %s!", v);
+ else
+ dict_add(dict_of_hosts, v, (char *) hp);
+ hp->h_hostname = v;
+ domain_strip(p, hostname);
+ if (strchr(p, '.') != 0)
+ free(p);
+ else
+ hp->h_lochost = p;
+ } break;
+ case HF_CONFIG: {
+ qelem *q;
+ qelem *vq = (qelem *) v;
+ hp->h_mask &= ~m;
+ if (hp->h_config)
+ q = hp->h_config;
+ else
+ q = hp->h_config = new_que();
+ ins_que(vq, q->q_back);
+ } break;
+ case HF_ETHER: {
+ qelem *q;
+ qelem *vq = (qelem *) v;
+ hp->h_mask &= ~m;
+ if (hp->h_ether)
+ q = hp->h_ether;
+ else
+ q = hp->h_ether = new_que();
+ ins_que(vq, q->q_back);
+ } break;
+ case HF_ARCH: hp->h_arch = v; break;
+ case HF_OS: hp->h_os = v; break;
+ case HF_CLUSTER: hp->h_cluster = v; break;
+ default: abort(); break;
+ }
+}
+
+ether_if *new_ether_if()
+{
+ ether_if *ep = ALLOC(ether_if);
+ ep->e_mask = 0;
+ ep->e_ioloc = current_location();
+ show_new("ether_if");
+ return ep;
+}
+
+void set_ether_if(ep,k, v)
+ether_if *ep;
+int k;
+char *v;
+{
+ int m = 1 << k;
+ if (ep->e_mask & m) {
+ yyerror("netif field \"%s\" already set", ether_if_strings[k]);
+ return;
+ }
+
+ ep->e_mask |= m;
+
+ switch (k) {
+ case EF_INADDR: {
+ extern u_long inet_addr();
+ ep->e_inaddr.s_addr = inet_addr(v);
+ if (ep->e_inaddr.s_addr == (u_long) -1)
+ yyerror("malformed IP dotted quad: %s", v);
+ free(v);
+ } break;
+ case EF_NETMASK: {
+ u_long nm = 0;
+ if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0)
+ ep->e_netmask = htonl(nm);
+ else
+ yyerror("malformed netmask: %s", v);
+ free(v);
+ } break;
+ case EF_HWADDR:
+ ep->e_hwaddr = v;
+ break;
+ default: abort(); break;
+ }
+}
+
+void set_disk_fs(dp, k, v)
+disk_fs *dp;
+int k;
+char *v;
+{
+ int m = 1 << k;
+ if (dp->d_mask & m) {
+ yyerror("fs field \"%s\" already set", disk_fs_strings[k]);
+ return;
+ }
+
+ dp->d_mask |= m;
+
+ switch (k) {
+ case DF_FSTYPE: dp->d_fstype = v; break;
+ case DF_OPTS: dp->d_opts = v; break;
+ case DF_DUMPSET: dp->d_dumpset = v; break;
+ case DF_LOG: dp->d_log = v; break;
+ case DF_PASSNO: dp->d_passno = atoi(v); free(v); break;
+ case DF_FREQ: dp->d_freq = atoi(v); free(v); break;
+ case DF_MOUNT: dp->d_mount = &((mount *) v)->m_q; break;
+ default: abort(); break;
+ }
+}
+
+disk_fs *new_disk_fs()
+{
+ disk_fs *dp = ALLOC(disk_fs);
+ dp->d_ioloc = current_location();
+ show_new("disk_fs");
+ return dp;
+}
+
+void set_mount(mp, k, v)
+mount *mp;
+int k;
+char *v;
+{
+ int m = 1 << k;
+ if (mp->m_mask & m) {
+ yyerror("mount tree field \"%s\" already set", mount_strings[k]);
+ return;
+ }
+
+ mp->m_mask |= m;
+
+ switch (k) {
+ case DM_VOLNAME:
+ dict_add(dict_of_volnames, v, (char *) mp);
+ mp->m_volname = v;
+ break;
+ case DM_EXPORTFS:
+ mp->m_exportfs = v;
+ break;
+ case DM_SEL:
+ mp->m_sel = v;
+ break;
+ default: abort(); break;
+ }
+}
+
+mount *new_mount()
+{
+ mount *fp = ALLOC(mount);
+ fp->m_ioloc = current_location();
+ show_new("mount");
+ return fp;
+}
+
+void set_fsmount(fp, k, v)
+fsmount *fp;
+int k;
+char *v;
+{
+ int m = 1 << k;
+ if (fp->f_mask & m) {
+ yyerror("mount field \"%s\" already set", fsmount_strings[k]);
+ return;
+ }
+
+ fp->f_mask |= m;
+
+ switch (k) {
+ case FM_LOCALNAME: fp->f_localname = v; break;
+ case FM_VOLNAME: fp->f_volname = v; break;
+ case FM_FSTYPE: fp->f_fstype = v; break;
+ case FM_OPTS: fp->f_opts = v; break;
+ case FM_FROM: fp->f_from = v; break;
+ default: abort(); break;
+ }
+}
+
+fsmount *new_fsmount()
+{
+ fsmount *fp = ALLOC(fsmount);
+ fp->f_ioloc = current_location();
+ show_new("fsmount");
+ return fp;
+}
+
+void init_que(q)
+qelem *q;
+{
+ q->q_forw = q->q_back = q;
+}
+
+qelem *new_que()
+{
+ qelem *q = ALLOC(qelem);
+ init_que(q);
+ return q;
+}
+
+void ins_que(elem, pred)
+qelem *elem, *pred;
+{
+ qelem *p;
+ p = pred->q_forw;
+ elem->q_back = pred;
+ elem->q_forw = p;
+ pred->q_forw = elem;
+ p->q_back = elem;
+}
+
+void rem_que(elem)
+qelem *elem;
+{
+ qelem *p, *p2;
+ p = elem->q_forw;
+ p2 = elem->q_back;
+
+ p2->q_forw = p;
+ p->q_back = p2;
+}
diff --git a/usr.sbin/amd/fsinfo/fsinfo.8 b/usr.sbin/amd/fsinfo/fsinfo.8
new file mode 100644
index 0000000..34db7c2
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsinfo.8
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1993 Jan-Simon Pendry.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fsinfo.8 8.1 (Berkeley) 6/28/93
+.\"
+.Dd June 28, 1993
+.Dt FSINFO 8
+.Os
+.Sh NAME
+.Nm fsinfo
+.Nd co-ordinate site-wide filesystem information
+.Sh SYNOPSIS
+.Nm \&fsinfo
+.Op Fl v
+.Op Fl a Ar autodir
+.Op Fl b Ar bootparams
+.Op Fl d Ar dumpsets
+.Op Fl e Ar exports
+.Op Fl f Ar fstabs
+.Op Fl h Ar hostname
+.Op Fl m Ar automounts
+.Op Fl I Ar dir
+.Op Fl D Ar string[=string]]
+.Op Fl U Ar string[=string]]
+.Ar config ...
+.Sh DESCRIPTION
+The
+.Nm fsinfo
+utility takes a set of system configuration information, and generates
+a co-ordinated set of
+.Xr amd ,
+.Xr mount
+and
+.Xr mountd
+configuration files.
+.Pp
+The
+.Nm fsinfo
+command is fully described in the document
+.%T "Amd - The 4.4BSD Automounter"
+.Sh "SEE ALSO"
+.Xr amd 8 ,
+.Xr mount 8 ,
+.Xr mountd 8 .
+.Sh HISTORY
+The
+.Nm fsinfo
+command first appeared in 4.4BSD.
diff --git a/usr.sbin/amd/fsinfo/fsinfo.c b/usr.sbin/amd/fsinfo/fsinfo.c
new file mode 100644
index 0000000..a4b867b
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsinfo.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsinfo.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsinfo.c,v 5.2.2.1 1992/02/09 15:09:33 jsp beta $
+ *
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+/*
+ * fsinfo
+ */
+
+#include "../fsinfo/fsinfo.h"
+#include "fsi_gram.h"
+#include <pwd.h>
+
+qelem *list_of_hosts;
+qelem *list_of_automounts;
+dict *dict_of_volnames;
+dict *dict_of_hosts;
+char *autodir = "/a";
+char hostname[MAXHOSTNAMELEN+1];
+char *username;
+int file_io_errors;
+int parse_errors;
+int errors;
+int verbose;
+char idvbuf[1024];
+
+char **g_argv;
+char *progname;
+
+/*
+ * Output file prefixes
+ */
+char *exportfs_pref;
+char *fstab_pref;
+char *dumpset_pref;
+char *mount_pref;
+char *bootparams_pref;
+
+/*
+ * Argument cracking...
+ */
+static void get_args(c, v)
+int c;
+char *v[];
+{
+ extern char *optarg;
+ extern int optind;
+ int ch;
+ int usage = 0;
+ char *iptr = idvbuf;
+
+ /*
+ * Determine program name
+ */
+ if (v[0]) {
+ progname = strrchr(v[0], '/');
+ if (progname && progname[1])
+ progname++;
+ else
+ progname = v[0];
+ }
+ if (!progname)
+ progname = "fsinfo";
+
+ while ((ch = getopt(c, v, "a:b:d:e:f:h:m:D:U:I:qv")) != EOF)
+ switch (ch) {
+ case 'a':
+ autodir = optarg;
+ break;
+ case 'b':
+ if (bootparams_pref)
+ fatal("-b option specified twice");
+ bootparams_pref = optarg;
+ break;
+ case 'd':
+ if (dumpset_pref)
+ fatal("-d option specified twice");
+ dumpset_pref = optarg;
+ break;
+ case 'h':
+ strncpy(hostname, optarg, sizeof(hostname)-1);
+ break;
+ case 'e':
+ if (exportfs_pref)
+ fatal("-e option specified twice");
+ exportfs_pref = optarg;
+ break;
+ case 'f':
+ if (fstab_pref)
+ fatal("-f option specified twice");
+ fstab_pref = optarg;
+ break;
+ case 'm':
+ if (mount_pref)
+ fatal("-m option specified twice");
+ mount_pref = optarg;
+ break;
+ case 'q':
+ verbose = -1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'I': case 'D': case 'U':
+ sprintf(iptr, "-%c%s ", ch, optarg);
+ iptr += strlen(iptr);
+ break;
+ default:
+ usage++;
+ break;
+ }
+
+ if (c != optind) {
+ g_argv = v + optind - 1;
+ if (yywrap())
+ fatal("Cannot read any input files");
+ } else {
+ usage++;
+ }
+
+ if (usage) {
+ fprintf(stderr,
+"\
+Usage: %s [-v] [-a autodir] [-h hostname] [-b bootparams] [-d dumpsets]\n\
+\t[-e exports] [-f fstabs] [-m automounts]\n\
+\t[-I dir] [-D|-U string[=string]] config ...\n", progname);
+ exit(1);
+ }
+
+
+ if (g_argv[0])
+ log("g_argv[0] = %s", g_argv[0]);
+ else
+ log("g_argv[0] = (nil)");
+}
+
+/*
+ * Determine username of caller
+ */
+static char *find_username()
+{
+ extern char *getlogin();
+ extern char *getenv();
+ char *u = getlogin();
+ if (!u) {
+ struct passwd *pw = getpwuid(getuid());
+ if (pw)
+ u = pw->pw_name;
+ }
+ if (!u)
+ u = getenv("USER");
+ if (!u)
+ u = getenv("LOGNAME");
+ if (!u)
+ u = "root";
+
+ return strdup(u);
+}
+
+/*
+ * MAIN
+ */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ /*
+ * Process arguments
+ */
+ get_args(argc, argv);
+
+ /*
+ * If no hostname given then use the local name
+ */
+ if (!*hostname && gethostname(hostname, sizeof(hostname)) < 0) {
+ perror("gethostname");
+ exit(1);
+ }
+
+ /*
+ * Get the username
+ */
+ username = find_username();
+
+ /*
+ * New hosts and automounts
+ */
+ list_of_hosts = new_que();
+ list_of_automounts = new_que();
+
+ /*
+ * New dictionaries
+ */
+ dict_of_volnames = new_dict();
+ dict_of_hosts = new_dict();
+
+ /*
+ * Parse input
+ */
+ show_area_being_processed("read config", 11);
+ if (yyparse())
+ errors = 1;
+ errors += file_io_errors + parse_errors;
+
+ if (errors == 0) {
+ /*
+ * Do semantic analysis of input
+ */
+ analyze_hosts(list_of_hosts);
+ analyze_automounts(list_of_automounts);
+ }
+
+ /*
+ * Give up if errors
+ */
+ if (errors == 0) {
+ /*
+ * Output data files
+ */
+
+ write_atab(list_of_automounts);
+ write_bootparams(list_of_hosts);
+ write_dumpset(list_of_hosts);
+ write_exportfs(list_of_hosts);
+ write_fstab(list_of_hosts);
+ }
+
+ col_cleanup(1);
+
+ exit(errors);
+}
diff --git a/usr.sbin/amd/fsinfo/fsinfo.h b/usr.sbin/amd/fsinfo/fsinfo.h
new file mode 100644
index 0000000..0d07e21
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/fsinfo.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fsinfo.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fsinfo.h,v 5.2.2.1 1992/02/09 15:09:51 jsp beta $
+ *
+ */
+
+/*
+ * Get this in now so that OS_HDR can use it
+ */
+#ifdef __STDC__
+#define P(x) x
+#define P_void void
+#define Const const
+#else
+#define P(x) ()
+#define P_void /* as nothing */
+#define Const /* as nothing */
+#endif /* __STDC__ */
+
+#ifdef __GNUC__
+#define INLINE /* __inline */
+#else
+#define INLINE
+#endif /* __GNUC__ */
+
+/*
+ * Pick up target dependent definitions
+ */
+#include "os-defaults.h"
+#include OS_HDR
+
+#ifdef VOIDP
+typedef void *voidp;
+#else
+typedef char *voidp;
+#endif /* VOIDP */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+
+/*
+ * Bogosity to deal with ether { ... }
+ */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+#include "fsi_data.h"
+
+extern char* strchr P((Const char*, int)); /* C */
+extern char* strrchr P((Const char*, int)); /* C */
+extern char *strdup P((char*)); /* C */
+extern void fatal();
+extern void warning();
+extern void error();
+extern void analyze_automounts P((qelem*));
+extern void analyze_hosts P((qelem*));
+extern void compute_automount_point P((char*, host*, char*));
+extern automount *new_automount P((char*));
+extern auto_tree *new_auto_tree P((char*, qelem*));
+extern host *new_host P((void));
+extern disk_fs *new_disk_fs P((void));
+extern void set_disk_fs P((disk_fs*, int, char*));
+extern ether_if *new_ether_if P((void));
+extern mount *new_mount P((void));
+extern void set_mount P((mount*, int, char*));
+extern fsmount *new_fsmount P((void));
+extern void set_fsmount P((fsmount*, int, char*));
+extern qelem *new_que P((void));
+extern void init_que P((qelem*));
+extern void ins_que P((qelem*, qelem*));
+extern void rem_que P((qelem*));
+extern dict *new_dict P((void));
+extern dict_ent *dict_locate P((dict*, char*));
+extern void dict_add P((dict*, char*, char*));
+extern int dict_iter P((dict*, int (*)()));
+extern void info_hdr();
+extern void gen_hdr();
+extern FILE *pref_open();
+extern int pref_close();
+extern ioloc *current_location();
+
+extern char *disk_fs_strings[];
+extern char *mount_strings[];
+extern char *fsmount_strings[];
+extern char *host_strings[];
+extern char *ether_if_strings[];
+extern char *autodir;
+extern char *progname;
+extern char hostname[];
+extern char *username;
+extern char **g_argv;
+extern char *fstab_pref;
+extern char *exportfs_pref;
+extern char *mount_pref;
+extern char *dumpset_pref;
+extern char *bootparams_pref;
+extern char idvbuf[];
+
+extern int file_io_errors;
+extern int parse_errors;
+extern int errors;
+extern int verbose;
+
+extern dict *dict_of_hosts;
+extern dict *dict_of_volnames;
+
+extern char *xcalloc();
+extern char *xmalloc();
+#define ALLOC(x) ((struct x *) xcalloc(1, sizeof(struct x)))
+#define STREQ(s,t) (*(s) == *(t) && strcmp((s)+1,(t)+1) == 0)
+#define ISSET(m,b) ((m) & (1<<(b)))
+#define BITSET(m,b) ((m) |= (1<<(b)))
+
+#define FIRST(ty, q) ((ty *) ((q)->q_forw))
+#define LAST(ty, q) ((ty *) ((q)->q_back))
+#define NEXT(ty, q) ((ty *) (((qelem *) q)->q_forw))
+#define HEAD(ty, q) ((ty *) q)
+#define ITER(v, ty, q) \
+ for ((v) = FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
diff --git a/usr.sbin/amd/fsinfo/wr_atab.c b/usr.sbin/amd/fsinfo/wr_atab.c
new file mode 100644
index 0000000..3e07965
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/wr_atab.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wr_atab.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wr_atab.c,v 5.2.2.1 1992/02/09 15:09:44 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+/*
+ * Write a sequence of automount mount map entries
+ */
+static int write_amount_info(af, ap, sk)
+FILE *af;
+automount *ap;
+int sk;
+{
+ int errors = 0;
+ if (ap->a_mount) {
+ /*
+ * A pseudo-directory.
+ * This can also be a top-level directory, in which
+ * case the type:=auto is not wanted...
+ *
+ * type:=auto;fs:=${map};pref:=whatever/
+ */
+ automount *ap2;
+ if (strlen(ap->a_name) > sk) {
+ fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n",
+ ap->a_name + sk, ap->a_name + sk);
+ }
+ ITER(ap2, automount, ap->a_mount)
+ errors += write_amount_info(af, ap2, sk);
+ } else if (ap->a_mounted) {
+ /*
+ * A mounted partition
+ * type:=link [ link entries ] type:=nfs [ nfs entries ]
+ */
+ dict_data *dd;
+ dict_ent *de = ap->a_mounted;
+ int done_type_link = 0;
+ char *key = ap->a_name + sk;
+
+ /*
+ * Output the map key
+ */
+ fputs(key, af);
+
+ /*
+ * First output any Link locations that would not
+ * otherwise be correctly mounted. These refer
+ * to filesystem which are not mounted in the same
+ * place which the automounter would use.
+ */
+ ITER(dd, dict_data, &de->de_q) {
+ mount *mp = (mount *) dd->dd_data;
+ /*
+ * If the mount point and the exported volname are the
+ * same then this filesystem will be recognised by
+ * the restart code - so we don't need to put out a
+ * special rule for it.
+ */
+ if (mp->m_dk->d_host->h_lochost) {
+ char amountpt[1024];
+ compute_automount_point(amountpt, mp->m_dk->d_host, mp->m_exported->m_volname);
+ if (strcmp(mp->m_dk->d_mountpt, amountpt) != 0) {
+ /*
+ * ap->a_volname is the name of the aliased volume
+ * mp->m_name is the mount point of the filesystem
+ * mp->m_volname is the volume name of the filesystems
+ */
+
+ /*
+ * Find length of key and volume names
+ */
+ int avlen = strlen(ap->a_volname);
+ int mnlen = strlen(mp->m_volname);
+ /*
+ * Make sure a -type:=link is output once
+ */
+ if (!done_type_link) {
+ done_type_link = 1;
+ fputs(" -type:=link", af);
+ }
+ /*
+ * Output a selector for the hostname,
+ * the device from which to mount and
+ * where to mount. This will correspond
+ * to the values output for the fstab.
+ */
+ if (mp->m_dk->d_host->h_lochost)
+ fprintf(af, " host==%s", mp->m_dk->d_host->h_lochost);
+ else
+ fprintf(af, " hostd==%s", mp->m_dk->d_host->h_hostname);
+ fprintf(af, ";fs:=%s", mp->m_name);
+ /*
+ * ... and a sublink if needed
+ */
+ if (mnlen < avlen) {
+ char *sublink = ap->a_volname + mnlen + 1;
+ fprintf(af, "/%s", sublink);
+ }
+ fputs(" ||", af);
+ }
+ }
+ }
+
+ /*
+ * Next do the NFS locations
+ */
+
+ if (done_type_link)
+ fputs(" -", af);
+
+ ITER(dd, dict_data, &de->de_q) {
+ mount *mp = (mount *) dd->dd_data;
+ int namelen = mp->m_name_len;
+ int exp_namelen = mp->m_exported->m_name_len;
+ int volnlen = strlen(ap->a_volname);
+ int mvolnlen = strlen(mp->m_volname);
+ fputc(' ', af);
+#ifdef notdef
+ fprintf(af, "\\\n /* avolname = %s, mname = %s,\n * mvolname = %s, mexp_name = %s,\n * mexp_volname = %s\n */\\\n",
+ ap->a_volname, mp->m_name, mp->m_volname, mp->m_exported->m_name, mp->m_exported->m_volname);
+#endif
+ /*
+ * Output any selectors
+ */
+ if (mp->m_sel)
+ fprintf(af, "%s;", mp->m_sel);
+ /*
+ * Print host and volname of exported filesystem
+ */
+ fprintf(af, "rhost:=%s",
+ mp->m_dk->d_host->h_lochost ?
+ mp->m_dk->d_host->h_lochost :
+ mp->m_dk->d_host->h_hostname);
+ fprintf(af, ";rfs:=%s", mp->m_exported->m_volname);
+ /*
+ * Now determine whether a sublink is required.
+ */
+ if (exp_namelen < namelen || mvolnlen < volnlen) {
+ char sublink[1024];
+ sublink[0] = '\0';
+ if (exp_namelen < namelen) {
+ strcat(sublink, mp->m_name + exp_namelen + 1);
+ if (mvolnlen < volnlen)
+ strcat(sublink, "/");
+ }
+ if (mvolnlen < volnlen)
+ strcat(sublink, ap->a_volname + mvolnlen + 1);
+
+ fprintf(af, ";sublink:=%s", sublink);
+ }
+ }
+ fputc('\n', af);
+ } else if (ap->a_symlink) {
+ /*
+ * A specific link.
+ *
+ * type:=link;fs:=whatever
+ */
+ fprintf(af, "%s type:=link;fs:=%s\n", ap->a_name + sk, ap->a_symlink);
+ }
+ return errors;
+}
+
+/*
+ * Write a single automount configuration file
+ */
+static int write_amount(q, def)
+qelem *q;
+char *def;
+{
+ automount *ap;
+ int errors = 0;
+ int direct = 0;
+
+ /*
+ * Output all indirect maps
+ */
+ ITER(ap, automount, q) {
+ FILE *af;
+ char *p;
+ /*
+ * If there is no a_mount node then this is really
+ * a direct mount, so just keep a count and continue.
+ * Direct mounts are output into a special file during
+ * the second pass below.
+ */
+ if (!ap->a_mount) {
+ direct++;
+ continue;
+ }
+ p = strrchr(ap->a_name, '/');
+ if (!p) p = ap->a_name;
+ else p++;
+ af = pref_open(mount_pref, p, gen_hdr, ap->a_name);
+ if (af) {
+ show_new(ap->a_name);
+ fputs("/defaults ", af);
+ if (*def)
+ fprintf(af, "%s;", def);
+ fputs("type:=nfs\n", af);
+ errors += write_amount_info(af, ap, strlen(ap->a_name) + 1);
+ errors += pref_close(af);
+ }
+ }
+
+ /*
+ * Output any direct map entries which were found during the
+ * previous pass over the data.
+ */
+ if (direct) {
+ FILE *af = pref_open(mount_pref, "direct.map", info_hdr, "direct mount");
+ if (af) {
+ show_new("direct mounts");
+ fputs("/defaults ", af);
+ if (*def)
+ fprintf(af, "%s;", def);
+ fputs("type:=nfs\n", af);
+ ITER(ap, automount, q)
+ if (!ap->a_mount)
+ errors += write_amount_info(af, ap, 1);
+ errors += pref_close(af);
+ }
+ }
+
+ return errors;
+}
+
+/*
+ * Write all the needed automount configuration files
+ */
+write_atab(q)
+qelem *q;
+{
+ int errors = 0;
+
+ if (mount_pref) {
+ auto_tree *tp;
+ show_area_being_processed("write automount", "");
+ ITER(tp, auto_tree, q)
+ errors += write_amount(tp->t_mount, tp->t_defaults);
+ }
+
+ return errors;
+}
diff --git a/usr.sbin/amd/fsinfo/wr_bparam.c b/usr.sbin/amd/fsinfo/wr_bparam.c
new file mode 100644
index 0000000..9ef0fcd
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/wr_bparam.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wr_bparam.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wr_bparam.c,v 5.2.2.1 1992/02/09 15:09:46 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+/*
+ * Write a host/path in NFS format
+ */
+static int write_nfsname(ef, fp, hn)
+FILE *ef;
+fsmount *fp;
+char *hn;
+{
+ int errors = 0;
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ domain_strip(h, hn);
+ fprintf(ef, "%s:%s", h, fp->f_volname);
+ free(h);
+ return errors;
+}
+
+/*
+ * Write a bootparams entry for a host
+ */
+static int write_boot_info(ef, hp)
+FILE *ef;
+host *hp;
+{
+ int errors = 0;
+ fprintf(ef, "%s\troot=", hp->h_hostname);
+ errors += write_nfsname(ef, hp->h_netroot, hp->h_hostname);
+ fputs(" swap=", ef);
+ errors += write_nfsname(ef, hp->h_netswap, hp->h_hostname);
+ fputs("\n", ef);
+
+ return 0;
+}
+
+/*
+ * Output a bootparams file
+ */
+int write_bootparams(q)
+qelem *q;
+{
+ int errors = 0;
+
+ if (bootparams_pref) {
+ FILE *ef = pref_open(bootparams_pref, "bootparams", info_hdr, "bootparams");
+ if (ef) {
+ host *hp;
+ ITER(hp, host, q)
+ if (hp->h_netroot && hp->h_netswap)
+ errors += write_boot_info(ef, hp);
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+
+ return errors;
+}
diff --git a/usr.sbin/amd/fsinfo/wr_dumpset.c b/usr.sbin/amd/fsinfo/wr_dumpset.c
new file mode 100644
index 0000000..d118feb
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/wr_dumpset.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wr_dumpset.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wr_dumpset.c,v 5.2.2.1 1992/02/09 15:09:47 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+static int write_dumpset_info(ef, q)
+FILE *ef;
+qelem *q;
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ if (dp->d_dumpset) {
+ fprintf(ef, "%s\t%s:%-30s\t# %s\n",
+ dp->d_dumpset,
+ dp->d_host->h_lochost ?
+ dp->d_host->h_lochost :
+ dp->d_host->h_hostname,
+ dp->d_mountpt,
+ dp->d_dev);
+ }
+ }
+ return errors;
+}
+
+int write_dumpset(q)
+qelem *q;
+{
+ int errors = 0;
+
+ if (dumpset_pref) {
+ FILE *ef = pref_open(dumpset_pref, "dumpsets", info_hdr, "exabyte dumpset");
+ if (ef) {
+ host *hp;
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs) {
+ errors += write_dumpset_info(ef, hp->h_disk_fs);
+ }
+ }
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+
+ return errors;
+}
diff --git a/usr.sbin/amd/fsinfo/wr_exportfs.c b/usr.sbin/amd/fsinfo/wr_exportfs.c
new file mode 100644
index 0000000..982b538f
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/wr_exportfs.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wr_exportfs.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wr_exportfs.c,v 5.2.2.1 1992/02/09 15:09:48 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+static int write_export_info(ef, q, errors)
+FILE *ef;
+qelem *q;
+int errors;
+{
+ mount *mp;
+
+ ITER(mp, mount, q) {
+ if (mp->m_mask & (1<<DM_EXPORTFS))
+ fprintf(ef, "%s\t%s\n", mp->m_volname, mp->m_exportfs);
+ if (mp->m_mount)
+ errors += write_export_info(ef, mp->m_mount, 0);
+ }
+
+ return errors;
+}
+
+static int write_dkexports(ef, q)
+FILE *ef;
+qelem *q;
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ if (dp->d_mount)
+ errors += write_export_info(ef, dp->d_mount, 0);
+ }
+ return errors;
+}
+
+int write_exportfs(q)
+qelem *q;
+{
+ int errors = 0;
+
+ if (exportfs_pref) {
+ host *hp;
+ show_area_being_processed("write exportfs", "");
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs) {
+ FILE *ef = pref_open(exportfs_pref, hp->h_hostname, gen_hdr, hp->h_hostname);
+ if (ef) {
+ show_new(hp->h_hostname);
+ errors += write_dkexports(ef, hp->h_disk_fs);
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+ }
+ }
+
+ return errors;
+}
diff --git a/usr.sbin/amd/fsinfo/wr_fstab.c b/usr.sbin/amd/fsinfo/wr_fstab.c
new file mode 100644
index 0000000..85d3687
--- /dev/null
+++ b/usr.sbin/amd/fsinfo/wr_fstab.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)wr_fstab.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: wr_fstab.c,v 5.2.2.1 1992/02/09 15:09:49 jsp beta $
+ *
+ */
+
+#include "../fsinfo/fsinfo.h"
+
+/* ---------- AIX 1 ------------------------------ */
+
+/*
+ * AIX 1 format
+ */
+static void write_aix1_dkfstab(ef, dp)
+FILE *ef;
+disk_fs *dp;
+{
+ char *hp = strdup(dp->d_host->h_hostname);
+ char *p = strchr(hp, '.');
+ if (p)
+ *p = '\0';
+
+ fprintf(ef, "\n%s:\n\tdev = %s\n\tvfs = %s\n\ttype = %s\n\tlog = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ dp->d_mountpt,
+ dp->d_dev,
+ dp->d_fstype,
+ dp->d_fstype,
+ dp->d_log,
+ dp->d_mountpt,
+ dp->d_opts);
+ free(hp);
+}
+
+static void write_aix1_dkrmount(ef, hn, fp)
+FILE *ef;
+char *hn;
+fsmount *fp;
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ char *hp = strdup(h);
+ char *p = strchr(hp, '.');
+ if (p)
+ *p = '\0';
+ domain_strip(h, hn);
+ fprintf(ef, "\n%s:\n\tsite = %s\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ fp->f_localname,
+ hp,
+ h,
+ fp->f_volname,
+ fp->f_fstype,
+ fp->f_fstype,
+ fp->f_localname,
+ fp->f_opts);
+
+ free(hp);
+ free(h);
+}
+
+/* ---------- AIX 3 ------------------------------ */
+
+/*
+ * AIX 3 format
+ */
+static void write_aix3_dkfstab(ef, dp)
+FILE *ef;
+disk_fs *dp;
+{
+ if (strcmp(dp->d_fstype, "jfs") == 0 && strncmp(dp->d_dev, "/dev/", 5) == 0 && !dp->d_log)
+ error("aix 3 needs a log device for journalled filesystem (jfs) mounts");
+
+ fprintf(ef, "\n%s:\n\tdev = %s\n\tvfs = %s\n\ttype = %s\n\tlog = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ dp->d_mountpt,
+ dp->d_dev,
+ dp->d_fstype,
+ dp->d_fstype,
+ dp->d_log,
+ dp->d_mountpt,
+ dp->d_opts);
+}
+
+static void write_aix3_dkrmount(ef, hn, fp)
+FILE *ef;
+char *hn;
+fsmount *fp;
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ domain_strip(h, hn);
+ fprintf(ef, "\n%s:\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ fp->f_localname,
+ h,
+ fp->f_volname,
+ fp->f_fstype,
+ fp->f_fstype,
+ fp->f_localname,
+ fp->f_opts);
+
+ free(h);
+}
+
+/* ---------- Ultrix ----------------------------- */
+
+static void write_ultrix_dkfstab(ef, dp)
+FILE *ef;
+disk_fs *dp;
+{
+ fprintf(ef, "%s:%s:%s:%s:%d:%d\n",
+ dp->d_dev,
+ dp->d_mountpt,
+ dp->d_fstype,
+ dp->d_opts,
+ dp->d_freq,
+ dp->d_passno);
+}
+
+static void write_ultrix_dkrmount(ef, hn, fp)
+FILE *ef;
+char *hn;
+fsmount *fp;
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ domain_strip(h, hn);
+ fprintf(ef, "%s@%s:%s:%s:%s:0:0\n",
+ fp->f_volname,
+ h,
+ fp->f_localname,
+ fp->f_fstype,
+ fp->f_opts);
+ free(h);
+}
+
+/* ---------- Generic ---------------------------- */
+
+/*
+ * Generic (BSD, SunOS, HPUX) format
+ */
+static void write_generic_dkfstab(ef, dp)
+FILE *ef;
+disk_fs *dp;
+{
+ fprintf(ef, "%s %s %s %s %d %d\n",
+ dp->d_dev,
+ dp->d_mountpt,
+ dp->d_fstype,
+ dp->d_opts,
+ dp->d_freq,
+ dp->d_passno);
+}
+
+static void write_generic_dkrmount(ef, hn, fp)
+FILE *ef;
+char *hn;
+fsmount *fp;
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ domain_strip(h, hn);
+ fprintf(ef, "%s:%s %s %s %s 0 0\n",
+ h,
+ fp->f_volname,
+ fp->f_localname,
+ fp->f_fstype,
+ fp->f_opts);
+ free(h);
+}
+
+/* ----------------------------------------------- */
+
+static struct os_fstab_type {
+ char *os_name;
+ void (*op_fstab)();
+ void (*op_mount)();
+} os_tabs[] = {
+ { "aix1", write_aix1_dkfstab, write_aix1_dkrmount }, /* AIX 1 */
+ { "aix3", write_aix3_dkfstab, write_aix3_dkrmount }, /* AIX 3 */
+ { "generic", write_generic_dkfstab, write_generic_dkrmount }, /* Generic */
+ { "u2_0", write_ultrix_dkfstab, write_ultrix_dkrmount }, /* Ultrix */
+ { "u3_0", write_ultrix_dkfstab, write_ultrix_dkrmount }, /* Ultrix */
+ { "u4_0", write_ultrix_dkfstab, write_ultrix_dkrmount }, /* Ultrix */
+ { 0, 0, 0 }
+};
+
+#define GENERIC_OS_NAME "generic"
+
+static struct os_fstab_type *find_fstab_type(hp)
+host *hp;
+{
+ struct os_fstab_type *op = 0;
+ char *os_name = 0;
+
+again:;
+ if (os_name == 0) {
+ if (ISSET(hp->h_mask, HF_OS))
+ os_name = hp->h_os;
+ else
+ os_name = GENERIC_OS_NAME;
+ }
+
+ for (op = os_tabs; op->os_name; op++)
+ if (strcmp(os_name, op->os_name) == 0)
+ return op;
+
+ os_name = GENERIC_OS_NAME;
+ goto again;
+}
+
+static int write_dkfstab(ef, q, output)
+FILE *ef;
+qelem *q;
+void (*output)();
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q)
+ if (strcmp(dp->d_fstype, "export") != 0)
+ (*output)(ef, dp);
+
+ return errors;
+}
+
+static int write_dkrmount(ef, q, hn, output)
+FILE *ef;
+qelem *q;
+char *hn;
+void (*output)();
+{
+ int errors = 0;
+ fsmount *fp;
+
+ ITER(fp, fsmount, q)
+ (*output)(ef, hn, fp);
+
+ return errors;
+}
+
+int write_fstab(q)
+qelem *q;
+{
+ int errors = 0;
+
+ if (fstab_pref) {
+ host *hp;
+ show_area_being_processed("write fstab", 4);
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs || hp->h_mount) {
+ FILE *ef = pref_open(fstab_pref, hp->h_hostname, gen_hdr, hp->h_hostname);
+ if (ef) {
+ struct os_fstab_type *op = find_fstab_type(hp);
+ show_new(hp->h_hostname);
+ if (hp->h_disk_fs)
+ errors += write_dkfstab(ef, hp->h_disk_fs, op->op_fstab);
+ else
+ log("No local disk mounts on %s", hp->h_hostname);
+
+ if (hp->h_mount)
+ errors += write_dkrmount(ef, hp->h_mount, hp->h_hostname, op->op_mount);
+
+ pref_close(ef);
+ }
+ } else {
+ error("no disk mounts on %s", hp->h_hostname);
+ }
+ }
+ }
+
+ return errors;
+}
diff --git a/usr.sbin/amd/include/am.h b/usr.sbin/amd/include/am.h
new file mode 100644
index 0000000..14a728d
--- /dev/null
+++ b/usr.sbin/amd/include/am.h
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)am.h 5.6 (Berkeley) 6/6/93
+ *
+ * $Id: am.h,v 5.2.2.1 1992/02/09 15:09:54 jsp beta $
+ *
+ */
+
+#include "config.h"
+
+/*
+ * Global declarations
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include "nfs_prot.h"
+#ifdef MNTENT_HDR
+#include MNTENT_HDR
+#endif /* MNTENT_HDR */
+#include <assert.h>
+
+#ifdef DEBUG_MEM
+#include <malloc.h>
+#endif /* DEBUG_MEM */
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif /* MAXHOSTNAMELEN */
+
+#ifndef MNTTYPE_AUTO
+#define MNTTYPE_AUTO "auto"
+#endif /* MNTTYPE_AUTO */
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif /* FALSE */
+
+#ifndef ROOT_MAP
+#define ROOT_MAP "\"root\""
+#endif /* ROOT_MAP */
+
+/*
+ * Flags from command line
+ */
+extern int print_pid; /* Print pid to stdout */
+extern int normalize_hosts; /* Normalize host names before use */
+extern int restart_existing_mounts;
+#ifdef HAS_NIS_MAPS
+extern char *domain; /* NIS domain to use */
+#endif /* HAS_NIS_MAPS */
+extern int am_timeo; /* Cache period */
+extern int afs_timeo; /* AFS timeout */
+extern int afs_retrans; /* AFS retrans */
+extern int am_timeo_w; /* Unmount timeout */
+extern char *mtab; /* Mount table */
+
+typedef enum {
+ Start,
+ Run,
+ Finishing,
+ Quit,
+ Done
+} serv_state;
+
+extern serv_state amd_state; /* Should we go now */
+extern int immediate_abort; /* Should close-down unmounts be retried */
+extern time_t do_mapc_reload; /* Flush & reload mount map cache */
+
+/*
+ * Useful constants
+ */
+extern char pid_fsname[]; /* kiska.southseas.nz:(pid%d) */
+extern char hostd[]; /* "kiska.southseas.nz" */
+extern char *hostdomain; /* "southseas.nz" */
+extern char *op_sys; /* "sos4" */
+extern char *arch; /* "sun4" */
+extern char *karch; /* "sun4c" */
+extern char *cluster; /* "r+d-kluster" */
+extern char *endian; /* "big" */
+extern char *auto_dir; /* "/a" */
+extern char copyright[]; /* Copyright info */
+extern char version[]; /* Version info */
+
+typedef struct am_ops am_ops;
+typedef struct am_node am_node;
+typedef struct am_opts am_opts;
+typedef struct mntfs mntfs;
+typedef struct fserver fserver;
+typedef struct fsrvinfo fsrvinfo;
+
+/*
+ * Debug defns.
+ */
+#ifdef DEBUG
+#define DEBUG_MTAB "./mtab"
+
+extern int debug_flags; /* Debug options */
+
+#define D_DAEMON 0x0001 /* Enter daemon mode */
+#define D_TRACE 0x0002 /* Do protocol trace */
+#define D_FULL 0x0004 /* Do full trace */
+#define D_MTAB 0x0008 /* Use local mtab */
+#define D_AMQ 0x0010 /* Register amq program */
+#define D_STR 0x0020 /* Debug string munging */
+#define D_MEM 0x0040 /* Trace memory allocations */
+
+/*
+ * Normally, don't enter daemon mode, and don't register amq
+ */
+#define D_TEST (~(D_DAEMON|D_MEM|D_STR))
+#endif /* DEBUG */
+
+/*
+ * Global variables.
+ */
+extern unsigned short nfs_port; /* Our NFS service port */
+extern struct in_addr myipaddr; /* (An) IP address of this host */
+
+extern int foreground; /* Foreground process */
+extern time_t next_softclock; /* Time to call softclock() */
+extern int task_notify_todo; /* Task notifier needs running */
+#ifdef HAS_TFS
+extern int nfs_server_code_available;
+#endif /* HAS_TFS */
+extern int last_used_map; /* Last map being used for mounts */
+extern AUTH *nfs_auth; /* Dummy uthorisation for remote servers */
+extern am_node **exported_ap; /* List of nodes */
+extern int first_free_map; /* First free node */
+extern am_node *root_node; /* Node for "root" */
+extern char *wire; /* Name of primary connected network */
+#define NEXP_AP (254)
+#define NEXP_AP_MARGIN (128)
+
+typedef int (*task_fun)P((voidp));
+typedef void (*cb_fun)P((int, int, voidp));
+typedef void (*fwd_fun)P((voidp, int, struct sockaddr_in *,
+ struct sockaddr_in *, voidp, int));
+
+/*
+ * String comparison macros
+ */
+#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
+#define FSTREQ(s1, s2) ((*(s1) == *(s2)) && STREQ((s1),(s2)))
+
+/*
+ * Linked list
+ */
+typedef struct qelem qelem;
+struct qelem {
+ qelem *q_forw;
+ qelem *q_back;
+};
+#define FIRST(ty, q) ((ty *) ((q)->q_forw))
+#define LAST(ty, q) ((ty *) ((q)->q_back))
+#define NEXT(ty, q) ((ty *) (((qelem *) q)->q_forw))
+#define PREV(ty, q) ((ty *) (((qelem *) q)->q_back))
+#define HEAD(ty, q) ((ty *) q)
+#define ITER(v, ty, q) \
+ for ((v) = FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
+
+/*
+ * List of mount table entries
+ */
+typedef struct mntlist mntlist;
+struct mntlist {
+ struct mntlist *mnext;
+ struct mntent *mnt;
+};
+
+/*
+ * Mount map
+ */
+typedef struct mnt_map mnt_map;
+
+/*
+ * Global routines
+ */
+extern int atoi P((Const char *)); /* C */
+extern void am_mounted P((am_node*));
+extern void am_unmounted P((am_node*));
+extern int background(P_void);
+extern int bind_resv_port P((int, unsigned short*));
+extern int compute_mount_flags P((struct mntent *));
+extern int softclock(P_void);
+#ifdef DEBUG
+extern int debug_option P((char*));
+#endif /* DEBUG */
+extern void deslashify P((char*));
+/*extern void domain_strip P((char*, char*));*/
+extern mntfs* dup_mntfs P((mntfs*));
+extern fserver* dup_srvr P((fserver*));
+extern int eval_fs_opts P((am_opts*, char*, char*, char*, char*, char*));
+extern char* expand_key P((char*));
+extern am_node* exported_ap_alloc(P_void);
+extern am_node* find_ap P((char*));
+extern am_node* find_mf P((mntfs*));
+extern mntfs* find_mntfs P((am_ops*, am_opts*, char*, char*, char*, char*, char*));
+extern void flush_mntfs(P_void);
+extern void flush_nfs_fhandle_cache P((fserver*));
+extern void forcibly_timeout_mp P((am_node*));
+extern FREE_RETURN_TYPE free P((voidp)); /* C */
+extern void free_mntfs P((mntfs*));
+extern void free_opts P((am_opts*));
+extern void free_map P((am_node*));
+extern void free_mntlist P((mntlist*));
+extern void free_srvr P((fserver*));
+extern int fwd_init(P_void);
+extern int fwd_packet P((int, voidp, int, struct sockaddr_in *,
+ struct sockaddr_in *, voidp, fwd_fun));
+extern void fwd_reply(P_void);
+extern void get_args P((int, char*[]));
+extern char *getwire P((void));
+#ifdef NEED_MNTOPT_PARSER
+extern char *hasmntopt P((struct mntent*, char*));
+#endif /* NEED_MNTOPT_PARSER */
+extern int hasmntval P((struct mntent*, char*));
+extern void host_normalize P((char **));
+extern char *inet_dquad P((char*, unsigned long));
+extern void init_map P((am_node*, char*));
+extern void insert_am P((am_node*, am_node*));
+extern void ins_que P((qelem*, qelem*));
+extern int islocalnet P((unsigned long));
+extern int make_nfs_auth P((void));
+extern void make_root_node(P_void);
+extern int make_rpc_packet P((char*, int, u_long, struct rpc_msg*, voidp, xdrproc_t, AUTH*));
+extern void map_flush_srvr P((fserver*));
+extern void mapc_add_kv P((mnt_map*, char*, char*));
+extern mnt_map* mapc_find P((char*, char*));
+extern void mapc_free P((mnt_map*));
+extern int mapc_keyiter P((mnt_map*, void (*)(char*,voidp), voidp));
+extern int mapc_search P((mnt_map*, char*, char**));
+extern void mapc_reload(P_void);
+extern void mapc_showtypes P((FILE*));
+extern int mkdirs P((char*, int));
+extern void mk_fattr P((am_node*, enum ftype));
+extern void mnt_free P((struct mntent*));
+extern int mount_auto_node P((char*, voidp));
+extern int mount_automounter P((int));
+extern int mount_exported(P_void);
+extern int mount_fs P((struct mntent*, int, caddr_t, int, MTYPE_TYPE));
+/*extern int mount_nfs_fh P((struct fhstatus*, char*, char*, char*, mntfs*));*/
+extern int mount_node P((am_node*));
+extern mntfs* new_mntfs(P_void);
+extern void new_ttl P((am_node*));
+extern am_node* next_map P((int*));
+extern int nfs_srvr_port P((fserver*, u_short*, voidp));
+extern void normalize_slash P((char*));
+extern void ops_showfstypes P((FILE*));
+extern int pickup_rpc_reply P((voidp, int, voidp, xdrproc_t));
+extern mntlist* read_mtab P((char*));
+extern mntfs* realloc_mntfs P((mntfs*, am_ops*, am_opts*, char*, char*, char*, char*, char*));
+extern void rem_que P((qelem*));
+extern void reschedule_timeout_mp(P_void);
+extern void restart(P_void);
+#ifdef UPDATE_MTAB
+extern void rewrite_mtab P((mntlist *));
+#endif /* UPDATE_MTAB */
+extern void rmdirs P((char*));
+extern am_node* root_ap P((char*, int));
+extern int root_keyiter P((void (*)(char*,voidp), voidp));
+extern void root_newmap P((char*, char*, char*));
+extern void rpc_msg_init P((struct rpc_msg*, u_long, u_long, u_long));
+extern void run_task P((task_fun, voidp, cb_fun, voidp));
+extern void sched_task P((cb_fun, voidp, voidp));
+extern void show_rcs_info P((Const char*, char*));
+extern void sigchld P((int));
+extern void srvrlog P((fserver*, char*));
+extern char* str3cat P((char*, char*, char*, char*));
+extern char* strcat P((char*, Const char*)); /* C */
+extern int strcmp P((Const char*, Const char*)); /* C */
+extern char* strdup P((Const char*));
+extern int strlen P((Const char*)); /* C */
+extern char* strnsave P((Const char*, int));
+extern char* strrchr P((Const char*, int)); /* C */
+extern char* strealloc P((char*, char *));
+extern char** strsplit P((char*, int, int));
+extern int switch_option P((char*));
+extern int switch_to_logfile P((char*));
+extern void do_task_notify(P_void);
+extern int timeout P((unsigned int, void (*fn)(), voidp));
+extern void timeout_mp(P_void);
+extern void umount_exported(P_void);
+extern int umount_fs P((char*));
+/*extern int unmount_node P((am_node*));
+extern int unmount_node_wrap P((voidp));*/
+extern void unregister_amq(P_void);
+extern void untimeout P((int));
+extern int valid_key P((char*));
+extern void wakeup P((voidp));
+extern void wakeup_task P((int,int,voidp));
+extern void wakeup_srvr P((fserver*));
+extern void write_mntent P((struct mntent*));
+#ifdef UPDATE_MTAB
+extern void unlock_mntlist P((void));
+#else
+#define unlock_mntlist()
+#endif /* UPDATE_MTAB */
+
+
+#define ALLOC(ty) ((struct ty *) xmalloc(sizeof(struct ty)))
+
+/*
+ * Options
+ */
+struct am_opts {
+ char *fs_glob; /* Smashed copy of global options */
+ char *fs_local; /* Expanded copy of local options */
+ char *fs_mtab; /* Mount table entry */
+ /* Other options ... */
+ char *opt_dev;
+ char *opt_delay;
+ char *opt_dir;
+ char *opt_fs;
+ char *opt_group;
+ char *opt_mount;
+ char *opt_opts;
+ char *opt_remopts;
+ char *opt_pref;
+ char *opt_cache;
+ char *opt_rfs;
+ char *opt_rhost;
+ char *opt_sublink;
+ char *opt_type;
+ char *opt_unmount;
+ char *opt_user;
+};
+
+/*
+ * File Handle
+ *
+ * This is interpreted by indexing the exported array
+ * by fhh_id.
+ *
+ * The whole structure is mapped onto a standard fhandle_t
+ * when transmitted.
+ */
+struct am_fh {
+ int fhh_pid; /* process id */
+ int fhh_id; /* map id */
+ int fhh_gen; /* generation number */
+};
+
+extern am_node *fh_to_mp P((nfs_fh*));
+extern am_node *fh_to_mp3 P((nfs_fh*,int*,int));
+extern void mp_to_fh P((am_node*, nfs_fh*));
+#define fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
+extern int auto_fmount P((am_node *mp));
+extern int auto_fumount P((am_node *mp));
+
+#define MAX_READDIR_ENTRIES 16
+
+typedef char* (*vfs_match)P((am_opts*));
+typedef int (*vfs_init)P((mntfs*));
+typedef int (*vmount_fs)P((am_node*));
+typedef int (*vfmount_fs)P((mntfs*));
+typedef int (*vumount_fs)P((am_node*));
+typedef int (*vfumount_fs)P((mntfs*));
+typedef am_node*(*vlookuppn)P((am_node*, char*, int*, int));
+typedef int (*vreaddir)P((am_node*, nfscookie, dirlist*, entry*, int));
+typedef am_node*(*vreadlink)P((am_node*, int*));
+typedef void (*vmounted)P((mntfs*));
+typedef void (*vumounted)P((am_node*));
+typedef fserver*(*vffserver)P((mntfs*));
+
+struct am_ops {
+ char *fs_type;
+ vfs_match fs_match;
+ vfs_init fs_init;
+ vmount_fs mount_fs;
+ vfmount_fs fmount_fs;
+ vumount_fs umount_fs;
+ vfumount_fs fumount_fs;
+ vlookuppn lookuppn;
+ vreaddir readdir;
+ vreadlink readlink;
+ vmounted mounted;
+ vumounted umounted;
+ vffserver ffserver;
+ int fs_flags;
+};
+extern am_node *efs_lookuppn P((am_node*, char*, int*, int));
+extern int efs_readdir P((am_node*, nfscookie, dirlist*, entry*, int));
+
+#define VLOOK_CREATE 0x1
+#define VLOOK_DELETE 0x2
+
+#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
+#define FS_MBACKGROUND 0x0002 /* Should background this mount */
+#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
+#define FS_MKMNT 0x0008 /* Need to make the mount point */
+#define FS_UBACKGROUND 0x0010 /* Unmount in background */
+#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
+#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
+#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
+
+#ifdef SUNOS4_COMPAT
+extern am_ops *sunos4_match P((am_opts*, char*, char*, char*, char*, char*));
+#endif /* SUNOS4_COMPAT */
+extern am_ops *ops_match P((am_opts*, char*, char*, char*, char*, char*));
+#include "fstype.h"
+
+/*
+ * Per-mountpoint statistics
+ */
+struct am_stats {
+ time_t s_mtime; /* Mount time */
+ u_short s_uid; /* Uid of mounter */
+ int s_getattr; /* Count of getattrs */
+ int s_lookup; /* Count of lookups */
+ int s_readdir; /* Count of readdirs */
+ int s_readlink; /* Count of readlinks */
+ int s_statfs; /* Count of statfs */
+};
+typedef struct am_stats am_stats;
+
+/*
+ * System statistics
+ */
+struct amd_stats {
+ int d_drops; /* Dropped requests */
+ int d_stale; /* Stale NFS handles */
+ int d_mok; /* Succesful mounts */
+ int d_merr; /* Failed mounts */
+ int d_uerr; /* Failed unmounts */
+};
+extern struct amd_stats amd_stats;
+
+/*
+ * List of fileservers
+ */
+struct fserver {
+ qelem fs_q; /* List of fileservers */
+ int fs_refc; /* Number of references to this node */
+ char *fs_host; /* Normalized hostname of server */
+ struct sockaddr_in *fs_ip; /* Network address of server */
+ int fs_cid; /* Callout id */
+ int fs_pinger; /* Ping (keepalive) interval */
+ int fs_flags; /* Flags */
+ char *fs_type; /* File server type */
+ voidp fs_private; /* Private data */
+ void (*fs_prfree)(); /* Free private data */
+};
+#define FSF_VALID 0x0001 /* Valid information available */
+#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
+#define FSF_ERROR 0x0004 /* Permanent error has occured */
+#define FSF_WANT 0x0008 /* Want a wakeup call */
+#define FSF_PINGING 0x0010 /* Already doing pings */
+#define FSRV_ISDOWN(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
+#define FSRV_ISUP(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
+
+/*
+ * List of mounted filesystems
+ */
+struct mntfs {
+ qelem mf_q; /* List of mounted filesystems */
+ am_ops *mf_ops; /* Operations on this mountpoint */
+ am_opts *mf_fo; /* File opts */
+ char *mf_mount; /* "/a/kiska/home/kiska" */
+ char *mf_info; /* Mount info */
+ char *mf_auto; /* Automount opts */
+ char *mf_mopts; /* FS mount opts */
+ char *mf_remopts; /* Remote FS mount opts */
+ fserver *mf_server; /* File server */
+ int mf_flags; /* Flags */
+ int mf_error; /* Error code from background mount */
+ int mf_refc; /* Number of references to this node */
+ int mf_cid; /* Callout id */
+ void (*mf_prfree)(); /* Free private space */
+ voidp mf_private; /* Private - per-fs data */
+};
+
+#define MFF_MOUNTED 0x0001 /* Node is mounted */
+#define MFF_MOUNTING 0x0002 /* Mount is in progress */
+#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
+#define MFF_RESTART 0x0008 /* Restarted node */
+#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
+#define MFF_ERROR 0x0020 /* This node failed to mount */
+#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
+#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
+#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
+
+/*
+ * Map of auto-mount points.
+ */
+struct am_node {
+ int am_mapno; /* Map number */
+ mntfs *am_mnt; /* Mounted filesystem */
+ char *am_name; /* "kiska"
+ Name of this node */
+ char *am_path; /* "/home/kiska"
+ Path of this node's mount point */
+ char *am_link; /* "/a/kiska/home/kiska/this/that"
+ Link to sub-directory */
+ am_node *am_parent, /* Parent of this node */
+ *am_ysib, /* Younger sibling of this node */
+ *am_osib, /* Older sibling of this node */
+ *am_child; /* First child of this node */
+ struct attrstat am_attr; /* File attributes */
+#define am_fattr am_attr.attrstat_u.attributes
+ int am_flags; /* Boolean flags */
+ int am_error; /* Specific mount error */
+ time_t am_ttl; /* Time to live */
+ int am_timeo_w; /* Wait interval */
+ int am_timeo; /* Timeout interval */
+ unsigned int am_gen; /* Generation number */
+ char *am_pref; /* Mount info prefix */
+ am_stats am_stats; /* Statistics gathering */
+};
+
+#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
+#define AMF_ROOT 0x0002 /* This is a root node */
+
+#define ONE_HOUR (60 * 60) /* One hour in seconds */
+
+/*
+ * The following values can be tuned...
+ */
+#define ALLOWED_MOUNT_TIME 40 /* 40s for a mount */
+#define AM_TTL (5 * 60) /* Default cache period */
+#define AM_TTL_W (2 * 60) /* Default unmount interval */
+#define AM_PINGER 30 /* NFS ping interval for live systems */
+#define AFS_TIMEO 8 /* Default afs timeout - .8s */
+#define AFS_RETRANS ((ALLOWED_MOUNT_TIME*10+5*afs_timeo)/afs_timeo * 2)
+ /* Default afs retrans - 1/10th seconds */
+
+#define RPC_XID_PORTMAP 0
+#define RPC_XID_MOUNTD 1
+#define RPC_XID_NFSPING 2
+#define RPC_XID_MASK (0x0f) /* 16 id's for now */
+#define MK_RPC_XID(type_id, uniq) ((type_id) | ((uniq) << 4))
diff --git a/usr.sbin/amd/include/config.h b/usr.sbin/amd/include/config.h
new file mode 100644
index 0000000..09b77bf
--- /dev/null
+++ b/usr.sbin/amd/include/config.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)config.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: config.h,v 5.2.2.1 1992/02/09 15:09:56 jsp beta $
+ *
+ */
+
+/*
+ * Get this in now so that OS_HDR can use it
+ */
+#ifdef __STDC__
+#define P(x) x
+#define P_void void
+#define Const const
+#else
+#define P(x) ()
+#define P_void /* as nothing */
+#define Const /* as nothing */
+#endif /* __STDC__ */
+
+#ifdef __GNUC__
+#define INLINE /* __inline */
+#else
+#define INLINE
+#endif /* __GNUC__ */
+
+/*
+ * Pick up target dependent definitions
+ */
+#include "os-defaults.h"
+#include OS_HDR
+
+#ifdef VOIDP
+typedef void *voidp;
+#else
+typedef char *voidp;
+#endif /* VOIDP */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+extern int errno;
+#include <sys/time.h>
+
+#define clocktime() (clock_valid ? clock_valid : time(&clock_valid))
+extern time_t time P((time_t *));
+extern time_t clock_valid; /* Clock needs recalculating */
+
+extern char *progname; /* "amd"|"mmd" */
+extern char hostname[]; /* "kiska" */
+extern int mypid; /* Current process id */
+
+#ifdef HAS_SYSLOG
+extern int syslogging; /* Really using syslog */
+#endif /* HAS_SYSLOG */
+extern FILE *logfp; /* Log file */
+extern int xlog_level; /* Logging level */
+extern int xlog_level_init;
+
+extern int orig_umask; /* umask() on startup */
+
+#define XLOG_FATAL 0x0001
+#define XLOG_ERROR 0x0002
+#define XLOG_USER 0x0004
+#define XLOG_WARNING 0x0008
+#define XLOG_INFO 0x0010
+#define XLOG_DEBUG 0x0020
+#define XLOG_MAP 0x0040
+#define XLOG_STATS 0x0080
+
+#define XLOG_DEFSTR "all,nomap,nostats" /* Default log options */
+#define XLOG_ALL (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
+
+#ifdef DEBUG
+#define D_ALL (~0)
+
+#ifdef DEBUG_MEM
+#define free(x) xfree(__FILE__,__LINE__,x)
+#endif /* DEBUG_MEM */
+
+#define Debug(x) if (!(debug_flags & (x))) ; else
+#define dlog Debug(D_FULL) dplog
+#endif /* DEBUG */
+
+/*
+ * Option tables
+ */
+struct opt_tab {
+ char *opt;
+ int flag;
+};
+
+extern struct opt_tab xlog_opt[];
+
+extern int cmdoption P((char*, struct opt_tab*, int*));
+extern void going_down P((int));
+#ifdef DEBUG
+extern void dplog ();
+/*extern void dplog P((char*, ...));*/
+#endif /* DEBUG */
+extern void plog ();
+/*extern void plog P((int, char*, ...));*/
+extern void show_opts P((int ch, struct opt_tab*));
+extern char* strchr P((const char*, int)); /* C */
+extern voidp xmalloc P((int));
+extern voidp xrealloc P((voidp, int));
diff --git a/usr.sbin/amd/include/fstype.h b/usr.sbin/amd/include/fstype.h
new file mode 100644
index 0000000..03493d2
--- /dev/null
+++ b/usr.sbin/amd/include/fstype.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)fstype.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: fstype.h,v 5.2.2.1 1992/02/09 15:09:57 jsp beta $
+ *
+ */
+
+/*
+ * File system types
+ */
+
+/*
+ * Automount File System
+ */
+#define HAS_AFS
+extern am_ops afs_ops; /* Automount file system (this!) */
+extern am_ops toplvl_ops; /* Top-level automount file system */
+extern am_ops root_ops; /* Root file system */
+extern qelem afs_srvr_list;
+extern fserver *find_afs_srvr P((mntfs*));
+
+/*
+ * Direct Automount File System
+ */
+#define HAS_DFS
+extern am_ops dfs_ops; /* Direct Automount file system (this too) */
+
+/*
+ * Error File System
+ */
+#define HAS_EFS
+extern am_ops efs_ops; /* Error file system */
+
+/*
+ * Inheritance File System
+ */
+#define HAS_IFS
+extern am_ops ifs_ops; /* Inheritance file system */
+
+/*
+ * Loopback File System
+ * LOFS is optional - you can compile without it.
+ */
+#ifdef OS_HAS_LOFS
+/*
+ * Most systems can't support this, and in
+ * any case most of the functionality is
+ * available with Symlink FS. In fact,
+ * lofs_ops is not yet available.
+ */
+#define HAS_LOFS
+extern am_ops lofs_ops;
+#endif
+
+/*
+ * Netw*rk File System
+ * Good, slow, NFS.
+ * NFS host - a whole tree
+ */
+#define HAS_NFS
+#define HAS_HOST
+#define HAS_NFSX
+extern am_ops nfs_ops; /* NFS */
+extern am_ops nfsx_ops; /* NFS X */
+extern am_ops host_ops; /* NFS host */
+#ifdef HOST_EXEC
+extern char *host_helper; /* "/usr/local/etc/amd-host" */
+#endif
+extern qelem nfs_srvr_list;
+extern fserver *find_nfs_srvr P((mntfs*));
+
+/*
+ * Program File System
+ * PFS is optional - you can compile without it.
+ * This is useful for things like RVD.
+ */
+#define HAS_PFS
+extern am_ops pfs_ops; /* PFS */
+
+/*
+ * Translucent File System
+ * TFS is optional - you can compile without it.
+ * This is just plain cute.
+ */
+#ifdef notdef
+extern am_ops tfs_ops; /* TFS */
+#endif
+#undef HAS_TFS
+
+/*
+ * Un*x File System
+ * Normal local disk file system.
+ */
+#define HAS_UFS
+extern am_ops ufs_ops; /* Un*x file system */
+
+/*
+ * Symbolic-link file system
+ * A "filesystem" which is just a symbol link.
+ *
+ * sfsx also checks that the target of the link exists.
+ */
+#define HAS_SFS
+extern am_ops sfs_ops; /* Symlink FS */
+#define HAS_SFSX
+extern am_ops sfsx_ops; /* Symlink FS with existence check */
+
+/*
+ * Union file system
+ */
+#define HAS_UNION_FS
+extern am_ops union_ops; /* Union FS */
diff --git a/usr.sbin/amd/include/re.h b/usr.sbin/amd/include/re.h
new file mode 100644
index 0000000..73d6bf4
--- /dev/null
+++ b/usr.sbin/amd/include/re.h
@@ -0,0 +1,21 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
diff --git a/usr.sbin/amd/include/remagic.h b/usr.sbin/amd/include/remagic.h
new file mode 100644
index 0000000..5acf447
--- /dev/null
+++ b/usr.sbin/amd/include/remagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff --git a/usr.sbin/amd/include/uwait.h b/usr.sbin/amd/include/uwait.h
new file mode 100644
index 0000000..c3f8cbe
--- /dev/null
+++ b/usr.sbin/amd/include/uwait.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)uwait.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: uwait.h,v 5.2.2.1 1992/02/09 15:10:01 jsp beta $
+ *
+ */
+
+#if defined(mc68k) || defined(mc68000) || defined(mc68020) || defined(sparc) || defined(hp9000s300) || defined(hp9000s800)
+#define BITS_BIGENDIAN
+#endif
+#if defined(vax) || defined(i386)
+#define BITS_LITTLENDIAN
+#endif
+#if !defined BITS_BIGENDIAN && !defined BITS_LITTLENDIAN
+ #error Do not know my byte ordering
+#endif
+
+/*
+ * Structure of the information in the first word returned by both
+ * wait and wait3. If w_stopval==WSTOPPED, then the second structure
+ * describes the information returned, else the first. See WUNTRACED below.
+ */
+union wait {
+ int w_status; /* used in syscall */
+ /*
+ * Terminated process status.
+ */
+ struct {
+#ifdef BITS_LITTLENDIAN
+ unsigned short w_Termsig:7; /* termination signal */
+ unsigned short w_Coredump:1; /* core dump indicator */
+ unsigned short w_Retcode:8; /* exit code if w_termsig==0 */
+#endif
+#ifdef BITS_BIGENDIAN
+ unsigned short w_Fill1:16; /* high 16 bits unused */
+ unsigned short w_Retcode:8; /* exit code if w_termsig==0 */
+ unsigned short w_Coredump:1; /* core dump indicator */
+ unsigned short w_Termsig:7; /* termination signal */
+#endif
+ } w_U;
+};
+#define w_termsig w_U.w_Termsig
+#define w_coredump w_U.w_Coredump
+#define w_retcode w_U.w_Retcode
+
+#define WIFSIGNALED(x) ((x).w_termsig != 0)
+#define WIFEXITED(x) ((x).w_termsig == 0)
diff --git a/usr.sbin/amd/maps/a_master b/usr.sbin/amd/maps/a_master
new file mode 100644
index 0000000..2f60dde
--- /dev/null
+++ b/usr.sbin/amd/maps/a_master
@@ -0,0 +1,79 @@
+#machine opts info
+achilles -opts:=rw,grpid,nosuid \
+ type:=ufs;hostd==achilles.doc;dev:=/dev/xy1g \
+ type:=nfs;hostd!=achilles.doc;rhost:=achilles.doc;rfs:=/home/achilles
+#
+dougal -opts:=rw,grpid,nosuid \
+ type:=ufs;hostd==dougal.doc;dev:=/dev/dsk/1s0 \
+ type:=nfs;hostd!=dougal.doc;rhost:=dougal.doc;rfs:=/home/dougal
+#
+dylan type:=auto;fs:=${map};pref:=${key}/
+dylan/dk2 -opts:=rw,grpid,nosuid \
+ hostd==dylan.doc;type:=ufs;dev:=/dev/dsk/2s0 \
+ hostd!=dylan.doc;type:=nfs;rhost:=dylan.doc;rfs:=/home/dylan/dk2
+#
+dylan/dk3 -opts:=rw,grpid,nosuid \
+ hostd==dylan.doc;type:=ufs;dev:=/dev/dsk/3s0 \
+ hostd!=dylan.doc;type:=nfs;rhost:=dylan.doc;rfs:=/home/dylan/dk3
+#
+dylan/dk5 -opts:=rw,grpid,nosuid \
+ hostd==dylan.doc;type:=ufs;dev:=/dev/dsk/5s0 \
+ hostd!=dylan.doc;type:=nfs;rhost:=dylan.doc;rfs:=/home/dylan/dk5
+#
+ganymede -opts:=rw,grpid,nosuid \
+ hostd!=${key}.${domain};type:=nfs;rhost:=${key}.${domain};rfs:=/home/${key}
+gummo -opts:=rw,grpid,nosuid \
+ hostd!=gummo.doc;type:=nfs;rhost:=gummo.doc;rfs:=/home/gummo
+#
+# Wildcard match
+* -opts:=rw,grpid,nosuid \
+ hostd!=${key}.${domain};type:=nfs;rhost:=${key}.${domain};rfs:=/home/${key}
+#
+#
+gould -opts:=rw,grpid,nosuid \
+ hostd!=gould.doc;type:=nfs;rhost:=gould.doc;rfs:=/home/gould
+toytown -opts:=rw,grpid,nosuid \
+ hostd!=toytown.doc;type:=nfs;rhost:=toytown.doc;rfs:=/home/${key}
+zebedee -opts:=rw,grpid,nosuid \
+ hostd!=zebedee.doc;type:=nfs;rhost:=zebedee.doc;rfs:=/home/zebedee
+#
+# Should be ENOENT from mountd on toytown...
+#
+testing -opts:=rw,grpid,nosuid \
+ hostd!=toytown.doc;type:=nfs;rhost:=toytown.doc;rfs:=/this/that
+#
+# Somewhere else
+#
+pebbles -opts:=rw,grpid,nosuid \
+ hostd!=pebbles.cc;type:=nfs;rhost:=pebbles.cc;rfs:=/home/cc/pebbles
+#
+# Specify where to mount
+#
+xtoy -opts:=rw,grpid,nosuid \
+ type:=nfs;rhost:=toytown.doc;rfs:=/home/toytown;fs:=/tmp/junk99
+#
+# Links...
+#
+alink type:=link;hostd==achilles.doc;fs:=/etc
+tlink type:=link;hostd==truth.doc;fs:=/etc
+uucp type:=link;hostd==truth.doc;fs:=/etc;sublink:=uucp
+#
+# Duplicate mounts to the same place
+#
+dup1 -opts:=rw,grpid,nosuid \
+ type:=nfs;rhost:=toytown.doc;rfs:=/home/toytown;fs:=/tmp/tt-home
+dup2 -opts:=rw,grpid,nosuid \
+ type:=nfs;rhost:=ganymede.doc;rfs:=/home/ganymede;fs:=/tmp/tt-home
+#
+# Symlink
+#
+link type:=link;fs:=dylan/dk2/adh
+#
+# Program mount
+#
+exec type:=program;mount:="/bin/true false";unmount:="/bin/true true"
+#
+# Alternate mount locations.
+#
+alt -host==truth;type:=nfs;rfs:=/var/spool/mail \
+ rhost:=toytown rhost:=charm rhost:=gummo
diff --git a/usr.sbin/amd/maps/a_net b/usr.sbin/amd/maps/a_net
new file mode 100644
index 0000000..ea2492b
--- /dev/null
+++ b/usr.sbin/amd/maps/a_net
@@ -0,0 +1,3 @@
+/defaults fs:=${autodir}/${rhost}/root/${rfs}
+* rhost:=${key};type=host;rfs:=/
+
diff --git a/usr.sbin/amd/mk-amd-map/Makefile b/usr.sbin/amd/mk-amd-map/Makefile
new file mode 100644
index 0000000..6db921a
--- /dev/null
+++ b/usr.sbin/amd/mk-amd-map/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/28/93
+
+PROG= mk-amd-map
+CFLAGS+=-I${.CURDIR}/../include
+CFLAGS+=-I${.CURDIR}/../rpcx
+CFLAGS+=-I${.CURDIR}/../config
+CFLAGS+=-DOS_HDR=\"os-bsd44.h\"
+MAN8= mk-amd-map.0
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/amd/mk-amd-map/mk-amd-map.8 b/usr.sbin/amd/mk-amd-map/mk-amd-map.8
new file mode 100644
index 0000000..20f3217
--- /dev/null
+++ b/usr.sbin/amd/mk-amd-map/mk-amd-map.8
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1993 Jan-Simon Pendry
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mk-amd-map.8 8.1 (Berkeley) 6/28/93
+.\"
+.Dd "June 28, 1993"
+.Dt MK-AMD-MAP 8
+.Os BSD 4.4
+.Sh NAME
+.Nm mk-amd-map
+.Nd create database maps for Amd
+.Sh SYNOPSIS
+.Nm
+.Op Fl p
+.Ar mapname
+.Sh DESCRIPTION
+.Nm
+creates the database maps used by the keyed map lookups in
+.Xr amd 8 .
+It reads input from the named file
+and outputs them to a correspondingly named
+hashed database.
+.Pp
+The
+.Fl p
+option prints the map on standard output instead of generating
+a database. This is usually used to merge continuation lines
+into one physical line.
+.Sh SEE ALSO
+.Xr amd 8
diff --git a/usr.sbin/amd/mk-amd-map/mk-amd-map.c b/usr.sbin/amd/mk-amd-map/mk-amd-map.c
new file mode 100644
index 0000000..c2dfb71
--- /dev/null
+++ b/usr.sbin/amd/mk-amd-map/mk-amd-map.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 1990, 1993 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mk-amd-map.c 8.1 (Berkeley) 6/28/93
+ *
+ * $Id: mk-amd-map.c,v 5.2.2.1 1992/02/09 15:09:18 jsp beta $
+ */
+
+/*
+ * Convert a file map into an ndbm map
+ */
+
+#ifndef lint
+char copyright[] = "\
+@(#)Copyright (c) 1990, 1993 Jan-Simon Pendry\n\
+@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
+@(#)Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char rcsid[] = "$Id: mk-amd-map.c,v 5.2.2.1 1992/02/09 15:09:18 jsp beta $";
+static char sccsid[] = "@(#)mk-amd-map.c 8.1 (Berkeley) 6/28/93";
+#endif /* not lint */
+
+#include "am.h"
+
+#ifndef SIGINT
+#include <signal.h>
+#endif
+
+#ifdef OS_HAS_NDBM
+#define HAS_DATABASE
+#include <ndbm.h>
+
+#ifdef DBM_SUFFIX
+#define USING_DB
+#endif
+
+#define create_database(name) dbm_open(name, O_RDWR|O_CREAT, 0644)
+
+static int store_data(db, k, v)
+voidp db;
+char *k, *v;
+{
+ datum key, val;
+
+ key.dptr = k; val.dptr = v;
+ key.dsize = strlen(k) + 1;
+ val.dsize = strlen(v) + 1;
+ return dbm_store((DBM *) db, key, val, DBM_INSERT);
+}
+
+#endif /* OS_HAS_NDBM */
+
+#ifdef HAS_DATABASE
+#include <fcntl.h>
+#include <ctype.h>
+
+static int read_line(buf, size, fp)
+char *buf;
+int size;
+FILE *fp;
+{
+ int done = 0;
+
+ do {
+ while (fgets(buf, size, fp)) {
+ int len = strlen(buf);
+ done += len;
+ if (len > 1 && buf[len-2] == '\\' &&
+ buf[len-1] == '\n') {
+ int ch;
+ buf += len - 2;
+ size -= len - 2;
+ *buf = '\n'; buf[1] = '\0';
+ /*
+ * Skip leading white space on next line
+ */
+ while ((ch = getc(fp)) != EOF &&
+ isascii(ch) && isspace(ch))
+ ;
+ (void) ungetc(ch, fp);
+ } else {
+ return done;
+ }
+ }
+ } while (size > 0 && !feof(fp));
+
+ return done;
+}
+
+/*
+ * Read through a map
+ */
+static int read_file(fp, map, db)
+FILE *fp;
+char *map;
+voidp db;
+{
+ char key_val[2048];
+ int chuck = 0;
+ int line_no = 0;
+ int errs = 0;
+
+ while (read_line(key_val, sizeof(key_val), fp)) {
+ char *kp;
+ char *cp;
+ char *hash;
+ int len = strlen(key_val);
+ line_no++;
+
+ /*
+ * Make sure we got the whole line
+ */
+ if (key_val[len-1] != '\n') {
+ fprintf(stderr, "line %d in \"%s\" is too long", line_no, map);
+ chuck = 1;
+ } else {
+ key_val[len-1] = '\0';
+ }
+
+ /*
+ * Strip comments
+ */
+ hash = strchr(key_val, '#');
+ if (hash)
+ *hash = '\0';
+
+ /*
+ * Find start of key
+ */
+ for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
+ ;
+
+ /*
+ * Ignore blank lines
+ */
+ if (!*kp)
+ goto again;
+
+ /*
+ * Find end of key
+ */
+ for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
+ ;
+
+ /*
+ * Check whether key matches, or whether
+ * the entry is a wildcard entry.
+ */
+ if (*cp)
+ *cp++ = '\0';
+ while (*cp && isascii(*cp) && isspace(*cp))
+ cp++;
+ if (*kp == '+') {
+ fprintf(stderr, "Can't interpolate %s\n", kp);
+ errs++;
+ } else if (*cp) {
+ if (db) {
+ if (store_data(db, kp, cp) < 0) {
+ fprintf(stderr, "Could store %s -> %s\n", kp, cp);
+ errs++;
+ }
+ } else {
+ printf("%s\t%s\n", kp, cp);
+ }
+ } else {
+ fprintf(stderr, "%s: line %d has no value field", map, line_no);
+ errs++;
+ }
+
+again:
+ /*
+ * If the last read didn't get a whole line then
+ * throw away the remainder before continuing...
+ */
+ if (chuck) {
+ while (fgets(key_val, sizeof(key_val), fp) &&
+ !strchr(key_val, '\n'))
+ ;
+ chuck = 0;
+ }
+ }
+ return errs;
+}
+
+static int remove_file(f)
+char *f;
+{
+ if (unlink(f) < 0 && errno != ENOENT)
+ return -1;
+ return 0;
+}
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ FILE *mapf;
+ char *map;
+ int rc = 0;
+ DBM *mapd;
+ static char maptmp[] = "dbmXXXXXX";
+ char maptpag[16];
+ char *mappag;
+#ifndef USING_DB
+ char maptdir[16];
+ char *mapdir;
+#endif
+ int len;
+ char *sl;
+ int printit = 0;
+ int usage = 0;
+ int ch;
+ extern int optind;
+
+ while ((ch = getopt(argc, argv, "p")) != EOF)
+ switch (ch) {
+ case 'p':
+ printit = 1;
+ break;
+ default:
+ usage++;
+ break;
+ }
+
+ if (usage || optind != (argc - 1)) {
+ fputs("Usage: mk-amd-map [-p] file-map\n", stderr);
+ exit(1);
+ }
+
+ map = argv[optind];
+ sl = strrchr(map, '/');
+ if (sl) {
+ *sl = '\0';
+ if (chdir(map) < 0) {
+ fputs("Can't chdir to ", stderr);
+ perror(map);
+ exit(1);
+ }
+ map = sl + 1;
+ }
+
+ if (!printit) {
+ len = strlen(map);
+#ifdef USING_DB
+ mappag = (char *) malloc(len + 5);
+ if (!mappag) {
+ perror("mk-amd-map: malloc");
+ exit(1);
+ }
+ mktemp(maptmp);
+ sprintf(maptpag, "%s%s", maptmp, DBM_SUFFIX);
+ if (remove_file(maptpag) < 0) {
+ fprintf(stderr, "Can't remove existing temporary file");
+ perror(maptpag);
+ exit(1);
+ }
+#else
+ mappag = (char *) malloc(len + 5);
+ mapdir = (char *) malloc(len + 5);
+ if (!mappag || !mapdir) {
+ perror("mk-amd-map: malloc");
+ exit(1);
+ }
+ mktemp(maptmp);
+ sprintf(maptpag, "%s.pag", maptmp);
+ sprintf(maptdir, "%s.dir", maptmp);
+ if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) {
+ fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag);
+ perror(maptdir);
+ exit(1);
+ }
+#endif
+ }
+
+ mapf = fopen(map, "r");
+ if (mapf && !printit)
+ mapd = create_database(maptmp);
+ else
+ mapd = 0;
+
+#ifndef DEBUG
+ signal(SIGINT, SIG_IGN);
+#endif
+
+ if (mapd || printit) {
+ int error = read_file(mapf, map, mapd);
+ if (mapd)
+ dbm_close(mapd);
+ (void) fclose(mapf);
+ if (printit) {
+ if (error) {
+ fprintf(stderr, "Error creating ndbm map for %s\n", map);
+ rc = 1;
+ }
+ } else {
+ if (error) {
+ fprintf(stderr, "Error reading source file %s\n", map);
+ rc = 1;
+ } else {
+#ifdef USING_DB
+ sprintf(mappag, "%s%s", map, DBM_SUFFIX);
+ if (rename(maptpag, mappag) < 0) {
+ fprintf(stderr, "Couldn't rename %s to ", maptpag);
+ perror(mappag);
+ /* Throw away the temporary map */
+ unlink(maptpag);
+ rc = 1;
+ }
+#else
+ sprintf(mappag, "%s.pag", map);
+ sprintf(mapdir, "%s.dir", map);
+ if (rename(maptpag, mappag) < 0) {
+ fprintf(stderr, "Couldn't rename %s to ", maptpag);
+ perror(mappag);
+ /* Throw away the temporary map */
+ unlink(maptpag);
+ unlink(maptdir);
+ rc = 1;
+ } else if (rename(maptdir, mapdir) < 0) {
+ fprintf(stderr, "Couldn't rename %s to ", maptdir);
+ perror(mapdir);
+ /* Put the .pag file back */
+ rename(mappag, maptpag);
+ /* Throw away remaining part of original map */
+ unlink(mapdir);
+ fprintf(stderr,
+ "WARNING: existing map \"%s.{dir,pag}\" destroyed\n",
+ map);
+ rc = 1;
+ }
+#endif
+ }
+ }
+ } else {
+ fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map);
+ perror("writing");
+ rc = 1;
+ }
+ exit(rc);
+}
+#else
+main()
+{
+ fputs("mk-amd-map: This system does not support hashed database files\n", stderr);
+ exit(1);
+}
+#endif /* HAS_DATABASE */
diff --git a/usr.sbin/amd/rpcx/amq.h b/usr.sbin/amd/rpcx/amq.h
new file mode 100644
index 0000000..7ec4d55
--- /dev/null
+++ b/usr.sbin/amd/rpcx/amq.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq.h,v 5.2.2.1 1992/02/09 15:09:22 jsp beta $
+ *
+ */
+
+#define AMQ_STRLEN 1024
+
+typedef char *amq_string;
+bool_t xdr_amq_string();
+
+
+typedef long *time_type;
+bool_t xdr_time_type();
+
+
+struct amq_mount_tree {
+ amq_string mt_mountinfo;
+ amq_string mt_directory;
+ amq_string mt_mountpoint;
+ amq_string mt_type;
+ time_type mt_mounttime;
+ u_short mt_mountuid;
+ int mt_getattr;
+ int mt_lookup;
+ int mt_readdir;
+ int mt_readlink;
+ int mt_statfs;
+ struct amq_mount_tree *mt_next;
+ struct amq_mount_tree *mt_child;
+};
+typedef struct amq_mount_tree amq_mount_tree;
+bool_t xdr_amq_mount_tree();
+
+
+typedef amq_mount_tree *amq_mount_tree_p;
+bool_t xdr_amq_mount_tree_p();
+
+
+struct amq_mount_info {
+ amq_string mi_type;
+ amq_string mi_mountpt;
+ amq_string mi_mountinfo;
+ amq_string mi_fserver;
+ int mi_error;
+ int mi_refc;
+ int mi_up;
+};
+typedef struct amq_mount_info amq_mount_info;
+bool_t xdr_amq_mount_info();
+
+
+typedef struct {
+ u_int amq_mount_info_list_len;
+ amq_mount_info *amq_mount_info_list_val;
+} amq_mount_info_list;
+bool_t xdr_amq_mount_info_list();
+
+
+typedef struct {
+ u_int amq_mount_tree_list_len;
+ amq_mount_tree_p *amq_mount_tree_list_val;
+} amq_mount_tree_list;
+bool_t xdr_amq_mount_tree_list();
+
+
+struct amq_mount_stats {
+ int as_drops;
+ int as_stale;
+ int as_mok;
+ int as_merr;
+ int as_uerr;
+};
+typedef struct amq_mount_stats amq_mount_stats;
+bool_t xdr_amq_mount_stats();
+
+
+enum amq_opt {
+ AMOPT_DEBUG = 0,
+ AMOPT_LOGFILE = 1,
+ AMOPT_XLOG = 2,
+ AMOPT_FLUSHMAPC = 3
+};
+typedef enum amq_opt amq_opt;
+bool_t xdr_amq_opt();
+
+
+struct amq_setopt {
+ amq_opt as_opt;
+ amq_string as_str;
+};
+typedef struct amq_setopt amq_setopt;
+bool_t xdr_amq_setopt();
+
+
+#define AMQ_PROGRAM ((u_long)300019)
+#define AMQ_VERSION ((u_long)1)
+#define AMQPROC_NULL ((u_long)0)
+extern voidp amqproc_null_1();
+#define AMQPROC_MNTTREE ((u_long)1)
+extern amq_mount_tree_p *amqproc_mnttree_1();
+#define AMQPROC_UMNT ((u_long)2)
+extern voidp amqproc_umnt_1();
+#define AMQPROC_STATS ((u_long)3)
+extern amq_mount_stats *amqproc_stats_1();
+#define AMQPROC_EXPORT ((u_long)4)
+extern amq_mount_tree_list *amqproc_export_1();
+#define AMQPROC_SETOPT ((u_long)5)
+extern int *amqproc_setopt_1();
+#define AMQPROC_GETMNTFS ((u_long)6)
+extern amq_mount_info_list *amqproc_getmntfs_1();
+#define AMQPROC_MOUNT ((u_long)7)
+extern int *amqproc_mount_1();
+#define AMQPROC_GETVERS ((u_long)8)
+extern amq_string *amqproc_getvers_1();
+
diff --git a/usr.sbin/amd/rpcx/amq.x b/usr.sbin/amd/rpcx/amq.x
new file mode 100644
index 0000000..d75805d
--- /dev/null
+++ b/usr.sbin/amd/rpcx/amq.x
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq.x 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq.x,v 5.2.2.1 1992/02/09 15:09:20 jsp beta $
+ *
+ */
+
+/*
+ * Protocol description used by the amq program
+ */
+
+const AMQ_STRLEN = 1024; /* Maximum length of a pathname */
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string amq_string<AMQ_STRLEN>;
+
+/*
+ * The type time_type should correspond to the system time_t
+ */
+typedef long time_type;
+
+/*
+ * A tree of what is mounted
+ */
+struct amq_mount_tree {
+ amq_string mt_mountinfo; /* Mounted filesystem */
+ amq_string mt_directory; /* Virtual mount */
+ amq_string mt_mountpoint; /* Mount point */
+ amq_string mt_type; /* Filesystem type */
+ time_type mt_mounttime; /* Mount time */
+ u_short mt_mountuid; /* Mounter */
+ int mt_getattr; /* Count of getattrs */
+ int mt_lookup; /* Count of lookups */
+ int mt_readdir; /* Count of readdirs */
+ int mt_readlink; /* Count of readlinks */
+ int mt_statfs; /* Count of statfss */
+ amq_mount_tree *mt_next; /* Sibling mount tree */
+ amq_mount_tree *mt_child; /* Child mount tree */
+};
+typedef amq_mount_tree *amq_mount_tree_p;
+
+/*
+ * List of mounted filesystems
+ */
+struct amq_mount_info {
+ amq_string mi_type; /* Type of mount */
+ amq_string mi_mountpt; /* Mount point */
+ amq_string mi_mountinfo; /* Mount info */
+ amq_string mi_fserver; /* Fileserver */
+ int mi_error; /* Error code */
+ int mi_refc; /* References */
+ int mi_up; /* Filesystem available */
+};
+typedef amq_mount_info amq_mount_info_list<>;
+
+/*
+ * A list of mount trees
+ */
+typedef amq_mount_tree_p amq_mount_tree_list<>;
+
+/*
+ * System wide stats
+ */
+struct amq_mount_stats {
+ int as_drops; /* Dropped requests */
+ int as_stale; /* Stale NFS handles */
+ int as_mok; /* Succesful mounts */
+ int as_merr; /* Failed mounts */
+ int as_uerr; /* Failed unmounts */
+};
+
+enum amq_opt {
+ AMOPT_DEBUG=0,
+ AMOPT_LOGFILE=1,
+ AMOPT_XLOG=2,
+ AMOPT_FLUSHMAPC=3
+};
+
+struct amq_setopt {
+ amq_opt as_opt; /* Option */
+ amq_string as_str; /* String */
+};
+
+program AMQ_PROGRAM {
+ version AMQ_VERSION {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ AMQPROC_NULL(void) = 0;
+
+ /*
+ * Returned the mount tree descending from
+ * the given directory. The directory must
+ * be a top-level mount point of the automounter.
+ */
+ amq_mount_tree_p
+ AMQPROC_MNTTREE(amq_string) = 1;
+
+ /*
+ * Force a timeout unmount on the specified directory.
+ */
+ void
+ AMQPROC_UMNT(amq_string) = 2;
+
+ /*
+ * Obtain system wide statistics from the automounter
+ */
+ amq_mount_stats
+ AMQPROC_STATS(void) = 3;
+
+ /*
+ * Obtain full tree
+ */
+ amq_mount_tree_list
+ AMQPROC_EXPORT(void) = 4;
+
+ /*
+ * Control debug options.
+ * Return status:
+ * -1: debug not available
+ * 0: everything wonderful
+ * >0: number of options not recognised
+ */
+ int
+ AMQPROC_SETOPT(amq_setopt) = 5;
+
+ /*
+ * List of mounted filesystems
+ */
+ amq_mount_info_list
+ AMQPROC_GETMNTFS(void) = 6;
+
+ /*
+ * Mount a filesystem
+ */
+ int
+ AMQPROC_MOUNT(amq_string) = 7;
+
+ /*
+ * Get version info
+ */
+ amq_string
+ AMQPROC_GETVERS(void) = 8;
+ } = 1;
+} = 300019; /* Allocated by Sun, 89/8/29 */
diff --git a/usr.sbin/amd/rpcx/amq_clnt.c b/usr.sbin/amd/rpcx/amq_clnt.c
new file mode 100644
index 0000000..5b70d11
--- /dev/null
+++ b/usr.sbin/amd/rpcx/amq_clnt.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq_clnt.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq_clnt.c,v 5.2.2.1 1992/02/09 15:09:24 jsp beta $
+ *
+ */
+
+#include "am.h"
+#include "amq.h"
+
+static struct timeval TIMEOUT = { ALLOWED_MOUNT_TIME, 0 };
+
+voidp
+amqproc_null_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static char res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_NULL, xdr_void, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((voidp)&res);
+}
+
+
+amq_mount_tree_p *
+amqproc_mnttree_1(argp, clnt)
+ amq_string *argp;
+ CLIENT *clnt;
+{
+ static amq_mount_tree_p res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_MNTTREE, xdr_amq_string, argp, xdr_amq_mount_tree_p, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+voidp
+amqproc_umnt_1(argp, clnt)
+ amq_string *argp;
+ CLIENT *clnt;
+{
+ static char res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_UMNT, xdr_amq_string, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((voidp)&res);
+}
+
+
+amq_mount_stats *
+amqproc_stats_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static amq_mount_stats res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_STATS, xdr_void, argp, xdr_amq_mount_stats, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_mount_tree_list *
+amqproc_export_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static amq_mount_tree_list res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_EXPORT, xdr_void, argp, xdr_amq_mount_tree_list, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+int *
+amqproc_setopt_1(argp, clnt)
+ amq_setopt *argp;
+ CLIENT *clnt;
+{
+ static int res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_SETOPT, xdr_amq_setopt, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_mount_info_list *
+amqproc_getmntfs_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static amq_mount_info_list res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_GETMNTFS, xdr_void, argp, xdr_amq_mount_info_list, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+int *
+amqproc_mount_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static int res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_MOUNT, xdr_amq_string, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_string *
+amqproc_getvers_1(argp, clnt)
+ voidp argp;
+ CLIENT *clnt;
+{
+ static amq_string res;
+
+ bzero((char *)&res, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_GETVERS, xdr_void, argp, xdr_amq_string, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
diff --git a/usr.sbin/amd/rpcx/amq_svc.c b/usr.sbin/amd/rpcx/amq_svc.c
new file mode 100644
index 0000000..0d3599f
--- /dev/null
+++ b/usr.sbin/amd/rpcx/amq_svc.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq_svc.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq_svc.c,v 5.2.2.1 1992/02/09 15:09:26 jsp beta $
+ *
+ */
+
+#include "am.h"
+#include "amq.h"
+extern bool_t xdr_amq_mount_info_qelem();
+
+void
+amq_program_1(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ union {
+ amq_string amqproc_mnttree_1_arg;
+ amq_string amqproc_umnt_1_arg;
+ amq_setopt amqproc_setopt_1_arg;
+ amq_string amqproc_mount_1_arg;
+ } argument;
+ char *result;
+ bool_t (*xdr_argument)(), (*xdr_result)();
+ char *(*local)();
+
+ switch (rqstp->rq_proc) {
+ case AMQPROC_NULL:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_void;
+ local = (char *(*)()) amqproc_null_1;
+ break;
+
+ case AMQPROC_MNTTREE:
+ xdr_argument = xdr_amq_string;
+ xdr_result = xdr_amq_mount_tree_p;
+ local = (char *(*)()) amqproc_mnttree_1;
+ break;
+
+ case AMQPROC_UMNT:
+ xdr_argument = xdr_amq_string;
+ xdr_result = xdr_void;
+ local = (char *(*)()) amqproc_umnt_1;
+ break;
+
+ case AMQPROC_STATS:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_amq_mount_stats;
+ local = (char *(*)()) amqproc_stats_1;
+ break;
+
+ case AMQPROC_EXPORT:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_amq_mount_tree_list;
+ local = (char *(*)()) amqproc_export_1;
+ break;
+
+ case AMQPROC_SETOPT:
+ xdr_argument = xdr_amq_setopt;
+ xdr_result = xdr_int;
+ local = (char *(*)()) amqproc_setopt_1;
+ break;
+
+ case AMQPROC_GETMNTFS:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_amq_mount_info_qelem;
+ local = (char *(*)()) amqproc_getmntfs_1;
+ break;
+
+ case AMQPROC_MOUNT:
+ xdr_argument = xdr_amq_string;
+ xdr_result = xdr_int;
+ local = (char *(*)()) amqproc_mount_1;
+ break;
+
+ case AMQPROC_GETVERS:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_amq_string;
+ local = (char *(*)()) amqproc_getvers_1;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ bzero((char *)&argument, sizeof(argument));
+ if (!svc_getargs(transp, xdr_argument, &argument)) {
+ svcerr_decode(transp);
+ return;
+ }
+ result = (*local)(&argument, rqstp);
+ if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, xdr_argument, &argument)) {
+ plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
+ going_down(1);
+ }
+}
+
diff --git a/usr.sbin/amd/rpcx/amq_xdr.c b/usr.sbin/amd/rpcx/amq_xdr.c
new file mode 100644
index 0000000..8a123a7
--- /dev/null
+++ b/usr.sbin/amd/rpcx/amq_xdr.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)amq_xdr.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: amq_xdr.c,v 5.2.2.1 1992/02/09 15:09:23 jsp beta $
+ *
+ */
+
+#include "am.h"
+#include "amq.h"
+
+
+bool_t
+xdr_amq_string(xdrs, objp)
+ XDR *xdrs;
+ amq_string *objp;
+{
+ if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_time_type(xdrs, objp)
+ XDR *xdrs;
+ time_type *objp;
+{
+ if (!xdr_long(xdrs, objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_amq_mount_tree(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree *objp;
+{
+ if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mt_type)) {
+ return (FALSE);
+ }
+ if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
+ return (FALSE);
+ }
+ if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mt_getattr)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mt_lookup)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mt_readdir)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mt_readlink)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mt_statfs)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&objp->mt_next, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&objp->mt_child, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_amq_mount_tree_p(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree_p *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+bool_t
+xdr_amq_mount_info(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_info *objp;
+{
+ if (!xdr_amq_string(xdrs, &objp->mi_type)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mi_mountpt)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mi_mountinfo)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->mi_fserver)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mi_error)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mi_refc)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->mi_up)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+bool_t
+xdr_amq_mount_info_list(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_info_list *objp;
+{
+ if (!xdr_array(xdrs, (char **)&objp->amq_mount_info_list_val, (u_int *)&objp->amq_mount_info_list_len, ~0, sizeof(amq_mount_info), xdr_amq_mount_info)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+bool_t
+xdr_amq_mount_tree_list(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_tree_list *objp;
+{
+ if (!xdr_array(xdrs, (char **)&objp->amq_mount_tree_list_val, (u_int *)&objp->amq_mount_tree_list_len, ~0, sizeof(amq_mount_tree_p), xdr_amq_mount_tree_p)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_amq_mount_stats(xdrs, objp)
+ XDR *xdrs;
+ amq_mount_stats *objp;
+{
+ if (!xdr_int(xdrs, &objp->as_drops)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_stale)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_mok)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_merr)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->as_uerr)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_amq_opt(xdrs, objp)
+ XDR *xdrs;
+ amq_opt *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_amq_setopt(xdrs, objp)
+ XDR *xdrs;
+ amq_setopt *objp;
+{
+ if (!xdr_amq_opt(xdrs, &objp->as_opt)) {
+ return (FALSE);
+ }
+ if (!xdr_amq_string(xdrs, &objp->as_str)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
diff --git a/usr.sbin/amd/rpcx/mount.h b/usr.sbin/amd/rpcx/mount.h
new file mode 100644
index 0000000..d30b0c3
--- /dev/null
+++ b/usr.sbin/amd/rpcx/mount.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mount.h,v 5.2.2.1 1992/02/09 15:09:27 jsp beta $
+ *
+ */
+
+#define MNTPATHLEN 1024
+#define MNTNAMLEN 255
+#define FHSIZE 32
+
+typedef char fhandle[FHSIZE];
+bool_t xdr_fhandle();
+
+
+struct fhstatus {
+ u_int fhs_status;
+ union {
+ fhandle fhs_fhandle;
+ } fhstatus_u;
+};
+typedef struct fhstatus fhstatus;
+bool_t xdr_fhstatus();
+
+
+typedef char *dirpath;
+bool_t xdr_dirpath();
+
+
+typedef char *name;
+bool_t xdr_name();
+
+
+typedef struct mountbody *mountlist;
+bool_t xdr_mountlist();
+
+
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+typedef struct mountbody mountbody;
+bool_t xdr_mountbody();
+
+
+typedef struct groupnode *groups;
+bool_t xdr_groups();
+
+
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+typedef struct groupnode groupnode;
+bool_t xdr_groupnode();
+
+
+typedef struct exportnode *exports;
+bool_t xdr_exports();
+
+
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+typedef struct exportnode exportnode;
+bool_t xdr_exportnode();
+
+
+#define MOUNTPROG ((u_long)100005)
+#define MOUNTVERS ((u_long)1)
+#define MOUNTPROC_NULL ((u_long)0)
+extern voidp mountproc_null_1();
+#define MOUNTPROC_MNT ((u_long)1)
+extern fhstatus *mountproc_mnt_1();
+#define MOUNTPROC_DUMP ((u_long)2)
+extern mountlist *mountproc_dump_1();
+#define MOUNTPROC_UMNT ((u_long)3)
+extern voidp mountproc_umnt_1();
+#define MOUNTPROC_UMNTALL ((u_long)4)
+extern voidp mountproc_umntall_1();
+#define MOUNTPROC_EXPORT ((u_long)5)
+extern exports *mountproc_export_1();
+#define MOUNTPROC_EXPORTALL ((u_long)6)
+extern exports *mountproc_exportall_1();
+
diff --git a/usr.sbin/amd/rpcx/mount_xdr.c b/usr.sbin/amd/rpcx/mount_xdr.c
new file mode 100644
index 0000000..f8d8f57
--- /dev/null
+++ b/usr.sbin/amd/rpcx/mount_xdr.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mount_xdr.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: mount_xdr.c,v 5.2.2.1 1992/02/09 15:09:28 jsp beta $
+ *
+ */
+
+#include "am.h"
+#include "mount.h"
+
+
+bool_t
+xdr_fhandle(xdrs, objp)
+ XDR *xdrs;
+ fhandle objp;
+{
+ if (!xdr_opaque(xdrs, objp, FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_fhstatus(xdrs, objp)
+ XDR *xdrs;
+ fhstatus *objp;
+{
+ if (!xdr_u_int(xdrs, &objp->fhs_status)) {
+ return (FALSE);
+ }
+ switch (objp->fhs_status) {
+ case 0:
+ if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_dirpath(xdrs, objp)
+ XDR *xdrs;
+ dirpath *objp;
+{
+ if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_name(xdrs, objp)
+ XDR *xdrs;
+ name *objp;
+{
+ if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_mountlist(xdrs, objp)
+ XDR *xdrs;
+ mountlist *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), xdr_mountbody)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+bool_t
+xdr_mountbody(xdrs, objp)
+ XDR *xdrs;
+ mountbody *objp;
+{
+ if (!xdr_name(xdrs, &objp->ml_hostname)) {
+ return (FALSE);
+ }
+ if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_mountlist(xdrs, &objp->ml_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_groups(xdrs, objp)
+ XDR *xdrs;
+ groups *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), xdr_groupnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_groupnode(xdrs, objp)
+ XDR *xdrs;
+ groupnode *objp;
+{
+ if (!xdr_name(xdrs, &objp->gr_name)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->gr_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_exports(xdrs, objp)
+ XDR *xdrs;
+ exports *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), xdr_exportnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_exportnode(xdrs, objp)
+ XDR *xdrs;
+ exportnode *objp;
+{
+ if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->ex_groups)) {
+ return (FALSE);
+ }
+ if (!xdr_exports(xdrs, &objp->ex_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
diff --git a/usr.sbin/amd/rpcx/nfs_prot.h b/usr.sbin/amd/rpcx/nfs_prot.h
new file mode 100644
index 0000000..62a75f7
--- /dev/null
+++ b/usr.sbin/amd/rpcx/nfs_prot.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfs_prot.h 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfs_prot.h,v 5.2.2.1 1992/02/09 15:09:29 jsp beta $
+ *
+ */
+
+#define xdr_nfsstat xdr_enum
+#define xdr_ftype xdr_enum
+
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV -1
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+enum nfsstat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_NAMETOOLONG = 63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99
+};
+typedef enum nfsstat nfsstat;
+bool_t xdr_nfsstat();
+
+
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5,
+ NFSOCK = 6,
+ NFBAD = 7,
+ NFFIFO = 8
+};
+typedef enum ftype ftype;
+/* static bool_t xdr_ftype(); */
+
+
+struct nfs_fh {
+ char data[NFS_FHSIZE];
+};
+typedef struct nfs_fh nfs_fh;
+bool_t xdr_nfs_fh();
+
+
+struct nfstime {
+ u_int seconds;
+ u_int useconds;
+};
+typedef struct nfstime nfstime;
+/* static bool_t xdr_nfstime(); */
+
+
+struct fattr {
+ ftype type;
+ u_int mode;
+ u_int nlink;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ u_int blocksize;
+ u_int rdev;
+ u_int blocks;
+ u_int fsid;
+ u_int fileid;
+ nfstime atime;
+ nfstime mtime;
+ nfstime ctime;
+};
+typedef struct fattr fattr;
+/* static bool_t xdr_fattr(); */
+
+
+struct sattr {
+ u_int mode;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ nfstime atime;
+ nfstime mtime;
+};
+typedef struct sattr sattr;
+/* static bool_t xdr_sattr(); */
+
+
+typedef char *filename;
+/* static bool_t xdr_filename(); */
+
+
+typedef char *nfspath;
+bool_t xdr_nfspath();
+
+
+struct attrstat {
+ nfsstat status;
+ union {
+ fattr attributes;
+ } attrstat_u;
+};
+typedef struct attrstat attrstat;
+bool_t xdr_attrstat();
+
+
+struct sattrargs {
+ nfs_fh file;
+ sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+bool_t xdr_sattrargs();
+
+
+struct diropargs {
+ nfs_fh dir;
+ filename name;
+};
+typedef struct diropargs diropargs;
+bool_t xdr_diropargs();
+
+
+struct diropokres {
+ nfs_fh file;
+ fattr attributes;
+};
+typedef struct diropokres diropokres;
+bool_t xdr_diropokres();
+
+
+struct diropres {
+ nfsstat status;
+ union {
+ diropokres diropres;
+ } diropres_u;
+};
+typedef struct diropres diropres;
+bool_t xdr_diropres();
+
+
+struct readlinkres {
+ nfsstat status;
+ union {
+ nfspath data;
+ } readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+bool_t xdr_readlinkres();
+
+
+struct readargs {
+ nfs_fh file;
+ u_int offset;
+ u_int count;
+ u_int totalcount;
+};
+typedef struct readargs readargs;
+bool_t xdr_readargs();
+
+
+struct readokres {
+ fattr attributes;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct readokres readokres;
+bool_t xdr_readokres();
+
+
+struct readres {
+ nfsstat status;
+ union {
+ readokres reply;
+ } readres_u;
+};
+typedef struct readres readres;
+bool_t xdr_readres();
+
+
+struct writeargs {
+ nfs_fh file;
+ u_int beginoffset;
+ u_int offset;
+ u_int totalcount;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct writeargs writeargs;
+bool_t xdr_writeargs();
+
+
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+typedef struct createargs createargs;
+bool_t xdr_createargs();
+
+
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+typedef struct renameargs renameargs;
+bool_t xdr_renameargs();
+
+
+struct linkargs {
+ nfs_fh from;
+ diropargs to;
+};
+typedef struct linkargs linkargs;
+bool_t xdr_linkargs();
+
+
+struct symlinkargs {
+ diropargs from;
+ nfspath to;
+ sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+bool_t xdr_symlinkargs();
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+/* static bool_t xdr_nfscookie(); */
+
+
+struct readdirargs {
+ nfs_fh dir;
+ nfscookie cookie;
+ u_int count;
+};
+typedef struct readdirargs readdirargs;
+bool_t xdr_readdirargs();
+
+
+struct entry {
+ u_int fileid;
+ filename name;
+ nfscookie cookie;
+ struct entry *nextentry;
+};
+typedef struct entry entry;
+/* static bool_t xdr_entry(); */
+
+
+struct dirlist {
+ entry *entries;
+ bool_t eof;
+};
+typedef struct dirlist dirlist;
+/* static bool_t xdr_dirlist(); */
+
+
+struct readdirres {
+ nfsstat status;
+ union {
+ dirlist reply;
+ } readdirres_u;
+};
+typedef struct readdirres readdirres;
+bool_t xdr_readdirres();
+
+
+struct statfsokres {
+ u_int tsize;
+ u_int bsize;
+ u_int blocks;
+ u_int bfree;
+ u_int bavail;
+};
+typedef struct statfsokres statfsokres;
+bool_t xdr_statfsokres();
+
+
+struct statfsres {
+ nfsstat status;
+ union {
+ statfsokres reply;
+ } statfsres_u;
+};
+typedef struct statfsres statfsres;
+bool_t xdr_statfsres();
+
+
+#define NFS_PROGRAM ((u_long)100003)
+#define NFS_VERSION ((u_long)2)
+#define NFSPROC_NULL ((u_long)0)
+extern voidp nfsproc_null_2();
+#define NFSPROC_GETATTR ((u_long)1)
+extern attrstat *nfsproc_getattr_2();
+#define NFSPROC_SETATTR ((u_long)2)
+extern attrstat *nfsproc_setattr_2();
+#define NFSPROC_ROOT ((u_long)3)
+extern voidp nfsproc_root_2();
+#define NFSPROC_LOOKUP ((u_long)4)
+extern diropres *nfsproc_lookup_2();
+#define NFSPROC_READLINK ((u_long)5)
+extern readlinkres *nfsproc_readlink_2();
+#define NFSPROC_READ ((u_long)6)
+extern readres *nfsproc_read_2();
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern voidp nfsproc_writecache_2();
+#define NFSPROC_WRITE ((u_long)8)
+extern attrstat *nfsproc_write_2();
+#define NFSPROC_CREATE ((u_long)9)
+extern diropres *nfsproc_create_2();
+#define NFSPROC_REMOVE ((u_long)10)
+extern nfsstat *nfsproc_remove_2();
+#define NFSPROC_RENAME ((u_long)11)
+extern nfsstat *nfsproc_rename_2();
+#define NFSPROC_LINK ((u_long)12)
+extern nfsstat *nfsproc_link_2();
+#define NFSPROC_SYMLINK ((u_long)13)
+extern nfsstat *nfsproc_symlink_2();
+#define NFSPROC_MKDIR ((u_long)14)
+extern diropres *nfsproc_mkdir_2();
+#define NFSPROC_RMDIR ((u_long)15)
+extern nfsstat *nfsproc_rmdir_2();
+#define NFSPROC_READDIR ((u_long)16)
+extern readdirres *nfsproc_readdir_2();
+#define NFSPROC_STATFS ((u_long)17)
+extern statfsres *nfsproc_statfs_2();
+
diff --git a/usr.sbin/amd/rpcx/nfs_prot_svc.c b/usr.sbin/amd/rpcx/nfs_prot_svc.c
new file mode 100644
index 0000000..21e47e3
--- /dev/null
+++ b/usr.sbin/amd/rpcx/nfs_prot_svc.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfs_prot_svc.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfs_prot_svc.c,v 5.2.2.1 1992/02/09 15:09:30 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+void nfs_program_2(rqstp, transp)
+struct svc_req *rqstp;
+SVCXPRT *transp;
+{
+ union {
+ nfs_fh nfsproc_getattr_2_arg;
+ sattrargs nfsproc_setattr_2_arg;
+ diropargs nfsproc_lookup_2_arg;
+ nfs_fh nfsproc_readlink_2_arg;
+ readargs nfsproc_read_2_arg;
+ writeargs nfsproc_write_2_arg;
+ createargs nfsproc_create_2_arg;
+ diropargs nfsproc_remove_2_arg;
+ renameargs nfsproc_rename_2_arg;
+ linkargs nfsproc_link_2_arg;
+ symlinkargs nfsproc_symlink_2_arg;
+ createargs nfsproc_mkdir_2_arg;
+ diropargs nfsproc_rmdir_2_arg;
+ readdirargs nfsproc_readdir_2_arg;
+ nfs_fh nfsproc_statfs_2_arg;
+ } argument;
+ char *result;
+ bool_t (*xdr_argument)(), (*xdr_result)();
+ char *(*local)();
+
+ switch (rqstp->rq_proc) {
+ case NFSPROC_NULL:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_void;
+ local = (char *(*)()) nfsproc_null_2;
+ break;
+
+ case NFSPROC_GETATTR:
+ xdr_argument = xdr_nfs_fh;
+ xdr_result = xdr_attrstat;
+ local = (char *(*)()) nfsproc_getattr_2;
+ break;
+
+ case NFSPROC_SETATTR:
+ xdr_argument = xdr_sattrargs;
+ xdr_result = xdr_attrstat;
+ local = (char *(*)()) nfsproc_setattr_2;
+ break;
+
+ case NFSPROC_ROOT:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_void;
+ local = (char *(*)()) nfsproc_root_2;
+ break;
+
+ case NFSPROC_LOOKUP:
+ xdr_argument = xdr_diropargs;
+ xdr_result = xdr_diropres;
+ local = (char *(*)()) nfsproc_lookup_2;
+ break;
+
+ case NFSPROC_READLINK:
+ xdr_argument = xdr_nfs_fh;
+ xdr_result = xdr_readlinkres;
+ local = (char *(*)()) nfsproc_readlink_2;
+ break;
+
+ case NFSPROC_READ:
+ xdr_argument = xdr_readargs;
+ xdr_result = xdr_readres;
+ local = (char *(*)()) nfsproc_read_2;
+ break;
+
+ case NFSPROC_WRITECACHE:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_void;
+ local = (char *(*)()) nfsproc_writecache_2;
+ break;
+
+ case NFSPROC_WRITE:
+ xdr_argument = xdr_writeargs;
+ xdr_result = xdr_attrstat;
+ local = (char *(*)()) nfsproc_write_2;
+ break;
+
+ case NFSPROC_CREATE:
+ xdr_argument = xdr_createargs;
+ xdr_result = xdr_diropres;
+ local = (char *(*)()) nfsproc_create_2;
+ break;
+
+ case NFSPROC_REMOVE:
+ xdr_argument = xdr_diropargs;
+ xdr_result = xdr_nfsstat;
+ local = (char *(*)()) nfsproc_remove_2;
+ break;
+
+ case NFSPROC_RENAME:
+ xdr_argument = xdr_renameargs;
+ xdr_result = xdr_nfsstat;
+ local = (char *(*)()) nfsproc_rename_2;
+ break;
+
+ case NFSPROC_LINK:
+ xdr_argument = xdr_linkargs;
+ xdr_result = xdr_nfsstat;
+ local = (char *(*)()) nfsproc_link_2;
+ break;
+
+ case NFSPROC_SYMLINK:
+ xdr_argument = xdr_symlinkargs;
+ xdr_result = xdr_nfsstat;
+ local = (char *(*)()) nfsproc_symlink_2;
+ break;
+
+ case NFSPROC_MKDIR:
+ xdr_argument = xdr_createargs;
+ xdr_result = xdr_diropres;
+ local = (char *(*)()) nfsproc_mkdir_2;
+ break;
+
+ case NFSPROC_RMDIR:
+ xdr_argument = xdr_diropargs;
+ xdr_result = xdr_nfsstat;
+ local = (char *(*)()) nfsproc_rmdir_2;
+ break;
+
+ case NFSPROC_READDIR:
+ xdr_argument = xdr_readdirargs;
+ xdr_result = xdr_readdirres;
+ local = (char *(*)()) nfsproc_readdir_2;
+ break;
+
+ case NFSPROC_STATFS:
+ xdr_argument = xdr_nfs_fh;
+ xdr_result = xdr_statfsres;
+ local = (char *(*)()) nfsproc_statfs_2;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ bzero((char *)&argument, sizeof(argument));
+ if (!svc_getargs(transp, xdr_argument, &argument)) {
+ svcerr_decode(transp);
+ return;
+ }
+ result = (*local)(&argument, rqstp);
+ if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, xdr_argument, &argument)) {
+ plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_1");
+ going_down(1);
+ }
+}
+
diff --git a/usr.sbin/amd/rpcx/nfs_prot_xdr.c b/usr.sbin/amd/rpcx/nfs_prot_xdr.c
new file mode 100644
index 0000000..1786d01
--- /dev/null
+++ b/usr.sbin/amd/rpcx/nfs_prot_xdr.c
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)nfs_prot_xdr.c 8.1 (Berkeley) 6/6/93
+ *
+ * $Id: nfs_prot_xdr.c,v 5.2.2.1 1992/02/09 15:09:32 jsp beta $
+ *
+ */
+
+#include "am.h"
+
+
+#ifndef xdr_nfsstat
+bool_t
+xdr_nfsstat(xdrs, objp)
+ XDR *xdrs;
+ nfsstat *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* xdr_nfsstat */
+
+
+
+#ifndef xdr_ftype
+static bool_t
+xdr_ftype(xdrs, objp)
+ XDR *xdrs;
+ ftype *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* xdr_ftype */
+
+
+
+bool_t
+xdr_nfs_fh(xdrs, objp)
+ XDR *xdrs;
+ nfs_fh *objp;
+{
+ if (!xdr_opaque(xdrs, objp->data, NFS_FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_nfstime(xdrs, objp)
+ XDR *xdrs;
+ nfstime *objp;
+{
+ if (!xdr_u_int(xdrs, &objp->seconds)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->useconds)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_fattr(xdrs, objp)
+ XDR *xdrs;
+ fattr *objp;
+{
+ if (!xdr_ftype(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->nlink)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocksize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->rdev)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fsid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->ctime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_sattr(xdrs, objp)
+ XDR *xdrs;
+ sattr *objp;
+{
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_filename(xdrs, objp)
+ XDR *xdrs;
+ filename *objp;
+{
+ if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_nfspath(xdrs, objp)
+ XDR *xdrs;
+ nfspath *objp;
+{
+ if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_attrstat(xdrs, objp)
+ XDR *xdrs;
+ attrstat *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_fattr(xdrs, &objp->attrstat_u.attributes)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_sattrargs(xdrs, objp)
+ XDR *xdrs;
+ sattrargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_diropargs(xdrs, objp)
+ XDR *xdrs;
+ diropargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->dir)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_diropokres(xdrs, objp)
+ XDR *xdrs;
+ diropokres *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_fattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_diropres(xdrs, objp)
+ XDR *xdrs;
+ diropres *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_diropokres(xdrs, &objp->diropres_u.diropres)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readlinkres(xdrs, objp)
+ XDR *xdrs;
+ readlinkres *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_nfspath(xdrs, &objp->readlinkres_u.data)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readargs(xdrs, objp)
+ XDR *xdrs;
+ readargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readokres(xdrs, objp)
+ XDR *xdrs;
+ readokres *objp;
+{
+ if (!xdr_fattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readres(xdrs, objp)
+ XDR *xdrs;
+ readres *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_readokres(xdrs, &objp->readres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_writeargs(xdrs, objp)
+ XDR *xdrs;
+ writeargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->beginoffset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_createargs(xdrs, objp)
+ XDR *xdrs;
+ createargs *objp;
+{
+ if (!xdr_diropargs(xdrs, &objp->where)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_renameargs(xdrs, objp)
+ XDR *xdrs;
+ renameargs *objp;
+{
+ if (!xdr_diropargs(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_linkargs(xdrs, objp)
+ XDR *xdrs;
+ linkargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_symlinkargs(xdrs, objp)
+ XDR *xdrs;
+ symlinkargs *objp;
+{
+ if (!xdr_diropargs(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_nfspath(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_nfscookie(xdrs, objp)
+ XDR *xdrs;
+ nfscookie objp;
+{
+ if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readdirargs(xdrs, objp)
+ XDR *xdrs;
+ readdirargs *objp;
+{
+ if (!xdr_nfs_fh(xdrs, &objp->dir)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_entry(xdrs, objp)
+ XDR *xdrs;
+ entry *objp;
+{
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&objp->nextentry, sizeof(entry), xdr_entry)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+static bool_t
+xdr_dirlist(xdrs, objp)
+ XDR *xdrs;
+ dirlist *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)&objp->entries, sizeof(entry), xdr_entry)) {
+ return (FALSE);
+ }
+ if (!xdr_bool(xdrs, &objp->eof)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_readdirres(xdrs, objp)
+ XDR *xdrs;
+ readdirres *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_dirlist(xdrs, &objp->readdirres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_statfsokres(xdrs, objp)
+ XDR *xdrs;
+ statfsokres *objp;
+{
+ if (!xdr_u_int(xdrs, &objp->tsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bfree)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bavail)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_statfsres(xdrs, objp)
+ XDR *xdrs;
+ statfsres *objp;
+{
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_statfsokres(xdrs, &objp->statfsres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
diff --git a/usr.sbin/amd/text/COPYRIGHT b/usr.sbin/amd/text/COPYRIGHT
new file mode 100644
index 0000000..f2e96a6
--- /dev/null
+++ b/usr.sbin/amd/text/COPYRIGHT
@@ -0,0 +1,3 @@
+Copyright (c) 1990 Jan-Simon Pendry
+Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+Copyright (c) 1990, 1993 The Regents of the University of California.
diff --git a/usr.sbin/amd/text/INSTALL b/usr.sbin/amd/text/INSTALL
new file mode 100644
index 0000000..d35aaaa
--- /dev/null
+++ b/usr.sbin/amd/text/INSTALL
@@ -0,0 +1,194 @@
+Installation Notes for Amd.
+
+NOTE: Please read all of this before starting.
+ It is not very long and may save you time in the long term.
+
+1. ``Getting started...''
+
+If you don't know what an Automounter does for you then read the
+documentation in doc/amdref.texinfo. You can either use TeX to print
+it out or read it directly using the GNU info package.
+
+2. ``Find out what version of UN*X you are running...''
+
+To install Amd you need a port for your version of UN*X. In the
+config/ directory are several files called os-*.h. One of these
+should correspond to your version of UN*X. Run the program
+"config/os-type" to find out what system Amd thinks you have. Check
+the correspondong config/os-??? file to make sure that you and Amd are
+in agreement. If os-type returns "unknown" then either no-one has yet
+done a port, or your version of UN*X is so braindead that a port is
+not possible (e.g. System V without reliable signals). The current
+known operating systems (grouped by architecture) are:
+
+ acis43 (AOS) ACIS 4.3BSD on an IBM RT
+ aix3 AIX 3.2
+ aux Apple A/UX
+ bsd44 4.4 BSD on whatever
+ concentrix Concentrix on an Alliant
+ dgux Data General AViiON
+ fpx4 Celerity FPX 4.1/2
+ hlh42 4.2 BSD on HLH Orion 1/05
+ hpux HP-UX 6.* and 7.* on a HP9000/300
+ irix3 SGI Iris
+ irix4 SGI Iris w/Irix 4.0.x
+ next NeXT
+ riscix 4.3 BSD on an Acorn Archimedes
+ sos3, sos4 SunOS 3.* and 4.* on a Sun-3 and Sun-4
+ u2_2 Ultrix 2.2 (or 2.*?) on a VAX (broken)
+ u3_0 Ultrix 3.0 (or 3.*?) on a VAX (broken)
+ u4_2 Ultrix 4.2
+ umax43 4.3 BSD on an Encore Multimax
+ xinu43 More/BSD (4.3 BSD) on a VAX or HP9000/300
+
+ + some others...
+
+If you do define a new operating system type foo, you may need to create a
+file called Makefile.foo which defines the special Makefile parameters.
+
+3. ``Hacking the Makefile...''
+
+Amd tries very hard to determine what type of machine you are using
+and how best to compile itself. If this does not work then you will
+have to find some heuristic which can differentiate your
+configuration. You may need to edit "config/arch" and
+"config/os-type". If you do make sure your changes can cope if
+/etc/motd is missing and please send it to the address below.
+
+To check whether things are working, run:
+ sh config/arch
+ sh config/os-type
+
+You may care to tailor some site specific preferences in "Makefile.com". The
+variables most likely to be changes are at the top. Any changes should be
+added to a file called config/Makefile.local (if they are applicable to all
+operating systems at your site) or Makefile.local.foo (where foo is the OS type
+as determined in part 2).
+
+Additionally, some configuration options may be altered in
+"config/Makefile.config". This means that you should not need to edit any
+distributed files apart from "config/Makefile.config". As a minimum, you
+should check:
+
+* You are using the correct C compiler. Amd, as shipped, does not use GCC.
+ Note that using GCC version 1.34 or later (e.g. 1.36) gives structure
+ passing problems with some parts of Sun's RPC library at least on Sun-4's.
+ The current workaround is to use the system CC to compile the part of the
+ automounter that gets hit by this problem. [[This is not the same problem
+ that is fixed by -fpcc-struct-return.]] Amd contains no "register"
+ declarations, so using old PCC based code generators is probably bad news.
+
+ To use GNU CC, add the following to config/Makefile.local{.os-type}:
+
+ CC = gcc ${GCCOPTS}
+
+* The installation directory (ETC) is set up correctly.
+
+* If you are running tests then it may be worth switching on the DEBUG flag
+ which will cause a running commentary to be printed to the log file. To
+ compile in the debug code, add the following to
+ config/Makefile.local{.os-type}:
+
+ DEBUG = -DDEBUG
+ CCOPTS = -g
+
+ The -g option will also allow you to use gdb. Using dbx is not advisable
+ since it puts a breakpoint on exit() which causes all of Amd's child
+ processes to dump core. gdb does not suffer from this problem.
+
+4. ``Build the executable...''
+
+Now you need to compile the automounter. To do this you type:
+
+ make
+
+in the top-level directory. You can also go into each of the program
+directories and just run make there.
+
+If you are porting to a new machine you may want to do:
+
+ make OS=foo
+
+where foo is the name of your version of UN*X as determined in part 1, until
+you have made the changes to config/os-type and/or config/arch. When the
+compilation is complete you will end up with a program called "A.arch_foo/amd".
+
+Try running:
+
+ A.arch_foo/amd -v
+
+and check the output. It should look something like:
+
+ Copyright (c) 1990 Jan-Simon Pendry
+ Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ Copyright (c) 1990 The Regents of the University of California.
+ amd 5.2.1.5 of 90/09/16 13:22:46 5.3Alpha5 #0: Sun Sep 16 13:23:28 BST 1990
+ Built by pendry@okeeffe.Berkeley.EDU for a tahoe running bsd44 (big-endian)
+ Map support for: root, passwd, nis, file, error.
+ fstypes: ufs, nfs, nfsx, host, link, program, auto, direct, toplvl, error.
+
+Make sure the O/S and architecture types were correctly derived during the
+build.
+
+5. ``Installation...''
+
+If you are not just testing Amd, then you can install it by typing:
+
+ make install
+
+to install "A.arch_foo/amd" in "/usr/local/etc/amd" (or as otherwise
+modified in part 3).
+
+6. ``Update /etc/rpc''
+
+Amq uses Sun RPC to talk to Amd using program number 300019 which has
+been registered with Sun. Add the following lines to /etc/rpc or your
+YP or Hesiod master:
+
+# Automount control protocol
+amd 300019 amq
+
+Amd does not require this addition - it just keeps rpcinfo happy.
+
+7. ``Hanging your machine...''
+
+WARNING: THIS MAY HANG YOUR MACHINE IF YOU GET IT WRONG.
+
+Running Amd with a carelessly thought out mount map can cause your Amd to
+enter a deadlock inside the kernel. For example, attempting to automount a
+directory which is automounted. This will cause the automounter to issue a mount
+request causing the kernel to send an NFS request back to the same automounter,
+which is currently stuck in a system call and unable to respond - even
+kill -KILL won't get you out of this one.
+
+There is nothing you can do to fix it without rebooting your machine, so...
+
+Find a diskless workstation and play with that first before trying this on
+your main 200 user service machine (unless you hate your users). Something
+like a diskless Sun-4 is best for development testing - you can compile on a
+Sun-4 server and run the binary on the diskless node. They reboot very fast
+as well between tests.
+
+Now you can try running Amd. Please read the documentation in doc/Amd.tex
+for more details. The configuration file "maps/a_master" provides a sample for
+you to play with. Something like:
+
+ ./amd -c 40 -D test,nodaemon /tmp/amnt ../maps/a_master &
+
+is good for testing. Note that Amd will clean up correctly if you send it a
+SIGINT or SIGTERM. Other signals are either ignored or will blow it away,
+leaving your machine in a potentially dangerous state.
+
+Remember that Amd needs to run as root in order to do mounts/unmounts
+though it does check this condition somewhere near line one of main().
+It will also need write permission in the working directory if you
+have built it with DEBUG defined and your system's mount table is
+reflected in a file. In this case watch out for NFS stepping in and
+mapping root to nobody.
+
+8. ``Report what happened...''
+
+If anything interesting happened, eg it didn't work, please report it to me
+-- Jan-Simon Pendry <jsp@doc.ic.ac.uk> -- as detailed in the README file.
+
+$Id: INSTALL,v 5.2.2.2 1992/05/31 16:49:22 jsp Exp $
diff --git a/usr.sbin/amd/text/README b/usr.sbin/amd/text/README
new file mode 100644
index 0000000..01d3a8b
--- /dev/null
+++ b/usr.sbin/amd/text/README
@@ -0,0 +1,37 @@
+This program is an automounter.
+
+This automounter is a value-added, replacement for the SunOS 4
+automount(8) program. Though based on that program in spirit, it
+contains no proprietary UN*X source code.
+
+The version you have here is release 5.3Alpha.
+
+This program is NOT in the Public Domain - it is covered by
+the usual Berkeley software distribution license - but feel free
+to take it and change it.
+
+It is believed to work correctly on Sun-3's (SunOS 3.5, 4.0, 4.1),
+Sun-4's (SunOS 4.0, 4.1), HP-9000/300 (HP-UX, MORE/bsd & BSD 4.3 Reno),
+IBM RTs (AOS 4.3), IBM RISC System/6000 (AIX 3.1), VAXen (Ultrix 4.0,
+MORE/bsd & BSD 4.3 Reno) and a wide variety of other systems. If
+your machine is not supported please feel free to try a port, but be
+sure to send me a record of the changes you had to make.
+
+
+This is the file text/README.
+
+See the file text/INSTALL for installation instructions.
+
+The documentation is in doc/amdref.texinfo. This is in GNU TeXinfo format
+and you will need a TeX system before you can print it out.
+
+Please forward *all* bug reports to Jan-Simon Pendry <jsp@doc.ic.ac.uk>
+quoting the details of the release and your configuration, which can be
+obtained by running the command "amd -v". Also send any additional
+information which may be relevant such as command line options and the maps
+being used. Thanks.
+
+The manual page (amd/amd.8) only lists the command line options. See the
+texinfo document doc/amdref.texinfo for a more detailed discussion.
+
+$Id: README,v 5.2.2.1 1992/02/09 15:11:35 jsp beta $
diff --git a/usr.sbin/amd/text/amd.start.ex b/usr.sbin/amd/text/amd.start.ex
new file mode 100644
index 0000000..d7cdc1f
--- /dev/null
+++ b/usr.sbin/amd/text/amd.start.ex
@@ -0,0 +1,87 @@
+#!/bin/sh -
+#
+# Copyright (c) 1989 Jan-Simon Pendry
+# Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Jan-Simon Pendry at Imperial College, London.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the 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.
+#
+# @(#)amd.start.ex 8.1 (Berkeley) 6/6/93
+#
+# Start amd
+#
+# $Id: amd.start.ex,v 5.2.2.1 1992/02/09 15:11:32 jsp beta $
+#
+PATH=/usr/sbin:/bin:/usr/bin:$PATH export PATH
+
+#
+# Either name of logfile or "syslog"
+#
+#LOGFILE=syslog
+LOGFILE=/var/run/amd.log
+
+#
+# Figure out whether domain name is in host name
+# If the hostname is just the machine name then
+# pass in the name of the local domain so that the
+# hostnames in the map are domain stripped correctly.
+#
+case `hostname` in
+*.*) dmn= ;;
+*) dmn='-d doc.ic.ac.uk'
+esac
+
+#
+# Zap earlier log file
+#
+case "$LOGFILE" in
+*/*)
+ mv "$LOGFILE" "$LOGFILE"-
+ > "$LOGFILE"
+ ;;
+syslog)
+ : nothing
+ ;;
+esac
+
+cd /usr/sbin
+#
+# -r restart
+# -d dmn local domain
+# -w wait wait between unmount attempts
+# -l log logfile or "syslog"
+#
+eval nice --4 ./amd -p > /var/run/amd.pid -r $dmn -w 240 -l "$LOGFILE" \
+ /homes amd.homes -cache:=inc \
+ /home amd.home -cache:=inc \
+ /vol amd.vol -cache:=inc
diff --git a/usr.sbin/arp/Makefile b/usr.sbin/arp/Makefile
new file mode 100644
index 0000000..f69a430
--- /dev/null
+++ b/usr.sbin/arp/Makefile
@@ -0,0 +1,13 @@
+# @(#)Makefile 8.2 (Berkeley) 4/18/94
+
+PROG= arp
+MAN8= arp.0
+CLEANFILES=arp4.0
+
+all: ${PROG} arp4.0 ${MAN8}
+
+beforeinstall:
+ install -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} arp4.0 \
+ ${DESTDIR}${MANDIR}4/arp.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/arp/arp.8 b/usr.sbin/arp/arp.8
new file mode 100644
index 0000000..27252dd
--- /dev/null
+++ b/usr.sbin/arp/arp.8
@@ -0,0 +1,127 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)arp.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt ARP 8
+.Os BSD 4.3
+.Sh NAME
+.Nm arp
+.Nd address resolution display and control
+.Sh SYNOPSIS
+.Nm arp
+.Ar hostname
+.Nm arp
+.Fl a
+.Nm arp
+.Fl d Ar hostname
+.Nm arp
+.Fl s Ar hostname ether_addr
+.Op Ar temp
+.Op Ar pub
+.Op Ar trail
+.Nm arp
+.Fl f Ar filename
+.Sh DESCRIPTION
+The
+.Nm arp
+program displays and modifies the Internet-to-Ethernet address translation
+tables used by the address resolution protocol
+.Pq Xr arp 4 .
+With no flags, the program displays the current
+.Tn ARP
+entry for
+.Ar hostname .
+The host may be specified by name or by number,
+using Internet dot notation.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+The program displays all of the current
+.Tn ARP
+entries.
+.It Fl d
+A super-user may delete an entry for the host called
+.Ar hostname
+with the
+.Fl d
+flag.
+.It Fl s Ar hostname ether_addr
+Create an
+.Tn ARP
+entry for the host called
+.Ar hostname
+with the Ethernet address
+.Ar ether_addr .
+The Ethernet address is given as six hex bytes separated by colons.
+The entry will be permanent unless the word
+.Ar temp
+is given in the command.
+If the word
+.Ar pub
+is given, the entry will be "published"; i.e., this system will
+act as an
+.Tn ARP
+server,
+responding to requests for
+.Ar hostname
+even though the host address is not its own.
+The word
+.Ar trail
+indicates that trailer encapsulations may be sent to this host.
+.It Fl f
+Causes the file
+.Ar filename
+to be read and multiple entries to be set in the
+.Tn ARP
+tables. Entries
+in the file should be of the form
+.Pp
+.Bd -filled -offset indent -compact
+.Ar hostname ether_addr
+.Op Ar temp
+.Op Ar pub
+.Op Ar trail
+.Ed
+.Pp
+with argument meanings as given above.
+.El
+.Sh SEE ALSO
+.Xr inet 3 ,
+.Xr arp 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
new file mode 100644
index 0000000..2182dc8
--- /dev/null
+++ b/usr.sbin/arp/arp.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 1984, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sun Microsystems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1984, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)arp.c 8.2 (Berkeley) 1/2/94";
+#endif /* not lint */
+
+/*
+ * arp - display, set, and delete arp table entries
+ */
+
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <errno.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <paths.h>
+
+extern int errno;
+static int pid;
+static int kflag;
+static int nflag;
+static int s = -1;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ch;
+
+ pid = getpid();
+ while ((ch = getopt(argc, argv, "ands")) != EOF)
+ switch((char)ch) {
+ case 'a':
+ dump(0);
+ exit(0);
+ case 'd':
+ if (argc < 3 || argc > 4)
+ usage();
+ delete(argv[2], argv[3]);
+ exit(0);
+ case 'n':
+ nflag = 1;
+ continue;
+ case 's':
+ if (argc < 4 || argc > 7)
+ usage();
+ exit(set(argc-2, &argv[2]) ? 1 : 0);
+ case '?':
+ default:
+ usage();
+ }
+ if (argc != 2)
+ usage();
+ get(argv[1]);
+ exit(0);
+}
+
+/*
+ * Process a file to set standard arp entries
+ */
+file(name)
+ char *name;
+{
+ FILE *fp;
+ int i, retval;
+ char line[100], arg[5][50], *args[5];
+
+ if ((fp = fopen(name, "r")) == NULL) {
+ fprintf(stderr, "arp: cannot open %s\n", name);
+ exit(1);
+ }
+ args[0] = &arg[0][0];
+ args[1] = &arg[1][0];
+ args[2] = &arg[2][0];
+ args[3] = &arg[3][0];
+ args[4] = &arg[4][0];
+ retval = 0;
+ while(fgets(line, 100, fp) != NULL) {
+ i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
+ arg[3], arg[4]);
+ if (i < 2) {
+ fprintf(stderr, "arp: bad line: %s\n", line);
+ retval = 1;
+ continue;
+ }
+ if (set(i, args))
+ retval = 1;
+ }
+ fclose(fp);
+ return (retval);
+}
+
+getsocket() {
+ if (s < 0) {
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0) {
+ perror("arp: socket");
+ exit(1);
+ }
+ }
+}
+
+struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
+struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
+struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
+int expire_time, flags, export_only, doing_proxy, found_entry;
+struct {
+ struct rt_msghdr m_rtm;
+ char m_space[512];
+} m_rtmsg;
+
+/*
+ * Set an individual arp entry
+ */
+set(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ register struct sockaddr_inarp *sin = &sin_m;
+ register struct sockaddr_dl *sdl;
+ register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
+ u_char *ea;
+ char *host = argv[0], *eaddr = argv[1];
+
+ getsocket();
+ argc -= 2;
+ argv += 2;
+ sdl_m = blank_sdl;
+ sin_m = blank_sin;
+ sin->sin_addr.s_addr = inet_addr(host);
+ if (sin->sin_addr.s_addr == -1) {
+ if (!(hp = gethostbyname(host))) {
+ fprintf(stderr, "arp: %s: ", host);
+ herror((char *)NULL);
+ return (1);
+ }
+ bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+ sizeof sin->sin_addr);
+ }
+ ea = (u_char *)LLADDR(&sdl_m);
+ if (ether_aton(eaddr, ea) == 0)
+ sdl_m.sdl_alen = 6;
+ doing_proxy = flags = export_only = expire_time = 0;
+ while (argc-- > 0) {
+ if (strncmp(argv[0], "temp", 4) == 0) {
+ struct timeval time;
+ gettimeofday(&time, 0);
+ expire_time = time.tv_sec + 20 * 60;
+ }
+ else if (strncmp(argv[0], "pub", 3) == 0) {
+ flags |= RTF_ANNOUNCE;
+ doing_proxy = SIN_PROXY;
+ } else if (strncmp(argv[0], "trail", 5) == 0) {
+ printf("%s: Sending trailers is no longer supported\n",
+ host);
+ }
+ argv++;
+ }
+tryagain:
+ if (rtmsg(RTM_GET) < 0) {
+ perror(host);
+ return (1);
+ }
+ sin = (struct sockaddr_inarp *)(rtm + 1);
+ sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
+ if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
+ if (sdl->sdl_family == AF_LINK &&
+ (rtm->rtm_flags & RTF_LLINFO) &&
+ !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
+ case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
+ case IFT_ISO88024: case IFT_ISO88025:
+ goto overwrite;
+ }
+ if (doing_proxy == 0) {
+ printf("set: can only proxy for %s\n", host);
+ return (1);
+ }
+ if (sin_m.sin_other & SIN_PROXY) {
+ printf("set: proxy entry exists for non 802 device\n");
+ return(1);
+ }
+ sin_m.sin_other = SIN_PROXY;
+ export_only = 1;
+ goto tryagain;
+ }
+overwrite:
+ if (sdl->sdl_family != AF_LINK) {
+ printf("cannot intuit interface index and type for %s\n", host);
+ return (1);
+ }
+ sdl_m.sdl_type = sdl->sdl_type;
+ sdl_m.sdl_index = sdl->sdl_index;
+ return (rtmsg(RTM_ADD));
+}
+
+/*
+ * Display an individual arp entry
+ */
+get(host)
+ char *host;
+{
+ struct hostent *hp;
+ struct sockaddr_inarp *sin = &sin_m;
+ u_char *ea;
+
+ sin_m = blank_sin;
+ sin->sin_addr.s_addr = inet_addr(host);
+ if (sin->sin_addr.s_addr == -1) {
+ if (!(hp = gethostbyname(host))) {
+ fprintf(stderr, "arp: %s: ", host);
+ herror((char *)NULL);
+ exit(1);
+ }
+ bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+ sizeof sin->sin_addr);
+ }
+ dump(sin->sin_addr.s_addr);
+ if (found_entry == 0) {
+ printf("%s (%s) -- no entry\n",
+ host, inet_ntoa(sin->sin_addr));
+ exit(1);
+ }
+}
+
+/*
+ * Delete an arp entry
+ */
+delete(host, info)
+ char *host;
+ char *info;
+{
+ struct hostent *hp;
+ register struct sockaddr_inarp *sin = &sin_m;
+ register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
+ struct sockaddr_dl *sdl;
+ u_char *ea;
+ char *eaddr;
+
+ if (info && strncmp(info, "pro", 3) )
+ export_only = 1;
+ getsocket();
+ sin_m = blank_sin;
+ sin->sin_addr.s_addr = inet_addr(host);
+ if (sin->sin_addr.s_addr == -1) {
+ if (!(hp = gethostbyname(host))) {
+ fprintf(stderr, "arp: %s: ", host);
+ herror((char *)NULL);
+ return (1);
+ }
+ bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+ sizeof sin->sin_addr);
+ }
+tryagain:
+ if (rtmsg(RTM_GET) < 0) {
+ perror(host);
+ return (1);
+ }
+ sin = (struct sockaddr_inarp *)(rtm + 1);
+ sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
+ if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
+ if (sdl->sdl_family == AF_LINK &&
+ (rtm->rtm_flags & RTF_LLINFO) &&
+ !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
+ case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
+ case IFT_ISO88024: case IFT_ISO88025:
+ goto delete;
+ }
+ }
+ if (sin_m.sin_other & SIN_PROXY) {
+ fprintf(stderr, "delete: can't locate %s\n",host);
+ return (1);
+ } else {
+ sin_m.sin_other = SIN_PROXY;
+ goto tryagain;
+ }
+delete:
+ if (sdl->sdl_family != AF_LINK) {
+ printf("cannot locate %s\n", host);
+ return (1);
+ }
+ if (rtmsg(RTM_DELETE) == 0)
+ printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
+}
+
+/*
+ * Dump the entire arp table
+ */
+dump(addr)
+u_long addr;
+{
+ int mib[6];
+ size_t needed;
+ char *host, *malloc(), *lim, *buf, *next;
+ struct rt_msghdr *rtm;
+ struct sockaddr_inarp *sin;
+ struct sockaddr_dl *sdl;
+ extern int h_errno;
+ struct hostent *hp;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET;
+ mib[4] = NET_RT_FLAGS;
+ mib[5] = RTF_LLINFO;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ quit("route-sysctl-estimate");
+ if ((buf = malloc(needed)) == NULL)
+ quit("malloc");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ quit("actual retrieval of routing table");
+ lim = buf + needed;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ sin = (struct sockaddr_inarp *)(rtm + 1);
+ sdl = (struct sockaddr_dl *)(sin + 1);
+ if (addr) {
+ if (addr != sin->sin_addr.s_addr)
+ continue;
+ found_entry = 1;
+ }
+ if (nflag == 0)
+ hp = gethostbyaddr((caddr_t)&(sin->sin_addr),
+ sizeof sin->sin_addr, AF_INET);
+ else
+ hp = 0;
+ if (hp)
+ host = hp->h_name;
+ else {
+ host = "?";
+ if (h_errno == TRY_AGAIN)
+ nflag = 1;
+ }
+ printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
+ if (sdl->sdl_alen)
+ ether_print(LLADDR(sdl));
+ else
+ printf("(incomplete)");
+ if (rtm->rtm_rmx.rmx_expire == 0)
+ printf(" permanent");
+ if (sin->sin_other & SIN_PROXY)
+ printf(" published (proxy only)");
+ if (rtm->rtm_addrs & RTA_NETMASK) {
+ sin = (struct sockaddr_inarp *)
+ (sdl->sdl_len + (char *)sdl);
+ if (sin->sin_addr.s_addr == 0xffffffff)
+ printf(" published");
+ if (sin->sin_len != 8)
+ printf("(wierd)");
+ }
+ printf("\n");
+ }
+}
+
+ether_print(cp)
+ u_char *cp;
+{
+ printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
+}
+
+ether_aton(a, n)
+ char *a;
+ u_char *n;
+{
+ int i, o[6];
+
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
+ &o[3], &o[4], &o[5]);
+ if (i != 6) {
+ fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
+ return (1);
+ }
+ for (i=0; i<6; i++)
+ n[i] = o[i];
+ return (0);
+}
+
+usage()
+{
+ printf("usage: arp hostname\n");
+ printf(" arp -a [kernel] [kernel_memory]\n");
+ printf(" arp -d hostname\n");
+ printf(" arp -s hostname ether_addr [temp] [pub]\n");
+ printf(" arp -f filename\n");
+ exit(1);
+}
+
+rtmsg(cmd)
+{
+ static int seq;
+ int rlen;
+ register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
+ register char *cp = m_rtmsg.m_space;
+ register int l;
+
+ errno = 0;
+ if (cmd == RTM_DELETE)
+ goto doit;
+ bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+ rtm->rtm_flags = flags;
+ rtm->rtm_version = RTM_VERSION;
+
+ switch (cmd) {
+ default:
+ fprintf(stderr, "arp: internal wrong cmd\n");
+ exit(1);
+ case RTM_ADD:
+ rtm->rtm_addrs |= RTA_GATEWAY;
+ rtm->rtm_rmx.rmx_expire = expire_time;
+ rtm->rtm_inits = RTV_EXPIRE;
+ rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
+ sin_m.sin_other = 0;
+ if (doing_proxy) {
+ if (export_only)
+ sin_m.sin_other = SIN_PROXY;
+ else {
+ rtm->rtm_addrs |= RTA_NETMASK;
+ rtm->rtm_flags &= ~RTF_HOST;
+ }
+ }
+ /* FALLTHROUGH */
+ case RTM_GET:
+ rtm->rtm_addrs |= RTA_DST;
+ }
+#define NEXTADDR(w, s) \
+ if (rtm->rtm_addrs & (w)) { \
+ bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
+
+ NEXTADDR(RTA_DST, sin_m);
+ NEXTADDR(RTA_GATEWAY, sdl_m);
+ NEXTADDR(RTA_NETMASK, so_mask);
+
+ rtm->rtm_msglen = cp - (char *)&m_rtmsg;
+doit:
+ l = rtm->rtm_msglen;
+ rtm->rtm_seq = ++seq;
+ rtm->rtm_type = cmd;
+ if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+ if (errno != ESRCH || cmd != RTM_DELETE) {
+ perror("writing to routing socket");
+ return (-1);
+ }
+ }
+ do {
+ l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+ } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
+ if (l < 0)
+ (void) fprintf(stderr, "arp: read from routing socket: %s\n",
+ strerror(errno));
+ return (0);
+}
+
+quit(msg)
+char *msg;
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(1);
+}
diff --git a/usr.sbin/arp/arp4.4 b/usr.sbin/arp/arp4.4
new file mode 100644
index 0000000..0cd7161
--- /dev/null
+++ b/usr.sbin/arp/arp4.4
@@ -0,0 +1,124 @@
+.\" Copyright (c) 1985, 1986, 1988, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)arp4.4 6.5 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt ARP 4
+.Os BSD 4
+.Sh NAME
+.Nm arp
+.Nd Address Resolution Protocol
+.Sh SYNOPSIS
+.Em "pseudo-device ether"
+.Sh DESCRIPTION
+The Address Resolution Protocol (ARP) is a protocol used to dynamically
+map between Internet host addresses and 10Mb/s Ethernet addresses.
+It is used by all the 10Mb/s Ethernet interface drivers.
+It is not specific to Internet protocols or to 10Mb/s Ethernet,
+but this implementation currently supports only that combination.
+.Pp
+ARP caches Internet-Ethernet address mappings.
+When an interface requests a mapping for an address not in the cache,
+ARP queues the message which requires the mapping and broadcasts
+a message on the associated network requesting the address mapping.
+If a response is provided, the new mapping is cached and any pending
+message is transmitted.
+ARP will queue at most one packet while waiting for a response to a
+mapping request;
+only the most recently ``transmitted'' packet is kept.
+If the target host does not respond after several requests,
+the host is considered to be down for a short period (normally 20 seconds),
+allowing an error to be returned to transmission attempts during this
+interval.
+The error is
+.Li EHOSTDOWN
+for a non-responding destination host, and
+.Li EHOSTUNREACH
+for a non-responding router.
+.Pp
+The ARP cache is stored in the system routing table as
+dynamically-created host routes.
+The route to a directly-attached Ethernet network is installed as a
+.Dq cloning
+route (one with the
+.Li RTF_CLONING
+flag set),
+causing routes to individual hosts on that network to be created on
+demand.
+These routes time out periodically (normally 20 minutes after validated;
+entries are not validated when not in use).
+An entry for a host which is not responding is a
+.Dq reject
+route (one with the
+.Li RTF_REJECT
+flag set).
+.Pp
+ARP entries may be added, deleted or changed with the
+.Xr arp 8
+utility.
+Manually-added entries may be temporary or permanent,
+and may be
+.Dq published ,
+in which case the system will respond to ARP requests for that host
+as if it were the target of the request.
+.Pp
+In the past,
+ARP was used to negotiate the use of a trailer encapsulation.
+This is no longer supported.
+.Pp
+ARP watches passively for hosts impersonating the local host (i.e. a host
+which responds to an ARP mapping request for the local host's address).
+.Sh DIAGNOSTICS
+.Em "duplicate IP address %x!! sent from ethernet address: %x:%x:%x:%x:%x:%x."
+ARP has discovered another host on the local network which responds to
+mapping requests for its own Internet address with a different Ethernet
+address, generally indicating that two hosts are attempting to use the
+same Internet address.
+.Sh SEE ALSO
+.Xr inet 4 ,
+.Xr route 4 ,
+.Xr arp 8 ,
+.Xr ifconfig 8 ,
+.Xr route 8
+.sp
+.Rs
+.%A Plummer, D.
+.%B "An Ethernet Address Resolution Protocol"
+.%T RFC826
+.Re
+.Rs
+.%A Leffler, S.J.
+.%A Karels, M.J.
+.%B "Trailer Encapsulations
+.%T RFC893
+.Re
+
diff --git a/usr.sbin/bad144/Makefile b/usr.sbin/bad144/Makefile
new file mode 100644
index 0000000..f3e10da
--- /dev/null
+++ b/usr.sbin/bad144/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= bad144
+MAN8= bad144.0
+MANSUBDIR=/vax
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bad144/bad144.8 b/usr.sbin/bad144/bad144.8
new file mode 100644
index 0000000..9ea8c88
--- /dev/null
+++ b/usr.sbin/bad144/bad144.8
@@ -0,0 +1,186 @@
+.\" Copyright (c) 1980, 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bad144.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt BAD144 8
+.Os BSD 4
+.Sh NAME
+.Nm bad144
+.Nd read/write dec standard 144 bad sector information
+.Sh SYNOPSIS
+.Nm bad144
+.Op Fl c
+.Op Fl f
+.Op Fl v
+.Ar disk
+.Oo
+.Ar sno
+.Op Ar bad ...
+.Oc
+.Nm bad144
+.Fl a
+.Op Fl c
+.Op Fl f
+.Op Fl v
+.Ar disk
+.Op Ar bad ...
+.Sh DESCRIPTION
+.Nm Bad144
+can be used to inspect the information stored on a disk that is used by
+the disk drivers to implement bad sector forwarding.
+.Pp
+Available options:
+.Pp
+.Bl -tag -width Ds
+.It Fl a
+The argument list consists of new bad sectors to be added to an existing
+list.
+The new sectors are sorted into the list,
+which must have been in order.
+Replacement sectors are moved to accommodate the additions;
+the new replacement sectors are cleared.
+.It Fl c
+Forces an attempt to copy the old sector to the replacement,
+and may be useful when replacing an unreliable sector.
+.It Fl f
+For a RP06, RM03, RM05, Fujitsu Eagle,
+or
+.Tn SMD
+disk on a Massbus, the
+.Fl f
+option may be used to mark the new bad sectors as ``bad''
+by reformatting them as unusable sectors.
+This option is
+.Em required unless
+the sectors have already been marked bad,
+or the system will not be notified that it should use the replacement sector.
+This option may be used while running multiuser; it is no longer necessary
+to perform format operations while running single-user.
+.It Fl v
+The entire process is described as it happens in gory detail if
+.Fl v
+(verbose) is given.
+.El
+.Pp
+The format of
+the information is specified by
+.Tn DEC
+standard 144, as follows.
+The bad sector information is located in the first 5 even numbered sectors
+of the last track of the disk pack. There are five identical copies of
+the information, described by the
+.Ar dkbad
+structure.
+.Pp
+Replacement sectors are allocated starting with the first sector before
+the bad sector information and working backwards towards the beginning
+of the disk. A maximum of 126 bad sectors are supported. The position
+of the bad sector in the bad sector table determines the replacement
+sector to which it corresponds.
+The bad sectors must be listed in ascending order.
+.Pp
+The bad sector information and replacement sectors are conventionally
+only accessible through the ``c'' file system partition of the disk. If
+that partition is used for a file system, the user is responsible for
+making sure that it does not overlap the bad sector information or any
+replacement sectors.
+Thus, one track plus 126 sectors must be reserved to allow use
+of all of the possible bad sector replacements.
+.Pp
+The bad sector structure is as follows:
+.Bd -literal
+struct dkbad {
+ long bt_csn; /* cartridge serial number */
+ u_short bt_mbz; /* unused; should be 0 */
+ u_short bt_flag; /* -1 => alignment cartridge */
+ struct bt_bad {
+ u_short bt_cyl; /* bad sector cylinder number */
+ u_short bt_trksec; /* track and sector number */
+ } bt_bad[126];
+};
+.Ed
+.Pp
+Unused slots in the
+.Ar bt_bad
+array are filled with all bits set, a putatively
+illegal value.
+.Pp
+.Nm Bad144
+is invoked by giving a device name (e.g. hk0, hp1, etc.).
+With no optional arguments
+it reads the first sector of the last track
+of the corresponding disk and prints out the bad sector information.
+It issues a warning if the bad sectors are out of order.
+.Nm Bad144
+may also be invoked with a serial number for the pack and a list
+of bad sectors.
+It will write the supplied information into all copies
+of the bad-sector file, replacing any previous information.
+Note, however, that
+.Nm bad144
+does not arrange for the specified sectors to be marked bad in this case.
+This procedure should only be used to restore known bad sector information which
+was destroyed.
+.Pp
+It is no longer necessary to reboot to allow the kernel
+to reread the bad-sector table from the drive.
+.Sh SEE ALSO
+.Xr badsect 8 ,
+.Xr format 8
+.Sh BUGS
+It should be possible to format disks on-line under
+.Tn UNIX .
+.Pp
+It should be possible to mark bad sectors on drives of all type.
+.Pp
+On an 11/750,
+the standard bootstrap drivers used to boot the system do
+not understand bad sectors,
+handle
+.Tn ECC
+errors, or the special
+.Tn SSE
+(skip sector) errors of RM80-type disks.
+This means that none of these errors can occur when reading the file
+.Pa /vmunix
+to boot. Sectors 0-15 of the disk drive
+must also not have any of these errors.
+.Pp
+The drivers which write a system core image on disk after a crash do not
+handle errors; thus the crash dump area must be free of errors and bad
+sectors.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.1 .
diff --git a/usr.sbin/bad144/bad144.c b/usr.sbin/bad144/bad144.c
new file mode 100644
index 0000000..0afa9e4
--- /dev/null
+++ b/usr.sbin/bad144/bad144.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 1993, 198019861988
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1993, 198019861988\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char sccsid[] = "@(#)bad144.c 8.1 (Berkeley) 6/6/93";
+#endif not lint
+
+/*
+ * bad144
+ *
+ * This program prints and/or initializes a bad block record for a pack,
+ * in the format used by the DEC standard 144.
+ * It can also add bad sector(s) to the record, moving the sector
+ * replacements as necessary.
+ *
+ * It is preferable to write the bad information with a standard formatter,
+ * but this program will do.
+ *
+ * RP06 sectors are marked as bad by inverting the format bit in the
+ * header; on other drives the valid-sector bit is cleared.
+ */
+#include <sys/param.h>
+#include <sys/dkbad.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/disklabel.h>
+#include <ufs/ffs/fs.h>
+
+#include <stdio.h>
+#include <paths.h>
+
+#define RETRIES 10 /* number of retries on reading old sectors */
+#define RAWPART "c" /* disk partition containing badsector tables */
+
+int fflag, add, copy, verbose, nflag;
+int compare();
+int dups;
+int badfile = -1; /* copy of badsector table to use, -1 if any */
+#define MAXSECSIZE 1024
+struct dkbad curbad, oldbad;
+#define DKBAD_MAGIC 0
+
+char label[BBSIZE];
+daddr_t size, getold(), badsn();
+struct disklabel *dp;
+char name[BUFSIZ];
+char *malloc();
+off_t lseek();
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct bt_bad *bt;
+ daddr_t sn, bn[126];
+ int i, f, nbad, new, bad, errs;
+
+ argc--, argv++;
+ while (argc > 0 && **argv == '-') {
+ (*argv)++;
+ while (**argv) {
+ switch (**argv) {
+#if vax
+ case 'f':
+ fflag++;
+ break;
+#endif
+ case 'a':
+ add++;
+ break;
+ case 'c':
+ copy++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'n':
+ nflag++;
+ verbose++;
+ break;
+ default:
+ if (**argv >= '0' && **argv <= '4') {
+ badfile = **argv - '0';
+ break;
+ }
+ goto usage;
+ }
+ (*argv)++;
+ }
+ argc--, argv++;
+ }
+ if (argc < 1) {
+usage:
+ fprintf(stderr,
+ "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
+ fprintf(stderr,
+ "to read or overwrite bad-sector table, e.g.: bad144 hp0\n");
+ fprintf(stderr,
+ "or bad144 -a [ -f ] [ -c ] disk bn ...\n");
+ fprintf(stderr, "where options are:\n");
+ fprintf(stderr, "\t-a add new bad sectors to the table\n");
+ fprintf(stderr, "\t-f reformat listed sectors as bad\n");
+ fprintf(stderr, "\t-c copy original sector to replacement\n");
+ exit(1);
+ }
+ if (argv[0][0] != '/')
+ (void)sprintf(name, "%s/r%s%s", _PATH_DEV, argv[0], RAWPART);
+ else
+ strcpy(name, argv[0]);
+ f = open(name, argc == 1? O_RDONLY : O_RDWR);
+ if (f < 0)
+ Perror(name);
+ if (read(f, label, sizeof(label)) < 0)
+ Perror("read");
+ for (dp = (struct disklabel *)(label + LABELOFFSET);
+ dp < (struct disklabel *)
+ (label + sizeof(label) - sizeof(struct disklabel));
+ dp = (struct disklabel *)((char *)dp + 64))
+ if (dp->d_magic == DISKMAGIC && dp->d_magic2 == DISKMAGIC)
+ break;
+ if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC) {
+ fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
+ exit(1);
+ }
+ if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
+ fprintf(stderr, "Disk sector size too large/small (%d)\n",
+ dp->d_secsize);
+ exit(7);
+ }
+ size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders;
+ argc--;
+ argv++;
+ if (argc == 0) {
+ sn = getold(f, &oldbad);
+ printf("bad block information at sector %d in %s:\n",
+ sn, name);
+ printf("cartridge serial number: %d(10)\n", oldbad.bt_csn);
+ switch (oldbad.bt_flag) {
+
+ case (u_short)-1:
+ printf("alignment cartridge\n");
+ break;
+
+ case DKBAD_MAGIC:
+ break;
+
+ default:
+ printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
+ break;
+ }
+ bt = oldbad.bt_bad;
+ for (i = 0; i < 126; i++) {
+ bad = (bt->bt_cyl<<16) + bt->bt_trksec;
+ if (bad < 0)
+ break;
+ printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
+ bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
+ bt++;
+ }
+ (void) checkold(&oldbad);
+ exit(0);
+ }
+ if (add) {
+ /*
+ * Read in the old badsector table.
+ * Verify that it makes sense, and the bad sectors
+ * are in order. Copy the old table to the new one.
+ */
+ (void) getold(f, &oldbad);
+ i = checkold(&oldbad);
+ if (verbose)
+ printf("Had %d bad sectors, adding %d\n", i, argc);
+ if (i + argc > 126) {
+ printf("bad144: not enough room for %d more sectors\n",
+ argc);
+ printf("limited to 126 by information format\n");
+ exit(1);
+ }
+ curbad = oldbad;
+ } else {
+ curbad.bt_csn = atoi(*argv++);
+ argc--;
+ curbad.bt_mbz = 0;
+ curbad.bt_flag = DKBAD_MAGIC;
+ if (argc > 126) {
+ printf("bad144: too many bad sectors specified\n");
+ printf("limited to 126 by information format\n");
+ exit(1);
+ }
+ i = 0;
+ }
+ errs = 0;
+ new = argc;
+ while (argc > 0) {
+ daddr_t sn = atoi(*argv++);
+ argc--;
+ if (sn < 0 || sn >= size) {
+ printf("%d: out of range [0,%d) for disk %s\n",
+ sn, size, dp->d_typename);
+ errs++;
+ continue;
+ }
+ bn[i] = sn;
+ curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
+ sn %= (dp->d_nsectors*dp->d_ntracks);
+ curbad.bt_bad[i].bt_trksec =
+ ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
+ i++;
+ }
+ if (errs)
+ exit(1);
+ nbad = i;
+ while (i < 126) {
+ curbad.bt_bad[i].bt_trksec = -1;
+ curbad.bt_bad[i].bt_cyl = -1;
+ i++;
+ }
+ if (add) {
+ /*
+ * Sort the new bad sectors into the list.
+ * Then shuffle the replacement sectors so that
+ * the previous bad sectors get the same replacement data.
+ */
+ qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
+ compare);
+ if (dups) {
+ fprintf(stderr,
+"bad144: bad sectors have been duplicated; can't add existing sectors\n");
+ exit(3);
+ }
+ shift(f, nbad, nbad-new);
+ }
+ if (badfile == -1)
+ i = 0;
+ else
+ i = badfile * 2;
+ for (; i < 10 && i < dp->d_nsectors; i += 2) {
+ if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
+ L_SET) < 0)
+ Perror("lseek");
+ if (verbose)
+ printf("write badsect file at %d\n",
+ size - dp->d_nsectors + i);
+ if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
+ sizeof(curbad)) {
+ char msg[80];
+ (void)sprintf(msg, "bad144: write bad sector file %d",
+ i/2);
+ perror(msg);
+ }
+ if (badfile != -1)
+ break;
+ }
+#ifdef vax
+ if (nflag == 0 && fflag)
+ for (i = nbad - new; i < nbad; i++)
+ format(f, bn[i]);
+#endif
+#ifdef DIOCSBAD
+ if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
+ fprintf(stderr,
+ "Can't sync bad-sector file; reboot for changes to take effect\n");
+#endif
+ exit(0);
+}
+
+daddr_t
+getold(f, bad)
+struct dkbad *bad;
+{
+ register int i;
+ daddr_t sn;
+ char msg[80];
+
+ if (badfile == -1)
+ i = 0;
+ else
+ i = badfile * 2;
+ for (; i < 10 && i < dp->d_nsectors; i += 2) {
+ sn = size - dp->d_nsectors + i;
+ if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
+ Perror("lseek");
+ if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
+ if (i > 0)
+ printf("Using bad-sector file %d\n", i/2);
+ return(sn);
+ }
+ (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
+ perror(msg);
+ if (badfile != -1)
+ break;
+ }
+ fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
+ exit(1);
+ /*NOTREACHED*/
+}
+
+checkold()
+{
+ register int i;
+ register struct bt_bad *bt;
+ daddr_t sn, lsn;
+ int errors = 0, warned = 0;
+
+ if (oldbad.bt_flag != DKBAD_MAGIC) {
+ fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
+ name);
+ errors++;
+ }
+ if (oldbad.bt_mbz != 0) {
+ fprintf(stderr, "bad144: %s: bad magic number\n", name);
+ errors++;
+ }
+ bt = oldbad.bt_bad;
+ for (i = 0; i < 126; i++, bt++) {
+ if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
+ break;
+ if ((bt->bt_cyl >= dp->d_ncylinders) ||
+ ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
+ ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
+ fprintf(stderr,
+ "bad144: cyl/trk/sect out of range in existing entry: ");
+ fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
+ badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
+ bt->bt_trksec & 0xff);
+ errors++;
+ }
+ sn = (bt->bt_cyl * dp->d_ntracks +
+ (bt->bt_trksec >> 8)) *
+ dp->d_nsectors + (bt->bt_trksec & 0xff);
+ if (i > 0 && sn < lsn && !warned) {
+ fprintf(stderr,
+ "bad144: bad sector file is out of order\n");
+ errors++;
+ warned++;
+ }
+ if (i > 0 && sn == lsn) {
+ fprintf(stderr,
+ "bad144: bad sector file contains duplicates (sn %d)\n",
+ sn);
+ errors++;
+ }
+ lsn = sn;
+ }
+ if (errors)
+ exit(1);
+ return (i);
+}
+
+/*
+ * Move the bad sector replacements
+ * to make room for the new bad sectors.
+ * new is the new number of bad sectors, old is the previous count.
+ */
+shift(f, new, old)
+{
+ daddr_t repl;
+
+ /*
+ * First replacement is last sector of second-to-last track.
+ */
+ repl = size - dp->d_nsectors - 1;
+ new--; old--;
+ while (new >= 0 && new != old) {
+ if (old < 0 ||
+ compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
+ /*
+ * Insert new replacement here-- copy original
+ * sector if requested and possible,
+ * otherwise write a zero block.
+ */
+ if (!copy ||
+ !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
+ blkzero(f, repl - new);
+ } else {
+ if (blkcopy(f, repl - old, repl - new) == 0)
+ fprintf(stderr,
+ "Can't copy replacement sector %d to %d\n",
+ repl-old, repl-new);
+ old--;
+ }
+ new--;
+ }
+}
+
+char *buf;
+
+/*
+ * Copy disk sector s1 to s2.
+ */
+blkcopy(f, s1, s2)
+daddr_t s1, s2;
+{
+ register tries, n;
+
+ if (buf == (char *)NULL) {
+ buf = malloc((unsigned)dp->d_secsize);
+ if (buf == (char *)NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(20);
+ }
+ }
+ for (tries = 0; tries < RETRIES; tries++) {
+ if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
+ Perror("lseek");
+ if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
+ break;
+ }
+ if (n != dp->d_secsize) {
+ fprintf(stderr, "bad144: can't read sector, %d: ", s1);
+ if (n < 0)
+ perror((char *)0);
+ return(0);
+ }
+ if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
+ Perror("lseek");
+ if (verbose)
+ printf("copying %d to %d\n", s1, s2);
+ if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
+ fprintf(stderr,
+ "bad144: can't write replacement sector, %d: ", s2);
+ perror((char *)0);
+ return(0);
+ }
+ return(1);
+}
+
+char *zbuf;
+
+blkzero(f, sn)
+daddr_t sn;
+{
+
+ if (zbuf == (char *)NULL) {
+ zbuf = malloc((unsigned)dp->d_secsize);
+ if (zbuf == (char *)NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(20);
+ }
+ }
+ if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
+ Perror("lseek");
+ if (verbose)
+ printf("zeroing %d\n", sn);
+ if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
+ fprintf(stderr,
+ "bad144: can't write replacement sector, %d: ", sn);
+ perror((char *)0);
+ }
+}
+
+compare(b1, b2)
+register struct bt_bad *b1, *b2;
+{
+ if (b1->bt_cyl > b2->bt_cyl)
+ return(1);
+ if (b1->bt_cyl < b2->bt_cyl)
+ return(-1);
+ if (b1->bt_trksec == b2->bt_trksec)
+ dups++;
+ return (b1->bt_trksec - b2->bt_trksec);
+}
+
+daddr_t
+badsn(bt)
+register struct bt_bad *bt;
+{
+ return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
+ + (bt->bt_trksec&0xff));
+}
+
+#ifdef vax
+
+struct rp06hdr {
+ short h_cyl;
+ short h_trksec;
+ short h_key1;
+ short h_key2;
+ char h_data[512];
+#define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
+};
+
+/*
+ * Most massbus and unibus drives
+ * have headers of this form
+ */
+struct hpuphdr {
+ u_short hpup_cyl;
+ u_char hpup_sect;
+ u_char hpup_track;
+ char hpup_data[512];
+#define HPUP_OKSECT 0xc000 /* this normally means sector is good */
+#define HPUP_16BIT 0x1000 /* 1 == 16 bit format */
+};
+int rp06format(), hpupformat();
+
+struct formats {
+ char *f_name; /* disk name */
+ int f_bufsize; /* size of sector + header */
+ int f_bic; /* value to bic in hpup_cyl */
+ int (*f_routine)(); /* routine for special handling */
+} formats[] = {
+ { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format },
+ { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
+ { 0, 0, 0, 0 }
+};
+
+/*ARGSUSED*/
+hpupformat(fp, dp, blk, buf, count)
+ struct formats *fp;
+ struct disklabel *dp;
+ daddr_t blk;
+ char *buf;
+ int count;
+{
+ struct hpuphdr *hdr = (struct hpuphdr *)buf;
+ int sect;
+
+ if (count < sizeof(struct hpuphdr)) {
+ hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
+ (blk / (dp->d_nsectors * dp->d_ntracks));
+ sect = blk % (dp->d_nsectors * dp->d_ntracks);
+ hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
+ hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+rp06format(fp, dp, blk, buf, count)
+ struct formats *fp;
+ struct disklabel *dp;
+ daddr_t blk;
+ char *buf;
+ int count;
+{
+
+ if (count < sizeof(struct rp06hdr)) {
+ fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
+ blk);
+ return (-1);
+ }
+ return (0);
+}
+
+format(fd, blk)
+ int fd;
+ daddr_t blk;
+{
+ register struct formats *fp;
+ static char *buf;
+ static char bufsize;
+ struct format_op fop;
+ int n;
+
+ for (fp = formats; fp->f_name; fp++)
+ if (strcmp(dp->d_typename, fp->f_name) == 0)
+ break;
+ if (fp->f_name == 0) {
+ fprintf(stderr, "bad144: don't know how to format %s disks\n",
+ dp->d_typename);
+ exit(2);
+ }
+ if (buf && bufsize < fp->f_bufsize) {
+ free(buf);
+ buf = NULL;
+ }
+ if (buf == NULL)
+ buf = malloc((unsigned)fp->f_bufsize);
+ if (buf == NULL) {
+ fprintf(stderr, "bad144: can't allocate sector buffer\n");
+ exit(3);
+ }
+ bufsize = fp->f_bufsize;
+ /*
+ * Here we do the actual formatting. All we really
+ * do is rewrite the sector header and flag the bad sector
+ * according to the format table description. If a special
+ * purpose format routine is specified, we allow it to
+ * process the sector as well.
+ */
+ if (verbose)
+ printf("format blk %d\n", blk);
+ bzero((char *)&fop, sizeof(fop));
+ fop.df_buf = buf;
+ fop.df_count = fp->f_bufsize;
+ fop.df_startblk = blk;
+ bzero(buf, fp->f_bufsize);
+ if (ioctl(fd, DIOCRFORMAT, &fop) < 0)
+ perror("bad144: read format");
+ if (fp->f_routine &&
+ (*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0)
+ return;
+ if (fp->f_bic) {
+ struct hpuphdr *xp = (struct hpuphdr *)buf;
+
+ xp->hpup_cyl &= ~fp->f_bic;
+ }
+ if (nflag)
+ return;
+ bzero((char *)&fop, sizeof(fop));
+ fop.df_buf = buf;
+ fop.df_count = fp->f_bufsize;
+ fop.df_startblk = blk;
+ if (ioctl(fd, DIOCWFORMAT, &fop) < 0)
+ Perror("write format");
+ if (fop.df_count != fp->f_bufsize) {
+ char msg[80];
+ (void)sprintf(msg, "bad144: write format %d", blk);
+ perror(msg);
+ }
+}
+#endif
+
+Perror(op)
+ char *op;
+{
+
+ fprintf(stderr, "bad144: "); perror(op);
+ exit(4);
+}
diff --git a/usr.sbin/chown/Makefile b/usr.sbin/chown/Makefile
new file mode 100644
index 0000000..084b4bc
--- /dev/null
+++ b/usr.sbin/chown/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= chown
+CFLAGS+=-DSUPPORT_DOT
+MAN1= chgrp.0
+MAN8= chown.0
+LINKS= ${BINDIR}/chown /usr/bin/chgrp
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/chown/chgrp.1 b/usr.sbin/chown/chgrp.1
new file mode 100644
index 0000000..1adcb80
--- /dev/null
+++ b/usr.sbin/chown/chgrp.1
@@ -0,0 +1,136 @@
+.\" Copyright (c) 1983, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chgrp.1 8.3 (Berkeley) 3/31/94
+.\"
+.Dd March 31, 1994
+.Dt CHGRP 1
+.Os BSD 4.2
+.Sh NAME
+.Nm chgrp
+.Nd change group
+.Sh SYNOPSIS
+.Nm chgrp
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Op Fl f
+.Ar group
+.Ar files ...
+.Sh DESCRIPTION
+The chgrp utility sets the group ID of the file named by each
+.Ar file
+operand to the
+.Ar group
+ID specified by the group operand.
+.Pp
+Options:
+.Bl -tag -width Ds
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+.It Fl R
+Change the group ID for the file hierarchies rooted
+in the files instead of just the files themselves.
+.It Fl f
+The force option ignores errors, except for usage errors and doesn't
+query about strange modes (unless the user does not have proper permissions).
+.El
+.Pp
+Symbolic links don't have groups, so unless the
+.Fl H
+or
+.Fl L
+option is set,
+.Nm chgrp
+on a symbolic link always succeeds and has no effect.
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+The
+.Ar group
+operand can be either a group name from the group database,
+or a numeric group ID.
+If a group name is also a numeric group ID, the operand is used as a
+group name.
+.Pp
+The user invoking
+.Nm chgrp
+must belong to the specified group and be the owner of the file,
+or be the super-user.
+.Pp
+The
+.Nm chgrp
+utility exits 0 on success, and >0 if an error occurs.
+.Sh COMPATIBILITY
+Previous versions of the
+.Nm chgrp
+utility changed the group of symbolic links specified on the command
+line.
+In this system, symbolic links do not have groups.
+.Sh FILES
+.Bl -tag -width /etc/group -compact
+.It Pa /etc/group
+Group ID file
+.El
+.Sh SEE ALSO
+.Xr chown 2 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr fts 3 ,
+.Xr symlink 7 ,
+.Xr chown 8
+.Sh STANDARDS
+The
+.Nm chgrp
+utility is expected to be POSIX 1003.2 compatible.
diff --git a/usr.sbin/chown/chown.8 b/usr.sbin/chown/chown.8
new file mode 100644
index 0000000..f0cd533
--- /dev/null
+++ b/usr.sbin/chown/chown.8
@@ -0,0 +1,149 @@
+.\" Copyright (c) 1990, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chown.8 8.3 (Berkeley) 3/31/94
+.\"
+.Dd March 31, 1994
+.Dt CHOWN 8
+.Os BSD 4
+.Sh NAME
+.Nm chown
+.Nd change file owner and group
+.Sh SYNOPSIS
+.Nm chown
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Op Fl f
+.Ar owner Op Ar :group
+.Ar file ...
+.Nm chown
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Op Fl f
+.Ar :group
+.Ar file ...
+.Sh DESCRIPTION
+.Nm Chown
+sets the user ID and/or the group ID of the specified files.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+.It Fl R
+Change the user ID and/or the group ID for the file hierarchies rooted
+in the files instead of just the files themselves.
+.It Fl f
+Don't report any failure to change file owner or group, nor modify
+the exit status to reflect such failures.
+.El
+.Pp
+Symbolic links don't have owners, so unless the
+.Fl H
+or
+.Fl L
+option is set,
+.Nm chown
+on a symbolic link always succeeds and has no effect.
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+The
+.Ar owner
+and
+.Ar group
+operands are both optional, however, one must be specified.
+If the
+.Ar group
+operand is specified, it must be preceded by a colon (``:'') character.
+.Pp
+The
+.Ar owner
+may be either a numeric user ID or a user name.
+If a user name is also a numeric user ID, the operand is used as a
+user name.
+The
+.Ar group
+may be either a numeric group ID or a group name.
+If a group name is also a numeric group ID, the operand is used as a
+group name.
+.Pp
+The ownership of a file may only be altered by a super-user for
+obvious security reasons.
+.Pp
+The
+.Nm chown
+utility exits 0 on success, and >0 if an error occurs.
+.Sh COMPATIBILITY
+Previous versions of the
+.Nm chown
+utility used the dot (``.'') character to distinguish the group name.
+This has been changed to be a colon (``:'') character so that user and
+group names may contain the dot character.
+.Pp
+Previous versions of the
+.Nm chown
+utility changed the owner of symbolic links specified on the command
+line.
+In this system, symbolic links do not have owners.
+.Sh SEE ALSO
+.Xr chgrp 1 ,
+.Xr find 1 ,
+.Xr chown 2 ,
+.Xr fts 3 ,
+.Xr symlink 7
+.Sh STANDARDS
+The
+.Nm chown
+command is expected to be POSIX 1003.2 compliant.
diff --git a/usr.sbin/chown/chown.c b/usr.sbin/chown/chown.c
new file mode 100644
index 0000000..9121777
--- /dev/null
+++ b/usr.sbin/chown/chown.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)chown.c 8.8 (Berkeley) 4/4/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void a_gid __P((char *));
+void a_uid __P((char *));
+void chownerr __P((char *));
+u_long id __P((char *, char *));
+void usage __P((void));
+
+uid_t uid;
+gid_t gid;
+int Rflag, ischown, fflag;
+char *gname, *myname;
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ FTS *ftsp;
+ FTSENT *p;
+ int Hflag, Lflag, Pflag, ch, fts_options, hflag, rval;
+ char *cp;
+
+ myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
+ ischown = myname[2] == 'o';
+
+ Hflag = Lflag = Pflag = hflag = 0;
+ while ((ch = getopt(argc, argv, "HLPRfh")) != EOF)
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'P':
+ Pflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ /*
+ * In System V (and probably POSIX.2) the -h option
+ * causes chown/chgrp to change the owner/group of
+ * the symbolic link. 4.4BSD's symbolic links don't
+ * have owners/groups, so it's an undocumented noop.
+ * Do syntax checking, though.
+ */
+ hflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 2)
+ usage();
+
+ fts_options = FTS_PHYSICAL;
+ if (Rflag) {
+ if (hflag)
+ errx(1,
+ "the -R and -h options may not be specified together.");
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ }
+
+ uid = gid = -1;
+ if (ischown) {
+#ifdef SUPPORT_DOT
+ if ((cp = strchr(*argv, '.')) != NULL) {
+ *cp++ = '\0';
+ a_gid(cp);
+ } else
+#endif
+ if ((cp = strchr(*argv, ':')) != NULL) {
+ *cp++ = '\0';
+ a_gid(cp);
+ }
+ a_uid(*argv);
+ } else
+ a_gid(*argv);
+
+ if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
+ err(1, NULL);
+
+ for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+ switch (p->fts_info) {
+ case FTS_D:
+ if (Rflag) /* Change it at FTS_DP. */
+ continue;
+ fts_set(ftsp, p, FTS_SKIP);
+ break;
+ case FTS_DNR: /* Warn, chown, continue. */
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ case FTS_ERR: /* Warn, continue. */
+ case FTS_NS:
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ continue;
+ case FTS_SL: /* Ignore. */
+ case FTS_SLNONE:
+ /*
+ * The only symlinks that end up here are ones that
+ * don't point to anything and ones that we found
+ * doing a physical walk.
+ */
+ continue;
+ default:
+ break;
+ }
+ if (chown(p->fts_accpath, uid, gid) && !fflag) {
+ chownerr(p->fts_path);
+ rval = 1;
+ }
+ }
+ if (errno)
+ err(1, "fts_read");
+ exit(rval);
+}
+
+void
+a_gid(s)
+ char *s;
+{
+ struct group *gr;
+
+ if (*s == '\0') /* Argument was "uid[:.]". */
+ return;
+ gname = s;
+ gid = ((gr = getgrnam(s)) == NULL) ? id(s, "group") : gr->gr_gid;
+}
+
+void
+a_uid(s)
+ char *s;
+{
+ struct passwd *pw;
+
+ if (*s == '\0') /* Argument was "[:.]gid". */
+ return;
+ uid = ((pw = getpwnam(s)) == NULL) ? id(s, "user") : pw->pw_uid;
+}
+
+u_long
+id(name, type)
+ char *name, *type;
+{
+ u_long val;
+ char *ep;
+
+ /*
+ * XXX
+ * We know that uid_t's and gid_t's are unsigned longs.
+ */
+ errno = 0;
+ val = strtoul(name, &ep, 10);
+ if (errno)
+ err(1, "%s", name);
+ if (*ep != '\0')
+ errx(1, "%s: illegal %s name", name, type);
+ return (val);
+}
+
+void
+chownerr(file)
+ char *file;
+{
+ static int euid = -1, ngroups = -1;
+ int groups[NGROUPS];
+
+ /* Check for chown without being root. */
+ if (errno != EPERM ||
+ uid != -1 && euid == -1 && (euid = geteuid()) != 0) {
+ if (fflag)
+ exit(0);
+ err(1, "%s", file);
+ }
+
+ /* Check group membership; kernel just returns EPERM. */
+ if (gid != -1 && ngroups == -1) {
+ ngroups = getgroups(NGROUPS, groups);
+ while (--ngroups >= 0 && gid != groups[ngroups]);
+ if (ngroups < 0) {
+ if (fflag)
+ exit(0);
+ errx(1, "you are not a member of group %s", gname);
+ }
+ }
+
+ if (!fflag)
+ warn("%s", file);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: %s [-R [-H | -L | -P]] [-f] %s file ...\n",
+ myname, ischown ? "[owner][:group]" : "group");
+ exit(1);
+}
diff --git a/usr.sbin/chroot/Makefile b/usr.sbin/chroot/Makefile
new file mode 100644
index 0000000..086a7bc
--- /dev/null
+++ b/usr.sbin/chroot/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= chroot
+MAN8= chroot.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/chroot/chroot.8 b/usr.sbin/chroot/chroot.8
new file mode 100644
index 0000000..76f488b
--- /dev/null
+++ b/usr.sbin/chroot/chroot.8
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chroot.8 8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt CHROOT 8
+.Os BSD 4.3
+.Sh NAME
+.Nm chroot
+.Nd change root directory
+.Sh SYNOPSIS
+.Nm chroot
+.Ar newroot
+.Op Ar command
+.Sh DESCRIPTION
+The
+.Nm chroot
+command changes its root directory to the supplied directory
+.Ar newroot
+and exec's
+.Ar command ,
+if supplied, or an interactive copy of your shell.
+.Pp
+Note,
+.Ar command
+or the shell are run as your real-user-id.
+.Sh ENVIRONMENT
+The following environment variable is referenced by
+.Nm chroot :
+.Bl -tag -width SHELL
+.It Ev SHELL
+If set,
+the string specified by
+.Ev SHELL
+is interpreted as the name of
+the shell to exec.
+If the variable
+.Ev SHELL
+is not set,
+.Pa /bin/sh
+is used.
+.El
+.Sh SEE ALSO
+.Xr chdir 2 ,
+.Xr chroot 2 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Nm chroot
+utility first appeared in 4.4BSD.
diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
new file mode 100644
index 0000000..81bf675
--- /dev/null
+++ b/usr.sbin/chroot/chroot.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)chroot.c 8.1 (Berkeley) 6/9/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch;
+ char *shell;
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ if (chdir(argv[0]) || chroot("."))
+ err(1, "%s", argv[0]);
+
+ if (argv[1]) {
+ execvp(argv[1], &argv[1]);
+ err(1, "%s", argv[1]);
+ }
+
+ if (!(shell = getenv("SHELL")))
+ shell = _PATH_BSHELL;
+ execlp(shell, shell, "-i", NULL);
+ err(1, "%s", shell);
+ /* NOTREACHED */
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: chroot newroot [command]\n");
+ exit(1);
+}
diff --git a/usr.sbin/config.new/Makefile b/usr.sbin/config.new/Makefile
new file mode 100644
index 0000000..6dc5a7e
--- /dev/null
+++ b/usr.sbin/config.new/Makefile
@@ -0,0 +1,14 @@
+# @(#)Makefile 8.2 (Berkeley) 4/19/94
+
+PROG= config
+SRCS= files.c gram.y hash.c main.c mkheaders.c mkioconf.c mkmakefile.c \
+ mkswap.c pack.c scan.l sem.c util.c
+CFLAGS+=-I${.CURDIR} -I.
+CLEANFILES=gram.c scan.c y.tab.h
+MAN8= config.new.0
+
+MLINKS+=config.new.0 config.0
+
+.include <bsd.prog.mk>
+
+.depend: gram.c scan.c
diff --git a/usr.sbin/config.new/config.h b/usr.sbin/config.new/config.h
new file mode 100644
index 0000000..dde683d
--- /dev/null
+++ b/usr.sbin/config.new/config.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)config.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Name/value lists. Values can be strings or pointers and/or can carry
+ * integers. The names can be NULL, resulting in simple value lists.
+ */
+struct nvlist {
+ struct nvlist *nv_next;
+ const char *nv_name;
+ union {
+ const char *un_str;
+ void *un_ptr;
+ } nv_un;
+#define nv_str nv_un.un_str
+#define nv_ptr nv_un.un_ptr
+ int nv_int;
+};
+
+/*
+ * Kernel configurations.
+ */
+struct config {
+ struct config *cf_next; /* linked list */
+ const char *cf_name; /* "vmunix" */
+ int cf_lineno; /* source line */
+ struct nvlist *cf_root; /* "root on ra0a" */
+ struct nvlist *cf_swap; /* "swap on ra0b and ra1b" */
+ struct nvlist *cf_dump; /* "dumps on ra0b" */
+};
+
+/*
+ * Attributes. These come in two flavors: "plain" and "interface".
+ * Plain attributes (e.g., "ether") simply serve to pull in files.
+ * Interface attributes (e.g., "scsi") carry three lists: locators,
+ * child devices, and references. The locators are those things
+ * that must be specified in order to configure a device instance
+ * using this attribute (e.g., "tg0 at scsi0"). The a_devs field
+ * lists child devices that can connect here (e.g., "tg"s), while
+ * the a_refs are parents that carry the attribute (e.g., actual
+ * SCSI host adapter drivers such as the SPARC "esp").
+ */
+struct attr {
+ const char *a_name; /* name of this attribute */
+ int a_iattr; /* true => allows children */
+ struct nvlist *a_locs; /* locators required */
+ int a_loclen; /* length of above list */
+ struct nvlist *a_devs; /* children */
+ struct nvlist *a_refs; /* parents */
+};
+
+/*
+ * The "base" part of a device ("uba", "sd"; but not "uba2" or
+ * "sd0"). It may be found "at" one or more attributes, including
+ * "at root" (this is represented by a NULL attribute).
+ *
+ * Each device may also export attributes. If any provide an output
+ * interface (e.g., "esp" provides "scsi"), other devices (e.g.,
+ * "tg"s) can be found at instances of this one (e.g., "esp"s).
+ * Such a connection must provide locators as specified by that
+ * interface attribute (e.g., "target").
+ *
+ * Each base carries a list of instances (via d_ihead). Note that this
+ * list "skips over" aliases; those must be found through the instances
+ * themselves.
+ */
+struct devbase {
+ const char *d_name; /* e.g., "sd" */
+ struct devbase *d_next; /* linked list */
+ int d_isdef; /* set once properly defined */
+ int d_ispseudo; /* is a pseudo-device */
+ int d_major; /* used for "root on sd0", e.g. */
+ struct nvlist *d_atlist; /* e.g., "at tg" (attr list) */
+ struct nvlist *d_vectors; /* interrupt vectors, if any */
+ struct nvlist *d_attrs; /* attributes, if any */
+ struct devi *d_ihead; /* first instance, if any */
+ struct devi **d_ipp; /* used for tacking on more instances */
+ int d_umax; /* highest unit number + 1 */
+};
+
+/*
+ * An "instance" of a device. The same instance may be listed more
+ * than once, e.g., "xx0 at isa? port FOO" + "xx0 at isa? port BAR".
+ *
+ * After everything has been read in and verified, the devi's are
+ * "packed" to collect all the information needed to generate ioconf.c.
+ * In particular, we try to collapse multiple aliases into a single entry.
+ * We then assign each "primary" (non-collapsed) instance a cfdata index.
+ * Note that there may still be aliases among these.
+ */
+struct devi {
+ /* created while parsing config file */
+ const char *i_name; /* e.g., "sd0" */
+ int i_unit; /* unit from name, e.g., 0 */
+ struct devbase *i_base;/* e.g., pointer to "sd" base */
+ struct devi *i_next; /* list of all instances */
+ struct devi *i_bsame; /* list on same base */
+ struct devi *i_alias; /* other aliases of this instance */
+ const char *i_at; /* where this is "at" (NULL if at root) */
+ struct attr *i_atattr; /* attr that allowed attach */
+ struct devbase *i_atdev;/* dev if "at <devname><unit>", else NULL */
+ const char **i_locs; /* locators (as given by i_atattr) */
+ int i_atunit; /* unit from "at" */
+ int i_cfflags; /* flags from config line */
+ int i_lineno; /* line # in config, for later errors */
+
+ /* created during packing or ioconf.c generation */
+/* i_loclen via i_atattr->a_loclen */
+ short i_collapsed; /* set => this alias no longer needed */
+ short i_cfindex; /* our index in cfdata */
+ short i_pvlen; /* number of parents */
+ short i_pvoff; /* offset in parents.vec */
+ short i_locoff; /* offset in locators.vec */
+ short i_ivoff; /* offset in interrupt vectors, if any */
+ struct devi **i_parents;/* the parents themselves */
+
+};
+/* special units */
+#define STAR (-1) /* unit number for, e.g., "sd*" */
+#define WILD (-2) /* unit number for, e.g., "sd?" */
+
+/*
+ * Files. Each file is either standard (always included) or optional,
+ * depending on whether it has names on which to *be* optional.
+ */
+struct files {
+ struct files *fi_next; /* linked list */
+ const char *fi_srcfile; /* the name of the "files" file that got us */
+ u_short fi_srcline; /* and the line number */
+ u_char fi_flags; /* as below */
+ char fi_lastc; /* last char from path */
+ const char *fi_path; /* full file path */
+ const char *fi_tail; /* name, i.e., rindex(fi_path, '/') + 1 */
+ const char *fi_base; /* tail minus ".c" (or whatever) */
+ struct nvlist *fi_opt; /* optional on ... */
+ const char *fi_mkrule; /* special make rule, if any */
+};
+
+/* flags */
+#define FI_SEL 0x01 /* selected */
+#define FI_CONFIGDEP 0x02 /* config-dependent */
+#define FI_DRIVER 0x04 /* device-driver */
+#define FI_NEEDSCOUNT 0x08 /* needs-count */
+#define FI_NEEDSFLAG 0x10 /* needs-flag */
+#define FI_HIDDEN 0x20 /* obscured by other(s), base names overlap */
+
+/*
+ * Hash tables look up name=value pairs. The pointer value of the name
+ * is assumed to be constant forever; this can be arranged by interning
+ * the name. (This is fairly convenient since our lexer does this for
+ * all identifier-like strings---it has to save them anyway, lest yacc's
+ * look-ahead wipe out the current one.)
+ */
+struct hashtab;
+
+const char *conffile; /* source file, e.g., "GENERIC.sparc" */
+const char *confdirbase; /* basename of compile directory, usu. same */
+const char *machine; /* machine type, e.g., "sparc" */
+int errors; /* counts calls to error() */
+int minmaxusers; /* minimum "maxusers" parameter */
+int defmaxusers; /* default "maxusers" parameter */
+int maxmaxusers; /* default "maxusers" parameter */
+int maxusers; /* configuration's "maxusers" parameter */
+struct nvlist *options; /* options */
+struct nvlist *mkoptions; /* makeoptions */
+struct hashtab *devbasetab; /* devbase lookup */
+struct hashtab *selecttab; /* selects things that are "optional foo" */
+struct hashtab *needcnttab; /* retains names marked "needs-count" */
+
+struct devbase *allbases; /* list of all devbase structures */
+struct config *allcf; /* list of configured kernels */
+struct devi *alldevi; /* list of all instances */
+struct devi *allpseudo; /* list of all pseudo-devices */
+int ndevi; /* number of devi's (before packing) */
+int npseudo; /* number of pseudo's */
+
+struct files *allfiles; /* list of all kernel source files */
+
+struct devi **packed; /* arrayified table for packed devi's */
+int npacked; /* size of packed table, <= ndevi */
+
+struct { /* pv[] table for config */
+ short *vec;
+ int used;
+} parents;
+struct { /* loc[] table for config */
+ const char **vec;
+ int used;
+} locators;
+
+/* files.c */
+void initfiles __P((void));
+void checkfiles __P((void));
+int fixfiles __P((void)); /* finalize */
+void addfile __P((const char *, struct nvlist *, int, const char *));
+
+/* hash.c */
+struct hashtab *ht_new __P((void));
+int ht_insrep __P((struct hashtab *, const char *, void *, int));
+#define ht_insert(ht, nam, val) ht_insrep(ht, nam, val, 0)
+#define ht_replace(ht, nam, val) ht_insrep(ht, nam, val, 1)
+void *ht_lookup __P((struct hashtab *, const char *));
+void initintern __P((void));
+const char *intern __P((const char *));
+
+/* main.c */
+void addoption __P((const char *name, const char *value));
+void addmkoption __P((const char *name, const char *value));
+
+/* mkheaders.c */
+int mkheaders __P((void));
+
+/* mkioconf.c */
+int mkioconf __P((void));
+
+/* mkmakefile.c */
+int mkmakefile __P((void));
+
+/* mkswap.c */
+int mkswap __P((void));
+
+/* pack.c */
+void pack __P((void));
+
+/* scan.l */
+int currentline __P((void));
+
+/* sem.c, other than for yacc actions */
+void initsem __P((void));
+
+/* util.c */
+void *emalloc __P((size_t));
+void *erealloc __P((void *, size_t));
+char *path __P((const char *));
+void error __P((const char *, ...)); /* immediate errs */
+void xerror __P((const char *, int, const char *, ...)); /* delayed errs */
+__dead void panic __P((const char *, ...));
+struct nvlist *newnv __P((const char *, const char *, void *, int));
+void nvfree __P((struct nvlist *));
+void nvfreel __P((struct nvlist *));
diff --git a/usr.sbin/config.new/config.new.8 b/usr.sbin/config.new/config.new.8
new file mode 100644
index 0000000..5eae8d3
--- /dev/null
+++ b/usr.sbin/config.new/config.new.8
@@ -0,0 +1,167 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)config.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt CONFIG.NEW 8
+.Os BSD 4
+.Sh NAME
+.Nm config.new
+.Nd build kernel compilation directories
+.Sh SYNOPSIS
+.Nm config
+.Op Fl p
+.Ar system-name
+.Sh DESCRIPTION
+.Pp
+This is the new version of the
+.Nm config
+program.
+It understands the more modern autoconfiguration scheme
+used on the SPARC and i386 platforms.
+The old version of config is still used with the
+HP300, DECstation, and derivative platforms.
+Only the version of
+.Nm config
+applicable to the architecture that you are running
+will be installed on your machine.
+.Pp
+.Nm Config
+builds a set of configuration files from the file
+.Ar system-name ,
+which describes
+the system to configure.
+.Pp
+.Nm Config
+should run from the
+.Pa conf
+subdirectory of the top-level machine-specific directory
+of the system source (usually
+.Pa /sys/MACHINE/conf ,
+where
+.Pa MACHINE
+is one of
+.Pa vax ,
+.Pa tahoe ,
+.Pa hp300 ,
+and so forth).
+.Nm Config
+assumes the directory
+.Pa ../../compile
+exists; it places all output files in a subdirectory there,
+creating the subdirectory if necessary.
+The subdirectory name is taken from the
+.Ar system-name ;
+thus, configuring with
+.Dq Li config PICKLE
+will use the directory
+.Pa ../../compile/PICKLE .
+.Pp
+If the
+.Fl p
+option is supplied,
+.Pa .PROF
+is appended to the compilation directory name, and
+.Nm config
+acts as if the lines
+.Dq Li makeoptions PROF="-pg"
+and
+.Dq Li options GPROF
+appeared in the configuration file.
+This will build a system that includes profiling code; see
+.Xr kgmon 8
+and
+.Xr gprof 1 .
+The
+.Fl p
+flag is expected to be used for
+.Dq one-shot
+profiles of existing systems;
+for regular profiling,
+it is probably wiser to make a separate configuration
+containing the
+.Li makeoptions
+line.
+.Pp
+The old undocumented
+.Fl g
+flag is no longer supported.
+Instead, use
+.Dq Li makeoptions DEBUG="-g"
+and (typically)
+.Dq Li options KGDB .
+.Pp
+The output of
+.Nm config
+consists of a number of files, principally
+.Pa ioconf.c ,
+a description of I/O devices that may be attached to the system; and a
+.Pa Makefile ,
+used by
+.Xr make 1
+in building the kernel.
+.Pp
+After running
+.Nm config ,
+it is wise to run
+.Dq Li make depend
+in the directory where the new makefile
+was created.
+.Nm Config
+prints a reminder of this when it completes.
+.Pp
+If
+.Nm config
+stops due to errors, the problems reported should be corrected and
+.Nm config
+should be run again.
+.Nm Config
+attempts to avoid changing the compilation directory
+if there are configuration errors,
+but this code is not well-tested,
+and some problems (such as running out of disk space)
+are unrecoverable.
+.Sh SEE ALSO
+The SYNOPSIS portion of each device in section 4.
+.Rs
+.%T "Building 4.4 BSD Systems with Config"
+.\" .%T "Device Support in 4.4BSD"
+.Re
+.sp
+.Xr config 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.1 .
+It was completely revised in
+.Bx 4.4 .
diff --git a/usr.sbin/config.new/files.c b/usr.sbin/config.new/files.c
new file mode 100644
index 0000000..40cddf8
--- /dev/null
+++ b/usr.sbin/config.new/files.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)files.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+extern const char *yyfile;
+
+/*
+ * We check that each full path name is unique. File base names
+ * should generally also be unique, e.g., having both a net/xx.c and
+ * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
+ * wrong, but is permitted under some conditions.
+ */
+static struct hashtab *basetab; /* file base names */
+static struct hashtab *pathtab; /* full path names */
+
+static struct files **nextfile;
+static struct files **unchecked;
+
+void
+initfiles()
+{
+
+ basetab = ht_new();
+ pathtab = ht_new();
+ nextfile = &allfiles;
+ unchecked = &allfiles;
+}
+
+static void
+showprev(pref, fi)
+ const char *pref;
+ register struct files *fi;
+{
+
+ xerror(fi->fi_srcfile, fi->fi_srcline,
+ "%sfile %s ...", pref, fi->fi_path);
+ errors--;
+}
+
+void
+addfile(path, opts, flags, rule)
+ const char *path;
+ struct nvlist *opts;
+ int flags;
+ const char *rule;
+{
+ struct files *fi;
+ const char *base, *dotp, *tail;
+ size_t baselen;
+ int needc, needf;
+ char buf[200];
+
+ /* check various errors */
+ needc = flags & FI_NEEDSCOUNT;
+ needf = flags & FI_NEEDSFLAG;
+ if (needc && needf) {
+ error("cannot mix needs-count and needs-flag");
+ goto bad;
+ }
+ if (opts == NULL && (needc || needf)) {
+ error("nothing to %s for %s", needc ? "count" : "flag", path);
+ goto bad;
+ }
+ if ((fi = ht_lookup(pathtab, path)) != NULL) {
+ showprev("", fi);
+ error("file %s listed again", path);
+ goto bad;
+ }
+
+ /* find last part of pathname, and same without trailing suffix */
+ tail = rindex(path, '/');
+ if (tail == NULL)
+ tail = path;
+ else
+ tail++;
+ dotp = rindex(tail, '.');
+ if (dotp == NULL || dotp[1] == 0 ||
+ (baselen = dotp - tail) >= sizeof(buf)) {
+ error("invalid pathname `%s'", path);
+ goto bad;
+ }
+
+ /*
+ * Make a copy of the path without the .c/.s/whatever suffix.
+ * This must be unique per "files" file (e.g., a specific
+ * file can override a standard file, but no standard file
+ * can override another standard file). This is not perfect
+ * but should catch any major errors.
+ */
+ bcopy(tail, buf, baselen);
+ buf[baselen] = 0;
+ base = intern(buf);
+ if ((fi = ht_lookup(basetab, base)) != NULL) {
+ if (fi->fi_srcfile != yyfile) {
+ showprev("note: ", fi);
+ error("is overriden by %s", path);
+ errors--; /* take it away */
+ fi->fi_flags |= FI_HIDDEN;
+ } else {
+ showprev("", fi);
+ error("collides with %s (both make %s.o)",
+ path, base);
+ goto bad;
+ }
+ }
+
+ /*
+ * Commit this file to memory.
+ */
+ fi = emalloc(sizeof *fi);
+ fi->fi_next = NULL;
+ fi->fi_srcfile = yyfile;
+ fi->fi_srcline = currentline();
+ fi->fi_flags = flags;
+ fi->fi_lastc = dotp[strlen(dotp) - 1];
+ fi->fi_path = path;
+ fi->fi_tail = tail;
+ fi->fi_base = base;
+ fi->fi_opt = opts;
+ fi->fi_mkrule = rule;
+ if (ht_insert(pathtab, path, fi))
+ panic("addfile: ht_insert(%s)", path);
+ (void)ht_replace(basetab, base, fi);
+ *nextfile = fi;
+ nextfile = &fi->fi_next;
+ return;
+bad:
+ nvfreel(opts);
+}
+
+/*
+ * We have finished reading some "files" file, either ../../conf/files
+ * or ./files.$machine. Make sure that everything that is flagged as
+ * needing a count is reasonable. (This prevents ../../conf/files from
+ * depending on some machine-specific device.)
+ */
+void
+checkfiles()
+{
+ register struct files *fi, *last;
+ register struct nvlist *nv;
+
+ last = NULL;
+ for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) {
+ if ((fi->fi_flags & FI_NEEDSCOUNT) == 0)
+ continue;
+ for (nv = fi->fi_opt; nv != NULL; nv = nv->nv_next)
+ if (ht_lookup(devbasetab, nv->nv_name) == NULL) {
+ xerror(fi->fi_srcfile, fi->fi_srcline,
+ "`%s' is not a countable device",
+ nv->nv_name);
+ /* keep fixfiles() from complaining again */
+ fi->fi_flags |= FI_HIDDEN;
+ }
+ }
+ if (last != NULL)
+ unchecked = &last->fi_next;
+}
+
+/*
+ * We have finished reading everything. Tack the files down: calculate
+ * selection and counts as needed.
+ */
+int
+fixfiles()
+{
+ register struct files *fi;
+ register struct nvlist *nv;
+ register struct devbase *dev;
+ int sel, err;
+
+ err = 0;
+ for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
+ if (fi->fi_flags & FI_HIDDEN)
+ continue;
+ if ((nv = fi->fi_opt) == NULL) { /* standard */
+ fi->fi_flags |= FI_SEL;
+ continue;
+ }
+ /* figure out whether it is selected */
+ sel = 0;
+ if (fi->fi_flags & FI_NEEDSCOUNT) {
+ /* ... and compute counts too */
+ do {
+ dev = ht_lookup(devbasetab, nv->nv_name);
+ if (dev == NULL) {
+ xerror(fi->fi_srcfile, fi->fi_srcline,
+ "`%s' is not a countable device",
+ nv->nv_name);
+ err = 1;
+ } else {
+ if (dev->d_umax)
+ sel = 1;
+ nv->nv_int = dev->d_umax;
+ (void)ht_insert(needcnttab,
+ nv->nv_name, nv);
+ }
+ } while ((nv = nv->nv_next) != NULL);
+ } else {
+ do {
+ if (ht_lookup(selecttab, nv->nv_name)) {
+ sel = 1;
+ break;
+ }
+ } while ((nv = nv->nv_next) != NULL);
+ if (fi->fi_flags & FI_NEEDSFLAG)
+ for (nv = fi->fi_opt; nv; nv = nv->nv_next)
+ nv->nv_int = sel;
+ }
+ /* if selected, we are go */
+ if (sel)
+ fi->fi_flags |= FI_SEL;
+ }
+ return (err);
+}
diff --git a/usr.sbin/config.new/gram.y b/usr.sbin/config.new/gram.y
new file mode 100644
index 0000000..6b53801
--- /dev/null
+++ b/usr.sbin/config.new/gram.y
@@ -0,0 +1,392 @@
+%{
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)gram.y 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "sem.h"
+
+#define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x")
+
+#define stop(s) error(s), exit(1)
+
+int include __P((const char *, int));
+void yyerror __P((const char *));
+int yylex __P((void));
+extern const char *lastfile;
+
+static struct config conf; /* at most one active at a time */
+
+/* the following is used to recover nvlist space after errors */
+static struct nvlist *alloc[1000];
+static int adepth;
+#define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i))
+#define new_n(n) new0(n, NULL, NULL, 0)
+#define new_ns(n, s) new0(n, s, NULL, 0)
+#define new_si(s, i) new0(NULL, s, NULL, i)
+#define new_nsi(n,s,i) new0(n, s, NULL, i)
+#define new_np(n, p) new0(n, NULL, p, 0)
+#define new_s(s) new0(NULL, s, NULL, 0)
+#define new_p(p) new0(NULL, NULL, p, 0)
+
+static void cleanup __P((void));
+static void setmachine __P((const char *));
+
+%}
+
+%union {
+ struct attr *attr;
+ struct devbase *devb;
+ struct nvlist *list;
+ const char *str;
+ int val;
+}
+
+%token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE
+%token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MINOR
+%token ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR
+%token <val> FFLAG NUMBER
+%token <str> PATHNAME WORD
+
+%type <list> fopts
+%type <val> fflgs
+%type <str> rule
+%type <attr> attr
+%type <devb> devbase
+%type <list> atlist interface_opt
+%type <str> atname
+%type <list> loclist_opt loclist locdef
+%type <str> locdefault
+%type <list> veclist_opt veclist
+%type <list> attrs_opt attrs
+%type <list> locators locator
+%type <list> swapdev_list dev_spec
+%type <str> device_instance
+%type <str> attachment
+%type <str> value
+%type <val> major_minor signed_number npseudo
+%type <val> flags_opt
+
+%%
+
+/*
+ * A configuration consists of a machine type, followed by the machine
+ * definition files (via the include() mechanism), followed by the
+ * configuration specification(s) proper. In effect, this is two
+ * separate grammars, with some shared terminals and nonterminals.
+ */
+Configuration:
+ hdrs machine_spec /* "machine foo" from machine descr. */
+ dev_defs dev_eof /* ../../conf/devices */
+ dev_defs dev_eof /* devices.foo */
+ specs; /* rest of machine description */
+
+hdrs:
+ hdrs hdr |
+ /* empty */;
+
+hdr:
+ include |
+ '\n';
+
+machine_spec:
+ XMACHINE WORD = { setmachine($2); } |
+ error = { stop("cannot proceed without machine specifier"); };
+
+dev_eof:
+ ENDFILE = { enddefs(lastfile); checkfiles(); };
+
+
+
+/*
+ * Various nonterminals shared between the grammars.
+ */
+file:
+ XFILE PATHNAME fopts fflgs rule = { addfile($2, $3, $4, $5); };
+
+/* order of options is important, must use right recursion */
+fopts:
+ WORD fopts = { ($$ = new_n($1))->nv_next = $2; } |
+ /* empty */ = { $$ = NULL; };
+
+fflgs:
+ fflgs FFLAG = { $$ = $1 | $2; } |
+ /* empty */ = { $$ = 0; };
+
+rule:
+ COMPILE_WITH WORD = { $$ = $2; } |
+ /* empty */ = { $$ = NULL; };
+
+include:
+ INCLUDE WORD = { (void)include($2, '\n'); };
+
+/*
+ * The machine definitions grammar.
+ */
+dev_defs:
+ dev_defs dev_def |
+ /* empty */;
+
+dev_def:
+ one_def '\n' = { adepth = 0; } |
+ '\n' |
+ error '\n' = { cleanup(); };
+
+one_def:
+ file |
+ /* include | */
+ DEFINE WORD interface_opt = { (void)defattr($2, $3); } |
+ DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt
+ = { defdev($2, 0, $4, $5, $6, $7); } |
+ MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } |
+ PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } |
+ MAJOR '{' majorlist '}';
+
+atlist:
+ atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } |
+ atname = { $$ = new_n($1); };
+
+atname:
+ WORD = { $$ = $1; } |
+ ROOT = { $$ = NULL; };
+
+veclist_opt:
+ VECTOR veclist = { $$ = $2; } |
+ /* empty */ = { $$ = NULL; };
+
+/* veclist order matters, must use right recursion */
+veclist:
+ WORD veclist = { ($$ = new_n($1))->nv_next = $2; } |
+ WORD = { $$ = new_n($1); };
+
+devbase:
+ WORD = { $$ = getdevbase($1); };
+
+interface_opt:
+ '{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } |
+ /* empty */ = { $$ = NULL; };
+
+loclist_opt:
+ loclist = { $$ = $1; } |
+ /* empty */ = { $$ = NULL; };
+
+/* loclist order matters, must use right recursion */
+loclist:
+ locdef ',' loclist = { ($$ = $1)->nv_next = $3; } |
+ locdef = { $$ = $1; };
+
+/* "[ WORD locdefault ]" syntax may be unnecessary... */
+locdef:
+ WORD locdefault = { $$ = new_nsi($1, $2, 0); } |
+ WORD = { $$ = new_nsi($1, NULL, 0); } |
+ '[' WORD locdefault ']' = { $$ = new_nsi($2, $3, 1); };
+
+locdefault:
+ '=' value = { $$ = $2; };
+
+value:
+ WORD = { $$ = $1; } |
+ signed_number = { char bf[40];
+ (void)sprintf(bf, FORMAT($1), $1);
+ $$ = intern(bf); };
+
+signed_number:
+ NUMBER = { $$ = $1; } |
+ '-' NUMBER = { $$ = -$2; };
+
+attrs_opt:
+ ':' attrs = { $$ = $2; } |
+ /* empty */ = { $$ = NULL; };
+
+attrs:
+ attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } |
+ attr = { $$ = new_p($1); };
+
+attr:
+ WORD = { $$ = getattr($1); };
+
+majorlist:
+ majorlist ',' majordef |
+ majordef;
+
+majordef:
+ devbase '=' NUMBER = { setmajor($1, $3); };
+
+
+
+/*
+ * The configuration grammar.
+ */
+specs:
+ specs spec |
+ /* empty */;
+
+spec:
+ config_spec '\n' = { adepth = 0; } |
+ '\n' |
+ error '\n' = { cleanup(); };
+
+config_spec:
+ file |
+ include |
+ OPTIONS opt_list |
+ MAKEOPTIONS mkopt_list |
+ MAXUSERS NUMBER = { setmaxusers($2); } |
+ CONFIG conf sysparam_list = { addconf(&conf); } |
+ PSEUDO_DEVICE WORD npseudo = { addpseudo($2, $3); } |
+ device_instance AT attachment locators flags_opt
+ = { adddev($1, $3, $4, $5); };
+
+mkopt_list:
+ mkopt_list ',' mkoption |
+ mkoption;
+
+mkoption:
+ WORD '=' value = { addmkoption($1, $3); }
+
+opt_list:
+ opt_list ',' option |
+ option;
+
+option:
+ WORD = { addoption($1, NULL); } |
+ WORD '=' value = { addoption($1, $3); };
+
+conf:
+ WORD = { conf.cf_name = $1;
+ conf.cf_lineno = currentline();
+ conf.cf_root = NULL;
+ conf.cf_swap = NULL;
+ conf.cf_dump = NULL; };
+
+sysparam_list:
+ sysparam_list sysparam |
+ sysparam;
+
+sysparam:
+ ROOT on_opt dev_spec = { setconf(&conf.cf_root, "root", $3); } |
+ SWAP on_opt swapdev_list = { setconf(&conf.cf_swap, "swap", $3); } |
+ DUMPS on_opt dev_spec = { setconf(&conf.cf_dump, "dumps", $3); };
+
+swapdev_list:
+ dev_spec AND swapdev_list = { ($$ = $1)->nv_next = $3; } |
+ dev_spec = { $$ = $1; };
+
+dev_spec:
+ WORD = { $$ = new_si($1, NODEV); } |
+ major_minor = { $$ = new_si(NULL, $1); };
+
+major_minor:
+ MAJOR NUMBER MINOR NUMBER = { $$ = makedev($2, $4); };
+
+on_opt:
+ ON | /* empty */;
+
+npseudo:
+ NUMBER = { $$ = $1; } |
+ /* empty */ = { $$ = 1; };
+
+device_instance:
+ WORD '*' = { $$ = starref($1); } |
+ WORD = { $$ = $1; };
+
+attachment:
+ ROOT = { $$ = NULL; } |
+ WORD '?' = { $$ = wildref($1); } |
+ WORD '*' = { $$ = starref($1); } |
+ WORD = { $$ = $1; };
+
+locators:
+ locators locator = { ($$ = $2)->nv_next = $1; } |
+ /* empty */ = { $$ = NULL; };
+
+locator:
+ WORD value = { $$ = new_ns($1, $2); } |
+ WORD '?' = { $$ = new_ns($1, NULL); };
+
+flags_opt:
+ FLAGS NUMBER = { $$ = $2; } |
+ /* empty */ = { $$ = 0; };
+
+%%
+
+void
+yyerror(s)
+ const char *s;
+{
+
+ error("%s", s);
+}
+
+/*
+ * Cleanup procedure after syntax error: release any nvlists
+ * allocated during parsing the current line.
+ */
+static void
+cleanup()
+{
+ register struct nvlist **np;
+ register int i;
+
+ for (np = alloc, i = adepth; --i >= 0; np++)
+ nvfree(*np);
+ adepth = 0;
+}
+
+static void
+setmachine(mch)
+ const char *mch;
+{
+ char buf[MAXPATHLEN];
+
+ machine = mch;
+ (void)sprintf(buf, "files.%s", mch);
+ if (include(buf, ENDFILE) ||
+ include("../../conf/files.newconf", ENDFILE))
+ exit(1);
+}
diff --git a/usr.sbin/config.new/hash.c b/usr.sbin/config.new/hash.c
new file mode 100644
index 0000000..d7617da
--- /dev/null
+++ b/usr.sbin/config.new/hash.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)hash.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+/*
+ * Interned strings are kept in a hash table. By making each string
+ * unique, the program can compare strings by comparing pointers.
+ */
+struct hashent {
+ struct hashent *h_next; /* hash buckets are chained */
+ const char *h_name; /* the string */
+ u_int h_hash; /* its hash value */
+ void *h_value; /* other values (for name=value) */
+};
+struct hashtab {
+ size_t ht_size; /* size (power of 2) */
+ u_int ht_mask; /* == ht_size - 1 */
+ u_int ht_used; /* number of entries used */
+ u_int ht_lim; /* when to expand */
+ struct hashent **ht_tab; /* base of table */
+};
+static struct hashtab strings;
+
+/*
+ * HASHFRACTION controls ht_lim, which in turn controls the average chain
+ * length. We allow a few entries, on average, as comparing them is usually
+ * cheap (the h_hash values prevent a strcmp).
+ */
+#define HASHFRACTION(sz) ((sz) * 3 / 2)
+
+/* round up to next multiple of y, where y is a power of 2 */
+#define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1))
+
+/*
+ * Allocate space that will never be freed.
+ */
+static void *
+poolalloc(size)
+ size_t size;
+{
+ register char *p;
+ register size_t alloc;
+ static char *pool;
+ static size_t nleft;
+
+ if (nleft < size) {
+ /*
+ * Compute a `good' size to allocate via malloc.
+ * 16384 is a guess at a good page size for malloc;
+ * 32 is a guess at malloc's overhead.
+ */
+ alloc = ROUND(size + 32, 16384) - 32;
+ p = emalloc(alloc);
+ nleft = alloc - size;
+ } else {
+ p = pool;
+ nleft -= size;
+ }
+ pool = p + size;
+ return (p);
+}
+
+/*
+ * Initialize a new hash table. The size must be a power of 2.
+ */
+static void
+ht_init(ht, sz)
+ register struct hashtab *ht;
+ size_t sz;
+{
+ register struct hashent **h;
+ register u_int n;
+
+ h = emalloc(sz * sizeof *h);
+ ht->ht_tab = h;
+ ht->ht_size = sz;
+ ht->ht_mask = sz - 1;
+ for (n = 0; n < sz; n++)
+ *h++ = NULL;
+ ht->ht_used = 0;
+ ht->ht_lim = HASHFRACTION(sz);
+}
+
+/*
+ * Expand an existing hash table.
+ */
+static void
+ht_expand(ht)
+ register struct hashtab *ht;
+{
+ register struct hashent *p, **h, **oldh, *q;
+ register u_int n, i;
+
+ n = ht->ht_size * 2;
+ h = emalloc(n * sizeof *h);
+ for (i = 0; i < n; i++)
+ h[i] = NULL;
+ oldh = ht->ht_tab;
+ n--;
+ for (i = ht->ht_size; i != 0; i--) {
+ for (p = *oldh++; p != NULL; p = q) {
+ q = p->h_next;
+ p->h_next = h[p->h_hash & n];
+ h[p->h_hash & n] = p;
+ }
+ }
+ free(ht->ht_tab);
+ ht->ht_tab = h;
+ ht->ht_mask = n;
+ ht->ht_size = ++n;
+ ht->ht_lim = HASHFRACTION(n);
+}
+
+/*
+ * Make a new hash entry, setting its h_next to NULL.
+ */
+static inline struct hashent *
+newhashent(name, h)
+ const char *name;
+ u_int h;
+{
+ register struct hashent *hp;
+ register char *m;
+
+ m = poolalloc(sizeof(*hp) + ALIGNBYTES);
+ hp = (struct hashent *)ALIGN(m);
+ hp->h_name = name;
+ hp->h_hash = h;
+ hp->h_next = NULL;
+ return (hp);
+}
+
+/*
+ * Hash a string.
+ */
+static inline u_int
+hash(str)
+ register const char *str;
+{
+ register u_int h;
+
+ for (h = 0; *str;)
+ h = (h << 5) + h + *str++;
+ return (h);
+}
+
+void
+initintern()
+{
+
+ ht_init(&strings, 128);
+}
+
+/*
+ * Generate a single unique copy of the given string. We expect this
+ * function to be used frequently, so it should be fast.
+ */
+const char *
+intern(s)
+ register const char *s;
+{
+ register struct hashtab *ht;
+ register struct hashent *hp, **hpp;
+ register u_int h;
+ register char *p;
+ register size_t l;
+
+ ht = &strings;
+ h = hash(s);
+ hpp = &ht->ht_tab[h & ht->ht_mask];
+ for (; (hp = *hpp) != NULL; hpp = &hp->h_next)
+ if (hp->h_hash == h && strcmp(hp->h_name, s) == 0)
+ return (hp->h_name);
+ l = strlen(s) + 1;
+ p = poolalloc(l);
+ bcopy(s, p, l);
+ *hpp = newhashent(p, h);
+ if (++ht->ht_used > ht->ht_lim)
+ ht_expand(ht);
+ return (p);
+}
+
+struct hashtab *
+ht_new()
+{
+ register struct hashtab *ht;
+
+ ht = emalloc(sizeof *ht);
+ ht_init(ht, 8);
+ return (ht);
+}
+
+/*
+ * Insert and/or replace.
+ */
+int
+ht_insrep(ht, nam, val, replace)
+ register struct hashtab *ht;
+ register const char *nam;
+ void *val;
+ int replace;
+{
+ register struct hashent *hp, **hpp;
+ register u_int h;
+
+ h = hash(nam);
+ hpp = &ht->ht_tab[h & ht->ht_mask];
+ for (; (hp = *hpp) != NULL; hpp = &hp->h_next) {
+ if (hp->h_name == nam) {
+ if (replace)
+ hp->h_value = val;
+ return (1);
+ }
+ }
+ *hpp = hp = newhashent(nam, h);
+ hp->h_value = val;
+ return (0);
+}
+
+void *
+ht_lookup(ht, nam)
+ register struct hashtab *ht;
+ register const char *nam;
+{
+ register struct hashent *hp, **hpp;
+ register u_int h;
+
+ h = hash(nam);
+ hpp = &ht->ht_tab[h & ht->ht_mask];
+ for (; (hp = *hpp) != NULL; hpp = &hp->h_next)
+ if (hp->h_name == nam)
+ return (hp->h_value);
+ return (NULL);
+}
diff --git a/usr.sbin/config.new/main.c b/usr.sbin/config.new/main.c
new file mode 100644
index 0000000..50b930e
--- /dev/null
+++ b/usr.sbin/config.new/main.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)main.c 8.1 (Berkeley) 6/6/93
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "config.h"
+
+int firstfile __P((const char *));
+int yyparse __P((void));
+
+extern char *optarg;
+extern int optind;
+
+static struct hashtab *opttab;
+static struct hashtab *mkopttab;
+static struct nvlist **nextopt;
+static struct nvlist **nextmkopt;
+
+static __dead void stop __P((void));
+static int do_option __P((struct hashtab *, struct nvlist ***,
+ const char *, const char *, const char *));
+static int crosscheck __P((void));
+static int badstar __P((void));
+static int mksymlinks __P((void));
+static int has_instances __P((struct devbase *, int));
+static int hasparent __P((struct devi *));
+static int cfcrosscheck __P((struct config *, const char *, struct nvlist *));
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register char *p;
+ int pflag, ch;
+ struct stat st;
+
+ pflag = 0;
+ while ((ch = getopt(argc, argv, "gp")) != EOF) {
+ switch (ch) {
+
+ case 'g':
+ /*
+ * In addition to DEBUG, you probably wanted to
+ * set "options KGDB" and maybe others. We could
+ * do that for you, but you really should just
+ * put them in the config file.
+ */
+ (void)fputs(
+ "-g is obsolete (use makeoptions DEBUG=\"-g\")\n",
+ stderr);
+ goto usage;
+
+ case 'p':
+ /*
+ * Essentially the same as makeoptions PROF="-pg",
+ * but also changes the path from ../../compile/FOO
+ * to ../../compile/FOO.prof; i.e., compile a
+ * profiling kernel based on a typical "regular"
+ * kernel.
+ *
+ * Note that if you always want profiling, you
+ * can (and should) use a "makeoptions" line.
+ */
+ pflag = 1;
+ break;
+
+ case '?':
+ default:
+ goto usage;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc != 1) {
+usage:
+ (void)fputs("usage: config [-p] sysname\n", stderr);
+ exit(1);
+ }
+ conffile = argv[0];
+ if (firstfile(conffile)) {
+ (void)fprintf(stderr, "config: cannot read %s: %s\n",
+ conffile, strerror(errno));
+ exit(2);
+ }
+
+ /*
+ * Init variables.
+ */
+ minmaxusers = 1;
+ maxmaxusers = 10000;
+ initintern();
+ initfiles();
+ initsem();
+ devbasetab = ht_new();
+ selecttab = ht_new();
+ needcnttab = ht_new();
+ opttab = ht_new();
+ mkopttab = ht_new();
+ nextopt = &options;
+ nextmkopt = &mkoptions;
+
+ /*
+ * Handle profiling (must do this before we try to create any
+ * files).
+ */
+ if (pflag) {
+ char *s;
+
+ s = emalloc(strlen(conffile) + sizeof(".PROF"));
+ (void)sprintf(s, "%s.PROF", conffile);
+ confdirbase = s;
+ (void)addmkoption(intern("PROF"), "-pg");
+ (void)addoption(intern("GPROF"), NULL);
+ } else
+ confdirbase = conffile;
+
+ /*
+ * Verify, creating if necessary, the compilation directory.
+ */
+ p = path(NULL);
+ if (stat(p, &st)) {
+ if (mkdir(p, 0777)) {
+ (void)fprintf(stderr, "config: cannot create %s: %s\n",
+ p, strerror(errno));
+ exit(2);
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ (void)fprintf(stderr, "config: %s is not a directory\n", p);
+ exit(2);
+ }
+
+ /*
+ * Parse config file (including machine definitions).
+ */
+ if (yyparse())
+ stop();
+
+ /*
+ * Fix (as in `set firmly in place') files.
+ */
+ if (fixfiles())
+ stop();
+
+ /*
+ * Perform cross-checking.
+ */
+ if (maxusers == 0) {
+ if (defmaxusers) {
+ (void)printf("maxusers not specified; %d assumed\n",
+ defmaxusers);
+ maxusers = defmaxusers;
+ } else {
+ (void)fprintf(stderr,
+ "config: need \"maxusers\" line\n");
+ errors++;
+ }
+ }
+ if (crosscheck() || errors)
+ stop();
+
+ /*
+ * Squeeze things down and finish cross-checks (STAR checks must
+ * run after packing).
+ */
+ pack();
+ if (badstar())
+ stop();
+
+ /*
+ * Ready to go. Build all the various files.
+ */
+ if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
+ mkioconf())
+ stop();
+ (void)printf("Don't forget to run \"make depend\"\n");
+ exit(0);
+}
+
+/*
+ * Make a symlink for "machine" so that "#include <machine/foo.h>" works.
+ */
+static int
+mksymlinks()
+{
+ int ret;
+ char *p, buf[200];
+
+ p = path("machine");
+ (void)sprintf(buf, "../../%s/include", machine);
+ (void)unlink(p);
+ ret = symlink(buf, p);
+ if (ret)
+ (void)fprintf(stderr, "config: symlink(%s -> %s): %s\n",
+ p, buf, strerror(errno));
+ free(p);
+ return (ret);
+}
+
+static __dead void
+stop()
+{
+ (void)fprintf(stderr, "*** Stop.\n");
+ exit(1);
+}
+
+/*
+ * Add an option from "options FOO". Note that this selects things that
+ * are "optional foo".
+ */
+void
+addoption(name, value)
+ const char *name, *value;
+{
+ register const char *n;
+ register char *p, c;
+ char low[500];
+
+ if (do_option(opttab, &nextopt, name, value, "options"))
+ return;
+
+ /* make lowercase, then add to select table */
+ for (n = name, p = low; (c = *n) != '\0'; n++)
+ *p++ = isupper(c) ? tolower(c) : c;
+ *p = 0;
+ n = intern(low);
+ (void)ht_insert(selecttab, n, (void *)n);
+}
+
+/*
+ * Add a "make" option.
+ */
+void
+addmkoption(name, value)
+ const char *name, *value;
+{
+
+ (void)do_option(mkopttab, &nextmkopt, name, value, "mkoptions");
+}
+
+/*
+ * Add a name=value pair to an option list. The value may be NULL.
+ */
+static int
+do_option(ht, nppp, name, value, type)
+ struct hashtab *ht;
+ struct nvlist ***nppp;
+ const char *name, *value, *type;
+{
+ register struct nvlist *nv;
+
+ /* assume it will work */
+ nv = newnv(name, value, NULL, 0);
+ if (ht_insert(ht, name, nv) == 0) {
+ **nppp = nv;
+ *nppp = &nv->nv_next;
+ return (0);
+ }
+
+ /* oops, already got that option */
+ nvfree(nv);
+ if ((nv = ht_lookup(ht, name)) == NULL)
+ panic("do_option");
+ if (nv->nv_str != NULL)
+ error("already have %s `%s=%s'", type, name, nv->nv_str);
+ else
+ error("already have %s `%s'", type, name);
+ return (1);
+}
+
+/*
+ * Return true if there is at least one instance of the given unit
+ * on the given base (or any units, if unit == WILD).
+ */
+static int
+has_instances(dev, unit)
+ register struct devbase *dev;
+ int unit;
+{
+ register struct devi *i;
+
+ if (unit == WILD)
+ return (dev->d_ihead != NULL);
+ for (i = dev->d_ihead; i != NULL; i = i->i_bsame)
+ if (unit == i->i_unit)
+ return (1);
+ return (0);
+}
+
+static int
+hasparent(i)
+ register struct devi *i;
+{
+ register struct nvlist *nv;
+ int atunit = i->i_atunit;
+
+ if (i->i_atdev != NULL && has_instances(i->i_atdev, atunit))
+ return (1);
+ if (i->i_atattr != NULL)
+ for (nv = i->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
+ if (has_instances(nv->nv_ptr, atunit))
+ return (1);
+ return (0);
+}
+
+static int
+cfcrosscheck(cf, what, nv)
+ register struct config *cf;
+ const char *what;
+ register struct nvlist *nv;
+{
+ register struct devbase *dev;
+ int errs;
+
+ for (errs = 0; nv != NULL; nv = nv->nv_next) {
+ if (nv->nv_name == NULL)
+ continue;
+ dev = ht_lookup(devbasetab, nv->nv_name);
+ if (dev == NULL)
+ panic("cfcrosscheck(%s)", nv->nv_name);
+ if (has_instances(dev, STAR) ||
+ has_instances(dev, minor(nv->nv_int) >> 3))
+ continue;
+ (void)fprintf(stderr,
+ "%s%d: %s says %s on %s, but there's no %s\n",
+ conffile, cf->cf_lineno,
+ cf->cf_name, what, nv->nv_str, nv->nv_str);
+ errs++;
+ }
+ return (errs);
+}
+
+/*
+ * Cross-check the configuration: make sure that each target device
+ * or attribute (`at foo[0*?]') names at least one real device. Also
+ * see that the root, swap, and dump devices for all configurations
+ * are there.
+ */
+int
+crosscheck()
+{
+ register struct devi *i;
+ register struct config *cf;
+ int errs;
+
+ errs = 0;
+ for (i = alldevi; i != NULL; i = i->i_next) {
+ if (i->i_at == NULL || hasparent(i))
+ continue;
+ xerror(conffile, i->i_lineno,
+ "%s at %s is orphaned", i->i_name, i->i_at);
+ if (i->i_atunit == WILD)
+ (void)fprintf(stderr, " (no %s's declared)\n",
+ i->i_base->d_name);
+ else
+ (void)fprintf(stderr, " (no %s declared)\n", i->i_at);
+ errs++;
+ }
+ if (allcf == NULL) {
+ (void)fprintf(stderr, "%s has no configurations!\n",
+ conffile);
+ errs++;
+ }
+ for (cf = allcf; cf != NULL; cf = cf->cf_next) {
+ if (cf->cf_root != NULL) { /* i.e., not swap generic */
+ errs += cfcrosscheck(cf, "root", cf->cf_root);
+ errs += cfcrosscheck(cf, "swap", cf->cf_swap);
+ errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
+ }
+ }
+ return (errs);
+}
+
+/*
+ * Check to see if there is more than one *'d unit for any device,
+ * or a *'d unit with a needs-count file.
+ */
+int
+badstar()
+{
+ register struct devbase *d;
+ register struct devi *i;
+ register int errs, n;
+
+ errs = 0;
+ for (d = allbases; d != NULL; d = d->d_next) {
+ for (i = d->d_ihead; i != NULL; i = i->i_bsame)
+ if (i->i_unit == STAR)
+ goto foundstar;
+ continue;
+ foundstar:
+ if (ht_lookup(needcnttab, d->d_name)) {
+ (void)fprintf(stderr,
+ "config: %s's cannot be *'d until its driver is fixed\n",
+ d->d_name);
+ errs++;
+ continue;
+ }
+ for (n = 0; i != NULL; i = i->i_alias)
+ if (!i->i_collapsed)
+ n++;
+ if (n < 1)
+ panic("badstar() n<1");
+ if (n == 1)
+ continue;
+ (void)fprintf(stderr,
+ "config: %d %s*'s in configuration; can only have 1\n",
+ n, d->d_name);
+ errs++;
+ }
+ return (errs);
+}
diff --git a/usr.sbin/config.new/mkheaders.c b/usr.sbin/config.new/mkheaders.c
new file mode 100644
index 0000000..f627243
--- /dev/null
+++ b/usr.sbin/config.new/mkheaders.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mkheaders.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+static int emitcnt __P((struct nvlist *));
+static int err __P((const char *, char *, FILE *));
+static char *cntname __P((const char *));
+
+/*
+ * Make headers containing counts, as needed.
+ */
+int
+mkheaders()
+{
+ register struct files *fi;
+
+ for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
+ if (fi->fi_flags & FI_HIDDEN)
+ continue;
+ if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) &&
+ emitcnt(fi->fi_opt))
+ return (1);
+ }
+ return (0);
+}
+
+static int
+emitcnt(head)
+ register struct nvlist *head;
+{
+ register struct nvlist *nv;
+ register FILE *fp;
+ register char *fname;
+ int cnt;
+ char nam[100];
+ char buf[BUFSIZ];
+
+ (void)sprintf(buf, "%s.h", head->nv_name);
+ fname = path(buf);
+ if ((fp = fopen(fname, "r")) == NULL)
+ goto writeit;
+ nv = head;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (nv == NULL)
+ goto writeit;
+ if (sscanf(buf, "#define %s %d", nam, &cnt) != 2 ||
+ strcmp(nam, cntname(nv->nv_name)) != 0 ||
+ cnt != nv->nv_int)
+ goto writeit;
+ nv = nv->nv_next;
+ }
+ if (ferror(fp))
+ return (err("read", fname, fp));
+ (void)fclose(fp);
+ if (nv == NULL)
+ return (0);
+writeit:
+ if ((fp = fopen(fname, "w")) == NULL) {
+ (void)fprintf(stderr, "config: cannot write %s: %s\n",
+ fname, strerror(errno));
+ return (1);
+ }
+ for (nv = head; nv != NULL; nv = nv->nv_next)
+ if (fprintf(fp, "#define\t%s\t%d\n",
+ cntname(nv->nv_name), nv->nv_int) < 0)
+ return (err("writ", fname, fp));
+ if (fclose(fp))
+ return (err("writ", fname, NULL));
+ return (0);
+}
+
+static int
+err(what, fname, fp)
+ const char *what;
+ char *fname;
+ FILE *fp;
+{
+
+ (void)fprintf(stderr, "config: error %sing %s: %s\n",
+ what, fname, strerror(errno));
+ if (fp)
+ (void)fclose(fp);
+ free(fname);
+ return (1);
+}
+
+static char *
+cntname(src)
+ register const char *src;
+{
+ register char *dst, c;
+ static char buf[100];
+
+ dst = buf;
+ *dst++ = 'N';
+ while ((c = *src++) != 0)
+ *dst++ = islower(c) ? toupper(c) : c;
+ *dst = 0;
+ return (buf);
+}
diff --git a/usr.sbin/config.new/mkioconf.c b/usr.sbin/config.new/mkioconf.c
new file mode 100644
index 0000000..8b1ebe0
--- /dev/null
+++ b/usr.sbin/config.new/mkioconf.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mkioconf.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+/*
+ * Make ioconf.c.
+ */
+static int cforder __P((const void *, const void *));
+static int emitcfdata __P((FILE *));
+static int emitexterns __P((FILE *));
+static int emithdr __P((FILE *));
+static int emitloc __P((FILE *));
+static int emitpseudo __P((FILE *));
+static int emitpv __P((FILE *));
+static int emitroots __P((FILE *));
+static int emitvec __P((FILE *));
+static char *vecname __P((char *, const char *, int));
+
+static const char *s_i386;
+
+#define SEP(pos, max) (((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
+
+/*
+ * NEWLINE can only be used in the emitXXX functions.
+ * In most cases it can be subsumed into an fprintf.
+ */
+#define NEWLINE if (putc('\n', fp) < 0) return (1)
+
+int
+mkioconf()
+{
+ register FILE *fp;
+ register char *fname;
+ int v;
+
+ s_i386 = intern("i386");
+
+ fname = path("ioconf.c");
+ qsort(packed, npacked, sizeof *packed, cforder);
+ if ((fp = fopen(fname, "w")) == NULL) {
+ (void)fprintf(stderr, "config: cannot write %s: %s\n",
+ fname, strerror(errno));
+ return (1);
+ }
+ v = emithdr(fp);
+ if (v != 0 || emitvec(fp) || emitexterns(fp) || emitloc(fp) ||
+ emitpv(fp) || emitcfdata(fp) || emitroots(fp) || emitpseudo(fp)) {
+ if (v >= 0)
+ (void)fprintf(stderr,
+ "config: error writing %s: %s\n",
+ fname, strerror(errno));
+ (void)fclose(fp);
+ /* (void)unlink(fname); */
+ free(fname);
+ return (1);
+ }
+ (void)fclose(fp);
+ free(fname);
+ return (0);
+}
+
+static int
+cforder(a, b)
+ const void *a, *b;
+{
+ register int n1, n2;
+
+ n1 = (*(struct devi **)a)->i_cfindex;
+ n2 = (*(struct devi **)b)->i_cfindex;
+ return (n1 - n2);
+}
+
+static int
+emithdr(ofp)
+ register FILE *ofp;
+{
+ register FILE *ifp;
+ register int n;
+ char ifn[200], buf[BUFSIZ];
+
+ if (fprintf(ofp, "\
+/*\n\
+ * MACHINE GENERATED: DO NOT EDIT\n\
+ *\n\
+ * ioconf.c, from \"%s\"\n\
+ */\n\n", conffile) < 0)
+ return (1);
+ (void)sprintf(ifn, "ioconf.incl.%s", machine);
+ if ((ifp = fopen(ifn, "r")) != NULL) {
+ while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
+ if (fwrite(buf, 1, n, ofp) != n)
+ return (1);
+ if (ferror(ifp)) {
+ (void)fprintf(stderr, "config: error reading %s: %s\n",
+ ifn, strerror(errno));
+ (void)fclose(ifp);
+ return (-1);
+ }
+ (void)fclose(ifp);
+ } else {
+ if (fputs("\
+#include <sys/param.h>\n\
+#include <sys/device.h>\n", ofp) < 0)
+ return (1);
+ }
+ return (0);
+}
+
+static int
+emitexterns(fp)
+ register FILE *fp;
+{
+ register struct devbase *d;
+
+ NEWLINE;
+ for (d = allbases; d != NULL; d = d->d_next) {
+ if (d->d_ihead == NULL)
+ continue;
+ if (fprintf(fp, "extern struct cfdriver %scd;\n",
+ d->d_name) < 0)
+ return (1);
+ }
+ NEWLINE;
+ return (0);
+}
+
+static int
+emitloc(fp)
+ register FILE *fp;
+{
+ register int i;
+
+ if (fprintf(fp, "\n/* locators */\n\
+static int loc[%d] = {", locators.used) < 0)
+ return (1);
+ for (i = 0; i < locators.used; i++)
+ if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
+ return (1);
+ return (fprintf(fp, "\n};\n") < 0);
+}
+
+/*
+ * Emit global parents-vector.
+ */
+static int
+emitpv(fp)
+ register FILE *fp;
+{
+ register int i;
+
+ if (fprintf(fp, "\n/* parent vectors */\n\
+static short pv[%d] = {", parents.used) < 0)
+ return (1);
+ for (i = 0; i < parents.used; i++)
+ if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
+ return (1);
+ return (fprintf(fp, "\n};\n") < 0);
+}
+
+/*
+ * Emit the cfdata array.
+ */
+static int
+emitcfdata(fp)
+ register FILE *fp;
+{
+ register struct devi **p, *i, **par;
+ register int unit, v;
+ register const char *vs, *state, *basename;
+ register struct nvlist *nv;
+ register struct attr *a;
+ char *loc;
+ char locbuf[20];
+
+ if (fprintf(fp, "\n\
+#define NORM FSTATE_NOTFOUND\n\
+#define STAR FSTATE_STAR\n\
+\n\
+struct cfdata cfdata[] = {\n\
+\t/* driver unit state loc flags parents ivstubs */\n") < 0)
+ return (1);
+ for (p = packed; (i = *p) != NULL; p++) {
+ /* the description */
+ if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
+ return (1);
+ par = i->i_parents;
+ for (v = 0; v < i->i_pvlen; v++)
+ if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
+ i->i_parents[v]->i_name) < 0)
+ return (1);
+ if (v == 0 && fputs("root", fp) < 0)
+ return (1);
+ a = i->i_atattr;
+ nv = a->a_locs;
+ for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
+ if (fprintf(fp, " %s %s",
+ nv->nv_name, i->i_locs[v]) < 0)
+ return (1);
+ if (fputs(" */\n", fp) < 0)
+ return (-1);
+
+ /* then the actual defining line */
+ basename = i->i_base->d_name;
+ if (i->i_unit == STAR) {
+ unit = i->i_base->d_umax;
+ state = "STAR";
+ } else {
+ unit = i->i_unit;
+ state = "NORM";
+ }
+ if (i->i_ivoff < 0) {
+ vs = "";
+ v = 0;
+ } else {
+ vs = "vec+";
+ v = i->i_ivoff;
+ }
+ if (i->i_locoff >= 0) {
+ (void)sprintf(locbuf, "loc+%3d", i->i_locoff);
+ loc = locbuf;
+ } else
+ loc = "loc";
+ if (fprintf(fp, "\
+\t{&%scd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n",
+ basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
+ state, loc, i->i_cfflags, i->i_pvoff, vs, v) < 0)
+ return (1);
+ }
+ return (fputs("\t{0}\n};\n", fp) < 0);
+}
+
+/*
+ * Emit the table of potential roots.
+ */
+static int
+emitroots(fp)
+ register FILE *fp;
+{
+ register struct devi **p, *i;
+
+ if (fputs("\nshort cfroots[] = {\n", fp) < 0)
+ return (1);
+ for (p = packed; (i = *p) != NULL; p++) {
+ if (i->i_at != NULL)
+ continue;
+ if (i->i_unit != 0 &&
+ (i->i_unit != STAR || i->i_base->d_umax != 0))
+ (void)fprintf(stderr,
+ "config: warning: `%s at root' is not unit 0\n",
+ i->i_name);
+ if (fprintf(fp, "\t%2d /* %s */,\n",
+ i->i_cfindex, i->i_name) < 0)
+ return (1);
+ }
+ return (fputs("\t-1\n};\n", fp) < 0);
+}
+
+/*
+ * Emit pseudo-device initialization.
+ */
+static int
+emitpseudo(fp)
+ register FILE *fp;
+{
+ register struct devi *i;
+ register struct devbase *d;
+
+ if (fputs("\n/* pseudo-devices */\n", fp) < 0)
+ return (1);
+ for (i = allpseudo; i != NULL; i = i->i_next)
+ if (fprintf(fp, "extern void %sattach __P((int));\n",
+ i->i_base->d_name) < 0)
+ return (1);
+ if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
+ return (1);
+ for (i = allpseudo; i != NULL; i = i->i_next) {
+ d = i->i_base;
+ if (fprintf(fp, "\t{ %sattach, %d },\n",
+ d->d_name, d->d_umax) < 0)
+ return (1);
+ }
+ return (fputs("\t{ 0, 0 }\n};\n", fp) < 0);
+}
+
+/*
+ * Emit interrupt vector declarations, and calculate offsets.
+ */
+static int
+emitvec(fp)
+ register FILE *fp;
+{
+ register struct nvlist *head, *nv;
+ register struct devi **p, *i;
+ register int j, nvec, unit;
+ char buf[200];
+
+ nvec = 0;
+ for (p = packed; (i = *p) != NULL; p++) {
+ if ((head = i->i_base->d_vectors) == NULL)
+ continue;
+ if ((unit = i->i_unit) == STAR)
+ panic("emitvec unit==STAR");
+ if (nvec == 0)
+ NEWLINE;
+ for (j = 0, nv = head; nv != NULL; j++, nv = nv->nv_next)
+ if (fprintf(fp,
+ "/* IVEC %s %d */ extern void %s();\n",
+ nv->nv_name, unit,
+ vecname(buf, nv->nv_name, unit)) < 0)
+ return (1);
+ nvec += j + 1;
+ }
+ if (nvec == 0)
+ return (0);
+ if (fprintf(fp, "\nstatic void (*vec[%d]) __P((void)) = {", nvec) < 0)
+ return (1);
+ nvec = 0;
+ for (p = packed; (i = *p) != NULL; p++) {
+ if ((head = i->i_base->d_vectors) == NULL)
+ continue;
+ i->i_ivoff = nvec;
+ unit = i->i_unit;
+ for (nv = head; nv != NULL; nv = nv->nv_next)
+ if (fprintf(fp, "%s%s,",
+ SEP(nvec++, 4),
+ vecname(buf, nv->nv_name, unit)) < 0)
+ return (1);
+ if (fprintf(fp, "%s0,", SEP(nvec++, 4)) < 0)
+ return (1);
+ }
+ return (fputs("\n};\n", fp) < 0);
+}
+
+static char *
+vecname(buf, name, unit)
+ char *buf;
+ const char *name;
+ int unit;
+{
+
+ /* @#%* 386 uses a different name format */
+ if (machine == s_i386) {
+ (void)sprintf(buf, "V%s%d", name, unit);
+ return (buf);
+ }
+ (void)sprintf(buf, "X%s%d", name, unit);
+ return (buf);
+}
diff --git a/usr.sbin/config.new/mkmakefile.c b/usr.sbin/config.new/mkmakefile.c
new file mode 100644
index 0000000..06971a5
--- /dev/null
+++ b/usr.sbin/config.new/mkmakefile.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+/*
+ * Make the Makefile.
+ */
+
+static int emitdefs __P((FILE *));
+static int emitobjs __P((FILE *));
+static int emitcfiles __P((FILE *));
+static int emitsfiles __P((FILE *));
+static int emitfiles __P((FILE *, int));
+static int emitrules __P((FILE *));
+static int emitload __P((FILE *));
+
+int
+mkmakefile()
+{
+ register FILE *ifp, *ofp;
+ register int lineno;
+ register int (*fn) __P((FILE *));
+ register char *ofname;
+ char line[BUFSIZ], ifname[200];
+
+ (void)sprintf(ifname, "Makefile.%s", machine);
+ if ((ifp = fopen(ifname, "r")) == NULL) {
+ (void)fprintf(stderr, "config: cannot read %s: %s\n",
+ ifname, strerror(errno));
+ return (1);
+ }
+ ofname = path("Makefile");
+ if ((ofp = fopen(ofname, "w")) == NULL) {
+ (void)fprintf(stderr, "config: cannot write %s: %s\n",
+ ofname, strerror(errno));
+ free(ofname);
+ return (1);
+ }
+ if (emitdefs(ofp) != 0)
+ goto wrerror;
+ lineno = 0;
+ while (fgets(line, sizeof(line), ifp) != NULL) {
+ lineno++;
+ if (line[0] != '%') {
+ if (fputs(line, ofp) < 0)
+ goto wrerror;
+ continue;
+ }
+ if (strcmp(line, "%OBJS\n") == 0)
+ fn = emitobjs;
+ else if (strcmp(line, "%CFILES\n") == 0)
+ fn = emitcfiles;
+ else if (strcmp(line, "%SFILES\n") == 0)
+ fn = emitsfiles;
+ else if (strcmp(line, "%RULES\n") == 0)
+ fn = emitrules;
+ else if (strcmp(line, "%LOAD\n") == 0)
+ fn = emitload;
+ else {
+ xerror(ifname, lineno,
+ "unknown %% construct ignored: %s", line);
+ continue;
+ }
+ if ((*fn)(ofp))
+ goto wrerror;
+ }
+ if (ferror(ifp)) {
+ (void)fprintf(stderr,
+ "config: error reading %s (at line %d): %s\n",
+ ifname, lineno, strerror(errno));
+ goto bad;
+ /* (void)unlink(ofname); */
+ free(ofname);
+ return (1);
+ }
+ if (fclose(ofp)) {
+ ofp = NULL;
+ goto wrerror;
+ }
+ (void)fclose(ifp);
+ free(ofname);
+ return (0);
+wrerror:
+ (void)fprintf(stderr, "config: error writing %s: %s\n",
+ ofname, strerror(errno));
+bad:
+ if (ofp != NULL)
+ (void)fclose(ofp);
+ /* (void)unlink(ofname); */
+ free(ofname);
+ return (1);
+}
+
+static int
+emitdefs(fp)
+ register FILE *fp;
+{
+ register struct nvlist *nv;
+ register char *sp;
+
+ if (fputs("IDENT=", fp) < 0)
+ return (1);
+ sp = "";
+ for (nv = options; nv != NULL; nv = nv->nv_next) {
+ if (fprintf(fp, "%s-D%s%s%s", sp, nv->nv_name,
+ nv->nv_str ? "=" : "", nv->nv_str ? nv->nv_str : "") < 0)
+ return (1);
+ sp = " ";
+ }
+ if (putc('\n', fp) < 0)
+ return (1);
+ if (fprintf(fp, "PARAM=-DMAXUSERS=%d\n", maxusers) < 0)
+ return (1);
+ for (nv = mkoptions; nv != NULL; nv = nv->nv_next)
+ if (fprintf(fp, "%s=%s\n", nv->nv_name, nv->nv_str) < 0)
+ return (1);
+ return (0);
+}
+
+static int
+emitobjs(fp)
+ register FILE *fp;
+{
+ register struct files *fi;
+ register int lpos, len, sp;
+
+ if (fputs("OBJS=", fp) < 0)
+ return (1);
+ sp = '\t';
+ lpos = 7;
+ for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
+ if ((fi->fi_flags & FI_SEL) == 0)
+ continue;
+ len = strlen(fi->fi_base) + 2;
+ if (lpos + len > 72) {
+ if (fputs(" \\\n", fp) < 0)
+ return (1);
+ sp = '\t';
+ lpos = 7;
+ }
+ if (fprintf(fp, "%c%s.o", sp, fi->fi_base) < 0)
+ return (1);
+ lpos += len + 1;
+ sp = ' ';
+ }
+ if (lpos != 7 && putc('\n', fp) < 0)
+ return (1);
+ return (0);
+}
+
+static int
+emitcfiles(fp)
+ FILE *fp;
+{
+
+ return (emitfiles(fp, 'c'));
+}
+
+static int
+emitsfiles(fp)
+ FILE *fp;
+{
+
+ return (emitfiles(fp, 's'));
+}
+
+static int
+emitfiles(fp, suffix)
+ register FILE *fp;
+ int suffix;
+{
+ register struct files *fi;
+ register struct config *cf;
+ register int lpos, len, sp;
+ char swapname[100];
+
+ if (fprintf(fp, "%cFILES=", toupper(suffix)) < 0)
+ return (1);
+ sp = '\t';
+ lpos = 7;
+ for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
+ if ((fi->fi_flags & FI_SEL) == 0)
+ continue;
+ len = strlen(fi->fi_path);
+ if (fi->fi_path[len - 1] != suffix)
+ continue;
+ if (*fi->fi_path != '/')
+ len += 3; /* "$S/" */
+ if (lpos + len > 72) {
+ if (fputs(" \\\n", fp) < 0)
+ return (1);
+ sp = '\t';
+ lpos = 7;
+ }
+ if (fprintf(fp, "%c%s%s", sp, *fi->fi_path != '/' ? "$S/" : "",
+ fi->fi_path) < 0)
+ return (1);
+ lpos += len + 1;
+ sp = ' ';
+ }
+ /*
+ * The allfiles list does not include the configuration-specific
+ * C source files. These files should be eliminated someday, but
+ * for now, we have to add them to ${CFILES} (and only ${CFILES}).
+ */
+ if (suffix == 'c') {
+ for (cf = allcf; cf != NULL; cf = cf->cf_next) {
+ if (cf->cf_root == NULL)
+ (void)sprintf(swapname,
+ "$S/%s/%s/swapgeneric.c",
+ machine, machine);
+ else
+ (void)sprintf(swapname, "swap%s.c",
+ cf->cf_name);
+ len = strlen(swapname);
+ if (lpos + len > 72) {
+ if (fputs(" \\\n", fp) < 0)
+ return (1);
+ sp = '\t';
+ lpos = 7;
+ }
+ if (fprintf(fp, "%c%s", sp, swapname) < 0)
+ return (1);
+ lpos += len + 1;
+ sp = ' ';
+ }
+ }
+ if (lpos != 7 && putc('\n', fp) < 0)
+ return (1);
+ return (0);
+}
+
+/*
+ * Emit the make-rules.
+ */
+static int
+emitrules(fp)
+ register FILE *fp;
+{
+ register struct files *fi;
+ register const char *cp;
+ int ch;
+ char buf[200];
+
+ for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
+ if ((fi->fi_flags & FI_SEL) == 0)
+ continue;
+ if (fprintf(fp, "%s.o: %s%s\n", fi->fi_base,
+ *fi->fi_path != '/' ? "$S/" : "", fi->fi_path) < 0)
+ return (1);
+ if ((cp = fi->fi_mkrule) == NULL) {
+ cp = fi->fi_flags & FI_DRIVER ? "DRIVER" : "NORMAL";
+ ch = fi->fi_lastc;
+ if (islower(ch))
+ ch = toupper(ch);
+ (void)sprintf(buf, "${%s_%c%s}", cp, ch,
+ fi->fi_flags & FI_CONFIGDEP ? "_C" : "");
+ cp = buf;
+ }
+ if (fprintf(fp, "\t%s\n\n", cp) < 0)
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Emit the load commands.
+ *
+ * This function is not to be called `spurt'.
+ */
+static int
+emitload(fp)
+ register FILE *fp;
+{
+ register struct config *cf;
+ register const char *nm, *swname;
+ int first;
+
+ if (fputs("all:", fp) < 0)
+ return (1);
+ for (cf = allcf; cf != NULL; cf = cf->cf_next) {
+ if (fprintf(fp, " %s", cf->cf_name) < 0)
+ return (1);
+ }
+ if (fputs("\n\n", fp) < 0)
+ return (1);
+ for (first = 1, cf = allcf; cf != NULL; cf = cf->cf_next) {
+ nm = cf->cf_name;
+ swname = cf->cf_root != NULL ? cf->cf_name : "generic";
+ if (fprintf(fp, "%s: ${SYSTEM_DEP} swap%s.o", nm, swname) < 0)
+ return (1);
+ if (first) {
+ if (fputs(" newvers", fp) < 0)
+ return (1);
+ first = 0;
+ }
+ if (fprintf(fp, "\n\
+\t${SYSTEM_LD_HEAD}\n\
+\t${SYSTEM_LD} swap%s.o\n\
+\t${SYSTEM_LD_TAIL}\n\
+\n\
+swap%s.o: ", swname, swname) < 0)
+ return (1);
+ if (cf->cf_root != NULL) {
+ if (fprintf(fp, "swap%s.c\n", nm) < 0)
+ return (1);
+ } else {
+ if (fprintf(fp, "$S/%s/%s/swapgeneric.c\n",
+ machine, machine) < 0)
+ return (1);
+ }
+ if (fputs("\t${NORMAL_C}\n\n", fp) < 0)
+ return (1);
+ }
+ return (0);
+}
diff --git a/usr.sbin/config.new/mkswap.c b/usr.sbin/config.new/mkswap.c
new file mode 100644
index 0000000..afea210
--- /dev/null
+++ b/usr.sbin/config.new/mkswap.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)mkswap.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+static int mkoneswap __P((struct config *));
+
+/*
+ * Make the various swap*.c files. Nothing to do for generic swap.
+ */
+int
+mkswap()
+{
+ register struct config *cf;
+
+ for (cf = allcf; cf != NULL; cf = cf->cf_next)
+ if (cf->cf_root != NULL && mkoneswap(cf))
+ return (1);
+ return (0);
+}
+
+static int
+mkoneswap(cf)
+ register struct config *cf;
+{
+ register struct nvlist *nv;
+ register FILE *fp;
+ register char *fname;
+ char buf[200];
+
+ (void)sprintf(buf, "swap%s.c", cf->cf_name);
+ fname = path(buf);
+ if ((fp = fopen(fname, "w")) == NULL) {
+ (void)fprintf(stderr, "config: cannot write %s: %s\n",
+ fname, strerror(errno));
+ return (1);
+ }
+ if (fputs("\
+#include <sys/param.h>\n\
+#include <sys/conf.h>\n\n", fp) < 0)
+ goto wrerror;
+ nv = cf->cf_root;
+ if (fprintf(fp, "dev_t\trootdev = makedev(%d, %d);\t/* %s */\n",
+ major(nv->nv_int), minor(nv->nv_int), nv->nv_str) < 0)
+ goto wrerror;
+ nv = cf->cf_dump;
+ if (fprintf(fp, "dev_t\tdumpdev = makedev(%d, %d);\t/* %s */\n",
+ major(nv->nv_int), minor(nv->nv_int), nv->nv_str) < 0)
+ goto wrerror;
+ if (fputs("\nstruct\tswdevt swdevt[] = {\n", fp) < 0)
+ goto wrerror;
+ for (nv = cf->cf_swap; nv != NULL; nv = nv->nv_next)
+ if (fprintf(fp, "\t{ makedev(%d, %d),\t0,\t0 },\t/* %s */\n",
+ major(nv->nv_int), minor(nv->nv_int), nv->nv_str) < 0)
+ goto wrerror;
+ if (fputs("\t{ NODEV, 0, 0 }\n};\n", fp) < 0)
+ goto wrerror;
+ if (fclose(fp)) {
+ fp = NULL;
+ goto wrerror;
+ }
+ free(fname);
+ return (0);
+wrerror:
+ (void)fprintf(stderr, "config: error writing %s: %s\n",
+ fname, strerror(errno));
+ if (fp != NULL)
+ (void)fclose(fp);
+ /* (void)unlink(fname); */
+ free(fname);
+ return (1);
+}
diff --git a/usr.sbin/config.new/pack.c b/usr.sbin/config.new/pack.c
new file mode 100644
index 0000000..8b525ec
--- /dev/null
+++ b/usr.sbin/config.new/pack.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)pack.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+/*
+ * Packing. We have three separate kinds of packing here.
+ *
+ * First, we pack device instances, to collapse things like
+ *
+ * uba0 at sbi0 nexus ?
+ * uba0 at bi0 nexus ?
+ *
+ * into a single instance that is "at sbi0 or bi0".
+ *
+ * Second, we pack locators. Given something like
+ *
+ * hp0 at mba0 drive 0
+ * hp* at mba* drive ?
+ * ht0 at mba0 drive 0
+ * tu0 at ht0 slave 0
+ * ht* at mba* drive ?
+ * tu* at ht* slave ?
+ *
+ * (where the default drive and slave numbers are -1), we have three
+ * locators whose value is 0 and three whose value is -1. Rather than
+ * emitting six integers, we emit just two.
+ *
+ * Finally, we pack parent vectors. This is very much like packing
+ * locators. Unlike locators, however, parent vectors are always
+ * terminated by -1 (rather like the way C strings always end with
+ * a NUL).
+ *
+ * When packing locators, we would like to find sequences such as
+ * {1 2 3} {2 3 4} {3} {4 5}
+ * and turn this into the flat sequence {1 2 3 4 5}, with each subsequence
+ * given by the appropriate offset (here 0, 1, 2, and 3 respectively).
+ * When we pack parent vectors, overlap of this sort is impossible.
+ * Non-overlapping packing is much easier, and so we use that here
+ * and miss out on the chance to squeeze the locator sequence optimally.
+ * (So it goes.)
+ */
+
+typedef int (*vec_cmp_func) __P((const void *, int, int));
+
+#define TAILHSIZE 128
+#define PVHASH(i) ((i) & (TAILHSIZE - 1))
+#define LOCHASH(l) (((int)(l) >> 2) & (TAILHSIZE - 1))
+struct tails {
+ struct tails *t_next;
+ int t_ends_at;
+};
+
+static struct tails *tails[TAILHSIZE];
+static int locspace;
+static int pvecspace;
+static int longest_pvec;
+
+static void packdevi __P((void));
+static void packlocs __P((void));
+static void packpvec __P((void));
+
+static void addparents __P((struct devi *src, struct devi *dst));
+static int nparents __P((struct devi **, struct devbase *, int));
+static int sameas __P((struct devi *, struct devi *));
+static int findvec __P((const void *, int, int, vec_cmp_func, int));
+static int samelocs __P((const void *, int, int));
+static int addlocs __P((const char **, int));
+static int loclencmp __P((const void *, const void *));
+static int samepv __P((const void *, int, int));
+static int addpv __P((short *, int));
+static int pvlencmp __P((const void *, const void *));
+static void resettails __P((void));
+
+void
+pack()
+{
+ register struct devi *i;
+ register int n;
+
+ /* Pack instances and make parent vectors. */
+ packdevi();
+
+ /*
+ * Now that we know what we have, find upper limits on space
+ * needed for the loc[] and pv[] tables, and find the longest
+ * single pvec. The loc and pv table sizes are bounded by
+ * what we would get if no packing occurred.
+ */
+ locspace = pvecspace = 0;
+ for (i = alldevi; i != NULL; i = i->i_next) {
+ if (i->i_collapsed)
+ continue;
+ locspace += i->i_atattr->a_loclen;
+ n = i->i_pvlen + 1;
+ if (n > longest_pvec)
+ longest_pvec = n;
+ pvecspace += n;
+ }
+
+ /* Allocate and pack loc[]. */
+ locators.vec = emalloc(locspace * sizeof(*locators.vec));
+ locators.used = 0;
+ packlocs();
+
+ /* Allocate and pack pv[]. */
+ parents.vec = emalloc(pvecspace * sizeof(*parents.vec));
+ parents.used = 0;
+ packpvec();
+}
+
+/*
+ * Pack instances together wherever possible. When everything is
+ * packed, go back and set up the parents for each. We must do this
+ * on a second pass because during the first one, we do not know which,
+ * if any, of the parents will collapse during packing.
+ */
+void
+packdevi()
+{
+ register struct devi *i, *l, *p;
+ register struct devbase *d;
+ register int j, m, n;
+
+ packed = emalloc((ndevi + 1) * sizeof *packed);
+ n = 0;
+ for (d = allbases; d != NULL; d = d->d_next) {
+ /*
+ * For each instance of each device, add or collapse
+ * all its aliases.
+ */
+ for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
+ m = n;
+ for (l = i; l != NULL; l = l->i_alias) {
+ l->i_pvlen = 0;
+ l->i_pvoff = -1;
+ l->i_locoff = -1;
+ l->i_ivoff = -1;
+ /* try to find an equivalent for l */
+ for (j = m; j < n; j++) {
+ p = packed[j];
+ if (sameas(l, p)) {
+ l->i_collapsed = 1;
+ l->i_cfindex = p->i_cfindex;
+ goto nextalias;
+ }
+ }
+ /* could not find a suitable alias */
+ l->i_collapsed = 0;
+ l->i_cfindex = n;
+ l->i_parents = emalloc(sizeof(*l->i_parents));
+ l->i_parents[0] = NULL;
+ packed[n++] = l;
+ nextalias:;
+ }
+ }
+ }
+ npacked = n;
+ packed[n] = NULL;
+ for (i = alldevi; i != NULL; i = i->i_next)
+ addparents(i, packed[i->i_cfindex]);
+}
+
+/*
+ * Return true if two aliases are "the same". In this case, they need
+ * to have the same config flags and the same locators.
+ */
+static int
+sameas(i1, i2)
+ register struct devi *i1, *i2;
+{
+ register const char **p1, **p2;
+
+ if (i1->i_cfflags != i2->i_cfflags)
+ return (0);
+ for (p1 = i1->i_locs, p2 = i2->i_locs; *p1 == *p2; p2++)
+ if (*p1++ == 0)
+ return (1);
+ return 0;
+}
+
+/*
+ * Add the parents associated with "src" to the (presumably uncollapsed)
+ * instance "dst".
+ */
+static void
+addparents(src, dst)
+ register struct devi *src, *dst;
+{
+ register struct nvlist *nv;
+ register struct devi *i, **p, **q;
+ register int j, n, old, new, ndup;
+
+ if (dst->i_collapsed)
+ panic("addparents() i_collapsed");
+
+ /* Collect up list of parents to add. */
+ if (src->i_at == NULL) /* none, 'cuz "at root" */
+ return;
+ if (src->i_atdev != NULL) {
+ n = nparents(NULL, src->i_atdev, src->i_atunit);
+ p = emalloc(n * sizeof *p);
+ if (n == 0)
+ return;
+ (void)nparents(p, src->i_atdev, src->i_atunit);
+ } else {
+ n = 0;
+ for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
+ n += nparents(NULL, nv->nv_ptr, src->i_atunit);
+ if (n == 0)
+ return;
+ p = emalloc(n * sizeof *p);
+ n = 0;
+ for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
+ n += nparents(p + n, nv->nv_ptr, src->i_atunit);
+ }
+ /* Now elide duplicates. */
+ ndup = 0;
+ for (j = 0; j < n; j++) {
+ i = p[j];
+ for (q = dst->i_parents; *q != NULL; q++) {
+ if (*q == i) {
+ ndup++;
+ p[j] = NULL;
+ break;
+ }
+ }
+ }
+ /* Finally, add all the non-duplicates. */
+ old = dst->i_pvlen;
+ new = old + (n - ndup);
+ if (old > new)
+ panic("addparents() old > new");
+ if (old == new) {
+ free(p);
+ return;
+ }
+ dst->i_parents = q = erealloc(dst->i_parents, (new + 1) * sizeof(*q));
+ dst->i_pvlen = new;
+ q[new] = NULL;
+ q += old;
+ for (j = 0; j < n; j++)
+ if (p[j] != NULL)
+ *q++ = p[j];
+ free(p);
+}
+
+/*
+ * Count up parents, and optionally store pointers to each.
+ */
+static int
+nparents(p, dev, unit)
+ register struct devi **p;
+ register struct devbase *dev;
+ register int unit;
+{
+ register struct devi *i, *l;
+ register int n;
+
+ n = 0;
+ /* for each instance ... */
+ for (i = dev->d_ihead; i != NULL; i = i->i_bsame) {
+ /* ... take each un-collapsed alias */
+ for (l = i; l != NULL; l = l->i_alias) {
+ if (!l->i_collapsed &&
+ (unit == WILD || unit == l->i_unit)) {
+ if (p != NULL)
+ *p++ = l;
+ n++;
+ }
+ }
+ }
+ return (n);
+}
+
+static void
+packlocs()
+{
+ register struct devi **p, *i;
+ register int l, o;
+
+ qsort(packed, npacked, sizeof *packed, loclencmp);
+ for (p = packed; (i = *p) != NULL; p++) {
+ if ((l = i->i_atattr->a_loclen) > 0) {
+ o = findvec(i->i_locs, LOCHASH(i->i_locs[l - 1]), l,
+ samelocs, locators.used);
+ i->i_locoff = o < 0 ? addlocs(i->i_locs, l) : o;
+ } else
+ i->i_locoff = -1;
+ }
+ resettails();
+}
+
+static void
+packpvec()
+{
+ register struct devi **p, *i, **par;
+ register int l, v, o;
+ register short *vec;
+
+ vec = emalloc(longest_pvec * sizeof(*vec));
+ qsort(packed, npacked, sizeof *packed, pvlencmp);
+ for (p = packed; (i = *p) != NULL; p++) {
+ l = i->i_pvlen;
+if (l > longest_pvec) panic("packpvec");
+ par = i->i_parents;
+ for (v = 0; v < l; v++)
+ vec[v] = par[v]->i_cfindex;
+ if (l == 0 ||
+ (o = findvec(vec, PVHASH(vec[l - 1]), l,
+ samepv, parents.used)) < 0)
+ o = addpv(vec, l);
+ i->i_pvoff = o;
+ }
+ free(vec);
+ resettails();
+}
+
+/*
+ * Return the index at which the given vector already exists, or -1
+ * if it is not anywhere in the current set. If we return -1, we assume
+ * our caller will add it at the end of the current set, and we make
+ * sure that next time, we will find it there.
+ */
+static int
+findvec(ptr, hash, len, cmp, nextplace)
+ const void *ptr;
+ int hash, len;
+ vec_cmp_func cmp;
+ int nextplace;
+{
+ register struct tails *t, **hp;
+ register int off;
+
+ hp = &tails[hash];
+ for (t = *hp; t != NULL; t = t->t_next) {
+ off = t->t_ends_at - len;
+ if (off >= 0 && (*cmp)(ptr, off, len))
+ return (off);
+ }
+ t = emalloc(sizeof(*t));
+ t->t_next = *hp;
+ *hp = t;
+ t->t_ends_at = nextplace + len;
+ return (-1);
+}
+
+/*
+ * Comparison function for locators.
+ */
+static int
+samelocs(ptr, off, len)
+ const void *ptr;
+ int off;
+ register int len;
+{
+ register const char **p, **q;
+
+ for (p = &locators.vec[off], q = (const char **)ptr; --len >= 0;)
+ if (*p++ != *q++)
+ return (0); /* different */
+ return (1); /* same */
+}
+
+/*
+ * Add the given locators at the end of the global loc[] table.
+ */
+static int
+addlocs(locs, len)
+ register const char **locs;
+ register int len;
+{
+ register const char **p;
+ register int ret;
+
+ ret = locators.used;
+ if ((locators.used = ret + len) > locspace)
+ panic("addlocs: overrun");
+ for (p = &locators.vec[ret]; --len >= 0;)
+ *p++ = *locs++;
+ return (ret);
+}
+
+/*
+ * Comparison function for qsort-by-locator-length, longest first.
+ * We rashly assume that subtraction of these lengths does not overflow.
+ */
+static int
+loclencmp(a, b)
+ const void *a, *b;
+{
+ register int l1, l2;
+
+ l1 = (*(struct devi **)a)->i_atattr->a_loclen;
+ l2 = (*(struct devi **)b)->i_atattr->a_loclen;
+ return (l2 - l1);
+}
+
+/*
+ * Comparison function for parent vectors.
+ */
+static int
+samepv(ptr, off, len)
+ const void *ptr;
+ int off;
+ register int len;
+{
+ register short *p, *q;
+
+ for (p = &parents.vec[off], q = (short *)ptr; --len >= 0;)
+ if (*p++ != *q++)
+ return (0); /* different */
+ return (1); /* same */
+}
+
+/*
+ * Add the given parent vectors at the end of the global pv[] table.
+ */
+static int
+addpv(pv, len)
+ register short *pv;
+ register int len;
+{
+ register short *p;
+ register int ret;
+ static int firstend = -1;
+
+ /*
+ * If the vector is empty, reuse the first -1. It will be
+ * there if there are any nonempty vectors at all, since we
+ * do the longest first. If there are no nonempty vectors,
+ * something is probably wrong, but we will ignore that here.
+ */
+ if (len == 0 && firstend >= 0)
+ return (firstend);
+ len++; /* account for trailing -1 */
+ ret = parents.used;
+ if ((parents.used = ret + len) > pvecspace)
+ panic("addpv: overrun");
+ for (p = &parents.vec[ret]; --len > 0;)
+ *p++ = *pv++;
+ *p = -1;
+ if (firstend < 0)
+ firstend = parents.used - 1;
+ return (ret);
+}
+
+/*
+ * Comparison function for qsort-by-parent-vector-length, longest first.
+ * We rashly assume that subtraction of these lengths does not overflow.
+ */
+static int
+pvlencmp(a, b)
+ const void *a, *b;
+{
+ register int l1, l2;
+
+ l1 = (*(struct devi **)a)->i_pvlen;
+ l2 = (*(struct devi **)b)->i_pvlen;
+ return (l2 - l1);
+}
+
+static void
+resettails()
+{
+ register struct tails **p, *t, *next;
+ register int i;
+
+ for (p = tails, i = TAILHSIZE; --i >= 0; p++) {
+ for (t = *p; t != NULL; t = next) {
+ next = t->t_next;
+ free(t);
+ }
+ *p = NULL;
+ }
+}
diff --git a/usr.sbin/config.new/scan.l b/usr.sbin/config.new/scan.l
new file mode 100644
index 0000000..b7301a3
--- /dev/null
+++ b/usr.sbin/config.new/scan.l
@@ -0,0 +1,238 @@
+%{
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)scan.l 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "config.h"
+#include "y.tab.h"
+
+int yyline;
+const char *yyfile;
+const char *lastfile;
+
+int include __P((const char *, int));
+
+/*
+ * Data for returning to previous files from include files.
+ */
+struct incl {
+ struct incl *in_prev; /* previous includes in effect, if any */
+ YY_BUFFER_STATE in_buf; /* previous lex state */
+ const char *in_fname; /* previous file name */
+ int in_lineno; /* previous line number */
+ int in_preveof; /* previous eoftoken */
+};
+static struct incl *incl;
+static int eoftoken; /* current EOF token */
+static void endinclude __P((void));
+
+#define yywrap() 1
+
+%}
+
+PATH [-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
+WORD [A-Za-z_][-A-Za-z_0-9]*
+
+%%
+
+ /* plain keywords */
+and { return AND; }
+at { return AT; }
+compile-with { return COMPILE_WITH; }
+config { return CONFIG; }
+define { return DEFINE; }
+device { return DEVICE; }
+dumps { return DUMPS; }
+flags { return FLAGS; }
+file { return XFILE; }
+include { return INCLUDE; }
+machine { return XMACHINE; }
+major { return MAJOR; }
+makeoptions { return MAKEOPTIONS; }
+maxusers { return MAXUSERS; }
+minor { return MINOR; }
+on { return ON; }
+options { return OPTIONS; }
+"pseudo-device" { return PSEUDO_DEVICE; }
+root { return ROOT; }
+swap { return SWAP; }
+vector { return VECTOR; }
+
+ /* keywords with values */
+config-dependent { yylval.val = FI_CONFIGDEP; return FFLAG; }
+device-driver { yylval.val = FI_DRIVER; return FFLAG; }
+needs-count { yylval.val = FI_NEEDSCOUNT; return FFLAG; }
+needs-flag { yylval.val = FI_NEEDSFLAG; return FFLAG; }
+
+ /* all the rest */
+{PATH} { yylval.str = intern(yytext); return PATHNAME; }
+{WORD} { yylval.str = intern(yytext); return WORD; }
+
+\"[^"]+/\" {
+ yylval.str = intern(yytext + 1);
+ (void)input(); /* eat closing quote */
+ return WORD;
+ }
+0[0-7]* {
+ yylval.val = strtol(yytext, NULL, 8);
+ return NUMBER;
+ }
+0[xX][0-9a-fA-F]+ {
+ yylval.val = strtol(yytext + 2, NULL, 16);
+ return NUMBER;
+ }
+[1-9][0-9]* {
+ yylval.val = strtol(yytext, NULL, 10);
+ return NUMBER;
+ }
+\n/[ \t] {
+ yyline++;
+ }
+\n {
+ yyline++;
+ return '\n';
+ }
+#.* { /* ignored (comment) */; }
+[ \t]* { /* ignored (white space) */; }
+. { return yytext[0]; }
+<<EOF>> {
+ int tok;
+
+ tok = eoftoken;
+ eoftoken = YY_NULL;
+ if (incl != NULL)
+ endinclude();
+ return (tok);
+ }
+
+%%
+
+/*
+ * Open the "main" file (conffile).
+ */
+int
+firstfile(fname)
+ const char *fname;
+{
+
+ if ((yyin = fopen(fname, "r")) == NULL)
+ return (-1);
+ yyfile = conffile = fname;
+ yyline = 1;
+ eoftoken = YY_NULL;
+ return (0);
+}
+
+/*
+ * Open the named file for inclusion at the current point. Returns 0 on
+ * success (file opened and previous state pushed), nonzero on failure
+ * (fopen failed, complaint made). The `ateof' parameter controls the
+ * token to be returned at the end of the include file (typically '\n'
+ * or ENDFILE).
+ */
+int
+include(fname, ateof)
+ const char *fname;
+ int ateof;
+{
+ register FILE *fp;
+ register struct incl *in;
+
+ if ((fp = fopen(fname, "r")) == NULL) {
+ error("cannot open %s for reading: %s\n",
+ fname, strerror(errno));
+ return (-1);
+ }
+ in = emalloc(sizeof *in);
+ in->in_prev = incl;
+ in->in_buf = YY_CURRENT_BUFFER;
+ in->in_fname = yyfile;
+ in->in_lineno = yyline;
+ in->in_preveof = eoftoken;
+ incl = in;
+ yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
+ yyfile = intern(fname);
+ yyline = 1;
+ eoftoken = ateof;
+ return (0);
+}
+
+/*
+ * Terminate the most recent inclusion.
+ */
+static void
+endinclude()
+{
+ register struct incl *in;
+
+ if ((in = incl) == NULL)
+ panic("endinclude");
+ incl = in->in_prev;
+ lastfile = yyfile;
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ (void)fclose(yyin);
+ yy_switch_to_buffer(in->in_buf);
+ yyfile = in->in_fname;
+ yyline = in->in_lineno;
+ eoftoken = in->in_preveof;
+ free(in);
+}
+
+/*
+ * Return the current line number. If yacc has looked ahead and caused
+ * us to consume a newline, we have to subtract one. yychar is yacc's
+ * token lookahead, so we can tell.
+ */
+int
+currentline()
+{
+ extern int yychar;
+
+ return (yyline - (yychar == '\n'));
+}
diff --git a/usr.sbin/config.new/sem.c b/usr.sbin/config.new/sem.c
new file mode 100644
index 0000000..aa60169
--- /dev/null
+++ b/usr.sbin/config.new/sem.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)sem.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+#include "sem.h"
+
+/*
+ * config semantics.
+ */
+
+#define NAMESIZE 100 /* local name buffers */
+
+static const char *s_generic;
+static const char *s_qmark;
+
+static struct hashtab *attrtab; /* for attribute lookup */
+static struct hashtab *cfhashtab; /* for config lookup */
+static struct hashtab *devitab; /* etc */
+
+static struct attr errattr;
+static struct devbase errdev;
+static struct devbase **nextbase;
+static struct config **nextcf;
+static struct devi **nextdevi;
+static struct devi **nextpseudo;
+
+static int has_errobj __P((struct nvlist *, void *));
+static struct nvlist *addtoattr __P((struct nvlist *, struct devbase *));
+static int exclude __P((struct nvlist *, const char *, const char *));
+static int resolve __P((struct nvlist **, const char *, const char *,
+ struct nvlist *, int));
+static int lresolve __P((struct nvlist **, const char *, const char *,
+ struct nvlist *, int));
+static struct devi *newdevi __P((const char *, int, struct devbase *d));
+static struct devi *getdevi __P((const char *));
+static const char *concat __P((const char *, int));
+static int split __P((const char *, size_t, char *, size_t, int *));
+static void selectbase __P((struct devbase *));
+static int onlist __P((struct nvlist *, void *));
+static const char **fixloc __P((const char *, struct attr *, struct nvlist *));
+
+void
+initsem()
+{
+
+ attrtab = ht_new();
+ errattr.a_name = "<internal>";
+
+ allbases = NULL;
+ nextbase = &allbases;
+
+ cfhashtab = ht_new();
+ allcf = NULL;
+ nextcf = &allcf;
+
+ devitab = ht_new();
+ alldevi = NULL;
+ nextdevi = &alldevi;
+ errdev.d_name = "<internal>";
+
+ allpseudo = NULL;
+ nextpseudo = &allpseudo;
+
+ s_generic = intern("generic");
+ s_qmark = intern("?");
+}
+
+void
+enddefs(fname)
+ const char *fname;
+{
+ register struct devbase *dev;
+
+ for (dev = allbases; dev != NULL; dev = dev->d_next) {
+ if (!dev->d_isdef) {
+ (void)fprintf(stderr,
+ "%s: device `%s' used but not defined\n",
+ fname, dev->d_name);
+ errors++;
+ continue;
+ }
+ }
+ if (errors) {
+ (void)fprintf(stderr, "*** Stop.\n");
+ exit(1);
+ }
+}
+
+void
+setdefmaxusers(min, def, max)
+ int min, def, max;
+{
+
+ if (min < 1 || min > def || def > max)
+ error("maxusers must have 1 <= min <= default <= max");
+ else {
+ minmaxusers = min;
+ defmaxusers = def;
+ maxmaxusers = max;
+ }
+}
+
+void
+setmaxusers(n)
+ int n;
+{
+
+ if (maxusers != 0) {
+ error("duplicate maxusers parameter");
+ return;
+ }
+ maxusers = n;
+ if (n < minmaxusers) {
+ error("warning: minimum of %d maxusers assumed\n", minmaxusers);
+ errors--; /* take it away */
+ maxusers = minmaxusers;
+ } else if (n > maxmaxusers) {
+ error("warning: maxusers (%d) > %d", n, maxmaxusers);
+ errors--;
+ }
+}
+
+/*
+ * Define an attribute, optionally with an interface (a locator list).
+ * Since an empty locator list is logically different from "no interface",
+ * all locator lists include a dummy head node, which we discard here.
+ */
+int
+defattr(name, locs)
+ const char *name;
+ struct nvlist *locs;
+{
+ register struct attr *a;
+ register struct nvlist *nv;
+ register int len;
+
+ a = emalloc(sizeof *a);
+ if (ht_insert(attrtab, name, a)) {
+ free(a);
+ error("attribute `%s' already defined", name);
+ nvfreel(locs);
+ return (1);
+ }
+ a->a_name = name;
+ if (locs != NULL) {
+ a->a_iattr = 1;
+ a->a_locs = locs->nv_next;
+ nvfree(locs);
+ } else {
+ a->a_iattr = 0;
+ a->a_locs = NULL;
+ }
+ len = 0;
+ for (nv = a->a_locs; nv != NULL; nv = nv->nv_next)
+ len++;
+ a->a_loclen = len;
+ a->a_devs = NULL;
+ a->a_refs = NULL;
+ return (0);
+}
+
+/*
+ * Return true if the given `error object' is embedded in the given
+ * pointer list.
+ */
+static int
+has_errobj(nv, obj)
+ register struct nvlist *nv;
+ register void *obj;
+{
+
+ for (; nv != NULL; nv = nv->nv_next)
+ if (nv->nv_ptr == obj)
+ return (1);
+ return (0);
+}
+
+/*
+ * Add a device base to a list in an attribute (actually, to any list).
+ * Note that this does not check for duplicates, and does reverse the
+ * list order, but no one cares anyway.
+ */
+static struct nvlist *
+addtoattr(l, dev)
+ register struct nvlist *l;
+ register struct devbase *dev;
+{
+ register struct nvlist *n;
+
+ n = newnv(NULL, NULL, dev, 0);
+ n->nv_next = l;
+ return (n);
+}
+
+/*
+ * Device a device, giving its allowable parent attachments, if any.
+ * This may (or may not) also define an interface attribute and/or refer
+ * to existing attributes. There may be a list of vectors.
+ */
+void
+defdev(dev, ispseudo, atlist, vectors, loclist, attrs)
+ register struct devbase *dev;
+ int ispseudo;
+ struct nvlist *atlist, *vectors, *loclist, *attrs;
+{
+ register struct nvlist *nv;
+ register struct attr *a;
+
+ if (dev == &errdev)
+ goto bad;
+ if (dev->d_isdef) {
+ error("redefinition of `%s'", dev->d_name);
+ goto bad;
+ }
+ dev->d_isdef = 1;
+ if (has_errobj(attrs, &errattr))
+ goto bad;
+
+ /*
+ * Handle implicit attribute definition from locator list. Do
+ * this before scanning the `at' list so that we can have, e.g.:
+ * device foo at other, foo { slot = -1 }
+ * (where you can plug in a foo-bus extender to a foo-bus).
+ */
+ if (loclist != NULL) {
+ nv = loclist;
+ loclist = NULL; /* defattr disposes of them for us */
+ if (defattr(dev->d_name, nv))
+ goto bad;
+ nv = newnv(dev->d_name, NULL, getattr(dev->d_name), 0);
+ nv->nv_next = attrs;
+ attrs = nv;
+ }
+
+ /* Committed! Set up fields. */
+ dev->d_ispseudo = ispseudo;
+ dev->d_atlist = atlist;
+ dev->d_vectors = vectors;
+ dev->d_attrs = attrs;
+
+ /*
+ * Turn the `at' list into interface attributes (map each
+ * nv_name to an attribute, or to NULL for root), and add
+ * this device to those attributes, so that children can
+ * be listed at this particular device if they are supported
+ * by that attribute.
+ */
+ for (nv = atlist; nv != NULL; nv = nv->nv_next) {
+ if (nv->nv_name == NULL) {
+ nv->nv_ptr = NULL; /* at root */
+ continue;
+ }
+ nv->nv_ptr = a = getattr(nv->nv_name);
+ if (a == &errattr)
+ continue; /* already complained */
+ if (!a->a_iattr)
+ error("%s cannot be at plain attribute `%s'",
+ dev->d_name, a->a_name);
+ else
+ a->a_devs = addtoattr(a->a_devs, dev);
+ }
+
+ /*
+ * For each interface attribute this device refers to, add this
+ * device to its reference list. This makes, e.g., finding all
+ * "scsi"s easier.
+ */
+ for (nv = attrs; nv != NULL; nv = nv->nv_next) {
+ a = nv->nv_ptr;
+ if (a->a_iattr)
+ a->a_refs = addtoattr(a->a_refs, dev);
+ }
+ return;
+bad:
+ nvfreel(atlist);
+ nvfreel(vectors);
+ nvfreel(loclist);
+ nvfreel(attrs);
+}
+
+/*
+ * Look up a devbase. Also makes sure it is a reasonable name,
+ * i.e., does not end in a digit or contain special characters.
+ */
+struct devbase *
+getdevbase(name)
+ const char *name;
+{
+ register u_char *p;
+ register struct devbase *dev;
+
+ p = (u_char *)name;
+ if (!isalpha(*p))
+ goto badname;
+ while (*++p) {
+ if (!isalnum(*p) && *p != '_')
+ goto badname;
+ }
+ if (isdigit(*--p)) {
+badname:
+ error("bad device base name `%s'", name);
+ return (&errdev);
+ }
+ dev = ht_lookup(devbasetab, name);
+ if (dev == NULL) {
+ dev = emalloc(sizeof *dev);
+ dev->d_name = name;
+ dev->d_next = NULL;
+ dev->d_isdef = 0;
+ dev->d_major = NODEV;
+ dev->d_atlist = NULL;
+ dev->d_vectors = NULL;
+ dev->d_attrs = NULL;
+ dev->d_ihead = NULL;
+ dev->d_ipp = &dev->d_ihead;
+ dev->d_umax = 0;
+ *nextbase = dev;
+ nextbase = &dev->d_next;
+ if (ht_insert(devbasetab, name, dev))
+ panic("getdevbase(%s)", name);
+ }
+ return (dev);
+}
+
+/*
+ * Look up an attribute.
+ */
+struct attr *
+getattr(name)
+ const char *name;
+{
+ struct attr *a;
+
+ if ((a = ht_lookup(attrtab, name)) == NULL) {
+ error("undefined attribute `%s'", name);
+ a = &errattr;
+ }
+ return (a);
+}
+
+/*
+ * Set the major device number for a device, so that it can be used
+ * as a root/swap/dumps "on" device in a configuration.
+ */
+void
+setmajor(d, n)
+ struct devbase *d;
+ int n;
+{
+
+ if (d != &errdev && d->d_major != NODEV)
+ error("device `%s' is already major %d",
+ d->d_name, d->d_major);
+ else
+ d->d_major = n;
+}
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+static int
+exclude(nv, name, what)
+ struct nvlist *nv;
+ const char *name, *what;
+{
+
+ if (nv != NULL) {
+ error("%s: swap generic must not specify %s", name, what);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Map things like "ra0b" => makedev(major("ra"), 0*8 + 'b'-'a').
+ * Handle the case where the device number is given but there is no
+ * corresponding name, and map NULL to the default.
+ */
+static int
+resolve(nvp, name, what, dflt, part)
+ register struct nvlist **nvp;
+ const char *name, *what;
+ struct nvlist *dflt;
+ register int part;
+{
+ register struct nvlist *nv;
+ register struct devbase *dev;
+ register const char *cp;
+ register int maj, min, l;
+ int unit;
+ char buf[NAMESIZE];
+
+ if ((u_int)(part -= 'a') >= 7)
+ panic("resolve");
+ if ((nv = *nvp) == NULL) {
+ /*
+ * Apply default. Easiest to do this by number.
+ */
+ maj = major(dflt->nv_int);
+ min = (minor(dflt->nv_int) & ~7) | part;
+ *nvp = nv = newnv(NULL, NULL, NULL, makedev(maj, min));
+ }
+ if (nv->nv_int != NODEV) {
+ /*
+ * By the numbers. Find the appropriate major number
+ * to make a name.
+ */
+ maj = major(nv->nv_int);
+ min = minor(nv->nv_int);
+ for (dev = allbases; dev != NULL; dev = dev->d_next)
+ if (dev->d_major == maj)
+ break;
+ if (dev == NULL)
+ (void)sprintf(buf, "<%d/%d>", maj, min);
+ else
+ (void)sprintf(buf, "%s%d%c", dev->d_name,
+ min >> 3, (min & 7) + 'a');
+ nv->nv_str = intern(buf);
+ return (0);
+ }
+
+ /*
+ * The normal case: things like "ra2b". Check for partition
+ * suffix, remove it if there, and split into name ("ra") and
+ * unit (2).
+ */
+ l = strlen(nv->nv_str);
+ cp = &nv->nv_str[l];
+ if (l > 1 && *--cp >= 'a' && *cp <= 'h' && isdigit(cp[-1])) {
+ l--;
+ part = *cp - 'a';
+ }
+ cp = nv->nv_str;
+ if (split(cp, l, buf, sizeof buf, &unit)) {
+ error("%s: invalid %s device name `%s'", name, what, cp);
+ return (1);
+ }
+ dev = ht_lookup(devbasetab, intern(buf));
+ if (dev == NULL || dev->d_major == NODEV) {
+ error("%s: can't make %s device from `%s'",
+ name, what, nv->nv_str);
+ return (1);
+ }
+ nv->nv_name = dev->d_name;
+ nv->nv_int = makedev(dev->d_major, unit * 8 + part);
+ return (0);
+}
+
+static int
+lresolve(nvp, name, what, dflt, part)
+ register struct nvlist **nvp;
+ const char *name, *what;
+ struct nvlist *dflt;
+ int part;
+{
+ int err;
+
+ while ((err = resolve(nvp, name, what, dflt, part)) == 0 &&
+ (*nvp)->nv_next != NULL)
+ nvp = &(*nvp)->nv_next;
+ return (err);
+}
+
+/*
+ * Add a completed configuration to the list.
+ */
+void
+addconf(cf0)
+ register struct config *cf0;
+{
+ register struct config *cf;
+ register struct nvlist *nv;
+ const char *name;
+
+ name = cf0->cf_name;
+ cf = emalloc(sizeof *cf);
+ if (ht_insert(cfhashtab, name, cf)) {
+ error("configuration `%s' already defined", name);
+ free(cf);
+ goto bad;
+ }
+ *cf = *cf0;
+
+ /*
+ * Look for "swap generic".
+ */
+ for (nv = cf->cf_swap; nv != NULL; nv = nv->nv_next)
+ if (nv->nv_str == s_generic)
+ break;
+ if (nv != NULL) {
+ /*
+ * Make sure no root or dump device specified, and no
+ * other swap devices. Note single | here (check all).
+ */
+ nv = cf->cf_swap;
+ if (exclude(cf->cf_root, name, "root device") |
+ exclude(nv->nv_next, name, "additional swap devices") |
+ exclude(cf->cf_dump, name, "dump device"))
+ goto bad;
+ } else {
+ nv = cf->cf_root;
+ if (nv == NULL) {
+ error("%s: no root device specified", name);
+ goto bad;
+ }
+ if (resolve(&cf->cf_root, name, "root", nv, 'a') |
+ lresolve(&cf->cf_swap, name, "swap", nv, 'b') |
+ resolve(&cf->cf_dump, name, "dumps", nv, 'b'))
+ goto bad;
+ }
+ *nextcf = cf;
+ nextcf = &cf->cf_next;
+ return;
+bad:
+ nvfreel(cf0->cf_root);
+ nvfreel(cf0->cf_swap);
+ nvfreel(cf0->cf_dump);
+}
+
+void
+setconf(npp, what, v)
+ register struct nvlist **npp;
+ const char *what;
+ struct nvlist *v;
+{
+
+ if (*npp != NULL) {
+ error("duplicate %s specification", what);
+ nvfreel(v);
+ } else
+ *npp = v;
+}
+
+static struct devi *
+newdevi(name, unit, d)
+ const char *name;
+ int unit;
+ struct devbase *d;
+{
+ register struct devi *i;
+
+ i = emalloc(sizeof *i);
+ i->i_name = name;
+ i->i_unit = unit;
+ i->i_base = d;
+ i->i_next = NULL;
+ i->i_bsame = NULL;
+ i->i_alias = NULL;
+ i->i_at = NULL;
+ i->i_atattr = NULL;
+ i->i_atdev = NULL;
+ i->i_locs = NULL;
+ i->i_cfflags = 0;
+ i->i_lineno = currentline();
+ if (unit >= d->d_umax)
+ d->d_umax = unit + 1;
+ return (i);
+}
+
+/*
+ * Add the named device as attaching to the named attribute (or perhaps
+ * another device instead) plus unit number.
+ */
+void
+adddev(name, at, loclist, flags)
+ const char *name, *at;
+ struct nvlist *loclist;
+ int flags;
+{
+ register struct devi *i; /* the new instance */
+ register struct attr *attr; /* attribute that allows attach */
+ register struct devbase *ib; /* i->i_base */
+ register struct devbase *ab; /* not NULL => at another dev */
+ register struct nvlist *nv;
+ const char *cp;
+ int atunit;
+ char atbuf[NAMESIZE];
+
+ ab = NULL;
+ if (at == NULL) {
+ /* "at root" */
+ if ((i = getdevi(name)) == NULL)
+ goto bad;
+ /*
+ * Must warn about i_unit > 0 later, after taking care of
+ * the STAR cases (we could do non-star's here but why
+ * bother?). Make sure this device can be at root.
+ */
+ ib = i->i_base;
+ if (!onlist(ib->d_atlist, NULL)) {
+ error("%s's cannot attach to the root", ib->d_name);
+ goto bad;
+ }
+ attr = &errattr; /* a convenient "empty" attr */
+ } else {
+ if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) {
+ error("invalid attachment name `%s'", at);
+ /* (void)getdevi(name); -- ??? */
+ goto bad;
+ }
+ if ((i = getdevi(name)) == NULL)
+ goto bad;
+ ib = i->i_base;
+ cp = intern(atbuf);
+ if ((attr = ht_lookup(attrtab, cp)) == NULL) {
+ /*
+ * Have to work a bit harder to see whether we have
+ * something like "tg0 at esp0" (where esp is merely
+ * not an attribute) or "tg0 at nonesuch0" (where
+ * nonesuch is not even a device).
+ */
+ if ((ab = ht_lookup(devbasetab, cp)) == NULL) {
+ error("%s at %s: `%s' unknown",
+ name, at, atbuf);
+ goto bad;
+ }
+ /*
+ * See if the named parent carries an attribute
+ * that allows it to supervise device ib.
+ */
+ for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
+ attr = nv->nv_ptr;
+ if (onlist(attr->a_devs, ib))
+ goto ok;
+ }
+ attr = &errattr;/* now onlist below will fail */
+ }
+ if (!onlist(attr->a_devs, ib)) {
+ error("%s's cannot attach to %s's", ib->d_name, atbuf);
+ goto bad;
+ }
+ }
+ok:
+ if ((i->i_locs = fixloc(name, attr, loclist)) == NULL)
+ goto bad;
+ if (i->i_unit == STAR && ib->d_vectors != NULL) {
+ error("%s's cannot be *'d as they have preset vectors",
+ ib->d_name);
+ goto bad;
+ }
+ i->i_at = at;
+ i->i_atattr = attr;
+ i->i_atdev = ab;
+ i->i_atunit = atunit;
+ i->i_cfflags = flags;
+ selectbase(ib);
+ /* all done, fall into ... */
+bad:
+ nvfreel(loclist);
+ return;
+}
+
+void
+addpseudo(name, number)
+ const char *name;
+ int number;
+{
+ register struct devbase *d;
+ register struct devi *i;
+
+ d = ht_lookup(devbasetab, name);
+ if (d == NULL) {
+ error("undefined pseudo-device %s", name);
+ return;
+ }
+ if (!d->d_ispseudo) {
+ error("%s is a real device, not a pseudo-device", name);
+ return;
+ }
+ if (ht_lookup(devitab, name) != NULL) {
+ error("`%s' already defined", name);
+ return;
+ }
+ i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */
+ if (ht_insert(devitab, name, i))
+ panic("addpseudo(%s)", name);
+ selectbase(d);
+ *nextpseudo = i;
+ nextpseudo = &i->i_next;
+ npseudo++;
+}
+
+/*
+ * Define a new instance of a specific device.
+ */
+static struct devi *
+getdevi(name)
+ const char *name;
+{
+ register struct devi *i, *firsti;
+ register struct devbase *d;
+ int unit;
+ char base[NAMESIZE];
+
+ if (split(name, strlen(name), base, sizeof base, &unit)) {
+ error("invalid device name `%s'", name);
+ return (NULL);
+ }
+ d = ht_lookup(devbasetab, intern(base));
+ if (d == NULL) {
+ error("%s: unknown device `%s'", name, base);
+ return (NULL);
+ }
+ if (d->d_ispseudo) {
+ error("%s: %s is a pseudo-device", name, base);
+ return (NULL);
+ }
+ firsti = ht_lookup(devitab, name);
+ i = newdevi(name, unit, d);
+ if (firsti == NULL) {
+ if (ht_insert(devitab, name, i))
+ panic("getdevi(%s)", name);
+ *d->d_ipp = i;
+ d->d_ipp = &i->i_bsame;
+ } else {
+ while (firsti->i_alias)
+ firsti = firsti->i_alias;
+ firsti->i_alias = i;
+ }
+ *nextdevi = i;
+ nextdevi = &i->i_next;
+ ndevi++;
+ return (i);
+}
+
+static const char *
+concat(name, c)
+ const char *name;
+ int c;
+{
+ register int len;
+ char buf[NAMESIZE];
+
+ len = strlen(name);
+ if (len + 2 > sizeof(buf)) {
+ error("device name `%s%c' too long", name, c);
+ len = sizeof(buf) - 2;
+ }
+ bcopy(name, buf, len);
+ buf[len] = c;
+ buf[len + 1] = 0;
+ return (intern(buf));
+}
+
+const char *
+starref(name)
+ const char *name;
+{
+
+ return (concat(name, '*'));
+}
+
+const char *
+wildref(name)
+ const char *name;
+{
+
+ return (concat(name, '?'));
+}
+
+/*
+ * Split a name like "foo0" into base name (foo) and unit number (0).
+ * Return 0 on success. To make this useful for names like "foo0a",
+ * the length of the "foo0" part is one of the arguments.
+ */
+static int
+split(name, nlen, base, bsize, aunit)
+ register const char *name;
+ size_t nlen;
+ char *base;
+ size_t bsize;
+ int *aunit;
+{
+ register const char *cp;
+ register int c, l;
+
+ l = nlen;
+ if (l < 2 || l >= bsize || isdigit(*name))
+ return (1);
+ c = (u_char)name[--l];
+ if (!isdigit(c)) {
+ if (c == '*')
+ *aunit = STAR;
+ else if (c == '?')
+ *aunit = WILD;
+ else
+ return (1);
+ } else {
+ cp = &name[l];
+ while (isdigit(cp[-1]))
+ l--, cp--;
+ *aunit = atoi(cp);
+ }
+ bcopy(name, base, l);
+ base[l] = 0;
+ return (0);
+}
+
+/*
+ * We have an instance of the base foo, so select it and all its
+ * attributes for "optional foo".
+ */
+static void
+selectbase(d)
+ register struct devbase *d;
+{
+ register struct attr *a;
+ register struct nvlist *nv;
+
+ (void)ht_insert(selecttab, d->d_name, (char *)d->d_name);
+ for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
+ a = nv->nv_ptr;
+ (void)ht_insert(selecttab, a->a_name, (char *)a->a_name);
+ }
+}
+
+/*
+ * Is the given pointer on the given list of pointers?
+ */
+static int
+onlist(nv, ptr)
+ register struct nvlist *nv;
+ register void *ptr;
+{
+ for (; nv != NULL; nv = nv->nv_next)
+ if (nv->nv_ptr == ptr)
+ return (1);
+ return (0);
+}
+
+static char *
+extend(p, name)
+ register char *p;
+ const char *name;
+{
+ register int l;
+
+ l = strlen(name);
+ bcopy(name, p, l);
+ p += l;
+ *p++ = ',';
+ *p++ = ' ';
+ return (p);
+}
+
+/*
+ * Check that we got all required locators, and default any that are
+ * given as "?" and have defaults. Return 0 on success.
+ */
+static const char **
+fixloc(name, attr, got)
+ const char *name;
+ register struct attr *attr;
+ register struct nvlist *got;
+{
+ register struct nvlist *m, *n;
+ register int ord;
+ register const char **lp;
+ int nmissing, nextra, nnodefault;
+ char *mp, *ep, *ndp;
+ char missing[1000], extra[1000], nodefault[1000];
+ static const char *nullvec[1];
+
+ /*
+ * Look for all required locators, and number the given ones
+ * according to the required order. While we are numbering,
+ * set default values for defaulted locators.
+ */
+ if (attr->a_loclen == 0) /* e.g., "at root" */
+ lp = nullvec;
+ else
+ lp = emalloc((attr->a_loclen + 1) * sizeof(const char *));
+ for (n = got; n != NULL; n = n->nv_next)
+ n->nv_int = -1;
+ nmissing = 0;
+ mp = missing;
+ /* yes, this is O(mn), but m and n should be small */
+ for (ord = 0, m = attr->a_locs; m != NULL; m = m->nv_next, ord++) {
+ for (n = got; n != NULL; n = n->nv_next) {
+ if (n->nv_name == m->nv_name) {
+ n->nv_int = ord;
+ break;
+ }
+ }
+ if (n == NULL && m->nv_int == 0) {
+ nmissing++;
+ mp = extend(mp, m->nv_name);
+ }
+ lp[ord] = m->nv_str;
+ }
+ if (ord != attr->a_loclen)
+ panic("fixloc");
+ lp[ord] = NULL;
+ nextra = 0;
+ ep = extra;
+ nnodefault = 0;
+ ndp = nodefault;
+ for (n = got; n != NULL; n = n->nv_next) {
+ if (n->nv_int >= 0) {
+ if (n->nv_str != NULL)
+ lp[n->nv_int] = n->nv_str;
+ else if (lp[n->nv_int] == NULL) {
+ nnodefault++;
+ ndp = extend(ndp, n->nv_name);
+ }
+ } else {
+ nextra++;
+ ep = extend(ep, n->nv_name);
+ }
+ }
+ if (nextra) {
+ ep[-2] = 0; /* kill ", " */
+ error("%s: extraneous locator%s: %s",
+ name, nextra > 1 ? "s" : "", extra);
+ }
+ if (nmissing) {
+ mp[-2] = 0;
+ error("%s: must specify %s", name, missing);
+ }
+ if (nnodefault) {
+ ndp[-2] = 0;
+ error("%s: cannot wildcard %s", name, nodefault);
+ }
+ if (nmissing || nnodefault) {
+ free(lp);
+ lp = NULL;
+ }
+ return (lp);
+}
diff --git a/usr.sbin/config.new/sem.h b/usr.sbin/config.new/sem.h
new file mode 100644
index 0000000..14d6c2b
--- /dev/null
+++ b/usr.sbin/config.new/sem.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)sem.h 8.1 (Berkeley) 6/6/93
+ */
+
+void enddefs __P((const char *));
+
+void setdefmaxusers __P((int, int, int));
+void setmaxusers __P((int));
+int defattr __P((const char *, struct nvlist *));
+void defdev __P((struct devbase *, int, struct nvlist *,
+ struct nvlist *, struct nvlist *, struct nvlist *));
+struct devbase *getdevbase __P((const char *name));
+struct attr *getattr __P((const char *name));
+void setmajor __P((struct devbase *d, int n));
+void addconf __P((struct config *));
+void setconf __P((struct nvlist **, const char *, struct nvlist *));
+void adddev __P((const char *, const char *, struct nvlist *, int));
+void addpseudo __P((const char *name, int number));
+const char *ref __P((const char *name));
+const char *starref __P((const char *name));
+const char *wildref __P((const char *name));
diff --git a/usr.sbin/config.new/util.c b/usr.sbin/config.new/util.c
new file mode 100644
index 0000000..6ef37db
--- /dev/null
+++ b/usr.sbin/config.new/util.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the 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.
+ *
+ * @(#)util.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "config.h"
+
+static void nomem __P((void));
+static void vxerror __P((const char *, int, const char *, va_list));
+
+/*
+ * Malloc, with abort on error.
+ */
+void *
+emalloc(size)
+ size_t size;
+{
+ void *p;
+
+ if ((p = malloc(size)) == NULL)
+ nomem();
+ return (p);
+}
+
+/*
+ * Realloc, with abort on error.
+ */
+void *
+erealloc(p, size)
+ void *p;
+ size_t size;
+{
+
+ if ((p = realloc(p, size)) == NULL)
+ nomem();
+ return (p);
+}
+
+static void
+nomem()
+{
+
+ (void)fprintf(stderr, "config: out of memory\n");
+ exit(1);
+}
+
+/*
+ * Prepend the compilation directory to a file name.
+ */
+char *
+path(file)
+ const char *file;
+{
+ register char *cp;
+#define CDIR "../../compile/"
+
+ if (file == NULL) {
+ cp = emalloc(sizeof(CDIR) + strlen(confdirbase));
+ (void)sprintf(cp, "%s%s", CDIR, confdirbase);
+ } else {
+ cp = emalloc(sizeof(CDIR) + strlen(confdirbase) + 1 +
+ strlen(file));
+ (void)sprintf(cp, "%s%s/%s", CDIR, confdirbase, file);
+ }
+ return (cp);
+}
+
+static struct nvlist *nvhead;
+
+struct nvlist *
+newnv(name, str, ptr, i)
+ const char *name, *str;
+ void *ptr;
+ int i;
+{
+ register struct nvlist *nv;
+
+ if ((nv = nvhead) == NULL)
+ nv = emalloc(sizeof(*nv));
+ else
+ nvhead = nv->nv_next;
+ nv->nv_next = NULL;
+ nv->nv_name = name;
+ if (ptr == NULL)
+ nv->nv_str = str;
+ else {
+ if (str != NULL)
+ panic("newnv");
+ nv->nv_ptr = ptr;
+ }
+ nv->nv_int = i;
+ return (nv);
+}
+
+/*
+ * Free an nvlist structure (just one).
+ */
+void
+nvfree(nv)
+ register struct nvlist *nv;
+{
+
+ nv->nv_next = nvhead;
+ nvhead = nv;
+}
+
+/*
+ * Free an nvlist (the whole list).
+ */
+void
+nvfreel(nv)
+ register struct nvlist *nv;
+{
+ register struct nvlist *next;
+
+ for (; nv != NULL; nv = next) {
+ next = nv->nv_next;
+ nv->nv_next = nvhead;
+ nvhead = nv;
+ }
+}
+
+/*
+ * External (config file) error. Complain, using current file
+ * and line number.
+ */
+void
+#if __STDC__
+error(const char *fmt, ...)
+#else
+error(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+ extern const char *yyfile;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vxerror(yyfile, currentline(), fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Delayed config file error (i.e., something was wrong but we could not
+ * find out about it until later).
+ */
+void
+#if __STDC__
+xerror(const char *file, int line, const char *fmt, ...)
+#else
+xerror(file, line, fmt, va_alist)
+ const char *file;
+ int line;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vxerror(file, line, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Internal form of error() and xerror().
+ */
+static void
+vxerror(file, line, fmt, ap)
+ const char *file;
+ int line;
+ const char *fmt;
+ va_list ap;
+{
+
+ (void)fprintf(stderr, "%s:%d: ", file, line);
+ (void)vfprintf(stderr, fmt, ap);
+ (void)putc('\n', stderr);
+ errors++;
+}
+
+/*
+ * Internal error, abort.
+ */
+__dead void
+#if __STDC__
+panic(const char *fmt, ...)
+#else
+panic(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)fprintf(stderr, "config: panic: ");
+ (void)vfprintf(stderr, fmt, ap);
+ (void)putc('\n', stderr);
+ va_end(ap);
+ exit(2);
+}
diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile
new file mode 100644
index 0000000..d21a5c3
--- /dev/null
+++ b/usr.sbin/config/Makefile
@@ -0,0 +1,12 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= config
+CFLAGS+=-I. -I${.CURDIR}
+SRCS= config.c main.c lang.c mkioconf.c mkmakefile.c mkglue.c mkheaders.c \
+ mkswapconf.c
+MAN8= config.0
+DPADD= ${LIBL}
+LDADD= -ll
+CLEANFILES+=y.tab.h lang.c config.c y.tab.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/config/SMM.doc/0.t b/usr.sbin/config/SMM.doc/0.t
new file mode 100644
index 0000000..ae5bf77
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/0.t
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)0.t 8.1 (Berkeley) 7/5/93
+.\"
+.bd S B 3
+.de UX
+.ie \\n(GA>0 \\$2UNIX\\$1
+.el \{\
+.if n \\$2UNIX\\$1*
+.if t \\$2UNIX\\$1\\f1\(dg\\fP
+.FS
+.if n *UNIX
+.if t \(dgUNIX
+.ie \\$3=1 is a Footnote of Bell Laboratories.
+.el is a Trademark of Bell Laboratories.
+.FE
+.nr GA 1\}
+..
+.de BR
+\fB\\$1\fP\\$2
+..
+.TL
+Building 4.4BSD Kernels with Config
+.AU
+Samuel J. Leffler and Michael J. Karels
+.AI
+Computer Systems Research Group
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, California 94720
+.de IR
+\fI\\$1\fP\\$2
+..
+.de DT
+.TA 8 16 24 32 40 48 56 64 72 80
+..
+.AB
+.PP
+This document describes the use of
+\fIconfig\fP\|(8) to configure and create bootable
+4.4BSD system images.
+It discusses the structure of system
+configuration files and how to configure
+systems with non-standard hardware configurations.
+Sections describing the preferred way to
+add new code to the system and how the system's autoconfiguration
+process operates are included. An appendix
+contains a summary of the rules used by the system
+in calculating the size of system data structures,
+and also indicates some of the standard system size
+limitations (and how to change them).
+Other configuration options are also listed.
+.sp
+.LP
+Revised July 5, 1993
+.AE
+.LP
+.OH 'Building 4.4BSD Kernels with Config''SMM:2-%'
+.EH 'SMM:2-%''Building 4.4BSD Kernels with Config'
diff --git a/usr.sbin/config/SMM.doc/1.t b/usr.sbin/config/SMM.doc/1.t
new file mode 100644
index 0000000..453041b
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/1.t
@@ -0,0 +1,61 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)1.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH Introduction
+.ne 2i
+.sp 3
+.NH
+INTRODUCTION
+.PP
+.I Config
+is a tool used in building 4.4BSD system images (the UNIX kernel).
+It takes a file describing a system's tunable parameters and
+hardware support, and generates a collection
+of files which are then used to build a copy of UNIX appropriate
+to that configuration.
+.I Config
+simplifies system maintenance by isolating system dependencies
+in a single, easy to understand, file.
+.PP
+This document describes the content and
+format of system configuration
+files and the rules which must be followed when creating
+these files. Example configuration files are constructed
+and discussed.
+.PP
+Later sections suggest guidelines to be used in modifying
+system source and explain some of the inner workings of the
+autoconfiguration process. Appendix D summarizes the rules
+used in calculating the most important system data structures
+and indicates some inherent system data structure size
+limitations (and how to go about modifying them).
diff --git a/usr.sbin/config/SMM.doc/2.t b/usr.sbin/config/SMM.doc/2.t
new file mode 100644
index 0000000..34e6b63
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/2.t
@@ -0,0 +1,188 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)2.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Contents
+.ne 2i
+.NH
+CONFIGURATION FILE CONTENTS
+.PP
+A system configuration must include at least the following
+pieces of information:
+.IP \(bu 3
+machine type
+.IP \(bu 3
+cpu type
+.IP \(bu 3
+system identification
+.IP \(bu 3
+timezone
+.IP \(bu 3
+maximum number of users
+.IP \(bu 3
+location of the root file system
+.IP \(bu 3
+available hardware
+.PP
+.I Config
+allows multiple system images to be generated from a single
+configuration description. Each system image is configured
+for identical hardware, but may have different locations for the root
+file system and, possibly, other system devices.
+.NH 2
+Machine type
+.PP
+The
+.I "machine type"
+indicates if the system is going to operate on a DEC VAX-11\(dg computer,
+.FS
+\(dg DEC, VAX, UNIBUS, MASSBUS and MicroVAX are trademarks of Digital
+Equipment Corporation.
+.FE
+or some other machine on which 4.4BSD operates. The machine type
+is used to locate certain data files which are machine specific, and
+also to select rules used in constructing the resultant
+configuration files.
+.NH 2
+Cpu type
+.PP
+The
+.I "cpu type"
+indicates which, of possibly many, cpu's the system is to operate on.
+For example, if the system is being configured for a VAX-11, it could
+be running on a VAX 8600, VAX-11/780, VAX-11/750, VAX-11/730 or MicroVAX II.
+(Other VAX cpu types, including the 8650, 785 and 725, are configured using
+the cpu designation for compatible machines introduced earlier.)
+Specifying
+more than one cpu type implies that the system should be configured to run
+on any of the cpu's specified. For some types of machines this is not
+possible and
+.I config
+will print a diagnostic indicating such.
+.NH 2
+System identification
+.PP
+The
+.I "system identification"
+is a moniker attached to the system, and often the machine on which the
+system is to run. For example, at Berkeley we have machines named Ernie
+(Co-VAX), Kim (No-VAX), and so on. The system identifier selected is used to
+create a global C ``#define'' which may be used to isolate system dependent
+pieces of code in the kernel. For example, Ernie's Varian driver used
+to be special cased because its interrupt vectors were wired together. The
+code in the driver which understood how to handle this non-standard hardware
+configuration was conditionally compiled in only if the system
+was for Ernie.
+.PP
+The system identifier ``GENERIC'' is given to a system which
+will run on any cpu of a particular machine type; it should not
+otherwise be used for a system identifier.
+.NH 2
+Timezone
+.PP
+The timezone in which the system is to run is used to define the
+information returned by the \fIgettimeofday\fP\|(2)
+system call. This value is specified as the number of hours east
+or west of GMT. Negative numbers indicate a value east of GMT.
+The timezone specification may also indicate the
+type of daylight savings time rules to be applied.
+.NH 2
+Maximum number of users
+.PP
+The system allocates many system data structures at boot time
+based on the maximum number of users the system will support.
+This number is normally between 8 and 40, depending
+on the hardware and expected job mix. The rules
+used to calculate system data structures are discussed in
+Appendix D.
+.NH 2
+Root file system location
+.PP
+When the system boots it must know the location of
+the root of the file system
+tree. This location and the part(s) of the disk(s) to be used
+for paging and swapping must be specified in order to create
+a complete configuration description.
+.I Config
+uses many rules to calculate default locations for these items;
+these are described in Appendix B.
+.PP
+When a generic system is configured, the root file system is left
+undefined until the system is booted. In this case, the root file
+system need not be specified, only that the system is a generic system.
+.NH 2
+Hardware devices
+.PP
+When the system boots it goes through an
+.I autoconfiguration
+phase. During this period, the system searches for all
+those hardware devices
+which the system builder has indicated might be present. This probing
+sequence requires certain pieces of information such as register
+addresses, bus interconnects, etc. A system's hardware may be configured
+in a very flexible manner or be specified without any flexibility
+whatsoever. Most people do not configure hardware devices into the
+system unless they are currently present on the machine, expect
+them to be present in the near future, or are simply guarding
+against a hardware
+failure somewhere else at the site (it is often wise to configure in
+extra disks in case an emergency requires moving one off a machine which
+has hardware problems).
+.PP
+The specification of hardware devices usually occupies the majority of
+the configuration file. As such, a large portion of this document will
+be spent understanding it. Section 6.3 contains a description of
+the autoconfiguration process, as it applies to those planning to
+write, or modify existing, device drivers.
+.NH 2
+Pseudo devices
+.PP
+Several system facilities are configured in a manner like that used
+for hardware devices although they are not associated with specific hardware.
+These system options are configured as
+.IR pseudo-devices .
+Some pseudo devices allow an optional parameter that sets the limit
+on the number of instances of the device that are active simultaneously.
+.NH 2
+System options
+.PP
+Other than the mandatory pieces of information described above, it
+is also possible to include various optional system facilities
+or to modify system behavior and/or limits.
+For example, 4.4BSD can be configured to support binary compatibility for
+programs built under 4.3BSD. Also, optional support is provided
+for disk quotas and tracing the performance of the virtual memory
+subsystem. Any optional facilities to be configured into
+the system are specified in the configuration file. The resultant
+files generated by
+.I config
+will automatically include the necessary pieces of the system.
diff --git a/usr.sbin/config/SMM.doc/3.t b/usr.sbin/config/SMM.doc/3.t
new file mode 100644
index 0000000..cbb904f
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/3.t
@@ -0,0 +1,299 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)3.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "System Building Process
+.ne 2i
+.NH
+SYSTEM BUILDING PROCESS
+.PP
+In this section we consider the steps necessary to build a bootable system
+image. We assume the system source is located in the ``/sys'' directory
+and that, initially, the system is being configured from source code.
+.PP
+Under normal circumstances there are 5 steps in building a system.
+.IP 1) 3
+Create a configuration file for the system.
+.IP 2) 3
+Make a directory for the system to be constructed in.
+.IP 3) 3
+Run
+.I config
+on the configuration file to generate the files required
+to compile and load the system image.
+.IP 4)
+Construct the source code interdependency rules for the
+configured system with
+.I make depend
+using
+.IR make (1).
+.IP 5)
+Compile and load the system with
+.IR make .
+.PP
+Steps 1 and 2 are usually done only once. When a system configuration
+changes it usually suffices to just run
+.I config
+on the modified configuration file, rebuild the source code dependencies,
+and remake the system. Sometimes,
+however, configuration dependencies may not be noticed in which case
+it is necessary to clean out the relocatable object files saved
+in the system's directory; this will be discussed later.
+.NH 2
+Creating a configuration file
+.PP
+Configuration files normally reside in the directory ``/sys/conf''.
+A configuration file is most easily constructed by copying an
+existing configuration file and modifying it. The 4.4BSD distribution
+contains a number of configuration files for machines at Berkeley;
+one may be suitable or, in worst case, a copy
+of the generic configuration file may be edited.
+.PP
+The configuration file must have the same name as the directory in
+which the configured system is to be built.
+Further,
+.I config
+assumes this directory is located in the parent directory of
+the directory in which it
+is run. For example, the generic
+system has a configuration file ``/sys/conf/GENERIC'' and an accompanying
+directory named ``/sys/GENERIC''.
+Although it is not required that the system sources and configuration
+files reside in ``/sys,'' the configuration and compilation procedure
+depends on the relative locations of directories within that hierarchy,
+as most of the system code and the files created by
+.I config
+use pathnames of the form ``../''.
+If the system files are not located in ``/sys,''
+it is desirable to make a symbolic link there for use in installation
+of other parts of the system that share files with the kernel.
+.PP
+When building the configuration file, be sure to include the items
+described in section 2. In particular, the machine type,
+cpu type, timezone, system identifier, maximum users, and root device
+must be specified. The specification of the hardware present may take
+a bit of work; particularly if your hardware is configured at non-standard
+places (e.g. device registers located at funny places or devices not
+supported by the system). Section 4 of this document
+gives a detailed description of the configuration file syntax,
+section 5 explains some sample configuration files, and
+section 6 discusses how to add new devices to
+the system. If the devices to be configured are not already
+described in one of the existing configuration files you should check
+the manual pages in section 4 of the UNIX Programmers Manual. For each
+supported device, the manual page synopsis entry gives a
+sample configuration line.
+.PP
+Once the configuration file is complete, run it through
+.I config
+and look for any errors. Never try and use a system which
+.I config
+has complained about; the results are unpredictable.
+For the most part,
+.IR config 's
+error diagnostics are self explanatory. It may be the case that
+the line numbers given with the error messages are off by one.
+.PP
+A successful run of
+.I config
+on your configuration file will generate a number of files in
+the configuration directory. These files are:
+.IP \(bu 3
+A file to be used by \fImake\fP\|(1)
+in compiling and loading the system,
+.IR Makefile .
+.IP \(bu 3
+One file for each possible system image for this machine,
+.IR swapxxx.c ,
+where
+.I xxx
+is the name of the system image,
+which describes where swapping, the root file system, and other
+miscellaneous system devices are located.
+.IP \(bu 3
+A collection of header files, one per possible device the
+system supports, which define the hardware configured.
+.IP \(bu 3
+A file containing the I/O configuration tables used by the system
+during its
+.I autoconfiguration
+phase,
+.IR ioconf.c .
+.IP \(bu 3
+An assembly language file of interrupt vectors which
+connect interrupts from the machine's external buses to the main
+system path for handling interrupts,
+and a file that contains counters and names for the interrupt vectors.
+.PP
+Unless you have reason to doubt
+.IR config ,
+or are curious how the system's autoconfiguration scheme
+works, you should never have to look at any of these files.
+.NH 2
+Constructing source code dependencies
+.PP
+When
+.I config
+is done generating the files needed to compile and link your system it
+will terminate with a message of the form ``Don't forget to run make depend''.
+This is a reminder that you should change over to the configuration
+directory for the system just configured and type ``make depend''
+to build the rules used by
+.I make
+to recognize interdependencies in the system source code.
+This will insure that any changes to a piece of the system
+source code will result in the proper modules being recompiled
+the next time
+.I make
+is run.
+.PP
+This step is particularly important if your site makes changes
+to the system include files. The rules generated specify which source code
+files are dependent on which include files. Without these rules,
+.I make
+will not recognize when it must rebuild modules
+due to the modification of a system header file.
+The dependency rules are generated by a pass of the C preprocessor
+and reflect the global system options.
+This step must be repeated when the configuration file is changed
+and
+.I config
+is used to regenerate the system makefile.
+.NH 2
+Building the system
+.PP
+The makefile constructed by
+.I config
+should allow a new system to be rebuilt by simply typing ``make image-name''.
+For example, if you have named your bootable system image ``vmunix'',
+then ``make vmunix''
+will generate a bootable image named ``vmunix''. Alternate system image names
+are used when the root file system location and/or swapping configuration
+is done in more than one way. The makefile which
+.I config
+creates has entry points for each system image defined in
+the configuration file.
+Thus, if you have configured ``vmunix'' to be a system with the root file
+system on an ``hp'' device and ``hkvmunix'' to be a system with the root
+file system on an ``hk'' device, then ``make vmunix hkvmunix'' will generate
+binary images for each.
+As the system will generally use the disk from which it is loaded
+as the root filesystem, separate system images are only required
+to support different swap configurations.
+.PP
+Note that the name of a bootable image is different from the system
+identifier. All bootable images are configured for the same system;
+only the information about the root file system and paging devices differ.
+(This is described in more detail in section 4.)
+.PP
+The last step in the system building process is to rearrange certain commonly
+used symbols in the symbol table of the system image; the makefile
+generated by
+.I config
+does this automatically for you.
+This is advantageous for programs such as
+\fInetstat\fP\|(1) and \fIvmstat\fP\|(1),
+which run much faster when the symbols they need are located at
+the front of the symbol table.
+Remember also that many programs expect
+the currently executing system to be named ``/vmunix''. If you install
+a new system and name it something other than ``/vmunix'', many programs
+are likely to give strange results.
+.NH 2
+Sharing object modules
+.PP
+If you have many systems which are all built on a single machine
+there are at least two approaches to saving time in building system
+images. The best way is to have a single system image which is run on
+all machines. This is attractive since it minimizes disk space used
+and time required to rebuild systems after making changes. However,
+it is often the case that one or more systems will require a separately
+configured system image. This may be due to limited memory (building
+a system with many unused device drivers can be expensive), or to
+configuration requirements (one machine may be a development machine
+where disk quotas are not needed, while another is a production machine
+where they are), etc. In these cases it is possible
+for common systems to share relocatable object modules which are not
+configuration dependent; most of the modules in the directory ``/sys/sys''
+are of this sort.
+.PP
+To share object modules, a generic system should be built. Then, for
+each system configure the system as before, but before recompiling and
+linking the system, type ``make links'' in the system compilation directory.
+This will cause the system
+to be searched for source modules which are safe to share between systems
+and generate symbolic links in the current directory to the appropriate
+object modules in the directory ``../GENERIC''. A shell script,
+``makelinks'' is generated with this request and may be checked for
+correctness. The file ``/sys/conf/defines'' contains a list of symbols
+which we believe are safe to ignore when checking the source code
+for modules which may be shared. Note that this list includes the definitions
+used to conditionally compile in the virtual memory tracing facilities, and
+the trace point support used only rarely (even at Berkeley).
+It may be necessary
+to modify this file to reflect local needs. Note further that
+interdependencies which are not directly visible
+in the source code are not caught. This means that if you place
+per-system dependencies in an include file, they will not be recognized
+and the shared code may be selected in an unexpected fashion.
+.NH 2
+Building profiled systems
+.PP
+It is simple to configure a system which will automatically
+collect profiling information as it operates. The profiling data
+may be collected with \fIkgmon\fP\|(8) and processed with
+\fIgprof\fP\|(1)
+to obtain information regarding the system's operation. Profiled
+systems maintain histograms of the program counter as well as the
+number of invocations of each routine. The \fIgprof\fP
+command will also generate a dynamic call graph of the executing
+system and propagate time spent in each routine along the arcs
+of the call graph (consult the \fIgprof\fP documentation for elaboration).
+The program counter sampling can be driven by the system clock, or
+if you have an alternate real time clock, this can be used. The
+latter is highly recommended, as use of the system clock will result
+in statistical anomalies, and time spent in the clock routine will
+not be accurately attributed.
+.PP
+To configure a profiled system, the
+.B \-p
+option should be supplied to \fIconfig\fP.
+A profiled system is about 5-10% larger in its text space due to
+the calls to count the subroutine invocations. When the system
+executes, the profiling data is stored in a buffer which is 1.2
+times the size of the text space. The overhead for running a
+profiled system varies; under normal load we see anywhere from 5-25%
+of the system time spent in the profiling code.
+.PP
+Note that systems configured for profiling should not be shared as
+described above unless all the other shared systems are also to be
+profiled.
diff --git a/usr.sbin/config/SMM.doc/4.t b/usr.sbin/config/SMM.doc/4.t
new file mode 100644
index 0000000..d267799
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/4.t
@@ -0,0 +1,442 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)4.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Syntax
+.ne 2i
+.NH
+CONFIGURATION FILE SYNTAX
+.PP
+In this section we consider the specific rules used in writing
+a configuration file. A complete grammar for the input language
+can be found in Appendix A and may be of use if you should have
+problems with syntax errors.
+.PP
+A configuration file is broken up into three logical pieces:
+.IP \(bu 3
+configuration parameters global to all system images
+specified in the configuration file,
+.IP \(bu 3
+parameters specific to each
+system image to be generated, and
+.IP \(bu 3
+device specifications.
+.NH 2
+Global configuration parameters
+.PP
+The global configuration parameters are the type of machine,
+cpu types, options, timezone, system identifier, and maximum users.
+Each is specified with a separate line in the configuration file.
+.IP "\fBmachine\fP \fItype\fP"
+.br
+The system is to run on the machine type specified. No more than
+one machine type can appear in the configuration file. Legal values
+are
+.B vax
+and
+\fBsun\fP.
+.IP "\fBcpu\fP ``\fItype\fP''"
+.br
+This system is to run on the cpu type specified.
+More than one cpu type specification
+can appear in a configuration file.
+Legal types for a
+.B vax
+machine are
+\fBVAX8600\fP, \fBVAX780\fP, \fBVAX750\fP,
+\fBVAX730\fP
+and
+\fBVAX630\fP (MicroVAX II).
+The 8650 is listed as an 8600, the 785 as a 780, and a 725 as a 730.
+.IP "\fBoptions\fP \fIoptionlist\fP"
+.br
+Compile the listed optional code into the system.
+Options in this list are separated by commas.
+Possible options are listed at the top of the generic makefile.
+A line of the form ``options FUNNY,HAHA'' generates global ``#define''s
+\-DFUNNY \-DHAHA in the resultant makefile.
+An option may be given a value by following its name with ``\fB=\fP'',
+then the value enclosed in (double) quotes.
+The following are major options are currently in use:
+COMPAT (include code for compatibility with 4.1BSD binaries),
+INET (Internet communication protocols),
+NS (Xerox NS communication protocols),
+and
+QUOTA (enable disk quotas).
+Other kernel options controlling system sizes and limits
+are listed in Appendix D;
+options for the network are found in Appendix E.
+There are additional options which are associated with certain
+peripheral devices; those are listed in the Synopsis section
+of the manual page for the device.
+.IP "\fBmakeoptions\fP \fIoptionlist\fP"
+.br
+Options that are used within the system makefile
+and evaluated by
+.I make
+are listed as
+.IR makeoptions .
+Options are listed with their values with the form
+``makeoptions name=value,name2=value2.''
+The values must be enclosed in double quotes if they include numerals
+or begin with a dash.
+.IP "\fBtimezone\fP \fInumber\fP [ \fBdst\fP [ \fInumber\fP ] ]"
+.br
+Specifies the timezone used by the system. This is measured in the
+number of hours your timezone is west of GMT.
+EST is 5 hours west of GMT, PST is 8. Negative numbers
+indicate hours east of GMT. If you specify
+\fBdst\fP, the system will operate under daylight savings time.
+An optional integer or floating point number may be included
+to specify a particular daylight saving time correction algorithm;
+the default value is 1, indicating the United States.
+Other values are: 2 (Australian style), 3 (Western European),
+4 (Middle European), and 5 (Eastern European). See
+\fIgettimeofday\fP\|(2) and \fIctime\fP\|(3) for more information.
+.IP "\fBident\fP \fIname\fP"
+.br
+This system is to be known as
+.IR name .
+This is usually a cute name like ERNIE (short for Ernie Co-Vax) or
+VAXWELL (for Vaxwell Smart).
+This value is defined for use in conditional compilation,
+and is also used to locate an optional list of source files specific
+to this system.
+.IP "\fBmaxusers\fP \fInumber\fP"
+.br
+The maximum expected number of simultaneously active user on this system is
+.IR number .
+This number is used to size several system data structures.
+.NH 2
+System image parameters
+.PP
+Multiple bootable images may be specified in a single configuration
+file. The systems will have the same global configuration parameters
+and devices, but the location of the root file system and other
+system specific devices may be different. A system image is specified
+with a ``config'' line:
+.IP
+\fBconfig\fP\ \fIsysname\fP\ \fIconfig-clauses\fP
+.LP
+The
+.I sysname
+field is the name given to the loaded system image; almost everyone
+names their standard system image ``vmunix''. The configuration clauses
+are one or more specifications indicating where the root file system
+is located and the number and location of paging devices.
+The device used by the system to process argument lists during
+.IR execve (2)
+calls may also be specified, though in practice this is almost
+always selected by
+.I config
+using one of its rules for selecting default locations for
+system devices.
+.PP
+A configuration clause is one of the following
+.IP
+.nf
+\fBroot\fP [ \fBon\fP ] \fIroot-device\fP
+\fBswap\fP [ \fBon\fP ] \fIswap-device\fP [ \fBand\fP \fIswap-device\fP ] ...
+\fBdumps\fP [ \fBon\fP ] \fIdump-device\fP
+\fBargs\fP [ \fBon\fP ] \fIarg-device\fP
+.LP
+(the ``on'' is optional.) Multiple configuration clauses
+are separated by white space;
+.I config
+allows specifications to be continued across multiple lines
+by beginning the continuation line with a tab character.
+The ``root'' clause specifies where the root file system
+is located, the ``swap'' clause indicates swapping and paging
+area(s), the ``dumps'' clause can be used to force system dumps
+to be taken on a particular device, and the ``args'' clause
+can be used to specify that argument list processing for
+.I execve
+should be done on a particular device.
+.PP
+The device names supplied in the clauses may be fully specified
+as a device, unit, and file system partition; or underspecified
+in which case
+.I config
+will use builtin rules to select default unit numbers and file
+system partitions. The defaulting rules are a bit complicated
+as they are dependent on the overall system configuration.
+For example, the swap area need not be specified at all if
+the root device is specified; in this case the swap area is
+placed in the ``b'' partition of the same disk where the root
+file system is located. Appendix B contains a complete list
+of the defaulting rules used in selecting system configuration
+devices.
+.PP
+The device names are translated to the
+appropriate major and minor device
+numbers on a per-machine basis. A file,
+``/sys/conf/devices.machine'' (where ``machine''
+is the machine type specified in the configuration file),
+is used to map a device name to its major block device number.
+The minor device number is calculated using the standard
+disk partitioning rules: on unit 0, partition ``a'' is minor device
+0, partition ``b'' is minor device 1, and so on; for units
+other than 0, add 8 times the unit number to get the minor
+device.
+.PP
+If the default mapping of device name to major/minor device
+number is incorrect for your configuration, it can be replaced
+by an explicit specification of the major/minor device.
+This is done by substituting
+.IP
+\fBmajor\fP \fIx\fP \fBminor\fP \fIy\fP
+.LP
+where the device name would normally be found. For example,
+.IP
+.nf
+\fBconfig\fP vmunix \fBroot\fP \fBon\fP \fBmajor\fP 99 \fBminor\fP 1
+.fi
+.PP
+Normally, the areas configured for swap space are sized by the system
+at boot time. If a non-standard size is to be used for one
+or more swap areas (less than the full partition),
+this can also be specified. To do this, the
+device name specified for a swap area should have a ``size''
+specification appended. For example,
+.IP
+.nf
+\fBconfig\fP vmunix \fBroot\fP \fBon\fP hp0 \fBswap\fP \fBon\fP hp0b \fBsize\fP 1200
+.fi
+.LP
+would force swapping to be done in partition ``b'' of ``hp0'' and
+the swap partition size would be set to 1200 sectors. A swap area
+sized larger than the associated disk partition is trimmed to the
+partition size.
+.PP
+To create a generic configuration, only the clause ``swap generic''
+should be specified; any extra clauses will cause an error.
+.NH 2
+Device specifications
+.PP
+Each device attached to a machine must be specified
+to
+.I config
+so that the system generated will know to probe for it during
+the autoconfiguration process carried out at boot time. Hardware
+specified in the configuration need not actually be present on
+the machine where the generated system is to be run. Only the
+hardware actually found at boot time will be used by the system.
+.PP
+The specification of hardware devices in the configuration file
+parallels the interconnection hierarchy of the machine to be
+configured. On the VAX, this means that a configuration file must
+indicate what MASSBUS and UNIBUS adapters are present, and to
+which \fInexi\fP they might be connected.*
+.FS
+* While VAX-11/750's and VAX-11/730 do not actually have
+nexi, the system treats them as having
+.I "simulated nexi"
+to simplify device configuration.
+.FE
+Similarly, devices
+and controllers must be indicated as possibly being connected
+to one or more adapters. A device description may provide a
+complete definition of the possible configuration parameters
+or it may leave certain parameters undefined and make the system
+probe for all the possible values. The latter allows a single
+device configuration list to match many possible physical
+configurations. For example, a disk may be indicated as present
+at UNIBUS adapter 0, or at any UNIBUS adapter which the system
+locates at boot time. The latter scheme, termed
+.IR wildcarding ,
+allows more flexibility in the physical configuration of a system;
+if a disk must be moved around for some reason, the system will
+still locate it at the alternate location.
+.PP
+A device specification takes one of the following forms:
+.IP
+.nf
+\fBmaster\fP \fIdevice-name\fP \fIdevice-info\fP
+\fBcontroller\fP \fIdevice-name\fP \fIdevice-info\fP [ \fIinterrupt-spec\fP ]
+\fBdevice\fP \fIdevice-name\fP \fIdevice-info\fP \fIinterrupt-spec\fP
+\fBdisk\fP \fIdevice-name\fP \fIdevice-info\fP
+\fBtape\fP \fIdevice-name\fP \fIdevice-info\fP
+.fi
+.LP
+A ``master'' is a MASSBUS tape controller; a ``controller'' is a
+disk controller, a UNIBUS tape controller, a MASSBUS adapter, or
+a UNIBUS adapter. A ``device'' is an autonomous device which
+connects directly to a UNIBUS adapter (as opposed to something
+like a disk which connects through a disk controller). ``Disk''
+and ``tape'' identify disk drives and tape drives connected to
+a ``controller'' or ``master.''
+.PP
+The
+.I device-name
+is one of the standard device names, as
+indicated in section 4 of the UNIX Programmers Manual,
+concatenated with the
+.I logical
+unit number to be assigned the device (the
+.I logical
+unit number may be different than the
+.I physical
+unit number indicated on the front of something
+like a disk; the
+.I logical
+unit number is used to refer to the UNIX device, not
+the physical unit number). For example, ``hp0'' is logical
+unit 0 of a MASSBUS storage device, even though it might
+be physical unit 3 on MASSBUS adapter 1.
+.PP
+The
+.I device-info
+clause specifies how the hardware is
+connected in the interconnection hierarchy. On the VAX,
+UNIBUS and MASSBUS adapters are connected to the internal
+system bus through
+a \fInexus\fP.
+Thus, one of the following
+specifications would be used:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP mba0 \fBat\fP \fBnexus\fP \fIx\fP
+\fBcontroller\fP uba0 \fBat\fP \fBnexus\fP \fIx\fP
+.fi
+.LP
+To tie a controller to a specific nexus, ``x'' would be supplied
+as the number of that nexus; otherwise ``x'' may be specified as
+``?'', in which
+case the system will probe all nexi present looking
+for the specified controller.
+.PP
+The remaining interconnections on the VAX are:
+.IP \(bu 3
+a controller
+may be connected to another controller (e.g. a disk controller attached
+to a UNIBUS adapter),
+.IP \(bu 3
+a master is always attached to a controller (a MASSBUS adapter),
+.IP \(bu 3
+a tape is always attached to a master (for MASSBUS
+tape drives),
+.IP \(bu 3
+a disk is always attached to a controller, and
+.IP \(bu 3
+devices
+are always attached to controllers (e.g. UNIBUS controllers attached
+to UNIBUS adapters).
+.LP
+The following lines give an example of each of these interconnections:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP hk0 \fBat\fP uba0 ...
+\fBmaster\fP ht0 \fBat\fP mba0 ...
+\fBdisk\fP hp0 \fBat\fP mba0 ...
+\fBtape\fP tu0 \fBat\fP ht0 ...
+\fBdisk\fP rk1 \fBat\fP hk0 ...
+\fBdevice\fP dz0 \fBat\fP uba0 ...
+.fi
+.LP
+Any piece of hardware which may be connected to a specific
+controller may also be wildcarded across multiple controllers.
+.PP
+The final piece of information needed by the system to configure
+devices is some indication of where or how a device will interrupt.
+For tapes and disks, simply specifying the \fIslave\fP or \fIdrive\fP
+number is sufficient to locate the control status register for the
+device.
+\fIDrive\fP numbers may be wildcarded
+on MASSBUS devices, but not on disks on a UNIBUS controller.
+For controllers, the control status register must be
+given explicitly, as well the number of interrupt vectors used and
+the names of the routines to which they should be bound.
+Thus the example lines given above might be completed as:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP hk0 \fBat\fP uba0 \fBcsr\fP 0177440 \fBvector\fP rkintr
+\fBmaster\fP ht0 \fBat\fP mba0 \fBdrive\fP 0
+\fBdisk\fP hp0 \fBat\fP mba0 \fBdrive\fP ?
+\fBtape\fP tu0 \fBat\fP ht0 \fBslave\fP 0
+\fBdisk\fP rk1 \fBat\fP hk0 \fBdrive\fP 1
+\fBdevice\fP dz0 \fBat\fP uba0 \fBcsr\fP 0160100 \fBvector\fP dzrint dzxint
+.fi
+.PP
+Certain device drivers require extra information passed to them
+at boot time to tailor their operation to the actual hardware present.
+The line printer driver, for example, needs to know how many columns
+are present on each non-standard line printer (i.e. a line printer
+with other than 80 columns). The drivers for the terminal multiplexors
+need to know which lines are attached to modem lines so that no one will
+be allowed to use them unless a connection is present. For this reason,
+one last parameter may be specified to a
+.IR device ,
+a
+.I flags
+field. It has the syntax
+.IP
+\fBflags\fP \fInumber\fP
+.LP
+and is usually placed after the
+.I csr
+specification. The
+.I number
+is passed directly to the associated driver. The manual pages
+in section 4 should be consulted to determine how each driver
+uses this value (if at all).
+Communications interface drivers commonly use the flags
+to indicate whether modem control signals are in use.
+.PP
+The exact syntax for each specific device is given in the Synopsis
+section of its manual page in section 4 of the manual.
+.NH 2
+Pseudo-devices
+.PP
+A number of drivers and software subsystems
+are treated like device drivers without any associated hardware.
+To include any of these pieces, a ``pseudo-device'' specification
+must be used. A specification for a pseudo device takes the form
+.IP
+.DT
+.nf
+\fBpseudo-device\fP \fIdevice-name\fP [ \fIhowmany\fP ]
+.fi
+.PP
+Examples of pseudo devices are
+\fBpty\fP, the pseudo terminal driver (where the optional
+.I howmany
+value indicates the number of pseudo terminals to configure, 32 default),
+and \fBloop\fP, the software loopback network pseudo-interface.
+Other pseudo devices for the network include
+\fBimp\fP (required when a CSS or ACC imp is configured)
+and \fBether\fP (used by the Address Resolution Protocol
+on 10 Mb/sec Ethernets).
+More information on configuring each of these can also be found
+in section 4 of the manual.
diff --git a/usr.sbin/config/SMM.doc/5.t b/usr.sbin/config/SMM.doc/5.t
new file mode 100644
index 0000000..3a0f449
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/5.t
@@ -0,0 +1,271 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)5.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Sample Configuration Files
+.ne 2i
+.NH
+SAMPLE CONFIGURATION FILES
+.PP
+In this section we will consider how to configure a
+sample VAX-11/780 system on which the hardware can be
+reconfigured to guard against various hardware mishaps.
+We then study the rules needed to configure a VAX-11/750
+to run in a networking environment.
+.NH 2
+VAX-11/780 System
+.PP
+Our VAX-11/780 is configured with hardware
+recommended in the document ``Hints on Configuring a VAX for 4.2BSD''
+(this is one of the high-end configurations).
+Table 1 lists the pertinent hardware to be configured.
+.DS B
+.TS
+box;
+l | l | l | l | l
+l | l | l | l | l.
+Item Vendor Connection Name Reference
+_
+cpu DEC VAX780
+MASSBUS controller Emulex nexus ? mba0 hp(4)
+disk Fujitsu mba0 hp0
+disk Fujitsu mba0 hp1
+MASSBUS controller Emulex nexus ? mba1
+disk Fujitsu mba1 hp2
+disk Fujitsu mba1 hp3
+UNIBUS adapter DEC nexus ?
+tape controller Emulex uba0 tm0 tm(4)
+tape drive Kennedy tm0 te0
+tape drive Kennedy tm0 te1
+terminal multiplexor Emulex uba0 dh0 dh(4)
+terminal multiplexor Emulex uba0 dh1
+terminal multiplexor Emulex uba0 dh2
+.TE
+.DE
+.ce
+Table 1. VAX-11/780 Hardware support.
+.LP
+We will call this machine ANSEL and construct a configuration
+file one step at a time.
+.PP
+The first step is to fill in the global configuration parameters.
+The machine is a VAX, so the
+.I "machine type"
+is ``vax''. We will assume this system will
+run only on this one processor, so the
+.I "cpu type"
+is ``VAX780''. The options are empty since this is going to
+be a ``vanilla'' VAX. The system identifier, as mentioned before,
+is ``ANSEL,'' and the maximum number of users we plan to support is
+about 40. Thus the beginning of the configuration file looks like
+this:
+.DS
+.ta 1.5i 2.5i 4.0i
+#
+# ANSEL VAX (a picture perfect machine)
+#
+machine vax
+cpu VAX780
+timezone 8 dst
+ident ANSEL
+maxusers 40
+.DE
+.PP
+To this we must then add the specifications for three
+system images. The first will be our standard system with the
+root on ``hp0'' and swapping on the same drive as the root.
+The second will have the root file system in the same location,
+but swap space interleaved among drives on each controller.
+Finally, the third will be a generic system,
+to allow us to boot off any of the four disk drives.
+.DS
+.ta 1.5i 2.5i
+config vmunix root on hp0
+config hpvmunix root on hp0 swap on hp0 and hp2
+config genvmunix swap generic
+.DE
+.PP
+Finally, the hardware must be specified. Let us first just try
+transcribing the information from Table 1.
+.DS
+.ta 1.5i 2.5i 4.0i
+controller mba0 at nexus ?
+disk hp0 at mba0 disk 0
+disk hp1 at mba0 disk 1
+controller mba1 at nexus ?
+disk hp2 at mba1 disk 2
+disk hp3 at mba1 disk 3
+controller uba0 at nexus ?
+controller tm0 at uba0 csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba0 csr 0160020 vector dhrint dhxint
+device dm0 at uba0 csr 0170500 vector dmintr
+device dh1 at uba0 csr 0160040 vector dhrint dhxint
+device dh2 at uba0 csr 0160060 vector dhrint dhxint
+.DE
+.LP
+(Oh, I forgot to mention one panel of the terminal multiplexor
+has modem control, thus the ``dm0'' device.)
+.PP
+This will suffice, but leaves us with little flexibility. Suppose
+our first disk controller were to break. We would like to recable the
+drives normally on the second controller so that all our disks could
+still be used without reconfiguring the system. To do this we wildcard
+the MASSBUS adapter connections and also the slave numbers. Further,
+we wildcard the UNIBUS adapter connections in case we decide some time
+in the future to purchase another adapter to offload the single UNIBUS
+we currently have. The revised device specifications would then be:
+.DS
+.ta 1.5i 2.5i 4.0i
+controller mba0 at nexus ?
+disk hp0 at mba? disk ?
+disk hp1 at mba? disk ?
+controller mba1 at nexus ?
+disk hp2 at mba? disk ?
+disk hp3 at mba? disk ?
+controller uba0 at nexus ?
+controller tm0 at uba? csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba? csr 0160020 vector dhrint dhxint
+device dm0 at uba? csr 0170500 vector dmintr
+device dh1 at uba? csr 0160040 vector dhrint dhxint
+device dh2 at uba? csr 0160060 vector dhrint dhxint
+.DE
+.LP
+The completed configuration file for ANSEL is shown in Appendix C.
+.NH 2
+VAX-11/750 with network support
+.PP
+Our VAX-11/750 system will be located on two 10Mb/s Ethernet
+local area networks and also the DARPA Internet. The system
+will have a MASSBUS drive for the root file system and two
+UNIBUS drives. Paging is interleaved among all three drives.
+We have sold our standard DEC terminal multiplexors since this
+machine will be accessed solely through the network. This
+machine is not intended to have a large user community, it
+does not have a great deal of memory. First the global parameters:
+.DS
+.ta 1.5i 2.5i 4.0i
+#
+# UCBVAX (Gateway to the world)
+#
+machine vax
+cpu "VAX780"
+cpu "VAX750"
+ident UCBVAX
+timezone 8 dst
+maxusers 32
+options INET
+options NS
+.DE
+.PP
+The multiple cpu types allow us to replace UCBVAX with a
+more powerful cpu without reconfiguring the system. The
+value of 32 given for the maximum number of users is done to
+force the system data structures to be over-allocated. That
+is desirable on this machine because, while it is not expected
+to support many users, it is expected to perform a great deal
+of work.
+The ``INET'' indicates that we plan to use the
+DARPA standard Internet protocols on this machine,
+and ``NS'' also includes support for Xerox NS protocols.
+Note that unlike 4.2BSD configuration files,
+the network protocol options do not require corresponding pseudo devices.
+.PP
+The system images and disks are configured next.
+.DS
+.ta 1.5i 2.5i 4.0i
+config vmunix root on hp swap on hp and rk0 and rk1
+config upvmunix root on up
+config hkvmunix root on hk swap on rk0 and rk1
+
+controller mba0 at nexus ?
+controller uba0 at nexus ?
+disk hp0 at mba? drive 0
+disk hp1 at mba? drive 1
+controller sc0 at uba? csr 0176700 vector upintr
+disk up0 at sc0 drive 0
+disk up1 at sc0 drive 1
+controller hk0 at uba? csr 0177440 vector rkintr
+disk rk0 at hk0 drive 0
+disk rk1 at hk0 drive 1
+.DE
+.PP
+UCBVAX requires heavy interleaving of its paging area to keep up
+with all the mail traffic it handles. The limiting factor on this
+system's performance is usually the number of disk arms, as opposed
+to memory or cpu cycles. The extra UNIBUS controller, ``sc0'',
+is in case the MASSBUS controller breaks and a spare controller
+must be installed (most of our old UNIBUS controllers have been
+replaced with the newer MASSBUS controllers, so we have a number
+of these around as spares).
+.PP
+Finally, we add in the network devices.
+Pseudo terminals are needed to allow users to
+log in across the network (remember the only hardwired terminal
+is the console).
+The software loopback device is used for on-machine communications.
+The connection to the Internet is through
+an IMP, this requires yet another
+.I pseudo-device
+(in addition to the actual hardware device used by the
+IMP software). And, finally, there are the two Ethernet devices.
+These use a special protocol, the Address Resolution Protocol (ARP),
+to map between Internet and Ethernet addresses. Thus, yet another
+.I pseudo-device
+is needed. The additional device specifications are show below.
+.DS
+.ta 1.5i 2.5i 4.0i
+pseudo-device pty
+pseudo-device loop
+pseudo-device imp
+device acc0 at uba? csr 0167600 vector accrint accxint
+pseudo-device ether
+device ec0 at uba? csr 0164330 vector ecrint eccollide ecxint
+device il0 at uba? csr 0164000 vector ilrint ilcint
+.DE
+.LP
+The completed configuration file for UCBVAX is shown in Appendix C.
+.NH 2
+Miscellaneous comments
+.PP
+It should be noted in these examples that neither system was
+configured to use disk quotas or the 4.1BSD compatibility mode.
+To use these optional facilities, and others, we would probably
+clean out our current configuration, reconfigure the system, then
+recompile and relink the system image(s). This could, of course,
+be avoided by figuring out which relocatable object files are
+affected by the reconfiguration, then reconfiguring and recompiling
+only those files affected by the configuration change. This technique
+should be used carefully.
diff --git a/usr.sbin/config/SMM.doc/6.t b/usr.sbin/config/SMM.doc/6.t
new file mode 100644
index 0000000..f02baed
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/6.t
@@ -0,0 +1,239 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)6.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Adding New Devices
+.ne 2i
+.NH
+ADDING NEW SYSTEM SOFTWARE
+.PP
+This section is not for the novice, it describes
+some of the inner workings of the configuration process as
+well as the pertinent parts of the system autoconfiguration process.
+It is intended to give
+those people who intend to install new device drivers and/or
+other system facilities sufficient information to do so in the
+manner which will allow others to easily share the changes.
+.PP
+This section is broken into four parts:
+.IP \(bu 3
+general guidelines to be followed in modifying system code,
+.IP \(bu 3
+how to add non-standard system facilities to 4.4BSD,
+.IP \(bu 3
+how to add a device driver to 4.4BSD, and
+.NH 2
+Modifying system code
+.PP
+If you wish to make site-specific modifications to the system
+it is best to bracket them with
+.DS
+#ifdef SITENAME
+\&...
+#endif
+.DE
+to allow your source to be easily distributed to others, and
+also to simplify \fIdiff\fP\|(1) listings. If you choose not
+to use a source code control system (e.g. SCCS, RCS), and
+perhaps even if you do, it is
+recommended that you save the old code with something
+of the form:
+.DS
+#ifndef SITENAME
+\&...
+#endif
+.DE
+We try to isolate our site-dependent code in individual files
+which may be configured with pseudo-device specifications.
+.PP
+Indicate machine-specific code with ``#ifdef vax'' (or other machine,
+as appropriate).
+4.4BSD underwent extensive work to make it extremely portable to
+machines with similar architectures\- you may someday find
+yourself trying to use a single copy of the source code on
+multiple machines.
+.NH 2
+Adding non-standard system facilities
+.PP
+This section considers the work needed to augment
+.IR config 's
+data base files for non-standard system facilities.
+.I Config
+uses a set of files that list the source modules that may be required
+when building a system.
+The data bases are taken from the directory in which
+.I config
+is run, normally /sys/conf.
+Three such files may be used:
+.IR files ,
+.IR files .machine,
+and
+.IR files .ident.
+The first is common to all systems,
+the second contains files unique to a single machine type,
+and the third is an optional list of modules for use on a specific machine.
+This last file may override specifications in the first two.
+The format of the
+.I files
+file has grown somewhat complex over time. Entries are normally of
+the form
+.IP
+.nf
+.DT
+\fIdir/source.c\fP \fItype\fP \fIoption-list\fP \fImodifiers\fP
+.LP
+for example,
+.IP
+.nf
+.DT
+\fIvaxuba/foo.c\fP \fBoptional\fP foo \fBdevice-driver\fP
+.LP
+The
+.I type
+is one of
+.B standard
+or
+.BR optional .
+Files marked as standard are included in all system configurations.
+Optional file specifications include a list of one or more system
+options that together require the inclusion of this module.
+The options in the list may be either names of devices that may
+be in the configuration file,
+or the names of system options that may be defined.
+An optional file may be listed multiple times with different options;
+if all of the options for any of the entries are satisfied,
+the module is included.
+.PP
+If a file is specified as a
+.IR device-driver ,
+any special compilation options for device drivers will be invoked.
+On the VAX this results in the use of the
+.B \-i
+option for the C optimizer. This is required when pointer references
+are made to memory locations in the VAX I/O address space.
+.PP
+Two other optional keywords modify the usage of the file.
+.I Config
+understands that certain files are used especially for
+kernel profiling. These files are indicated in the
+.I files
+files with a
+.I profiling-routine
+keyword. For example, the current profiling subroutines
+are sequestered off in a separate file with the following
+entry:
+.IP
+.nf
+.DT
+\fIsys/subr_mcount.c\fP \fBoptional\fP \fBprofiling-routine\fP
+.fi
+.LP
+The
+.I profiling-routine
+keyword forces
+.I config
+not to compile the source file with the
+.B \-pg
+option.
+.PP
+The second keyword which can be of use is the
+.I config-dependent
+keyword. This causes
+.I config
+to compile the indicated module with the global configuration
+parameters. This allows certain modules, such as
+.I machdep.c
+to size system data structures based on the maximum number
+of users configured for the system.
+.NH 2
+Adding device drivers to 4.4BSD
+.PP
+The I/O system and
+.I config
+have been designed to easily allow new device support to be added.
+The system source directories are organized as follows:
+.DS
+.TS
+lw(1.0i) l.
+/sys/h machine independent include files
+/sys/sys machine-independent system source files
+/sys/conf site configuration files and basic templates
+/sys/net network-protocol-independent, but network-related code
+/sys/netinet DARPA Internet code
+/sys/netimp IMP support code
+/sys/netns Xerox NS code
+/sys/vax VAX-specific mainline code
+/sys/vaxif VAX network interface code
+/sys/vaxmba VAX MASSBUS device drivers and related code
+/sys/vaxuba VAX UNIBUS device drivers and related code
+.TE
+.DE
+.PP
+Existing block and character device drivers for the VAX
+reside in ``/sys/vax'', ``/sys/vaxmba'', and ``/sys/vaxuba''. Network
+interface drivers reside in ``/sys/vaxif''. Any new device
+drivers should be placed in the appropriate source code directory
+and named so as not to conflict with existing devices.
+Normally, definitions for things like device registers are placed in
+a separate file in the same directory. For example, the ``dh''
+device driver is named ``dh.c'' and its associated include file is
+named ``dhreg.h''.
+.PP
+Once the source for the device driver has been placed in a directory,
+the file ``/sys/conf/files.machine'', and possibly
+``/sys/conf/devices.machine'' should be modified. The
+.I files
+files in the conf directory contain a line for each C source or binary-only
+file in the system. Those files which are machine independent are
+located in ``/sys/conf/files,'' while machine specific files
+are in ``/sys/conf/files.machine.'' The ``devices.machine'' file
+is used to map device names to major block device numbers. If the device
+driver being added provides support for a new disk
+you will want to modify this file (the format is obvious).
+.PP
+In addition to including the driver in the
+.I files
+file, it must also be added to the device configuration tables. These
+are located in ``/sys/vax/conf.c'', or similar for machines other than
+the VAX. If you don't understand what to add to this file, you should
+study an entry for an existing driver.
+Remember that the position in the
+device table specifies the major device number.
+The block major number is needed in the ``devices.machine'' file
+if the device is a disk.
+.PP
+With the configuration information in place, your configuration
+file appropriately modified, and a system reconfigured and rebooted
+you should incorporate the shell commands needed to install the special
+files in the file system to the file ``/dev/MAKEDEV'' or
+``/dev/MAKEDEV.local''. This is discussed in the document ``Installing
+and Operating 4.4BSD''.
diff --git a/usr.sbin/config/SMM.doc/Makefile b/usr.sbin/config/SMM.doc/Makefile
new file mode 100644
index 0000000..3a2f188
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/Makefile
@@ -0,0 +1,10 @@
+# @(#)Makefile 8.1 (Berkeley) 6/8/93
+
+DIR= smm/02.config
+SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t a.t b.t c.t d.t e.t
+MACROS= -ms
+
+paper.ps: ${SRCS}
+ ${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
+
+.include <bsd.doc.mk>
diff --git a/usr.sbin/config/SMM.doc/a.t b/usr.sbin/config/SMM.doc/a.t
new file mode 100644
index 0000000..dfcb954
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/a.t
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)a.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Grammar
+.bp
+.LG
+.B
+.ce
+APPENDIX A. CONFIGURATION FILE GRAMMAR
+.sp
+.R
+.NL
+.PP
+The following grammar is a compressed form of the actual
+\fIyacc\fP\|(1) grammar used by
+.I config
+to parse configuration files.
+Terminal symbols are shown all in upper case, literals
+are emboldened; optional clauses are enclosed in brackets, ``[''
+and ``]''; zero or more instantiations are denoted with ``*''.
+.sp
+.nf
+.DT
+Configuration ::= [ Spec \fB;\fP ]*
+
+Spec ::= Config_spec
+ | Device_spec
+ | \fBtrace\fP
+ | /* lambda */
+
+/* configuration specifications */
+
+Config_spec ::= \fBmachine\fP ID
+ | \fBcpu\fP ID
+ | \fBoptions\fP Opt_list
+ | \fBident\fP ID
+ | System_spec
+ | \fBtimezone\fP [ \fB\-\fP ] NUMBER [ \fBdst\fP [ NUMBER ] ]
+ | \fBtimezone\fP [ \fB\-\fP ] FPNUMBER [ \fBdst\fP [ NUMBER ] ]
+ | \fBmaxusers\fP NUMBER
+
+/* system configuration specifications */
+
+System_spec ::= \fBconfig\fP ID System_parameter [ System_parameter ]*
+
+System_parameter ::= swap_spec | root_spec | dump_spec | arg_spec
+
+swap_spec ::= \fBswap\fP [ \fBon\fP ] swap_dev [ \fBand\fP swap_dev ]*
+
+swap_dev ::= dev_spec [ \fBsize\fP NUMBER ]
+
+root_spec ::= \fBroot\fP [ \fBon\fP ] dev_spec
+
+dump_spec ::= \fBdumps\fP [ \fBon\fP ] dev_spec
+
+arg_spec ::= \fBargs\fP [ \fBon\fP ] dev_spec
+
+dev_spec ::= dev_name | major_minor
+
+major_minor ::= \fBmajor\fP NUMBER \fBminor\fP NUMBER
+
+dev_name ::= ID [ NUMBER [ ID ] ]
+
+/* option specifications */
+
+Opt_list ::= Option [ \fB,\fP Option ]*
+
+Option ::= ID [ \fB=\fP Opt_value ]
+
+Opt_value ::= ID | NUMBER
+
+Mkopt_list ::= Mkoption [ \fB,\fP Mkoption ]*
+
+Mkoption ::= ID \fB=\fP Opt_value
+
+/* device specifications */
+
+Device_spec ::= \fBdevice\fP Dev_name Dev_info Int_spec
+ | \fBmaster\fP Dev_name Dev_info
+ | \fBdisk\fP Dev_name Dev_info
+ | \fBtape\fP Dev_name Dev_info
+ | \fBcontroller\fP Dev_name Dev_info [ Int_spec ]
+ | \fBpseudo-device\fP Dev [ NUMBER ]
+
+Dev_name ::= Dev NUMBER
+
+Dev ::= \fBuba\fP | \fBmba\fP | ID
+
+Dev_info ::= Con_info [ Info ]*
+
+Con_info ::= \fBat\fP Dev NUMBER
+ | \fBat\fP \fBnexus\fP NUMBER
+
+Info ::= \fBcsr\fP NUMBER
+ | \fBdrive\fP NUMBER
+ | \fBslave\fP NUMBER
+ | \fBflags\fP NUMBER
+
+Int_spec ::= \fBvector\fP ID [ ID ]*
+ | \fBpriority\fP NUMBER
+.fi
+.sp
+.SH
+Lexical Conventions
+.LP
+The terminal symbols are loosely defined as:
+.IP ID
+.br
+One or more alphabetics, either upper or lower case, and underscore,
+``_''.
+.IP NUMBER
+.br
+Approximately the C language specification for an integer number.
+That is, a leading ``0x'' indicates a hexadecimal value,
+a leading ``0'' indicates an octal value, otherwise the number is
+expected to be a decimal value. Hexadecimal numbers may use either
+upper or lower case alphabetics.
+.IP FPNUMBER
+.br
+A floating point number without exponent. That is a number of the
+form ``nnn.ddd'', where the fractional component is optional.
+.LP
+In special instances a question mark, ``?'', can be substituted for
+a ``NUMBER'' token. This is used to effect wildcarding in device
+interconnection specifications.
+.LP
+Comments in configuration files are indicated by a ``#'' character
+at the beginning of the line; the remainder of the line is discarded.
+.LP
+A specification
+is interpreted as a continuation of the previous line
+if the first character of the line is tab.
diff --git a/usr.sbin/config/SMM.doc/b.t b/usr.sbin/config/SMM.doc/b.t
new file mode 100644
index 0000000..7281610
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/b.t
@@ -0,0 +1,137 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)b.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Device Defaulting Rules
+.bp
+.LG
+.B
+.ce
+APPENDIX B. RULES FOR DEFAULTING SYSTEM DEVICES
+.sp
+.R
+.NL
+.PP
+When \fIconfig\fP processes a ``config'' rule which does
+not fully specify the location of the root file system,
+paging area(s), device for system dumps, and device for
+argument list processing it applies a set of rules to
+define those values left unspecified. The following list
+of rules are used in defaulting system devices.
+.IP 1) 3
+If a root device is not specified, the swap
+specification must indicate a ``generic'' system is to be built.
+.IP 2) 3
+If the root device does not specify a unit number, it
+defaults to unit 0.
+.IP 3) 3
+If the root device does not include a partition specification,
+it defaults to the ``a'' partition.
+.IP 4) 3
+If no swap area is specified, it defaults to the ``b''
+partition of the root device.
+.IP 5) 3
+If no device is specified for processing argument lists, the
+first swap partition is selected.
+.IP 6) 3
+If no device is chosen for system dumps, the first swap
+partition is selected (see below to find out where dumps are
+placed within the partition).
+.PP
+The following table summarizes the default partitions selected
+when a device specification is incomplete, e.g. ``hp0''.
+.DS
+.TS
+l l.
+Type Partition
+_
+root ``a''
+swap ``b''
+args ``b''
+dumps ``b''
+.TE
+.DE
+.SH
+Multiple swap/paging areas
+.PP
+When multiple swap partitions are specified, the system treats the
+first specified as a ``primary'' swap area which is always used.
+The remaining partitions are then interleaved into the paging
+system at the time a
+.IR swapon (2)
+system call is made. This is normally done at boot time with
+a call to
+.IR swapon (8)
+from the /etc/rc file.
+.SH
+System dumps
+.PP
+System dumps are automatically taken after a system crash,
+provided the device driver for the ``dumps'' device supports
+this. The dump contains the contents of memory, but not
+the swap areas. Normally the dump device is a disk in
+which case the information is copied to a location at the
+back of the partition. The dump is placed in the back of the
+partition because the primary swap and dump device are commonly
+the same device and this allows the system to be rebooted without
+immediately overwriting the saved information. When a dump has
+occurred, the system variable \fIdumpsize\fP
+is set to a non-zero value indicating the size (in bytes) of
+the dump. The \fIsavecore\fP\|(8)
+program then copies the information from the dump partition to
+a file in a ``crash'' directory and also makes a copy of the
+system which was running at the time of the crash (usually
+``/vmunix''). The offset to the system dump is defined in the
+system variable \fIdumplo\fP (a sector offset from
+the front of the dump partition). The
+.I savecore
+program operates by reading the contents of \fIdumplo\fP, \fIdumpdev\fP,
+and \fIdumpmagic\fP from /dev/kmem, then comparing the value
+of \fIdumpmagic\fP read from /dev/kmem to that located in
+corresponding location in the dump area of the dump partition.
+If a match is found,
+.I savecore
+assumes a crash occurred and reads \fIdumpsize\fP from the dump area
+of the dump partition. This value is then used in copying the
+system dump. Refer to
+\fIsavecore\fP\|(8)
+for more information about its operation.
+.PP
+The value \fIdumplo\fP is calculated to be
+.DS
+\fIdumpdev-size\fP \- \fImemsize\fP
+.DE
+where \fIdumpdev-size\fP is the size of the disk partition
+where system dumps are to be placed, and
+\fImemsize\fP is the size of physical memory.
+If the disk partition is not large enough to hold a full
+dump, \fIdumplo\fP is set to 0 (the start of the partition).
diff --git a/usr.sbin/config/SMM.doc/c.t b/usr.sbin/config/SMM.doc/c.t
new file mode 100644
index 0000000..0f28fda
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/c.t
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)c.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Sample Config Files
+.bp
+.LG
+.B
+.ce
+APPENDIX C. SAMPLE CONFIGURATION FILES
+.sp
+.R
+.NL
+.PP
+The following configuration files are developed in section 5;
+they are included here for completeness.
+.sp 2
+.nf
+.ta 1.5i 2.5i 4.0i
+#
+# ANSEL VAX (a picture perfect machine)
+#
+machine vax
+cpu VAX780
+timezone 8 dst
+ident ANSEL
+maxusers 40
+
+config vmunix root on hp0
+config hpvmunix root on hp0 swap on hp0 and hp2
+config genvmunix swap generic
+
+controller mba0 at nexus ?
+disk hp0 at mba? disk ?
+disk hp1 at mba? disk ?
+controller mba1 at nexus ?
+disk hp2 at mba? disk ?
+disk hp3 at mba? disk ?
+controller uba0 at nexus ?
+controller tm0 at uba? csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba? csr 0160020 vector dhrint dhxint
+device dm0 at uba? csr 0170500 vector dmintr
+device dh1 at uba? csr 0160040 vector dhrint dhxint
+device dh2 at uba? csr 0160060 vector dhrint dhxint
+.bp
+#
+# UCBVAX - Gateway to the world
+#
+machine vax
+cpu "VAX780"
+cpu "VAX750"
+ident UCBVAX
+timezone 8 dst
+maxusers 32
+options INET
+options NS
+
+config vmunix root on hp swap on hp and rk0 and rk1
+config upvmunix root on up
+config hkvmunix root on hk swap on rk0 and rk1
+
+controller mba0 at nexus ?
+controller uba0 at nexus ?
+disk hp0 at mba? drive 0
+disk hp1 at mba? drive 1
+controller sc0 at uba? csr 0176700 vector upintr
+disk up0 at sc0 drive 0
+disk up1 at sc0 drive 1
+controller hk0 at uba? csr 0177440 vector rkintr
+disk rk0 at hk0 drive 0
+disk rk1 at hk0 drive 1
+pseudo-device pty
+pseudo-device loop
+pseudo-device imp
+device acc0 at uba? csr 0167600 vector accrint accxint
+pseudo-device ether
+device ec0 at uba? csr 0164330 vector ecrint eccollide ecxint
+device il0 at uba? csr 0164000 vector ilrint ilcint
diff --git a/usr.sbin/config/SMM.doc/d.t b/usr.sbin/config/SMM.doc/d.t
new file mode 100644
index 0000000..db9ab80
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/d.t
@@ -0,0 +1,272 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)d.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Data Structure Sizing Rules
+.bp
+.LG
+.B
+.ce
+APPENDIX D. VAX KERNEL DATA STRUCTURE SIZING RULES
+.sp
+.R
+.NL
+.PP
+Certain system data structures are sized at compile time
+according to the maximum number of simultaneous users expected,
+while others are calculated at boot time based on the
+physical resources present, e.g. memory. This appendix lists
+both sets of rules and also includes some hints on changing
+built-in limitations on certain data structures.
+.SH
+Compile time rules
+.PP
+The file \fI/sys/conf\|/param.c\fP contains the definitions of
+almost all data structures sized at compile time. This file
+is copied into the directory of each configured system to allow
+configuration-dependent rules and values to be maintained.
+(Each copy normally depends on the copy in /sys/conf,
+and global modifications cause the file to be recopied unless
+the makefile is modified.)
+The rules implied by its contents are summarized below (here
+MAXUSERS refers to the value defined in the configuration file
+in the ``maxusers'' rule).
+Most limits are computed at compile time and stored in global variables
+for use by other modules; they may generally be patched in the system
+binary image before rebooting to test new values.
+.IP \fBnproc\fP
+.br
+The maximum number of processes which may be running at any time.
+It is referred to in other calculations as NPROC and is defined to be
+.DS
+20 + 8 * MAXUSERS
+.DE
+.IP \fBntext\fP
+.br
+The maximum number of active shared text segments.
+The constant is intended to allow for network servers and common commands
+that remain in the table.
+It is defined as
+.DS
+36 + MAXUSERS.
+.DE
+.IP \fBninode\fP
+.br
+The maximum number of files in the file system which may be
+active at any time. This includes files in use by users, as
+well as directory files being read or written by the system
+and files associated with bound sockets in the UNIX IPC domain.
+It is defined as
+.DS
+(NPROC + 16 + MAXUSERS) + 32
+.DE
+.IP \fBnfile\fP
+.br
+The number of ``file table'' structures. One file
+table structure is used for each open, unshared, file descriptor.
+Multiple file descriptors may reference a single file table
+entry when they are created through a \fIdup\fP call, or as the
+result of a \fIfork\fP. This is defined to be
+.DS
+16 * (NPROC + 16 + MAXUSERS) / 10 + 32
+.DE
+.IP \fBncallout\fP
+.br
+The number of ``callout'' structures. One callout
+structure is used per internal system event handled with
+a timeout. Timeouts are used for terminal delays,
+watchdog routines in device drivers, protocol timeout processing, etc.
+This is defined as
+.DS
+16 + NPROC
+.DE
+.IP \fBnclist\fP
+.br
+The number of ``c-list'' structures. C-list structures are
+used in terminal I/O, and currently each holds 60 characters.
+Their number is defined as
+.DS
+60 + 12 * MAXUSERS
+.DE
+.IP \fBnmbclusters\fP
+.br
+The maximum number of pages which may be allocated by the network.
+This is defined as 256 (a quarter megabyte of memory) in /sys/h/mbuf.h.
+In practice, the network rarely uses this much memory. It starts off
+by allocating 8 kilobytes of memory, then requesting more as
+required. This value represents an upper bound.
+.IP \fBnquota\fP
+.br
+The number of ``quota'' structures allocated. Quota structures
+are present only when disc quotas are configured in the system. One
+quota structure is kept per user. This is defined to be
+.DS
+(MAXUSERS * 9) / 7 + 3
+.DE
+.IP \fBndquot\fP
+.br
+The number of ``dquot'' structures allocated. Dquot structures
+are present only when disc quotas are configured in the system.
+One dquot structure is required per user, per active file system quota.
+That is, when a user manipulates a file on a file system on which
+quotas are enabled, the information regarding the user's quotas on
+that file system must be in-core. This information is cached, so
+that not all information must be present in-core all the time.
+This is defined as
+.DS
+NINODE + (MAXUSERS * NMOUNT) / 4
+.DE
+where NMOUNT is the maximum number of mountable file systems.
+.LP
+In addition to the above values, the system page tables (used to
+map virtual memory in the kernel's address space) are sized at
+compile time by the SYSPTSIZE definition in the file /sys/vax/vmparam.h.
+This is defined to be
+.DS
+20 + MAXUSERS
+.DE
+pages of page tables.
+Its definition affects
+the size of many data structures allocated at boot time because
+it constrains the amount of virtual memory which may be addressed
+by the running system. This is often the limiting factor
+in the size of the buffer cache, in which case a message is printed
+when the system configures at boot time.
+.SH
+Run-time calculations
+.PP
+The most important data structures sized at run-time are those used in
+the buffer cache. Allocation is done by allocating physical memory
+(and system virtual memory) immediately after the system
+has been started up; look in the file /sys/vax/machdep.c.
+The amount of physical memory which may be allocated to the buffer
+cache is constrained by the size of the system page tables, among
+other things. While the system may calculate
+a large amount of memory to be allocated to the buffer cache,
+if the system page
+table is too small to map this physical
+memory into the virtual address space
+of the system, only as much as can be mapped will be used.
+.PP
+The buffer cache is comprised of a number of ``buffer headers''
+and a pool of pages attached to these headers. Buffer headers
+are divided into two categories: those used for swapping and
+paging, and those used for normal file I/O. The system tries
+to allocate 10% of the first two megabytes and 5% of the remaining
+available physical memory for the buffer
+cache (where \fIavailable\fP does not count that space occupied by
+the system's text and data segments). If this results in fewer
+than 16 pages of memory allocated, then 16 pages are allocated.
+This value is kept in the initialized variable \fIbufpages\fP
+so that it may be patched in the binary image (to allow tuning
+without recompiling the system),
+or the default may be overridden with a configuration-file option.
+For example, the option \fBoptions BUFPAGES="3200"\fP
+causes 3200 pages (3.2M bytes) to be used by the buffer cache.
+A sufficient number of file I/O buffer headers are then allocated
+to allow each to hold 2 pages each.
+Each buffer maps 8K bytes.
+If the number of buffer pages is larger than can be mapped
+by the buffer headers, the number of pages is reduced.
+The number of buffer headers allocated
+is stored in the global variable \fInbuf\fP,
+which may be patched before the system is booted.
+The system option \fBoptions NBUF="1000"\fP forces the allocation
+of 1000 buffer headers.
+Half as many swap I/O buffer headers as file I/O buffers
+are allocated,
+but no more than 256.
+.SH
+System size limitations
+.PP
+As distributed, the sum of the virtual sizes of the core-resident
+processes is limited to 256M bytes. The size of the text
+segment of a single process is currently limited to 6M bytes.
+It may be increased to no greater than the data segment size limit
+(see below) by redefining MAXTSIZ.
+This may be done with a configuration file option,
+e.g. \fBoptions MAXTSIZ="(10*1024*1024)"\fP
+to set the limit to 10 million bytes.
+Other per-process limits discussed here may be changed with similar options
+with names given in parentheses.
+Soft, user-changeable limits are set to 512K bytes for stack (DFLSSIZ)
+and 6M bytes for the data segment (DFLDSIZ) by default;
+these may be increased up to the hard limit
+with the \fIsetrlimit\fP\|(2) system call.
+The data and stack segment size hard limits are set by a system configuration
+option to one of 17M, 33M or 64M bytes.
+One of these sizes is chosen based on the definition of MAXDSIZ;
+with no option, the limit is 17M bytes; with an option
+\fBoptions MAXDSIZ="(32*1024*1024)"\fP (or any value between 17M and 33M),
+the limit is increased to 33M bytes, and values larger than 33M
+result in a limit of 64M bytes.
+You must be careful in doing this that you have adequate paging space.
+As normally configured , the system has 16M or 32M bytes per paging area,
+depending on disk size.
+The best way to get more space is to provide multiple, thereby
+interleaved, paging areas.
+Increasing the virtual memory limits results in interleaving of
+swap space in larger sections (from 500K bytes to 1M or 2M bytes).
+.PP
+By default, the virtual memory system allocates enough memory
+for system page tables mapping user page tables
+to allow 256 megabytes of simultaneous active virtual memory.
+That is, the sum of the virtual memory sizes of all (completely- or partially-)
+resident processes can not exceed this limit.
+If the limit is exceeded, some process(es) must be swapped out.
+To increase the amount of resident virtual space possible,
+you can alter the constant USRPTSIZE (in
+/sys/vax/vmparam.h).
+Each page of system page tables allows 8 megabytes of user virtual memory.
+.PP
+Because the file system block numbers are stored in
+page table \fIpg_blkno\fP
+entries, the maximum size of a file system is limited to
+2^24 1024 byte blocks. Thus no file system can be larger than 8 gigabytes.
+.PP
+The number of mountable file systems is set at 20 by the definition
+of NMOUNT in /sys/h/param.h.
+This should be sufficient; if not, the value can be increased up to 255.
+If you have many disks, it makes sense to make some of
+them single file systems, and the paging areas don't count in this total.
+.PP
+The limit to the number of files that a process may have open simultaneously
+is set to 64.
+This limit is set by the NOFILE definition in /sys/h/param.h.
+It may be increased arbitrarily, with the caveat that the user structure
+expands by 5 bytes for each file, and thus UPAGES (/sys/vax/machparam.h)
+must be increased accordingly.
+.PP
+The amount of physical memory is currently limited to 64 Mb
+by the size of the index fields in the core-map (/sys/h/cmap.h).
+The limit may be increased by following instructions in that file
+to enlarge those fields.
diff --git a/usr.sbin/config/SMM.doc/e.t b/usr.sbin/config/SMM.doc/e.t
new file mode 100644
index 0000000..0a9505b
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/e.t
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)e.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Network configuration options
+.bp
+.LG
+.B
+.ce
+APPENDIX E. NETWORK CONFIGURATION OPTIONS
+.sp
+.R
+.NL
+.PP
+The network support in the kernel is self-configuring
+according to the protocol support options (INET and NS) and the network
+hardware discovered during autoconfiguration.
+There are several changes that may be made to customize network behavior
+due to local restrictions.
+Within the Internet protocol routines, the following options
+set in the system configuration file are supported:
+.IP \fBGATEWAY\fP
+.br
+The machine is to be used as a gateway.
+This option currently makes only minor changes.
+First, the size of the network routing hash table is increased.
+Secondly, machines that have only a single hardware network interface
+will not forward IP packets; without this option, they will also refrain
+from sending any error indication to the source of unforwardable packets.
+Gateways with only a single interface are assumed to have missing
+or broken interfaces, and will return ICMP unreachable errors to hosts
+sending them packets to be forwarded.
+.IP \fBTCP_COMPAT_42\fP
+.br
+This option forces the system to limit its initial TCP sequence numbers
+to positive numbers.
+Without this option, 4.4BSD systems may have problems with TCP connections
+to 4.2BSD systems that connect but never transfer data.
+The problem is a bug in the 4.2BSD TCP.
+.IP \fBIPFORWARDING\fP
+.br
+Normally, 4.4BSD machines with multiple network interfaces
+will forward IP packets received that should be resent to another host.
+If the line ``options IPFORWARDING="0"'' is in the system configuration
+file, IP packet forwarding will be disabled.
+.IP \fBIPSENDREDIRECTS\fP
+.br
+When forwarding IP packets, 4.4BSD IP will note when a packet is forwarded
+using the same interface on which it arrived.
+When this is noted, if the source machine is on the directly-attached
+network, an ICMP redirect is sent to the source host.
+If the packet was forwarded using a route to a host or to a subnet,
+a host redirect is sent, otherwise a network redirect is sent.
+The generation of redirects may be inhibited with the configuration
+option ``options IPSENDREDIRECTS="0".''
+.br
+.IP \fBSUBNETSARELOCAL\fP
+TCP calculates a maximum segment size to use for each connection,
+and sends no datagrams larger than that size.
+This size will be no larger than that supported on the outgoing
+interface.
+Furthermore, if the destination is not on the local network,
+the size will be no larger than 576 bytes.
+For this test, other subnets of a directly-connected subnetted
+network are considered to be local unless the line
+``options SUBNETSARELOCAL="0"'' is used in the system configuration file.
+.LP
+The following options are supported by the Xerox NS protocols:
+.IP \fBNSIP\fP
+.br
+This option allows NS IDP datagrams to be encapsulated in Internet IP
+packets for transmission to a collaborating NSIP host.
+This may be used to pass IDP packets through IP-only link layer networks.
+See
+.IR nsip (4P)
+for details.
+.IP \fBTHREEWAYSHAKE\fP
+.br
+The NS Sequenced Packet Protocol does not require a three-way handshake
+before considering a connection to be in the established state.
+(A three-way handshake consists of a connection request, an acknowledgement
+of the request along with a symmetrical opening indication,
+and then an acknowledgement of the reciprocal opening packet.)
+This option forces a three-way handshake before data may be transmitted
+on Sequenced Packet sockets.
diff --git a/usr.sbin/config/SMM.doc/spell.ok b/usr.sbin/config/SMM.doc/spell.ok
new file mode 100644
index 0000000..4132452
--- /dev/null
+++ b/usr.sbin/config/SMM.doc/spell.ok
@@ -0,0 +1,306 @@
+ACC
+ANSEL
+ARP
+Autoconfiguration
+BUFPAGES
+CANTWAIT
+CH
+COMPAT
+CSS
+Co
+Config
+Config''SMM:2
+DCLR
+DFLDSIZ
+DFLSSIZ
+DFUNNY
+DHAHA
+DMA
+Dev
+Dquot
+ECC
+EMULEX
+Emulex
+Ethernet
+FPNUMBER
+FUNNY,HAHA
+HAVEBDP
+ICMP
+IDP
+IE
+INET
+IP
+IPC
+IPFORWARDING
+IPL
+IPSENDREDIRECTS
+Info
+Karels
+LH
+Leffler
+MAKEDEV
+MAKEDEV.local
+MASSBUS
+MAXDSIZ
+MAXTSIZ
+Makefile
+Mb
+MicroVAX
+Mkopt
+Mkoption
+NBUF
+NEED16
+NEEDBDP
+NINODE
+NMOUNT
+NOFILE
+NPROC
+NS
+NSC
+NSIP
+NUP
+PST
+RCS
+RDY
+RH
+RK07
+RK611
+SCCS
+SITENAME
+SMM:2
+SUBNETSARELOCAL
+SYSPTSIZE
+TCP
+THREEWAYSHAKE
+Timezone
+UCBVAX
+UDP
+UNIBUS
+UPAGES
+UPCS2
+USRPTSIZE
+VAX
+VAX630
+VAX730
+VAX750
+VAX780
+VAX8600
+VAXWELL
+VAXen
+Vax
+Vaxwell
+acc0
+accrint
+accxint
+addr
+arg
+args
+assym.s
+autoconfiguration
+autoconfigure
+autoconfigured
+backpointer
+badaddr
+blkno
+br
+br5
+buf
+bufpages
+buses
+caddr
+callout
+catchall
+cmap.h
+cmd
+conf
+conf.c
+config
+csr
+ct.c
+ctlr
+cvec
+datagrams
+define''s
+dev
+devices.machine
+dgo
+dh.c
+dh0
+dh1
+dh2
+dhreg.h
+dhrint
+dhxint
+dinfo
+dk
+dk.h
+dm0
+dmintr
+dname
+dquot
+dst
+dumpdev
+dumplo
+dumpmagic
+dumpsize
+dz.c
+dz0
+dzrint
+dzxint
+ec0
+eccollide
+ecrint
+ecxint
+endif
+es
+files.machine
+filesystem
+foo
+foo.c
+genvmunix
+gettimeofday
+gigabytes
+gprof
+hardwired
+hd
+hk
+hk0
+hkvmunix
+howmany
+hp0
+hp0b
+hp1
+hp2
+hp3
+hpvmunix
+ht0
+hz
+ident
+ifdef
+ifndef
+il0
+ilcint
+ilrint
+info
+intr
+ioconf.c
+kgmon
+linterrs
+loopback
+machdep.c
+machparam.h
+makefile
+makelinks
+makeoptions
+maxusers
+mba
+mba0
+mba1
+mbuf.h
+mcount.c
+memsize
+minfo
+mname
+moniker
+mspw
+nbuf
+ncallout
+nclist
+ndquot
+ndrive
+netimp
+netinet
+netns
+netstat
+nexi
+nexus
+nfile
+ninode
+nmbclusters
+nnn.ddd
+nproc
+nquota
+nsip
+ntext
+optionlist
+param.c
+param.h
+pathnames
+pg
+physaddr
+pty
+rc
+reg
+rk.c
+rk0
+rk1
+rkintr
+savecore
+sc
+sc0
+sc1
+scdriver
+setrlimit
+sizeof
+softc
+source.c
+subr
+swapxxx.c
+sysname
+te0
+te1
+timezone
+tm0
+tmintr
+tu0
+uba
+uba.c
+uba0
+ubago
+uballoc
+ubamem
+ubanum
+ubareg.h
+ubarelse
+ubavar.h
+ubglue.s
+ubinfo
+ud
+ui
+um
+up.c
+up0
+up1
+up2
+upaddr
+upattach
+upba
+upcs1
+upcs2
+updevice
+updgo
+updinfo
+updtab
+upintr
+upip
+upmaptype
+upminfo
+upprobe
+upslave
+upstd
+upvmunix
+upwatch
+upwstart
+value,name2
+value2
+vax
+vaxif
+vaxmba
+vaxuba
+vmparam.h
+vmunix
+wildcard
+wildcarded
+wildcarding
+xclu
+xxx
diff --git a/usr.sbin/config/config.8 b/usr.sbin/config/config.8
new file mode 100644
index 0000000..aef26a2
--- /dev/null
+++ b/usr.sbin/config/config.8
@@ -0,0 +1,174 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)config.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt CONFIG 8
+.Os BSD 4
+.Sh NAME
+.Nm config
+.Nd build system configuration files
+.Sh SYNOPSIS
+.Nm config
+.Op Fl p
+.Ar system_name
+.Sh DESCRIPTION
+.Pp
+This is the old version of the
+.Nm config
+program.
+It understands the old autoconfiguration scheme
+used on the HP300, DECstation, and derivative platforms.
+The new version of config is used with the
+SPARC and i386 platforms.
+Only the version of
+.Nm config
+applicable to the architecture that you are running
+will be installed on your machine.
+.Pp
+.Nm Config
+builds a set of system configuration files from the file
+.Ar SYSTEM_NAME
+which describes
+the system to configure.
+A second file
+tells
+.Nm config
+what files are needed to generate a system and
+can be augmented by configuration specific set of files
+that give alternate files for a specific machine.
+(see the
+.Sx FILES
+section below)
+.Pp
+Available option and operand:
+.Pp
+.Bl -tag -width SYSTEM_NAME
+.It Fl p
+If the
+.Fl p
+option is supplied,
+.Nm config
+will configure a system for profiling; for example,
+.Xr kgmon 8
+and
+.Xr gprof 1 .
+.It Ar SYSTEM_NAME
+specifies the name of the system configuration file
+containing device specifications, configuration options
+and other system parameters for one system configuration.
+.El
+.Pp
+.Nm Config
+should be run from the
+.Pa conf
+subdirectory of the system source (usually
+.Pa /sys/conf ) .
+.Nm Config
+assumes the directory
+.Pa ../SYSTEM_NAME
+exists and places all output files there.
+The output of
+.Nm config
+consists of a number of files; for the
+.Tn VAX ,
+they are:
+.Pa ioconf.c ,
+a description
+of what I/O devices are attached to the system;
+.Pa ubglue.s ,
+a set of interrupt service routines for devices
+attached to the
+.Tn UNIBUS ;
+.Pa ubvec.s ,
+offsets into a structure used for counting per-device interrupts;
+.Pa Makefile ,
+used by
+.Xr make 1
+in building the system;
+header files,
+definitions of
+the number of various devices that will be compiled into the system;
+swap configuration files,
+definitions for
+the disk areas to be used for swapping, the root file system,
+argument processing, and system dumps.
+.Pp
+After running
+.Nm config ,
+it is necessary to run
+.Dq Li make depend
+in the directory where the new makefile
+was created.
+.Nm Config
+prints a reminder of this when it completes.
+.Pp
+If any other error messages are produced by
+.Nm config ,
+the problems in the configuration file should be corrected and
+.Nm config
+should be run again.
+Attempts to compile a system that had configuration errors
+are likely to fail.
+.Sh FILES
+.Bl -tag -width /sys/conf/Makefile.vax -compact
+.It Pa /sys/conf/Makefile.vax
+generic makefile for the
+.Tn VAX
+.It Pa /sys/conf/files
+list of common files system is built from
+.It Pa /sys/conf/files.vax
+list of
+.Tn VAX
+specific files
+.It Pa /sys/conf/devices.vax
+name to major device mapping file for the
+.Tn VAX
+.It Pa /sys/conf/files. Ns Em ERNIE
+list of files specific to
+.Em ERNIE
+system
+.El
+.Sh SEE ALSO
+The SYNOPSIS portion of each device in section 4.
+.Rs
+.%T "Building 4.3 BSD UNIX System with Config"
+.Re
+.sp
+.Xr config.new 8
+.Sh BUGS
+The line numbers reported in error messages are usually off by one.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.1 .
diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h
new file mode 100644
index 0000000..6cd4d7f
--- /dev/null
+++ b/usr.sbin/config/config.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 1980, 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.
+ *
+ * @(#)config.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Config.
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NODEV ((dev_t)-1)
+
+struct file_list {
+ struct file_list *f_next;
+ char *f_fn; /* the name */
+ u_char f_type; /* see below */
+ u_char f_flags; /* see below */
+ char *f_special; /* special make rule if present */
+ char *f_needs;
+ /*
+ * Random values:
+ * swap space parameters for swap areas
+ * root device, etc. for system specifications
+ */
+ union {
+ struct { /* when swap specification */
+ dev_t fuw_swapdev;
+ int fuw_swapsize;
+ int fuw_swapflag;
+ } fuw;
+ struct { /* when system specification */
+ dev_t fus_rootdev;
+ dev_t fus_dumpdev;
+ } fus;
+ struct { /* when component dev specification */
+ dev_t fup_compdev;
+ int fup_compinfo;
+ } fup;
+ } fun;
+#define f_swapdev fun.fuw.fuw_swapdev
+#define f_swapsize fun.fuw.fuw_swapsize
+#define f_swapflag fun.fuw.fuw_swapflag
+#define f_rootdev fun.fus.fus_rootdev
+#define f_dumpdev fun.fus.fus_dumpdev
+#define f_compdev fun.fup.fup_compdev
+#define f_compinfo fun.fup.fup_compinfo
+};
+
+/*
+ * Types.
+ */
+#define DRIVER 1
+#define NORMAL 2
+#define INVISIBLE 3
+#define PROFILING 4
+#define SYSTEMSPEC 5
+#define SWAPSPEC 6
+#define COMPDEVICE 7
+#define COMPSPEC 8
+
+/*
+ * Attributes (flags).
+ */
+#define CONFIGDEP 1
+
+struct idlst {
+ char *id;
+ struct idlst *id_next;
+};
+
+struct device {
+ int d_type; /* CONTROLLER, DEVICE, bus adaptor */
+ struct device *d_conn; /* what it is connected to */
+ char *d_name; /* name of device (e.g. rk11) */
+ struct idlst *d_vec; /* interrupt vectors */
+ int d_pri; /* interrupt priority */
+ int d_addr; /* address of csr */
+ int d_unit; /* unit number */
+ int d_drive; /* drive number */
+ int d_slave; /* slave number */
+#define QUES -1 /* -1 means '?' */
+#define UNKNOWN -2 /* -2 means not set yet */
+ int d_dk; /* if init 1 set to number for iostat */
+ int d_flags; /* flags for device init */
+ char *d_port; /* io port base manifest constant */
+ int d_portn; /* io port base (if number not manifest) */
+ char *d_mask; /* interrupt mask */
+ int d_maddr; /* io memory base */
+ int d_msize; /* io memory size */
+ int d_drq; /* DMA request */
+ int d_irq; /* interrupt request */
+ struct device *d_next; /* Next one in list */
+};
+#define TO_NEXUS (struct device *)-1
+#define TO_VBA (struct device *)-2
+
+struct config {
+ char *c_dev;
+ char *s_sysname;
+};
+
+/*
+ * Config has a global notion of which machine type is
+ * being used. It uses the name of the machine in choosing
+ * files and directories. Thus if the name of the machine is ``vax'',
+ * it will build from ``Makefile.vax'' and use ``../vax/inline''
+ * in the makerules, etc.
+ */
+int machine;
+char *machinename;
+#define MACHINE_VAX 1
+#define MACHINE_TAHOE 2
+#define MACHINE_HP300 3
+#define MACHINE_I386 4
+#define MACHINE_MIPS 5
+#define MACHINE_PMAX 6
+#define MACHINE_LUNA68K 7
+#define MACHINE_NEWS3400 8
+
+/*
+ * For each machine, a set of CPU's may be specified as supported.
+ * These and the options (below) are put in the C flags in the makefile.
+ */
+struct cputype {
+ char *cpu_name;
+ struct cputype *cpu_next;
+} *cputype;
+
+/*
+ * A set of options may also be specified which are like CPU types,
+ * but which may also specify values for the options.
+ * A separate set of options may be defined for make-style options.
+ */
+struct opt {
+ char *op_name;
+ char *op_value;
+ struct opt *op_next;
+} *opt, *mkopt;
+
+char *ident;
+char *ns();
+char *tc();
+char *qu();
+char *get_word();
+char *get_quoted_word();
+char *path();
+char *raise();
+
+int do_trace;
+
+#if MACHINE_VAX
+int seen_mba, seen_uba;
+#endif
+#if MACHINE_TAHOE
+int seen_vba;
+#endif
+#if MACHINE_I386
+int seen_isa;
+#endif
+int seen_cd;
+
+struct device *connect();
+struct device *dtab;
+dev_t nametodev();
+char *devtoname();
+
+char errbuf[80];
+int yyline;
+
+struct file_list *ftab, *conf_list, **confp, *comp_list, **compp;
+
+int zone, hadtz;
+int dst;
+int hz;
+int profiling;
+int debugging;
+
+int maxusers;
+
+#define eq(a,b) (!strcmp(a,b))
diff --git a/usr.sbin/config/config.y b/usr.sbin/config/config.y
new file mode 100644
index 0000000..6784d9e
--- /dev/null
+++ b/usr.sbin/config/config.y
@@ -0,0 +1,1109 @@
+%union {
+ char *str;
+ int val;
+ struct file_list *file;
+ struct idlst *lst;
+}
+
+%token AND
+%token ANY
+%token ARGS
+%token AT
+%token BIO
+%token COMMA
+%token CONFIG
+%token CONTROLLER
+%token CPU
+%token CSR
+%token DEVICE
+%token DISK
+%token DRIVE
+%token DRQ
+%token DST
+%token DUMPS
+%token EQUALS
+%token FLAGS
+%token HZ
+%token IDENT
+%token INTERLEAVE
+%token IOMEM
+%token IOSIZ
+%token IRQ
+%token MACHINE
+%token MAJOR
+%token MASTER
+%token MAXUSERS
+%token MINOR
+%token MINUS
+%token NET
+%token NEXUS
+%token ON
+%token OPTIONS
+%token MAKEOPTIONS
+%token PORT
+%token PRIORITY
+%token PSEUDO_DEVICE
+%token ROOT
+%token SEMICOLON
+%token SEQUENTIAL
+%token SIZE
+%token SLAVE
+%token SWAP
+%token TIMEZONE
+%token TTY
+%token TRACE
+%token VECTOR
+
+%token <str> ID
+%token <val> NUMBER
+%token <val> FPNUMBER
+
+%type <str> Save_id
+%type <str> Opt_value
+%type <str> Dev
+%type <lst> Id_list
+%type <val> optional_size
+%type <val> optional_sflag
+%type <str> device_name
+%type <val> major_minor
+%type <val> arg_device_spec
+%type <val> root_device_spec
+%type <val> dump_device_spec
+%type <file> swap_device_spec
+%type <file> comp_device_spec
+
+%{
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)config.y 8.1 (Berkeley) 6/6/93
+ */
+
+#include "config.h"
+#include <ctype.h>
+#include <stdio.h>
+
+struct device cur;
+struct device *curp = 0;
+char *temp_id;
+char *val_id;
+
+%}
+%%
+Configuration:
+ Many_specs
+ = { verifysystemspecs(); }
+ ;
+
+Many_specs:
+ Many_specs Spec
+ |
+ /* lambda */
+ ;
+
+Spec:
+ Device_spec SEMICOLON
+ = { newdev(&cur); } |
+ Config_spec SEMICOLON
+ |
+ TRACE SEMICOLON
+ = { do_trace = !do_trace; } |
+ SEMICOLON
+ |
+ error SEMICOLON
+ ;
+
+Config_spec:
+ MACHINE Save_id
+ = {
+ if (!strcmp($2, "vax")) {
+ machine = MACHINE_VAX;
+ machinename = "vax";
+ } else if (!strcmp($2, "tahoe")) {
+ machine = MACHINE_TAHOE;
+ machinename = "tahoe";
+ } else if (!strcmp($2, "hp300")) {
+ machine = MACHINE_HP300;
+ machinename = "hp300";
+ } else if (!strcmp($2, "i386")) {
+ machine = MACHINE_I386;
+ machinename = "i386";
+ } else if (!strcmp($2, "mips")) {
+ machine = MACHINE_MIPS;
+ machinename = "mips";
+ } else if (!strcmp($2, "pmax")) {
+ machine = MACHINE_PMAX;
+ machinename = "pmax";
+ } else if (!strcmp($2, "luna68k")) {
+ machine = MACHINE_LUNA68K;
+ machinename = "luna68k";
+ } else if (!strcmp($2, "news3400")) {
+ machine = MACHINE_NEWS3400;
+ machinename = "news3400";
+ } else
+ yyerror("Unknown machine type");
+ } |
+ CPU Save_id
+ = {
+ struct cputype *cp =
+ (struct cputype *)malloc(sizeof (struct cputype));
+ cp->cpu_name = ns($2);
+ cp->cpu_next = cputype;
+ cputype = cp;
+ free(temp_id);
+ } |
+ OPTIONS Opt_list
+ |
+ MAKEOPTIONS Mkopt_list
+ |
+ IDENT ID
+ = { ident = ns($2); } |
+ System_spec
+ |
+ HZ NUMBER
+ = { hz = $2; }|
+ TIMEZONE NUMBER
+ = { zone = 60 * $2; check_tz(); } |
+ TIMEZONE NUMBER DST NUMBER
+ = { zone = 60 * $2; dst = $4; check_tz(); } |
+ TIMEZONE NUMBER DST
+ = { zone = 60 * $2; dst = 1; check_tz(); } |
+ TIMEZONE FPNUMBER
+ = { zone = $2; check_tz(); } |
+ TIMEZONE FPNUMBER DST NUMBER
+ = { zone = $2; dst = $4; check_tz(); } |
+ TIMEZONE FPNUMBER DST
+ = { zone = $2; dst = 1; check_tz(); } |
+ TIMEZONE MINUS NUMBER
+ = { zone = -60 * $3; check_tz(); } |
+ TIMEZONE MINUS NUMBER DST NUMBER
+ = { zone = -60 * $3; dst = $5; check_tz(); } |
+ TIMEZONE MINUS NUMBER DST
+ = { zone = -60 * $3; dst = 1; check_tz(); } |
+ TIMEZONE MINUS FPNUMBER
+ = { zone = -$3; check_tz(); } |
+ TIMEZONE MINUS FPNUMBER DST NUMBER
+ = { zone = -$3; dst = $5; check_tz(); } |
+ TIMEZONE MINUS FPNUMBER DST
+ = { zone = -$3; dst = 1; check_tz(); } |
+ MAXUSERS NUMBER
+ = { maxusers = $2; };
+
+System_spec:
+ System_id System_parameter_list
+ = { checksystemspec(*confp); }
+ ;
+
+System_id:
+ CONFIG Save_id
+ = { mkconf($2); }
+ ;
+
+System_parameter_list:
+ System_parameter_list System_parameter
+ | System_parameter
+ ;
+
+System_parameter:
+ swap_spec
+ | root_spec
+ | dump_spec
+ | arg_spec
+ ;
+
+swap_spec:
+ SWAP optional_on swap_device_list
+ ;
+
+swap_device_list:
+ swap_device_list AND swap_device
+ | swap_device
+ ;
+
+swap_device:
+ swap_device_spec optional_size optional_sflag
+ = { mkswap(*confp, $1, $2, $3); }
+ ;
+
+swap_device_spec:
+ device_name
+ = {
+ struct file_list *fl = newflist(SWAPSPEC);
+
+ if (eq($1, "generic"))
+ fl->f_fn = $1;
+ else {
+ fl->f_swapdev = nametodev($1, 0, 'b');
+ fl->f_fn = devtoname(fl->f_swapdev);
+ }
+ $$ = fl;
+ }
+ | major_minor
+ = {
+ struct file_list *fl = newflist(SWAPSPEC);
+
+ fl->f_swapdev = $1;
+ fl->f_fn = devtoname($1);
+ $$ = fl;
+ }
+ ;
+
+root_spec:
+ ROOT optional_on root_device_spec
+ = {
+ struct file_list *fl = *confp;
+
+ if (fl && fl->f_rootdev != NODEV)
+ yyerror("extraneous root device specification");
+ else
+ fl->f_rootdev = $3;
+ }
+ ;
+
+root_device_spec:
+ device_name
+ = { $$ = nametodev($1, 0, 'a'); }
+ | major_minor
+ ;
+
+dump_spec:
+ DUMPS optional_on dump_device_spec
+ = {
+ struct file_list *fl = *confp;
+
+ if (fl && fl->f_dumpdev != NODEV)
+ yyerror("extraneous dump device specification");
+ else
+ fl->f_dumpdev = $3;
+ }
+
+ ;
+
+dump_device_spec:
+ device_name
+ = { $$ = nametodev($1, 0, 'b'); }
+ | major_minor
+ ;
+
+arg_spec:
+ ARGS optional_on arg_device_spec
+ = { yyerror("arg device specification obsolete, ignored"); }
+ ;
+
+arg_device_spec:
+ device_name
+ = { $$ = nametodev($1, 0, 'b'); }
+ | major_minor
+ ;
+
+major_minor:
+ MAJOR NUMBER MINOR NUMBER
+ = { $$ = makedev($2, $4); }
+ ;
+
+optional_on:
+ ON
+ | /* empty */
+ ;
+
+optional_size:
+ SIZE NUMBER
+ = { $$ = $2; }
+ | /* empty */
+ = { $$ = 0; }
+ ;
+
+optional_sflag:
+ SEQUENTIAL
+ = { $$ = 2; }
+ | /* empty */
+ = { $$ = 0; }
+ ;
+
+device_name:
+ Save_id
+ = { $$ = $1; }
+ | Save_id NUMBER
+ = {
+ char buf[80];
+
+ (void) sprintf(buf, "%s%d", $1, $2);
+ $$ = ns(buf); free($1);
+ }
+ | Save_id NUMBER ID
+ = {
+ char buf[80];
+
+ (void) sprintf(buf, "%s%d%s", $1, $2, $3);
+ $$ = ns(buf); free($1);
+ }
+ ;
+
+Opt_list:
+ Opt_list COMMA Option
+ |
+ Option
+ ;
+
+Option:
+ Save_id
+ = {
+ struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+ op->op_name = ns($1);
+ op->op_next = opt;
+ op->op_value = 0;
+ opt = op;
+ free(temp_id);
+ } |
+ Save_id EQUALS Opt_value
+ = {
+ struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+ op->op_name = ns($1);
+ op->op_next = opt;
+ op->op_value = ns($3);
+ opt = op;
+ free(temp_id);
+ free(val_id);
+ } ;
+
+Opt_value:
+ ID
+ = { $$ = val_id = ns($1); } |
+ NUMBER
+ = {
+ char nb[16];
+ (void) sprintf(nb, "%d", $1);
+ $$ = val_id = ns(nb);
+ } ;
+
+
+Save_id:
+ ID
+ = { $$ = temp_id = ns($1); }
+ ;
+
+Mkopt_list:
+ Mkopt_list COMMA Mkoption
+ |
+ Mkoption
+ ;
+
+Mkoption:
+ Save_id EQUALS Opt_value
+ = {
+ struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+ op->op_name = ns($1);
+ op->op_next = mkopt;
+ op->op_value = ns($3);
+ mkopt = op;
+ free(temp_id);
+ free(val_id);
+ } ;
+
+Dev:
+ ID
+ = { $$ = ns($1); }
+ ;
+
+Device_spec:
+ DEVICE Dev_name Dev_info Int_spec
+ = { cur.d_type = DEVICE; } |
+ MASTER Dev_name Dev_info Int_spec
+ = { cur.d_type = MASTER; } |
+ DISK Dev_name Dev_info Int_spec
+ = { cur.d_dk = 1; cur.d_type = DEVICE; } |
+ CONTROLLER Dev_name Dev_info Int_spec
+ = { cur.d_type = CONTROLLER; } |
+ PSEUDO_DEVICE Init_dev Dev
+ = {
+ cur.d_name = $3;
+ cur.d_type = PSEUDO_DEVICE;
+ } |
+ PSEUDO_DEVICE Init_dev Dev NUMBER
+ = {
+ cur.d_name = $3;
+ cur.d_type = PSEUDO_DEVICE;
+ cur.d_slave = $4;
+ } |
+ PSEUDO_DEVICE Dev_name Cdev_init Cdev_info
+ = {
+ if (!eq(cur.d_name, "cd"))
+ yyerror("improper spec for pseudo-device");
+ seen_cd = 1;
+ cur.d_type = DEVICE;
+ verifycomp(*compp);
+ };
+
+Cdev_init:
+ /* lambda */
+ = { mkcomp(&cur); };
+
+Cdev_info:
+ optional_on comp_device_list comp_option_list
+ ;
+
+comp_device_list:
+ comp_device_list AND comp_device
+ | comp_device
+ ;
+
+comp_device:
+ comp_device_spec
+ = { addcomp(*compp, $1); }
+ ;
+
+comp_device_spec:
+ device_name
+ = {
+ struct file_list *fl = newflist(COMPSPEC);
+
+ fl->f_compdev = nametodev($1, 0, 'c');
+ fl->f_fn = devtoname(fl->f_compdev);
+ $$ = fl;
+ }
+ | major_minor
+ = {
+ struct file_list *fl = newflist(COMPSPEC);
+
+ fl->f_compdev = $1;
+ fl->f_fn = devtoname($1);
+ $$ = fl;
+ }
+ ;
+
+comp_option_list:
+ comp_option_list comp_option
+ |
+ /* lambda */
+ ;
+
+comp_option:
+ INTERLEAVE NUMBER
+ = { cur.d_pri = $2; } |
+ FLAGS NUMBER
+ = { cur.d_flags = $2; };
+
+Dev_name:
+ Init_dev Dev NUMBER
+ = {
+ cur.d_name = $2;
+ if (eq($2, "mba"))
+ seen_mba = 1;
+ else if (eq($2, "uba"))
+ seen_uba = 1;
+ else if (eq($2, "vba"))
+ seen_vba = 1;
+ else if (eq($2, "isa"))
+ seen_isa = 1;
+ cur.d_unit = $3;
+ };
+
+Init_dev:
+ /* lambda */
+ = { init_dev(&cur); };
+
+Dev_info:
+ Con_info Info_list
+ |
+ /* lambda */
+ ;
+
+Con_info:
+ AT Dev NUMBER
+ = {
+ if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
+ (void) sprintf(errbuf,
+ "%s must be connected to a nexus", cur.d_name);
+ yyerror(errbuf);
+ }
+ cur.d_conn = connect($2, $3);
+ } |
+ AT NEXUS NUMBER
+ = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; };
+
+Info_list:
+ Info_list Info
+ |
+ /* lambda */
+ ;
+
+Info:
+ CSR NUMBER
+ = { cur.d_addr = $2; } |
+ DRIVE NUMBER
+ = { cur.d_drive = $2; } |
+ SLAVE NUMBER
+ = {
+ if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS &&
+ cur.d_conn->d_type == MASTER)
+ cur.d_slave = $2;
+ else
+ yyerror("can't specify slave--not to master");
+ } |
+ IRQ NUMBER
+ = { cur.d_irq = $2; } |
+ DRQ NUMBER
+ = { cur.d_drq = $2; } |
+ IOMEM NUMBER
+ = { cur.d_maddr = $2; } |
+ IOSIZ NUMBER
+ = { cur.d_msize = $2; } |
+ PORT device_name
+ = { cur.d_port = ns($2); } |
+ PORT NUMBER
+ = { cur.d_portn = $2; } |
+ TTY
+ = { cur.d_mask = "tty"; } |
+ BIO
+ = { cur.d_mask = "bio"; } |
+ NET
+ = { cur.d_mask = "net"; } |
+ FLAGS NUMBER
+ = { cur.d_flags = $2; };
+
+Int_spec:
+ VECTOR Id_list
+ = { cur.d_vec = $2; } |
+ PRIORITY NUMBER
+ = { cur.d_pri = $2; } |
+ /* lambda */
+ ;
+
+Id_list:
+ Save_id
+ = {
+ struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
+ a->id = $1; a->id_next = 0; $$ = a;
+ } |
+ Save_id Id_list =
+ {
+ struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
+ a->id = $1; a->id_next = $2; $$ = a;
+ };
+
+%%
+
+yyerror(s)
+ char *s;
+{
+
+ fprintf(stderr, "config: line %d: %s\n", yyline + 1, s);
+}
+
+/*
+ * return the passed string in a new space
+ */
+char *
+ns(str)
+ register char *str;
+{
+ register char *cp;
+
+ cp = malloc((unsigned)(strlen(str)+1));
+ (void) strcpy(cp, str);
+ return (cp);
+}
+
+/*
+ * add a device to the list of devices
+ */
+newdev(dp)
+ register struct device *dp;
+{
+ register struct device *np;
+
+ np = (struct device *) malloc(sizeof *np);
+ *np = *dp;
+ np->d_next = 0;
+ if (curp == 0)
+ dtab = np;
+ else
+ curp->d_next = np;
+ curp = np;
+}
+
+/*
+ * note that a configuration should be made
+ */
+mkconf(sysname)
+ char *sysname;
+{
+ register struct file_list *fl, **flp;
+
+ fl = (struct file_list *) malloc(sizeof *fl);
+ fl->f_type = SYSTEMSPEC;
+ fl->f_needs = sysname;
+ fl->f_rootdev = NODEV;
+ fl->f_dumpdev = NODEV;
+ fl->f_fn = 0;
+ fl->f_next = 0;
+ for (flp = confp; *flp; flp = &(*flp)->f_next)
+ ;
+ *flp = fl;
+ confp = flp;
+}
+
+struct file_list *
+newflist(ftype)
+ u_char ftype;
+{
+ struct file_list *fl = (struct file_list *)malloc(sizeof (*fl));
+
+ fl->f_type = ftype;
+ fl->f_next = 0;
+ fl->f_swapdev = NODEV;
+ fl->f_swapsize = 0;
+ fl->f_needs = 0;
+ fl->f_fn = 0;
+ return (fl);
+}
+
+/*
+ * Add a swap device to the system's configuration
+ */
+mkswap(system, fl, size, flag)
+ struct file_list *system, *fl;
+ int size, flag;
+{
+ register struct file_list **flp;
+ char name[80];
+
+ if (system == 0 || system->f_type != SYSTEMSPEC) {
+ yyerror("\"swap\" spec precedes \"config\" specification");
+ return;
+ }
+ if (size < 0) {
+ yyerror("illegal swap partition size");
+ return;
+ }
+ /*
+ * Append swap description to the end of the list.
+ */
+ flp = &system->f_next;
+ for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next)
+ ;
+ fl->f_next = *flp;
+ *flp = fl;
+ fl->f_swapsize = size;
+ fl->f_swapflag = flag;
+ /*
+ * If first swap device for this system,
+ * set up f_fn field to insure swap
+ * files are created with unique names.
+ */
+ if (system->f_fn)
+ return;
+ if (eq(fl->f_fn, "generic"))
+ system->f_fn = ns(fl->f_fn);
+ else
+ system->f_fn = ns(system->f_needs);
+}
+
+mkcomp(dp)
+ register struct device *dp;
+{
+ register struct file_list *fl, **flp;
+ char buf[80];
+
+ fl = (struct file_list *) malloc(sizeof *fl);
+ fl->f_type = COMPDEVICE;
+ fl->f_compinfo = dp->d_unit;
+ fl->f_fn = ns(dp->d_name);
+ (void) sprintf(buf, "%s%d", dp->d_name, dp->d_unit);
+ fl->f_needs = ns(buf);
+ fl->f_next = 0;
+ for (flp = compp; *flp; flp = &(*flp)->f_next)
+ ;
+ *flp = fl;
+ compp = flp;
+}
+
+addcomp(compdev, fl)
+ struct file_list *compdev, *fl;
+{
+ register struct file_list **flp;
+ char name[80];
+
+ if (compdev == 0 || compdev->f_type != COMPDEVICE) {
+ yyerror("component spec precedes device specification");
+ return;
+ }
+ /*
+ * Append description to the end of the list.
+ */
+ flp = &compdev->f_next;
+ for (; *flp && (*flp)->f_type == COMPSPEC; flp = &(*flp)->f_next)
+ ;
+ fl->f_next = *flp;
+ *flp = fl;
+}
+
+/*
+ * find the pointer to connect to the given device and number.
+ * returns 0 if no such device and prints an error message
+ */
+struct device *
+connect(dev, num)
+ register char *dev;
+ register int num;
+{
+ register struct device *dp;
+ struct device *huhcon();
+
+ if (num == QUES)
+ return (huhcon(dev));
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if ((num != dp->d_unit) || !eq(dev, dp->d_name))
+ continue;
+ if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
+ (void) sprintf(errbuf,
+ "%s connected to non-controller", dev);
+ yyerror(errbuf);
+ return (0);
+ }
+ return (dp);
+ }
+ (void) sprintf(errbuf, "%s %d not defined", dev, num);
+ yyerror(errbuf);
+ return (0);
+}
+
+/*
+ * connect to an unspecific thing
+ */
+struct device *
+huhcon(dev)
+ register char *dev;
+{
+ register struct device *dp, *dcp;
+ struct device rdev;
+ int oldtype;
+
+ /*
+ * First make certain that there are some of these to wildcard on
+ */
+ for (dp = dtab; dp != 0; dp = dp->d_next)
+ if (eq(dp->d_name, dev))
+ break;
+ if (dp == 0) {
+ (void) sprintf(errbuf, "no %s's to wildcard", dev);
+ yyerror(errbuf);
+ return (0);
+ }
+ oldtype = dp->d_type;
+ dcp = dp->d_conn;
+ /*
+ * Now see if there is already a wildcard entry for this device
+ * (e.g. Search for a "uba ?")
+ */
+ for (; dp != 0; dp = dp->d_next)
+ if (eq(dev, dp->d_name) && dp->d_unit == -1)
+ break;
+ /*
+ * If there isn't, make one because everything needs to be connected
+ * to something.
+ */
+ if (dp == 0) {
+ dp = &rdev;
+ init_dev(dp);
+ dp->d_unit = QUES;
+ dp->d_name = ns(dev);
+ dp->d_type = oldtype;
+ newdev(dp);
+ dp = curp;
+ /*
+ * Connect it to the same thing that other similar things are
+ * connected to, but make sure it is a wildcard unit
+ * (e.g. up connected to sc ?, here we make connect sc? to a
+ * uba?). If other things like this are on the NEXUS or
+ * if they aren't connected to anything, then make the same
+ * connection, else call ourself to connect to another
+ * unspecific device.
+ */
+ if (dcp == TO_NEXUS || dcp == 0)
+ dp->d_conn = dcp;
+ else
+ dp->d_conn = connect(dcp->d_name, QUES);
+ }
+ return (dp);
+}
+
+init_dev(dp)
+ register struct device *dp;
+{
+
+ dp->d_name = "OHNO!!!";
+ dp->d_type = DEVICE;
+ dp->d_conn = 0;
+ dp->d_vec = 0;
+ dp->d_addr = dp->d_flags = dp->d_dk = 0;
+ dp->d_pri = -1;
+ dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN;
+ dp->d_port = (char *)0;
+ dp->d_portn = 0;
+ dp->d_irq = -1;
+ dp->d_drq = -1;
+ dp->d_maddr = 0;
+ dp->d_msize = 0;
+ dp->d_mask = "null";
+}
+
+/*
+ * make certain that this is a reasonable type of thing to connect to a nexus
+ */
+check_nexus(dev, num)
+ register struct device *dev;
+ int num;
+{
+
+ switch (machine) {
+
+ case MACHINE_VAX:
+ if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba") &&
+ !eq(dev->d_name, "bi"))
+ yyerror("only uba's, mba's, and bi's should be connected to the nexus");
+ if (num != QUES)
+ yyerror("can't give specific nexus numbers");
+ break;
+
+ case MACHINE_TAHOE:
+ if (!eq(dev->d_name, "vba"))
+ yyerror("only vba's should be connected to the nexus");
+ break;
+
+ case MACHINE_HP300:
+ case MACHINE_LUNA68K:
+ if (num != QUES)
+ dev->d_addr = num;
+ break;
+
+ case MACHINE_I386:
+ if (!eq(dev->d_name, "isa"))
+ yyerror("only isa's should be connected to the nexus");
+ break;
+
+ case MACHINE_NEWS3400:
+ if (!eq(dev->d_name, "iop") && !eq(dev->d_name, "hb") &&
+ !eq(dev->d_name, "vme"))
+ yyerror("only iop's, hb's and vme's should be connected to the nexus");
+ break;
+ }
+}
+
+/*
+ * Check the timezone to make certain it is sensible
+ */
+
+check_tz()
+{
+ if (abs(zone) > 12 * 60)
+ yyerror("timezone is unreasonable");
+ else
+ hadtz = 1;
+}
+
+/*
+ * Check system specification and apply defaulting
+ * rules on root, argument, dump, and swap devices.
+ */
+checksystemspec(fl)
+ register struct file_list *fl;
+{
+ char buf[BUFSIZ];
+ register struct file_list *swap;
+ int generic;
+
+ if (fl == 0 || fl->f_type != SYSTEMSPEC) {
+ yyerror("internal error, bad system specification");
+ exit(1);
+ }
+ swap = fl->f_next;
+ generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
+ if (fl->f_rootdev == NODEV && !generic) {
+ yyerror("no root device specified");
+ exit(1);
+ }
+ /*
+ * Default swap area to be in 'b' partition of root's
+ * device. If root specified to be other than on 'a'
+ * partition, give warning, something probably amiss.
+ */
+ if (swap == 0 || swap->f_type != SWAPSPEC) {
+ dev_t dev;
+
+ swap = newflist(SWAPSPEC);
+ dev = fl->f_rootdev;
+ if (minor(dev) & 07) {
+ (void) sprintf(buf,
+"Warning, swap defaulted to 'b' partition with root on '%c' partition",
+ (minor(dev) & 07) + 'a');
+ yyerror(buf);
+ }
+ swap->f_swapdev =
+ makedev(major(dev), (minor(dev) &~ 07) | ('b' - 'a'));
+ swap->f_fn = devtoname(swap->f_swapdev);
+ mkswap(fl, swap, 0);
+ }
+ /*
+ * Make sure a generic swap isn't specified, along with
+ * other stuff (user must really be confused).
+ */
+ if (generic) {
+ if (fl->f_rootdev != NODEV)
+ yyerror("root device specified with generic swap");
+ if (fl->f_dumpdev != NODEV)
+ yyerror("dump device specified with generic swap");
+ return;
+ }
+ /*
+ * Default dump device and warn if place is not a
+ * swap area.
+ */
+ if (fl->f_dumpdev == NODEV)
+ fl->f_dumpdev = swap->f_swapdev;
+ if (fl->f_dumpdev != swap->f_swapdev) {
+ struct file_list *p = swap->f_next;
+
+ for (; p && p->f_type == SWAPSPEC; p = p->f_next)
+ if (fl->f_dumpdev == p->f_swapdev)
+ return;
+ (void) sprintf(buf,
+ "Warning: dump device is not a swap partition");
+ yyerror(buf);
+ }
+}
+
+/*
+ * Verify all devices specified in the system specification
+ * are present in the device specifications.
+ */
+verifysystemspecs()
+{
+ register struct file_list *fl;
+ dev_t checked[50], *verifyswap();
+ register dev_t *pchecked = checked;
+
+ for (fl = conf_list; fl; fl = fl->f_next) {
+ if (fl->f_type != SYSTEMSPEC)
+ continue;
+ if (!finddev(fl->f_rootdev))
+ deverror(fl->f_needs, "root");
+ *pchecked++ = fl->f_rootdev;
+ pchecked = verifyswap(fl->f_next, checked, pchecked);
+#define samedev(dev1, dev2) \
+ ((minor(dev1) &~ 07) != (minor(dev2) &~ 07))
+ if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) {
+ if (!finddev(fl->f_dumpdev))
+ deverror(fl->f_needs, "dump");
+ *pchecked++ = fl->f_dumpdev;
+ }
+ }
+}
+
+/*
+ * Do as above, but for swap devices.
+ */
+dev_t *
+verifyswap(fl, checked, pchecked)
+ register struct file_list *fl;
+ dev_t checked[];
+ register dev_t *pchecked;
+{
+
+ for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
+ if (eq(fl->f_fn, "generic"))
+ continue;
+ if (alreadychecked(fl->f_swapdev, checked, pchecked))
+ continue;
+ if (!finddev(fl->f_swapdev))
+ fprintf(stderr,
+ "config: swap device %s not configured", fl->f_fn);
+ *pchecked++ = fl->f_swapdev;
+ }
+ return (pchecked);
+}
+
+/*
+ * Verify that components of a compound device have themselves been config'ed
+ */
+verifycomp(fl)
+ register struct file_list *fl;
+{
+ char *dname = fl->f_needs;
+
+ for (fl = fl->f_next; fl; fl = fl->f_next) {
+ if (fl->f_type != COMPSPEC || finddev(fl->f_compdev))
+ continue;
+ fprintf(stderr,
+ "config: %s: component device %s not configured\n",
+ dname, fl->f_needs);
+ }
+}
+
+/*
+ * Has a device already been checked
+ * for it's existence in the configuration?
+ */
+alreadychecked(dev, list, last)
+ dev_t dev, list[];
+ register dev_t *last;
+{
+ register dev_t *p;
+
+ for (p = list; p < last; p++)
+ if (samedev(*p, dev))
+ return (1);
+ return (0);
+}
+
+deverror(systemname, devtype)
+ char *systemname, *devtype;
+{
+
+ fprintf(stderr, "config: %s: %s device not configured\n",
+ systemname, devtype);
+}
+
+/*
+ * Look for the device in the list of
+ * configured hardware devices. Must
+ * take into account stuff wildcarded.
+ */
+/*ARGSUSED*/
+finddev(dev)
+ dev_t dev;
+{
+
+ /* punt on this right now */
+ return (1);
+}
diff --git a/usr.sbin/config/lang.l b/usr.sbin/config/lang.l
new file mode 100644
index 0000000..535ffcd
--- /dev/null
+++ b/usr.sbin/config/lang.l
@@ -0,0 +1,215 @@
+%{
+/*-
+ * Copyright (c) 1980, 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.
+ *
+ * @(#)lang.l 8.1 (Berkeley) 6/6/93
+ */
+
+#include <ctype.h>
+#include "y.tab.h"
+#include "config.h"
+
+#define tprintf if (do_trace) printf
+
+/*
+ * Key word table
+ */
+
+struct kt {
+ char *kt_name;
+ int kt_val;
+} key_words[] = {
+ { "and", AND },
+ { "args", ARGS },
+ { "at", AT },
+#if MACHINE_I386
+ { "bio", BIO },
+#endif MACHINE_I386
+ { "config", CONFIG },
+ { "controller", CONTROLLER },
+ { "cpu", CPU },
+ { "csr", CSR },
+ { "device", DEVICE },
+ { "disk", DISK },
+ { "drive", DRIVE },
+#if MACHINE_I386
+ { "drq", DRQ },
+#endif MACHINE_I386
+ { "dst", DST },
+ { "dumps", DUMPS },
+ { "flags", FLAGS },
+ { "hz", HZ },
+ { "ident", IDENT },
+ { "interleave", INTERLEAVE },
+#if MACHINE_I386
+ { "iomem", IOMEM },
+ { "iosiz", IOSIZ },
+ { "irq", IRQ },
+#endif MACHINE_I386
+ { "machine", MACHINE },
+ { "major", MAJOR },
+ { "makeoptions", MAKEOPTIONS },
+ { "master", MASTER },
+ { "maxusers", MAXUSERS },
+ { "minor", MINOR },
+#if MACHINE_I386
+ { "net", NET },
+#endif MACHINE_I386
+ { "nexus", NEXUS },
+ { "on", ON },
+ { "options", OPTIONS },
+#if MACHINE_I386
+ { "port", PORT },
+#endif MACHINE_I386
+ { "priority", PRIORITY },
+ { "pseudo-device",PSEUDO_DEVICE },
+ { "root", ROOT },
+#if MACHINE_HP300 || MACHINE_LUNA68K
+ { "scode", NEXUS },
+#endif
+ { "sequential", SEQUENTIAL },
+ { "size", SIZE },
+ { "slave", SLAVE },
+ { "swap", SWAP },
+ { "tape", DEVICE },
+#if MACHINE_I386
+ { "tty", TTY },
+#endif MACHINE_I386
+ { "timezone", TIMEZONE },
+ { "trace", TRACE },
+ { "vector", VECTOR },
+ { 0, 0 },
+};
+%}
+WORD [A-Za-z_][-A-Za-z_]*
+%%
+{WORD} {
+ int i;
+
+ if ((i = kw_lookup(yytext)) == -1)
+ {
+ yylval.str = yytext;
+ tprintf("id(%s) ", yytext);
+ return ID;
+ }
+ tprintf("(%s) ", yytext);
+ return i;
+ }
+\"[^"]+\" {
+ yytext[strlen(yytext)-1] = '\0';
+ yylval.str = yytext + 1;
+ return ID;
+ }
+0[0-7]* {
+ yylval.val = octal(yytext);
+ tprintf("#O:%o ", yylval.val);
+ return NUMBER;
+ }
+0x[0-9a-fA-F]+ {
+ yylval.val = hex(yytext);
+ tprintf("#X:%x ", yylval.val);
+ return NUMBER;
+ }
+[1-9][0-9]* {
+ yylval.val = atoi(yytext);
+ tprintf("#D:%d ", yylval.val);
+ return NUMBER;
+ }
+[0-9]"."[0-9]* {
+ double atof();
+ yylval.val = (int) (60 * atof(yytext) + 0.5);
+ return FPNUMBER;
+ }
+"-" {
+ return MINUS;
+ }
+"?" {
+ yylval.val = -1;
+ tprintf("? ");
+ return NUMBER;
+ }
+\n/[ \t] {
+ yyline++;
+ tprintf("\n... ");
+ }
+\n {
+ yyline++;
+ tprintf("\n");
+ return SEMICOLON;
+ }
+#.* { /* Ignored (comment) */; }
+[ \t]* { /* Ignored (white space) */; }
+";" { return SEMICOLON; }
+"," { return COMMA; }
+"=" { return EQUALS; }
+"@" { return AT; }
+. { return yytext[0]; }
+
+%%
+/*
+ * kw_lookup
+ * Look up a string in the keyword table. Returns a -1 if the
+ * string is not a keyword otherwise it returns the keyword number
+ */
+
+kw_lookup(word)
+register char *word;
+{
+ register struct kt *kp;
+
+ for (kp = key_words; kp->kt_name != 0; kp++)
+ if (eq(word, kp->kt_name))
+ return kp->kt_val;
+ return -1;
+}
+
+/*
+ * Number conversion routines
+ */
+
+octal(str)
+char *str;
+{
+ int num;
+
+ (void) sscanf(str, "%o", &num);
+ return num;
+}
+
+hex(str)
+char *str;
+{
+ int num;
+
+ (void) sscanf(str+2, "%x", &num);
+ return num;
+}
diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c
new file mode 100644
index 0000000..37030f0
--- /dev/null
+++ b/usr.sbin/config/main.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1980, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "y.tab.h"
+#include "config.h"
+
+static char *PREFIX;
+
+/*
+ * Config builds a set of files for building a UNIX
+ * system given a description of the desired system.
+ */
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ extern char *optarg;
+ extern int optind;
+ struct stat buf;
+ int ch;
+ char *p;
+
+ while ((ch = getopt(argc, argv, "gp")) != EOF)
+ switch (ch) {
+ case 'g':
+ debugging++;
+ break;
+ case 'p':
+ profiling++;
+ break;
+ case '?':
+ default:
+ goto usage;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+usage: fputs("usage: config [-gp] sysname\n", stderr);
+ exit(1);
+ }
+
+ if (freopen(PREFIX = *argv, "r", stdin) == NULL) {
+ perror(PREFIX);
+ exit(2);
+ }
+ if (stat(p = path((char *)NULL), &buf)) {
+ if (mkdir(p, 0777)) {
+ perror(p);
+ exit(2);
+ }
+ }
+ else if ((buf.st_mode & S_IFMT) != S_IFDIR) {
+ fprintf(stderr, "config: %s isn't a directory.\n", p);
+ exit(2);
+ }
+
+ dtab = NULL;
+ confp = &conf_list;
+ compp = &comp_list;
+ if (yyparse())
+ exit(3);
+ switch (machine) {
+
+ case MACHINE_VAX:
+ vax_ioconf(); /* Print ioconf.c */
+ ubglue(); /* Create ubglue.s */
+ break;
+
+ case MACHINE_TAHOE:
+ tahoe_ioconf();
+ vbglue();
+ break;
+
+ case MACHINE_HP300:
+ case MACHINE_LUNA68K:
+ hp300_ioconf();
+ hpglue();
+ break;
+
+ case MACHINE_I386:
+ i386_ioconf(); /* Print ioconf.c */
+ vector(); /* Create vector.s */
+ break;
+
+ case MACHINE_MIPS:
+ case MACHINE_PMAX:
+ pmax_ioconf();
+ break;
+
+ case MACHINE_NEWS3400:
+ news_ioconf();
+ break;
+
+ default:
+ printf("Specify machine type, e.g. ``machine vax''\n");
+ exit(1);
+ }
+ /*
+ * make symbolic links in compilation directory
+ * for "sys" (to make genassym.c work along with #include <sys/xxx>)
+ * and similarly for "machine".
+ */
+ {
+ char xxx[80];
+
+ (void) sprintf(xxx, "../../%s/include", machinename);
+ (void) symlink(xxx, path("machine"));
+ }
+ makefile(); /* build Makefile */
+ headers(); /* make a lot of .h files */
+ swapconf(); /* swap config files */
+ printf("Don't forget to run \"make depend\"\n");
+ exit(0);
+}
+
+/*
+ * get_word
+ * returns EOF on end of file
+ * NULL on end of line
+ * pointer to the word otherwise
+ */
+char *
+get_word(fp)
+ register FILE *fp;
+{
+ static char line[80];
+ register int ch;
+ register char *cp;
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch != ' ' && ch != '\t')
+ break;
+ if (ch == EOF)
+ return ((char *)EOF);
+ if (ch == '\n')
+ return (NULL);
+ cp = line;
+ *cp++ = ch;
+ while ((ch = getc(fp)) != EOF) {
+ if (isspace(ch))
+ break;
+ *cp++ = ch;
+ }
+ *cp = 0;
+ if (ch == EOF)
+ return ((char *)EOF);
+ (void) ungetc(ch, fp);
+ return (line);
+}
+
+/*
+ * get_quoted_word
+ * like get_word but will accept something in double or single quotes
+ * (to allow embedded spaces).
+ */
+char *
+get_quoted_word(fp)
+ register FILE *fp;
+{
+ static char line[256];
+ register int ch;
+ register char *cp;
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch != ' ' && ch != '\t')
+ break;
+ if (ch == EOF)
+ return ((char *)EOF);
+ if (ch == '\n')
+ return (NULL);
+ cp = line;
+ if (ch == '"' || ch == '\'') {
+ register int quote = ch;
+
+ while ((ch = getc(fp)) != EOF) {
+ if (ch == quote)
+ break;
+ if (ch == '\n') {
+ *cp = 0;
+ printf("config: missing quote reading `%s'\n",
+ line);
+ exit(2);
+ }
+ *cp++ = ch;
+ }
+ } else {
+ *cp++ = ch;
+ while ((ch = getc(fp)) != EOF) {
+ if (isspace(ch))
+ break;
+ *cp++ = ch;
+ }
+ if (ch != EOF)
+ (void) ungetc(ch, fp);
+ }
+ *cp = 0;
+ if (ch == EOF)
+ return ((char *)EOF);
+ return (line);
+}
+
+/*
+ * prepend the path to a filename
+ */
+char *
+path(file)
+ char *file;
+{
+ register char *cp;
+
+#define CDIR "../../compile/"
+ cp = malloc((unsigned int)(sizeof(CDIR) + strlen(PREFIX) +
+ (file ? strlen(file) : 0) + 2));
+ (void) strcpy(cp, CDIR);
+ (void) strcat(cp, PREFIX);
+ if (file) {
+ (void) strcat(cp, "/");
+ (void) strcat(cp, file);
+ }
+ return (cp);
+}
diff --git a/usr.sbin/config/mkglue.c b/usr.sbin/config/mkglue.c
new file mode 100644
index 0000000..e738515
--- /dev/null
+++ b/usr.sbin/config/mkglue.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkglue.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Make the bus adaptor interrupt glue files.
+ */
+#include <stdio.h>
+#include "config.h"
+#include "y.tab.h"
+#include <ctype.h>
+
+/*
+ * Create the UNIBUS interrupt vector glue file.
+ */
+ubglue()
+{
+ register FILE *fp, *gp;
+ register struct device *dp, *mp;
+
+ fp = fopen(path("ubglue.s"), "w");
+ if (fp == 0) {
+ perror(path("ubglue.s"));
+ exit(1);
+ }
+ gp = fopen(path("ubvec.s"), "w");
+ if (gp == 0) {
+ perror(path("ubvec.s"));
+ exit(1);
+ }
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != (struct device *)-1 &&
+ !eq(mp->d_name, "mba")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ dump_ubavec(fp, id->id,
+ dp->d_unit);
+ break;
+ }
+ if (!strcmp(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ dump_std(fp, gp);
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != (struct device *)-1 &&
+ !eq(mp->d_name, "mba")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ dump_intname(fp, id->id,
+ dp->d_unit);
+ break;
+ }
+ if (!strcmp(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ dump_ctrs(fp);
+ (void) fclose(fp);
+ (void) fclose(gp);
+}
+
+static int cntcnt = 0; /* number of interrupt counters allocated */
+
+/*
+ * Print a UNIBUS interrupt vector.
+ */
+dump_ubavec(fp, vector, number)
+ register FILE *fp;
+ char *vector;
+ int number;
+{
+ char nbuf[80];
+ register char *v = nbuf;
+
+ (void) sprintf(v, "%s%d", vector, number);
+ fprintf(fp, "\t.globl\t_X%s\n\t.align\t2\n_X%s:\n\tpushr\t$0x3f\n",
+ v, v);
+ fprintf(fp, "\tincl\t_fltintrcnt+(4*%d)\n", cntcnt++);
+ if (strncmp(vector, "dzx", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdzdma\n\n", number);
+ else if (strncmp(vector, "dpx", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdpxdma\n\n", number);
+ else if (strncmp(vector, "dpr", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdprdma\n\n", number);
+ else {
+ if (strncmp(vector, "uur", 3) == 0) {
+ fprintf(fp, "#ifdef UUDMA\n");
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjsb\tuudma\n", number);
+ fprintf(fp, "#endif\n");
+ }
+ fprintf(fp, "\tpushl\t$%d\n", number);
+ fprintf(fp, "\tcalls\t$1,_%s\n\tpopr\t$0x3f\n", vector);
+ fprintf(fp, "\tincl\t_cnt+V_INTR\n\trei\n\n");
+ }
+}
+
+/*
+ * Create the VERSAbus interrupt vector glue file.
+ */
+vbglue()
+{
+ register FILE *fp, *gp;
+ register struct device *dp, *mp;
+
+ fp = fopen(path("vbglue.s"), "w");
+ if (fp == 0) {
+ perror(path("vbglue.s"));
+ exit(1);
+ }
+ gp = fopen(path("vbvec.s"), "w");
+ if (gp == 0) {
+ perror(path("vbvec.s"));
+ exit(1);
+ }
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ struct idlst *id, *id2;
+
+ mp = dp->d_conn;
+ if (mp == 0 || mp == (struct device *)-1 ||
+ eq(mp->d_name, "mba"))
+ continue;
+ for (id = dp->d_vec; id; id = id->id_next)
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id == id2) {
+ dump_vbavec(fp, id->id, dp->d_unit);
+ break;
+ }
+ if (eq(id->id, id2->id))
+ break;
+ }
+ }
+ dump_std(fp, gp);
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != (struct device *)-1 &&
+ !eq(mp->d_name, "mba")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ dump_intname(fp, id->id,
+ dp->d_unit);
+ break;
+ }
+ if (eq(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ dump_ctrs(fp);
+ (void) fclose(fp);
+ (void) fclose(gp);
+}
+
+/*
+ * Print a VERSAbus interrupt vector
+ */
+dump_vbavec(fp, vector, number)
+ register FILE *fp;
+ char *vector;
+ int number;
+{
+ char nbuf[80];
+ register char *v = nbuf;
+
+ (void) sprintf(v, "%s%d", vector, number);
+ fprintf(fp, "SCBVEC(%s):\n", v);
+ fprintf(fp, "\tCHECK_SFE(4)\n");
+ fprintf(fp, "\tSAVE_FPSTAT(4)\n");
+ fprintf(fp, "\tPUSHR\n");
+ fprintf(fp, "\tincl\t_fltintrcnt+(4*%d)\n", cntcnt++);
+ fprintf(fp, "\tpushl\t$%d\n", number);
+ fprintf(fp, "\tcallf\t$8,_%s\n", vector);
+ fprintf(fp, "\tincl\t_cnt+V_INTR\n");
+ fprintf(fp, "\tPOPR\n");
+ fprintf(fp, "\tREST_FPSTAT\n");
+ fprintf(fp, "\trei\n\n");
+}
+
+/*
+ * HP9000/300 interrupts are auto-vectored.
+ * Code is hardwired in locore.s
+ */
+hpglue() {}
+
+static char *vaxinames[] = {
+ "clock", "cnr", "cnx", "tur", "tux",
+ "mba0", "mba1", "mba2", "mba3",
+ "uba0", "uba1", "uba2", "uba3"
+};
+static char *tahoeinames[] = {
+ "clock", "cnr", "cnx", "rmtr", "rmtx", "buserr",
+};
+static struct stdintrs {
+ char **si_names; /* list of standard interrupt names */
+ int si_n; /* number of such names */
+} stdintrs[] = {
+ { vaxinames, sizeof (vaxinames) / sizeof (vaxinames[0]) },
+ { tahoeinames, (sizeof (tahoeinames) / sizeof (tahoeinames[0])) }
+};
+/*
+ * Start the interrupt name table with the names
+ * of the standard vectors not directly associated
+ * with a bus. Also, dump the defines needed to
+ * reference the associated counters into a separate
+ * file which is prepended to locore.s.
+ */
+dump_std(fp, gp)
+ register FILE *fp, *gp;
+{
+ register struct stdintrs *si = &stdintrs[machine-1];
+ register char **cpp;
+ register int i;
+
+ fprintf(fp, "\n\t.globl\t_intrnames\n");
+ fprintf(fp, "\n\t.globl\t_eintrnames\n");
+ fprintf(fp, "\t.data\n");
+ fprintf(fp, "_intrnames:\n");
+ cpp = si->si_names;
+ for (i = 0; i < si->si_n; i++) {
+ register char *cp, *tp;
+ char buf[80];
+
+ cp = *cpp;
+ if (cp[0] == 'i' && cp[1] == 'n' && cp[2] == 't') {
+ cp += 3;
+ if (*cp == 'r')
+ cp++;
+ }
+ for (tp = buf; *cp; cp++)
+ if (islower(*cp))
+ *tp++ = toupper(*cp);
+ else
+ *tp++ = *cp;
+ *tp = '\0';
+ fprintf(gp, "#define\tI_%s\t%d\n", buf, i*sizeof (long));
+ fprintf(fp, "\t.asciz\t\"%s\"\n", *cpp);
+ cpp++;
+ }
+}
+
+dump_intname(fp, vector, number)
+ register FILE *fp;
+ char *vector;
+ int number;
+{
+ register char *cp = vector;
+
+ fprintf(fp, "\t.asciz\t\"");
+ /*
+ * Skip any "int" or "intr" in the name.
+ */
+ while (*cp)
+ if (cp[0] == 'i' && cp[1] == 'n' && cp[2] == 't') {
+ cp += 3;
+ if (*cp == 'r')
+ cp++;
+ } else {
+ putc(*cp, fp);
+ cp++;
+ }
+ fprintf(fp, "%d\"\n", number);
+}
+
+/*
+ * Reserve space for the interrupt counters.
+ */
+dump_ctrs(fp)
+ register FILE *fp;
+{
+ struct stdintrs *si = &stdintrs[machine-1];
+
+ fprintf(fp, "_eintrnames:\n");
+ fprintf(fp, "\n\t.globl\t_intrcnt\n");
+ fprintf(fp, "\n\t.globl\t_eintrcnt\n");
+ fprintf(fp, "\t.align 2\n");
+ fprintf(fp, "_intrcnt:\n");
+ fprintf(fp, "\t.space\t4 * %d\n", si->si_n);
+ fprintf(fp, "_fltintrcnt:\n");
+ fprintf(fp, "\t.space\t4 * %d\n", cntcnt);
+ fprintf(fp, "_eintrcnt:\n\n");
+ fprintf(fp, "\t.text\n");
+}
+
+/*
+ * Create the ISA interrupt vector glue file.
+ */
+vector() {
+ register FILE *fp, *gp;
+ register struct device *dp, *mp;
+ int count;
+
+ fp = fopen(path("vector.s"), "w");
+ if (fp == 0) {
+ perror(path("vector.s"));
+ exit(1);
+ }
+ fprintf(fp,"\
+/*\n\
+ * AT/386\n\
+ * Interrupt vector routines\n\
+ * Generated by config program\n\
+ */ \n\
+\n\
+#include \"i386/isa/isa.h\"\n\
+#include \"i386/isa/icu.h\"\n\
+\n\
+#define VEC(name) .align 4; .globl _V/**/name; _V/**/name:\n\n");
+
+ fprintf(fp,"\
+ .globl _hardclock\n\
+VEC(clk)\n\
+ INTR1(0, _highmask, 0)\n\
+ call _hardclock \n\
+ INTREXIT1\n\n\n");
+
+ count=0;
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && /* mp != (struct device *)-1 &&*/
+ eq(mp->d_name, "isa")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ if(dp->d_irq == -1) continue;
+ fprintf(fp,"\t.globl _%s, _%s%dmask\n\t.data\n",
+ id->id, dp->d_name, dp->d_unit);
+ fprintf(fp,"_%s%dmask:\t.long 0\n\t.text\n",
+ dp->d_name, dp->d_unit);
+ fprintf(fp,"VEC(%s%d)\n\tINTR%d(%d, ",
+ dp->d_name, dp->d_unit,
+ dp->d_irq / 8 + 1, dp->d_unit);
+ if(eq(dp->d_mask,"null"))
+ fprintf(fp,"_%s%dmask, ",
+ dp->d_name, dp->d_unit);
+ else
+ fprintf(fp,"_%smask, ",
+ dp->d_mask);
+ fprintf(fp,"%d)\n\tcall\t_%s\n\tINTREXIT%d\n\n\n",
+ ++count, id->id, (dp->d_irq > 7)?2:1);
+ break;
+ }
+ if (!strcmp(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ (void) fclose(fp);
+}
diff --git a/usr.sbin/config/mkheaders.c b/usr.sbin/config/mkheaders.c
new file mode 100644
index 0000000..7929987
--- /dev/null
+++ b/usr.sbin/config/mkheaders.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkheaders.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Make all the .h files for the optional entries
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "config.h"
+#include "y.tab.h"
+
+headers()
+{
+ register struct file_list *fl;
+
+ for (fl = ftab; fl != 0; fl = fl->f_next)
+ if (fl->f_needs != 0)
+ do_count(fl->f_needs, fl->f_needs, 1);
+}
+
+/*
+ * count all the devices of a certain type and recurse to count
+ * whatever the device is connected to
+ */
+do_count(dev, hname, search)
+ register char *dev, *hname;
+ int search;
+{
+ register struct device *dp, *mp;
+ register int count, hicount;
+
+ /*
+ * After this loop, "count" will be the actual number of units,
+ * and "hicount" will be the highest unit declared. do_header()
+ * must use this higher of these values.
+ */
+ for (hicount = count = 0, dp = dtab; dp != 0; dp = dp->d_next)
+ if (dp->d_unit != -1 && eq(dp->d_name, dev)) {
+ if (dp->d_type == PSEUDO_DEVICE) {
+ count =
+ dp->d_slave != UNKNOWN ? dp->d_slave : 1;
+ break;
+ }
+ count++;
+ /*
+ * Allow holes in unit numbering,
+ * assumption is unit numbering starts
+ * at zero.
+ */
+ if (dp->d_unit + 1 > hicount)
+ hicount = dp->d_unit + 1;
+ if (search) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != TO_NEXUS &&
+ mp->d_conn != 0 && mp->d_conn != TO_NEXUS) {
+ do_count(mp->d_name, hname, 0);
+ search = 0;
+ }
+ }
+ }
+ do_header(dev, hname, count > hicount ? count : hicount);
+}
+
+do_header(dev, hname, count)
+ char *dev, *hname;
+ int count;
+{
+ char *file, *name, *inw, *toheader(), *tomacro();
+ struct file_list *fl, *fl_head, *tflp;
+ FILE *inf, *outf;
+ int inc, oldcount;
+
+ file = toheader(hname);
+ name = tomacro(dev);
+ inf = fopen(file, "r");
+ oldcount = -1;
+ if (inf == 0) {
+ outf = fopen(file, "w");
+ if (outf == 0) {
+ perror(file);
+ exit(1);
+ }
+ fprintf(outf, "#define %s %d\n", name, count);
+ (void) fclose(outf);
+ return;
+ }
+ fl_head = NULL;
+ for (;;) {
+ char *cp;
+ if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
+ break;
+ if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
+ break;
+ inw = ns(inw);
+ cp = get_word(inf);
+ if (cp == 0 || cp == (char *)EOF)
+ break;
+ inc = atoi(cp);
+ if (eq(inw, name)) {
+ oldcount = inc;
+ inc = count;
+ }
+ cp = get_word(inf);
+ if (cp == (char *)EOF)
+ break;
+ fl = (struct file_list *) malloc(sizeof *fl);
+ bzero(fl, sizeof(*fl));
+ fl->f_fn = inw;
+ fl->f_type = inc;
+ fl->f_next = fl_head;
+ fl_head = fl;
+ }
+ (void) fclose(inf);
+ if (count == oldcount) {
+ for (fl = fl_head; fl != NULL; fl = tflp) {
+ tflp = fl->f_next;
+ free(fl);
+ }
+ return;
+ }
+ if (oldcount == -1) {
+ fl = (struct file_list *) malloc(sizeof *fl);
+ bzero(fl, sizeof(*fl));
+ fl->f_fn = name;
+ fl->f_type = count;
+ fl->f_next = fl_head;
+ fl_head = fl;
+ }
+ outf = fopen(file, "w");
+ if (outf == 0) {
+ perror(file);
+ exit(1);
+ }
+ for (fl = fl_head; fl != NULL; fl = tflp) {
+ fprintf(outf,
+ "#define %s %u\n", fl->f_fn, count ? fl->f_type : 0);
+ tflp = fl->f_next;
+ free(fl);
+ }
+ (void) fclose(outf);
+}
+
+/*
+ * convert a dev name to a .h file name
+ */
+char *
+toheader(dev)
+ char *dev;
+{
+ static char hbuf[80];
+
+ (void) strcpy(hbuf, path(dev));
+ (void) strcat(hbuf, ".h");
+ return (hbuf);
+}
+
+/*
+ * convert a dev name to a macro name
+ */
+char *tomacro(dev)
+ register char *dev;
+{
+ static char mbuf[20];
+ register char *cp;
+
+ cp = mbuf;
+ *cp++ = 'N';
+ while (*dev)
+ *cp++ = islower(*dev) ? toupper(*dev++) : *dev++;
+ *cp++ = 0;
+ return (mbuf);
+}
diff --git a/usr.sbin/config/mkioconf.c b/usr.sbin/config/mkioconf.c
new file mode 100644
index 0000000..394ca7e
--- /dev/null
+++ b/usr.sbin/config/mkioconf.c
@@ -0,0 +1,1085 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkioconf.c 8.2 (Berkeley) 1/21/94";
+#endif /* not lint */
+
+#include <stdio.h>
+#include "y.tab.h"
+#include "config.h"
+
+/*
+ * build the ioconf.c file
+ */
+char *qu();
+char *intv();
+char *wnum();
+void pseudo_ioconf();
+
+#if MACHINE_VAX
+vax_ioconf()
+{
+ register struct device *dp, *mp, *np;
+ register int uba_n, slave;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "#include \"vax/include/pte.h\"\n");
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"sys/buf.h\"\n");
+ fprintf(fp, "#include \"sys/map.h\"\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#include \"vax/mba/mbavar.h\"\n");
+ fprintf(fp, "#include \"vax/uba/ubavar.h\"\n\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#define C (caddr_t)\n\n");
+ /*
+ * First print the mba initialization structures
+ */
+ if (seen_mba) {
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp == 0 || mp == TO_NEXUS ||
+ !eq(mp->d_name, "mba"))
+ continue;
+ fprintf(fp, "extern struct mba_driver %sdriver;\n",
+ dp->d_name);
+ }
+ fprintf(fp, "\nstruct mba_device mbdinit[] = {\n");
+ fprintf(fp, "\t/* Device, Unit, Mba, Drive, Dk */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0 ||
+ mp == TO_NEXUS || !eq(mp->d_name, "mba"))
+ continue;
+ if (dp->d_addr) {
+ printf("can't specify csr address on mba for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_vec != 0) {
+ printf("can't specify vector for %s%d on mba\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive == UNKNOWN) {
+ printf("drive not specified for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_slave != UNKNOWN) {
+ printf("can't specify slave number for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ fprintf(fp, "\t{ &%sdriver, %d, %s,",
+ dp->d_name, dp->d_unit, qu(mp->d_unit));
+ fprintf(fp, " %s, %d },\n",
+ qu(dp->d_drive), dp->d_dk);
+ }
+ fprintf(fp, "\t0\n};\n\n");
+ /*
+ * Print the mbsinit structure
+ * Driver Controller Unit Slave
+ */
+ fprintf(fp, "struct mba_slave mbsinit [] = {\n");
+ fprintf(fp, "\t/* Driver, Ctlr, Unit, Slave */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ /*
+ * All slaves are connected to something which
+ * is connected to the massbus.
+ */
+ if ((mp = dp->d_conn) == 0 || mp == TO_NEXUS)
+ continue;
+ np = mp->d_conn;
+ if (np == 0 || np == TO_NEXUS ||
+ !eq(np->d_name, "mba"))
+ continue;
+ fprintf(fp, "\t{ &%sdriver, %s",
+ mp->d_name, qu(mp->d_unit));
+ fprintf(fp, ", %2d, %s },\n",
+ dp->d_unit, qu(dp->d_slave));
+ }
+ fprintf(fp, "\t0\n};\n\n");
+ }
+ /*
+ * Now generate interrupt vectors for the unibus
+ */
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if (dp->d_vec != 0) {
+ struct idlst *ip;
+ mp = dp->d_conn;
+ if (mp == 0 || mp == TO_NEXUS ||
+ (!eq(mp->d_name, "uba") && !eq(mp->d_name, "bi")))
+ continue;
+ fprintf(fp,
+ "extern struct uba_driver %sdriver;\n",
+ dp->d_name);
+ fprintf(fp, "extern ");
+ ip = dp->d_vec;
+ for (;;) {
+ fprintf(fp, "X%s%d()", ip->id, dp->d_unit);
+ ip = ip->id_next;
+ if (ip == 0)
+ break;
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ";\n");
+ fprintf(fp, "int\t (*%sint%d[])() = { ", dp->d_name,
+ dp->d_unit);
+ ip = dp->d_vec;
+ for (;;) {
+ fprintf(fp, "X%s%d", ip->id, dp->d_unit);
+ ip = ip->id_next;
+ if (ip == 0)
+ break;
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ", 0 } ;\n");
+ }
+ }
+ fprintf(fp, "\nstruct uba_ctlr ubminit[] = {\n");
+ fprintf(fp, "/*\t driver,\tctlr,\tubanum,\talive,\tintr,\taddr */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_type != CONTROLLER || mp == TO_NEXUS || mp == 0 ||
+ !eq(mp->d_name, "uba"))
+ continue;
+ if (dp->d_vec == 0) {
+ printf("must specify vector for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr == 0) {
+ printf("must specify csr address for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives need their own entries; dont ");
+ printf("specify drive or slave for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_flags) {
+ printf("controllers (e.g. %s%d) ",
+ dp->d_name, dp->d_unit);
+ printf("don't have flags, only devices do\n");
+ continue;
+ }
+ fprintf(fp,
+ "\t{ &%sdriver,\t%d,\t%s,\t0,\t%sint%d, C 0%o },\n",
+ dp->d_name, dp->d_unit, qu(mp->d_unit),
+ dp->d_name, dp->d_unit, dp->d_addr);
+ }
+ fprintf(fp, "\t0\n};\n");
+/* unibus devices */
+ fprintf(fp, "\nstruct uba_device ubdinit[] = {\n");
+ fprintf(fp,
+"\t/* driver, unit, ctlr, ubanum, slave, intr, addr, dk, flags*/\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || dp->d_type != DEVICE || mp == 0 ||
+ mp == TO_NEXUS || mp->d_type == MASTER ||
+ eq(mp->d_name, "mba"))
+ continue;
+ np = mp->d_conn;
+ if (np != 0 && np != TO_NEXUS && eq(np->d_name, "mba"))
+ continue;
+ np = 0;
+ if (eq(mp->d_name, "uba")) {
+ if (dp->d_vec == 0) {
+ printf("must specify vector for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr == 0) {
+ printf("must specify csr for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives/slaves can be specified ");
+ printf("only for controllers, ");
+ printf("not for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ uba_n = mp->d_unit;
+ slave = QUES;
+ } else {
+ if ((np = mp->d_conn) == 0) {
+ printf("%s%d isn't connected to anything ",
+ mp->d_name, mp->d_unit);
+ printf(", so %s%d is unattached\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ uba_n = np->d_unit;
+ if (dp->d_drive == UNKNOWN) {
+ printf("must specify ``drive number'' ");
+ printf("for %s%d\n", dp->d_name, dp->d_unit);
+ continue;
+ }
+ /* NOTE THAT ON THE UNIBUS ``drive'' IS STORED IN */
+ /* ``SLAVE'' AND WE DON'T WANT A SLAVE SPECIFIED */
+ if (dp->d_slave != UNKNOWN) {
+ printf("slave numbers should be given only ");
+ printf("for massbus tapes, not for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_vec != 0) {
+ printf("interrupt vectors should not be ");
+ printf("given for drive %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr != 0) {
+ printf("csr addresses should be given only ");
+ printf("on controllers, not on %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ slave = dp->d_drive;
+ }
+ fprintf(fp, "\t{ &%sdriver, %2d, %s,",
+ eq(mp->d_name, "uba") ? dp->d_name : mp->d_name, dp->d_unit,
+ eq(mp->d_name, "uba") ? " -1" : qu(mp->d_unit));
+ fprintf(fp, " %s, %2d, %s, C 0%-6o, %d, 0x%x },\n",
+ qu(uba_n), slave, intv(dp), dp->d_addr, dp->d_dk,
+ dp->d_flags);
+ }
+ fprintf(fp, "\t0\n};\n");
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+#endif
+
+#if MACHINE_TAHOE
+tahoe_ioconf()
+{
+ register struct device *dp, *mp, *np;
+ register int vba_n, slave;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"tahoe/include/pte.h\"\n");
+ fprintf(fp, "#include \"sys/buf.h\"\n");
+ fprintf(fp, "#include \"sys/map.h\"\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#include \"tahoe/vba/vbavar.h\"\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#define C (caddr_t)\n\n");
+ /*
+ * Now generate interrupt vectors for the versabus
+ */
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp == 0 || mp == TO_NEXUS || !eq(mp->d_name, "vba"))
+ continue;
+ if (dp->d_vec != 0) {
+ struct idlst *ip;
+ fprintf(fp,
+ "extern struct vba_driver %sdriver;\n",
+ dp->d_name);
+ fprintf(fp, "extern ");
+ ip = dp->d_vec;
+ for (;;) {
+ fprintf(fp, "X%s%d()", ip->id, dp->d_unit);
+ ip = ip->id_next;
+ if (ip == 0)
+ break;
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ";\n");
+ fprintf(fp, "int\t (*%sint%d[])() = { ", dp->d_name,
+ dp->d_unit);
+ ip = dp->d_vec;
+ for (;;) {
+ fprintf(fp, "X%s%d", ip->id, dp->d_unit);
+ ip = ip->id_next;
+ if (ip == 0)
+ break;
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ", 0 } ;\n");
+ } else if (dp->d_type == DRIVER) /* devices w/o interrupts */
+ fprintf(fp,
+ "extern struct vba_driver %sdriver;\n",
+ dp->d_name);
+ }
+ fprintf(fp, "\nstruct vba_ctlr vbminit[] = {\n");
+ fprintf(fp, "/*\t driver,\tctlr,\tvbanum,\talive,\tintr,\taddr */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_type != CONTROLLER || mp == TO_NEXUS || mp == 0 ||
+ !eq(mp->d_name, "vba"))
+ continue;
+ if (dp->d_vec == 0) {
+ printf("must specify vector for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr == 0) {
+ printf("must specify csr address for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives need their own entries; dont ");
+ printf("specify drive or slave for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_flags) {
+ printf("controllers (e.g. %s%d) ",
+ dp->d_name, dp->d_unit);
+ printf("don't have flags, only devices do\n");
+ continue;
+ }
+ fprintf(fp,
+ "\t{ &%sdriver,\t%d,\t%s,\t0,\t%sint%d, C 0x%x },\n",
+ dp->d_name, dp->d_unit, qu(mp->d_unit),
+ dp->d_name, dp->d_unit, dp->d_addr);
+ }
+ fprintf(fp, "\t0\n};\n");
+/* versabus devices */
+ fprintf(fp, "\nstruct vba_device vbdinit[] = {\n");
+ fprintf(fp,
+"\t/* driver, unit, ctlr, vbanum, slave, intr, addr, dk, flags*/\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || dp->d_type != DEVICE || mp == 0 ||
+ mp == TO_NEXUS || mp->d_type == MASTER ||
+ eq(mp->d_name, "mba"))
+ continue;
+ np = mp->d_conn;
+ if (np != 0 && np != TO_NEXUS && eq(np->d_name, "mba"))
+ continue;
+ np = 0;
+ if (eq(mp->d_name, "vba")) {
+ if (dp->d_vec == 0)
+ printf(
+ "Warning, no interrupt vector specified for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ if (dp->d_addr == 0) {
+ printf("must specify csr for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives/slaves can be specified ");
+ printf("only for controllers, ");
+ printf("not for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ vba_n = mp->d_unit;
+ slave = QUES;
+ } else {
+ if ((np = mp->d_conn) == 0) {
+ printf("%s%d isn't connected to anything ",
+ mp->d_name, mp->d_unit);
+ printf(", so %s%d is unattached\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ vba_n = np->d_unit;
+ if (dp->d_drive == UNKNOWN) {
+ printf("must specify ``drive number'' ");
+ printf("for %s%d\n", dp->d_name, dp->d_unit);
+ continue;
+ }
+ /* NOTE THAT ON THE UNIBUS ``drive'' IS STORED IN */
+ /* ``SLAVE'' AND WE DON'T WANT A SLAVE SPECIFIED */
+ if (dp->d_slave != UNKNOWN) {
+ printf("slave numbers should be given only ");
+ printf("for massbus tapes, not for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_vec != 0) {
+ printf("interrupt vectors should not be ");
+ printf("given for drive %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr != 0) {
+ printf("csr addresses should be given only ");
+ printf("on controllers, not on %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ slave = dp->d_drive;
+ }
+ fprintf(fp, "\t{ &%sdriver, %2d, %s,",
+ eq(mp->d_name, "vba") ? dp->d_name : mp->d_name, dp->d_unit,
+ eq(mp->d_name, "vba") ? " -1" : qu(mp->d_unit));
+ fprintf(fp, " %s, %2d, %s, C 0x%-6x, %d, 0x%x },\n",
+ qu(vba_n), slave, intv(dp), dp->d_addr, dp->d_dk,
+ dp->d_flags);
+ }
+ fprintf(fp, "\t0\n};\n");
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+#endif
+
+#if MACHINE_HP300 || MACHINE_LUNA68K
+hp300_ioconf()
+{
+ register struct device *dp, *mp;
+ register int hpib, slave;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"sys/buf.h\"\n");
+ fprintf(fp, "#include \"sys/map.h\"\n");
+ fprintf(fp, "\n");
+ if (machine == MACHINE_HP300)
+ fprintf(fp, "#include \"hp/dev/device.h\"\n\n");
+ else
+ fprintf(fp, "#include \"luna68k/dev/device.h\"\n\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#define C (caddr_t)\n");
+ fprintf(fp, "#define D (struct driver *)\n\n");
+ /*
+ * First print the hpib controller initialization structures
+ */
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0)
+ continue;
+ fprintf(fp, "extern struct driver %sdriver;\n", dp->d_name);
+ }
+ fprintf(fp, "\nstruct hp_ctlr hp_cinit[] = {\n");
+ fprintf(fp, "/*\tdriver,\t\tunit,\talive,\taddr,\tflags */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES ||
+ dp->d_type != MASTER && dp->d_type != CONTROLLER)
+ continue;
+ if (mp != TO_NEXUS) {
+ printf("%s%s must be attached to an sc (nexus)\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("can't specify drive/slave for %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ fprintf(fp,
+ "\t{ &%sdriver,\t%d,\t0,\tC 0x%x,\t0x%x },\n",
+ dp->d_name, dp->d_unit, dp->d_addr, dp->d_flags);
+ }
+ fprintf(fp, "\t0\n};\n");
+/* devices */
+ fprintf(fp, "\nstruct hp_device hp_dinit[] = {\n");
+ fprintf(fp,
+ "/*driver,\tcdriver,\tunit,\tctlr,\tslave,\taddr,\tdk,\tflags*/\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp == 0 || dp->d_type != DEVICE || hpbadslave(mp, dp))
+ continue;
+ if (mp == TO_NEXUS) {
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("can't specify drive/slave for %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ slave = QUES;
+ hpib = QUES;
+ } else {
+ if (dp->d_addr != 0) {
+ printf("can't specify sc for device %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ if (mp->d_type == CONTROLLER) {
+ if (dp->d_drive == UNKNOWN) {
+ printf("must specify drive for %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ slave = dp->d_drive;
+ } else {
+ if (dp->d_slave == UNKNOWN) {
+ printf("must specify slave for %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ slave = dp->d_slave;
+ }
+ hpib = mp->d_unit;
+ }
+ fprintf(fp, "{ &%sdriver,\t", dp->d_name);
+ if (mp == TO_NEXUS)
+ fprintf(fp, "D 0x0,\t");
+ else
+ fprintf(fp, "&%sdriver,", mp->d_name);
+ fprintf(fp, "\t%d,\t%d,\t%d,\tC 0x%x,\t%d,\t0x%x },\n",
+ dp->d_unit, hpib, slave,
+ dp->d_addr, dp->d_dk, dp->d_flags);
+ }
+ fprintf(fp, "0\n};\n");
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+
+#define ishpibdev(n) (eq(n,"rd") || eq(n,"ct") || eq(n,"mt") || eq(n,"ppi"))
+#define isscsidev(n) (eq(n,"sd") || eq(n,"st") || eq(n,"ac"))
+
+hpbadslave(mp, dp)
+ register struct device *dp, *mp;
+{
+
+ if (mp == TO_NEXUS && ishpibdev(dp->d_name) ||
+ mp != TO_NEXUS && eq(mp->d_name, "hpib") &&
+ !ishpibdev(dp->d_name)) {
+ printf("%s%s must be attached to an hpib\n",
+ dp->d_name, wnum(dp->d_unit));
+ return (1);
+ }
+ if (mp == TO_NEXUS && isscsidev(dp->d_name) ||
+ mp != TO_NEXUS && eq(mp->d_name, "scsi") &&
+ !isscsidev(dp->d_name)) {
+ printf("%s%s must be attached to a scsi\n",
+ dp->d_name, wnum(dp->d_unit));
+ return (1);
+ }
+ return (0);
+}
+#endif
+
+#if MACHINE_I386
+char *sirq();
+
+i386_ioconf()
+{
+ register struct device *dp, *mp, *np;
+ register int uba_n, slave;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "/*\n");
+ fprintf(fp, " * ioconf.c \n");
+ fprintf(fp, " * Generated by config program\n");
+ fprintf(fp, " */\n\n");
+ fprintf(fp, "#include \"machine/pte.h\"\n");
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"sys/buf.h\"\n");
+ fprintf(fp, "#include \"sys/map.h\"\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#define V(s) __CONCAT(V,s)\n");
+ fprintf(fp, "#define C (caddr_t)\n\n");
+ /*
+ * First print the isa initialization structures
+ */
+ if (seen_isa) {
+
+ fprintf(fp, "/*\n");
+ fprintf(fp, " * ISA devices\n");
+ fprintf(fp, " */\n\n");
+ fprintf(fp, "#include \"i386/isa/isa_device.h\"\n");
+ fprintf(fp, "#include \"i386/isa/isa.h\"\n");
+ fprintf(fp, "#include \"i386/isa/icu.h\"\n\n");
+
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp == 0 || mp == TO_NEXUS ||
+ !eq(mp->d_name, "isa"))
+ continue;
+ fprintf(fp,
+"extern struct isa_driver %sdriver; extern V(%s%d)();\n",
+ dp->d_name, dp->d_name, dp->d_unit);
+ }
+ fprintf(fp, "\nstruct isa_device isa_devtab_bio[] = {\n");
+ fprintf(fp, "\
+/* driver iobase irq drq maddr msiz intr unit */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0 ||
+ mp == TO_NEXUS || !eq(mp->d_name, "isa"))
+ continue;
+ if (!eq(dp->d_mask, "bio")) continue;
+ if (dp->d_port)
+ fprintf(fp, "{ &%sdriver, %8.8s,", dp->d_name, dp->d_port);
+ else
+ fprintf(fp, "{ &%sdriver, 0x%03x,", dp->d_name, dp->d_portn);
+ fprintf(fp, " %5.5s, %2d, C 0x%05X, %5d, V(%s%d), %2d },\n",
+ sirq(dp->d_irq), dp->d_drq, dp->d_maddr,
+ dp->d_msize, dp->d_name, dp->d_unit, dp->d_unit);
+ }
+ fprintf(fp, "0\n};\n");
+
+ fprintf(fp, "struct isa_device isa_devtab_tty[] = {\n");
+ fprintf(fp, "\
+/* driver iobase irq drq maddr msiz intr unit */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0 ||
+ mp == TO_NEXUS || !eq(mp->d_name, "isa"))
+ continue;
+ if (!eq(dp->d_mask, "tty")) continue;
+ if (dp->d_port)
+ fprintf(fp, "{ &%sdriver, %8.8s,", dp->d_name, dp->d_port);
+ else
+ fprintf(fp, "{ &%sdriver, 0x%03x,", dp->d_name, dp->d_portn);
+ fprintf(fp, " %5.5s, %2d, C 0x%05X, %5d, V(%s%d), %2d },\n",
+ sirq(dp->d_irq), dp->d_drq, dp->d_maddr,
+ dp->d_msize, dp->d_name, dp->d_unit, dp->d_unit);
+ }
+ fprintf(fp, "0\n};\n\n");
+
+ fprintf(fp, "struct isa_device isa_devtab_net[] = {\n");
+ fprintf(fp, "\
+/* driver iobase irq drq maddr msiz intr unit */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0 ||
+ mp == TO_NEXUS || !eq(mp->d_name, "isa"))
+ continue;
+ if (!eq(dp->d_mask, "net")) continue;
+ if (dp->d_port)
+ fprintf(fp, "{ &%sdriver, %8.8s,", dp->d_name, dp->d_port);
+ else
+ fprintf(fp, "{ &%sdriver, 0x%03x,", dp->d_name, dp->d_portn);
+ fprintf(fp, " %5.5s, %2d, C 0x%05X, %5d, V(%s%d), %2d },\n",
+ sirq(dp->d_irq), dp->d_drq, dp->d_maddr,
+ dp->d_msize, dp->d_name, dp->d_unit, dp->d_unit);
+ }
+ fprintf(fp, "0\n};\n\n");
+
+ fprintf(fp, "struct isa_device isa_devtab_null[] = {\n");
+ fprintf(fp, "\
+/* driver iobase irq drq maddr msiz intr unit */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || mp == 0 ||
+ mp == TO_NEXUS || !eq(mp->d_name, "isa"))
+ continue;
+ if (!eq(dp->d_mask, "null")) continue;
+ if (dp->d_port)
+ fprintf(fp, "{ &%sdriver, %8.8s,", dp->d_name, dp->d_port);
+ else
+ fprintf(fp, "{ &%sdriver, 0x%03x,", dp->d_name, dp->d_portn);
+ fprintf(fp, " %5.5s, %2d, C 0x%05X, %5d, V(%s%d), %2d },\n",
+ sirq(dp->d_irq), dp->d_drq, dp->d_maddr,
+ dp->d_msize, dp->d_name, dp->d_unit, dp->d_unit);
+ }
+ fprintf(fp, "0\n};\n\n");
+ }
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+
+char *
+sirq(num)
+{
+
+ if (num == -1)
+ return ("0");
+ sprintf(errbuf, "IRQ%d", num);
+ return (errbuf);
+}
+#endif
+
+#if MACHINE_PMAX
+pmax_ioconf()
+{
+ register struct device *dp, *mp;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "#include \"sys/types.h\"\n");
+ fprintf(fp, "#include \"sys/time.h\"\n");
+ fprintf(fp, "#include \"pmax/dev/device.h\"\n\n");
+ fprintf(fp, "#define C (char *)\n\n");
+
+ /* print controller initialization structures */
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if (dp->d_type == PSEUDO_DEVICE)
+ continue;
+ fprintf(fp, "extern struct driver %sdriver;\n", dp->d_name);
+ }
+ fprintf(fp, "\nstruct pmax_ctlr pmax_cinit[] = {\n");
+ fprintf(fp, "/*\tdriver,\t\tunit,\taddr,\t\tpri,\tflags */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if (dp->d_type != CONTROLLER && dp->d_type != MASTER)
+ continue;
+ if (dp->d_conn != TO_NEXUS) {
+ printf("%s%s must be attached to a nexus (internal bus)\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("can't specify drive/slave for %s%s\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ if (dp->d_unit == UNKNOWN || dp->d_unit == QUES)
+ dp->d_unit = 0;
+ fprintf(fp,
+ "\t{ &%sdriver,\t%d,\tC 0x%x,\t%d,\t0x%x },\n",
+ dp->d_name, dp->d_unit, dp->d_addr, dp->d_pri,
+ dp->d_flags);
+ }
+ fprintf(fp, "\t0\n};\n");
+
+ /* print devices connected to other controllers */
+ fprintf(fp, "\nstruct scsi_device scsi_dinit[] = {\n");
+ fprintf(fp,
+ "/*driver,\tcdriver,\tunit,\tctlr,\tdrive,\tslave,\tdk,\tflags*/\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if (dp->d_type == CONTROLLER || dp->d_type == MASTER ||
+ dp->d_type == PSEUDO_DEVICE)
+ continue;
+ mp = dp->d_conn;
+ if (mp == 0 ||
+ !eq(mp->d_name, "asc") && !eq(mp->d_name, "sii")) {
+ printf("%s%s: devices must be attached to a SCSI (asc or sii) controller\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ if ((unsigned)dp->d_drive > 6) {
+ printf("%s%s: SCSI drive must be in the range 0..6\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ /* may want to allow QUES later */
+ if ((unsigned)dp->d_slave > 7) {
+ printf("%s%s: SCSI slave (LUN) must be in the range 0..7\n",
+ dp->d_name, wnum(dp->d_unit));
+ continue;
+ }
+ fprintf(fp, "{ &%sdriver,\t&%sdriver,", dp->d_name, mp->d_name);
+ fprintf(fp, "\t%d,\t%d,\t%d,\t%d,\t%d,\t0x%x },\n",
+ dp->d_unit, mp->d_unit, dp->d_drive, dp->d_slave,
+ dp->d_dk, dp->d_flags);
+ }
+ fprintf(fp, "0\n};\n");
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+#endif
+
+#if MACHINE_NEWS3400
+int have_iop = 0;
+int have_hb = 0;
+int have_vme = 0;
+
+news_ioconf()
+{
+ register struct device *dp, *mp;
+ register int slave;
+ FILE *fp;
+
+ fp = fopen(path("ioconf.c"), "w");
+ if (fp == 0) {
+ perror(path("ioconf.c"));
+ exit(1);
+ }
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"sys/buf.h\"\n");
+ fprintf(fp, "#include \"sys/map.h\"\n");
+ fprintf(fp, "#include \"vm/vm.h\"\n");
+ fprintf(fp, "#include \"iop.h\"\n");
+ fprintf(fp, "#include \"hb.h\"\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#if NIOP > 0\n");
+ fprintf(fp, "#include \"news3400/iop/iopvar.h\"\n");
+ fprintf(fp, "#endif\n");
+ fprintf(fp, "#if NHB > 0\n");
+ fprintf(fp, "#include \"news3400/hbdev/hbvar.h\"\n");
+ fprintf(fp, "#endif\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#define C (caddr_t)\n\n");
+ fprintf(fp, "\n");
+
+/* BEGIN HB */
+ fprintf(fp, "#if NHB > 0\n");
+ /*
+ * Now generate interrupt vectors for the HYPER-BUS
+ */
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ if (dp->d_pri >= 0) {
+ mp = dp->d_conn;
+ if (mp == 0 || mp == TO_NEXUS ||
+ !eq(mp->d_name, "hb"))
+ continue;
+ fprintf(fp, "extern struct hb_driver %sdriver;\n",
+ dp->d_name);
+ have_hb++;
+ }
+ }
+ /*
+ * Now spew forth the hb_cinfo structure
+ */
+ fprintf(fp, "\nstruct hb_ctlr hminit[] = {\n");
+ fprintf(fp, "/*\t driver,\tctlr,\talive,\taddr,\tintpri */\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if ((dp->d_type != MASTER && dp->d_type != CONTROLLER)
+ || mp == TO_NEXUS || mp == 0 ||
+ !eq(mp->d_name, "hb"))
+ continue;
+ if (dp->d_pri < 0) {
+ printf("must specify priority for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives need their own entries; ");
+ printf("dont specify drive or slave for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_flags) {
+ printf("controllers (e.g. %s%d) don't have flags, ");
+ printf("only devices do\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ fprintf(fp, "\t{ &%sdriver,\t%d,\t0,\tC 0x%x,\t%d },\n",
+ dp->d_name, dp->d_unit, dp->d_addr, dp->d_pri);
+ }
+ fprintf(fp, "\t0\n};\n");
+ /*
+ * Now we go for the hb_device stuff
+ */
+ fprintf(fp, "\nstruct hb_device hdinit[] = {\n");
+ fprintf(fp,
+"\t/* driver, unit, ctlr, slave, addr, pri, dk, flags*/\n");
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (dp->d_unit == QUES || dp->d_type != DEVICE || mp == 0 ||
+ mp == TO_NEXUS || /* mp->d_type == MASTER || */
+ eq(mp->d_name, "iop") || eq(mp->d_name, "vme"))
+ continue;
+ if (eq(mp->d_name, "hb")) {
+ if (dp->d_pri < 0) {
+ printf("must specify vector for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive != UNKNOWN || dp->d_slave != UNKNOWN) {
+ printf("drives/slaves can be specified only ");
+ printf("for controllers, not for device %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ slave = QUES;
+ } else {
+ if (mp->d_conn == 0) {
+ printf("%s%d isn't connected to anything, ",
+ mp->d_name, mp->d_unit);
+ printf("so %s%d is unattached\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_drive == UNKNOWN) {
+ printf("must specify ``drive number'' for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ /* NOTE THAT ON THE IOP ``drive'' IS STORED IN */
+ /* ``SLAVE'' AND WE DON'T WANT A SLAVE SPECIFIED */
+ if (dp->d_slave != UNKNOWN) {
+ printf("slave numbers should be given only ");
+ printf("for massbus tapes, not for %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_pri >= 0) {
+ printf("interrupt priority should not be ");
+ printf("given for drive %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ if (dp->d_addr != 0) {
+ printf("csr addresses should be given only");
+ printf("on controllers, not on %s%d\n",
+ dp->d_name, dp->d_unit);
+ continue;
+ }
+ slave = dp->d_drive;
+ }
+ fprintf(fp,
+"\t{ &%sdriver, %2d, %s, %2d, C 0x%x, %d, %d, 0x%x },\n",
+ eq(mp->d_name, "hb") ? dp->d_name : mp->d_name, dp->d_unit,
+ eq(mp->d_name, "hb") ? " -1" : qu(mp->d_unit),
+ slave, dp->d_addr, dp->d_pri, dp->d_dk, dp->d_flags);
+ }
+ fprintf(fp, "\t0\n};\n\n");
+ fprintf(fp, "#endif\n\n");
+/* END HB */
+ pseudo_ioconf(fp);
+ (void) fclose(fp);
+}
+#endif
+
+char *
+intv(dev)
+ register struct device *dev;
+{
+ static char buf[20];
+
+ if (dev->d_vec == 0)
+ return (" 0");
+ (void) sprintf(buf, "%sint%d", dev->d_name, dev->d_unit);
+ return (buf);
+}
+
+char *
+qu(num)
+{
+
+ if (num == QUES)
+ return ("'?'");
+ if (num == UNKNOWN)
+ return (" -1");
+ (void) sprintf(errbuf, "%3d", num);
+ return (errbuf);
+}
+
+char *
+wnum(num)
+{
+
+ if (num == QUES || num == UNKNOWN)
+ return ("?");
+ (void) sprintf(errbuf, "%d", num);
+ return (errbuf);
+}
+
+void
+pseudo_ioconf(fp)
+ register FILE *fp;
+{
+ register struct device *dp;
+
+ (void)fprintf(fp, "\n#include <sys/device.h>\n\n");
+ for (dp = dtab; dp != NULL; dp = dp->d_next)
+ if (dp->d_type == PSEUDO_DEVICE)
+ (void)fprintf(fp, "extern void %sattach __P((int));\n",
+ dp->d_name);
+ /*
+ * XXX concatonated disks are pseudo-devices but appear as DEVICEs
+ * since they don't adhere to normal pseudo-device conventions
+ * (i.e. one entry with total count in d_slave).
+ */
+ if (seen_cd)
+ (void)fprintf(fp, "extern void cdattach __P((int));\n");
+ /* XXX temporary for HP300, others */
+ (void)fprintf(fp, "\n#include <sys/systm.h> /* XXX */\n");
+ (void)fprintf(fp, "#define etherattach (void (*)__P((int)))nullop\n");
+ (void)fprintf(fp, "#define iteattach (void (*) __P((int)))nullop\n");
+ (void)fprintf(fp, "\nstruct pdevinit pdevinit[] = {\n");
+ for (dp = dtab; dp != NULL; dp = dp->d_next)
+ if (dp->d_type == PSEUDO_DEVICE)
+ (void)fprintf(fp, "\t{ %sattach, %d },\n", dp->d_name,
+ dp->d_slave > 0 ? dp->d_slave : 1);
+ /*
+ * XXX count up cds and put out an entry
+ */
+ if (seen_cd) {
+ struct file_list *fl;
+ int cdmax = -1;
+
+ for (fl = comp_list; fl != NULL; fl = fl->f_next)
+ if (fl->f_type == COMPDEVICE && fl->f_compinfo > cdmax)
+ cdmax = fl->f_compinfo;
+ (void)fprintf(fp, "\t{ cdattach, %d },\n", cdmax+1);
+ }
+ (void)fprintf(fp, "\t{ 0, 0 }\n};\n");
+ if (seen_cd)
+ comp_config(fp);
+}
+
+comp_config(fp)
+ FILE *fp;
+{
+ register struct file_list *fl;
+ register struct device *dp;
+
+ fprintf(fp, "\n#include \"dev/cdvar.h\"\n");
+ fprintf(fp, "\nstruct cddevice cddevice[] = {\n");
+ fprintf(fp, "/*\tunit\tileave\tflags\tdk\tdevs\t\t\t\t*/\n");
+
+ fl = comp_list;
+ while (fl) {
+ if (fl->f_type != COMPDEVICE) {
+ fl = fl->f_next;
+ continue;
+ }
+ for (dp = dtab; dp != 0; dp = dp->d_next)
+ if (dp->d_type == DEVICE &&
+ eq(dp->d_name, fl->f_fn) &&
+ dp->d_unit == fl->f_compinfo)
+ break;
+ if (dp == 0)
+ continue;
+ fprintf(fp, "\t%d,\t%d,\t%d,\t%d,\t{",
+ dp->d_unit, dp->d_pri < 0 ? 0 : dp->d_pri,
+ dp->d_flags, 1);
+ for (fl = fl->f_next; fl->f_type == COMPSPEC; fl = fl->f_next)
+ fprintf(fp, " 0x%x,", fl->f_compdev);
+ fprintf(fp, " NODEV },\n");
+ }
+ fprintf(fp, "\t-1,\t0,\t0,\t0,\t{ 0 },\n};\n");
+}
diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c
new file mode 100644
index 0000000..fed803d
--- /dev/null
+++ b/usr.sbin/config/mkmakefile.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 1993, 19801990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkmakefile.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Build the makefile for the system, from
+ * the information in the files files and the
+ * additional files for the machine being compiled to.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "y.tab.h"
+#include "config.h"
+
+#define next_word(fp, wd) \
+ { register char *word = get_word(fp); \
+ if (word == (char *)EOF) \
+ return; \
+ else \
+ wd = word; \
+ }
+#define next_quoted_word(fp, wd) \
+ { register char *word = get_quoted_word(fp); \
+ if (word == (char *)EOF) \
+ return; \
+ else \
+ wd = word; \
+ }
+
+static struct file_list *fcur;
+char *tail();
+
+/*
+ * Lookup a file, by name.
+ */
+struct file_list *
+fl_lookup(file)
+ register char *file;
+{
+ register struct file_list *fp;
+
+ for (fp = ftab ; fp != 0; fp = fp->f_next) {
+ if (eq(fp->f_fn, file))
+ return (fp);
+ }
+ return (0);
+}
+
+/*
+ * Lookup a file, by final component name.
+ */
+struct file_list *
+fltail_lookup(file)
+ register char *file;
+{
+ register struct file_list *fp;
+
+ for (fp = ftab ; fp != 0; fp = fp->f_next) {
+ if (eq(tail(fp->f_fn), tail(file)))
+ return (fp);
+ }
+ return (0);
+}
+
+/*
+ * Make a new file list entry
+ */
+struct file_list *
+new_fent()
+{
+ register struct file_list *fp;
+
+ fp = (struct file_list *) malloc(sizeof *fp);
+ bzero(fp, sizeof *fp);
+ if (fcur == 0)
+ fcur = ftab = fp;
+ else
+ fcur->f_next = fp;
+ fcur = fp;
+ return (fp);
+}
+
+static struct users {
+ int u_default;
+ int u_min;
+ int u_max;
+} users[] = {
+ { 24, 8, 1024 }, /* MACHINE_VAX */
+ { 4, 2, 128 }, /* MACHINE_TAHOE */
+ { 8, 2, 64 }, /* MACHINE_HP300 */
+ { 8, 2, 64 }, /* MACHINE_I386 */
+ { 8, 2, 64 }, /* MACHINE_MIPS */
+ { 8, 2, 64 }, /* MACHINE_PMAX */
+ { 8, 2, 64 }, /* MACHINE_LUNA68K */
+ { 8, 2, 64 }, /* MACHINE_NEWS3400 */
+};
+#define NUSERS (sizeof (users) / sizeof (users[0]))
+
+/*
+ * Build the makefile from the skeleton
+ */
+makefile()
+{
+ FILE *ifp, *ofp;
+ char line[BUFSIZ];
+ struct opt *op;
+ struct users *up;
+
+ read_files();
+ strcpy(line, "Makefile.");
+ (void) strcat(line, machinename);
+ ifp = fopen(line, "r");
+ if (ifp == 0) {
+ perror(line);
+ exit(1);
+ }
+ ofp = fopen(path("Makefile"), "w");
+ if (ofp == 0) {
+ perror(path("Makefile"));
+ exit(1);
+ }
+ fprintf(ofp, "IDENT=-D%s", raise(ident));
+ if (profiling)
+ fprintf(ofp, " -DGPROF");
+ if (cputype == 0) {
+ printf("cpu type must be specified\n");
+ exit(1);
+ }
+ { struct cputype *cp;
+ for (cp = cputype; cp; cp = cp->cpu_next)
+ fprintf(ofp, " -D%s", cp->cpu_name);
+ }
+ for (op = opt; op; op = op->op_next)
+ if (op->op_value)
+ fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
+ else
+ fprintf(ofp, " -D%s", op->op_name);
+ fprintf(ofp, "\n");
+ if (hadtz == 0)
+ printf("timezone not specified; gmt assumed\n");
+ if ((unsigned)machine > NUSERS) {
+ printf("maxusers config info isn't present, using vax\n");
+ up = &users[MACHINE_VAX-1];
+ } else
+ up = &users[machine-1];
+ if (maxusers == 0) {
+ printf("maxusers not specified; %d assumed\n", up->u_default);
+ maxusers = up->u_default;
+ } else if (maxusers < up->u_min) {
+ printf("minimum of %d maxusers assumed\n", up->u_min);
+ maxusers = up->u_min;
+ } else if (maxusers > up->u_max)
+ printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
+ fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d",
+ zone, dst, maxusers);
+ if (hz > 0)
+ fprintf(ofp, " -DHZ=%d", hz);
+ fprintf(ofp, "\n");
+ for (op = mkopt; op; op = op->op_next)
+ fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
+ if (debugging)
+ fprintf(ofp, "DEBUG=-g\n");
+ if (profiling)
+ fprintf(ofp, "PROF=-pg\n");
+ while (fgets(line, BUFSIZ, ifp) != 0) {
+ if (*line != '%') {
+ fprintf(ofp, "%s", line);
+ continue;
+ }
+ if (eq(line, "%OBJS\n"))
+ do_objs(ofp);
+ else if (eq(line, "%CFILES\n"))
+ do_cfiles(ofp);
+ else if (eq(line, "%RULES\n"))
+ do_rules(ofp);
+ else if (eq(line, "%LOAD\n"))
+ do_load(ofp);
+ else
+ fprintf(stderr,
+ "Unknown %% construct in generic makefile: %s",
+ line);
+ }
+ (void) fclose(ifp);
+ (void) fclose(ofp);
+}
+
+/*
+ * Read in the information about files used in making the system.
+ * Store it in the ftab linked list.
+ */
+read_files()
+{
+ FILE *fp;
+ register struct file_list *tp, *pf;
+ register struct device *dp;
+ struct device *save_dp;
+ register struct opt *op;
+ char *wd, *this, *needs, *special;
+ char fname[32];
+ int nreqs, first = 1, configdep, isdup, std, filetype;
+
+ ftab = 0;
+ (void) strcpy(fname, "../../conf/files");
+openit:
+ fp = fopen(fname, "r");
+ if (fp == 0) {
+ perror(fname);
+ exit(1);
+ }
+next:
+ /*
+ * filename [ standard | optional ] [ config-dependent ]
+ * [ dev* | profiling-routine ] [ device-driver]
+ * [ compile-with "compile rule" ]
+ */
+ wd = get_word(fp);
+ if (wd == (char *)EOF) {
+ (void) fclose(fp);
+ if (first == 1) {
+ (void) sprintf(fname, "files.%s", machinename);
+ first++;
+ goto openit;
+ }
+ if (first == 2) {
+ (void) sprintf(fname, "files.%s", raise(ident));
+ first++;
+ fp = fopen(fname, "r");
+ if (fp != 0)
+ goto next;
+ }
+ return;
+ }
+ if (wd == 0)
+ goto next;
+ this = ns(wd);
+ next_word(fp, wd);
+ if (wd == 0) {
+ printf("%s: No type for %s.\n",
+ fname, this);
+ exit(1);
+ }
+ if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
+ isdup = 1;
+ else
+ isdup = 0;
+ tp = 0;
+ if (first == 3 && (tp = fltail_lookup(this)) != 0)
+ printf("%s: Local file %s overrides %s.\n",
+ fname, this, tp->f_fn);
+ nreqs = 0;
+ special = 0;
+ configdep = 0;
+ needs = 0;
+ std = 0;
+ filetype = NORMAL;
+ if (eq(wd, "standard"))
+ std = 1;
+ else if (!eq(wd, "optional")) {
+ printf("%s: %s must be optional or standard\n", fname, this);
+ exit(1);
+ }
+nextparam:
+ next_word(fp, wd);
+ if (wd == 0)
+ goto doneparam;
+ if (eq(wd, "config-dependent")) {
+ configdep++;
+ goto nextparam;
+ }
+ if (eq(wd, "compile-with")) {
+ next_quoted_word(fp, wd);
+ if (wd == 0) {
+ printf("%s: %s missing compile command string.\n",
+ fname);
+ exit(1);
+ }
+ special = ns(wd);
+ goto nextparam;
+ }
+ nreqs++;
+ if (eq(wd, "device-driver")) {
+ filetype = DRIVER;
+ goto nextparam;
+ }
+ if (eq(wd, "profiling-routine")) {
+ filetype = PROFILING;
+ goto nextparam;
+ }
+ if (needs == 0 && nreqs == 1)
+ needs = ns(wd);
+ if (isdup)
+ goto invis;
+ for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next)
+ if (eq(dp->d_name, wd)) {
+ if (std && dp->d_type == PSEUDO_DEVICE &&
+ dp->d_slave <= 0)
+ dp->d_slave = 1;
+ goto nextparam;
+ }
+ if (std) {
+ dp = (struct device *) malloc(sizeof *dp);
+ init_dev(dp);
+ dp->d_name = ns(wd);
+ dp->d_type = PSEUDO_DEVICE;
+ dp->d_slave = 1;
+ save_dp->d_next = dp;
+ goto nextparam;
+ }
+ for (op = opt; op != 0; op = op->op_next)
+ if (op->op_value == 0 && opteq(op->op_name, wd)) {
+ if (nreqs == 1) {
+ free(needs);
+ needs = 0;
+ }
+ goto nextparam;
+ }
+invis:
+ while ((wd = get_word(fp)) != 0)
+ ;
+ if (tp == 0)
+ tp = new_fent();
+ tp->f_fn = this;
+ tp->f_type = INVISIBLE;
+ tp->f_needs = needs;
+ tp->f_flags = isdup;
+ tp->f_special = special;
+ goto next;
+
+doneparam:
+ if (std == 0 && nreqs == 0) {
+ printf("%s: what is %s optional on?\n",
+ fname, this);
+ exit(1);
+ }
+
+save:
+ if (wd) {
+ printf("%s: syntax error describing %s\n",
+ fname, this);
+ exit(1);
+ }
+ if (filetype == PROFILING && profiling == 0)
+ goto next;
+ if (tp == 0)
+ tp = new_fent();
+ tp->f_fn = this;
+ tp->f_type = filetype;
+ tp->f_flags = 0;
+ if (configdep)
+ tp->f_flags |= CONFIGDEP;
+ tp->f_needs = needs;
+ tp->f_special = special;
+ if (pf && pf->f_type == INVISIBLE)
+ pf->f_flags = 1; /* mark as duplicate */
+ goto next;
+}
+
+opteq(cp, dp)
+ char *cp, *dp;
+{
+ char c, d;
+
+ for (; ; cp++, dp++) {
+ if (*cp != *dp) {
+ c = isupper(*cp) ? tolower(*cp) : *cp;
+ d = isupper(*dp) ? tolower(*dp) : *dp;
+ if (c != d)
+ return (0);
+ }
+ if (*cp == 0)
+ return (1);
+ }
+}
+
+do_objs(fp)
+ FILE *fp;
+{
+ register struct file_list *tp, *fl;
+ register int lpos, len;
+ register char *cp, och, *sp;
+ char swapname[32];
+
+ fprintf(fp, "OBJS=");
+ lpos = 6;
+ for (tp = ftab; tp != 0; tp = tp->f_next) {
+ if (tp->f_type == INVISIBLE)
+ continue;
+ sp = tail(tp->f_fn);
+ for (fl = conf_list; fl; fl = fl->f_next) {
+ if (fl->f_type != SWAPSPEC)
+ continue;
+ (void) sprintf(swapname, "swap%s.c", fl->f_fn);
+ if (eq(sp, swapname))
+ goto cont;
+ }
+ cp = sp + (len = strlen(sp)) - 1;
+ och = *cp;
+ *cp = 'o';
+ if (len + lpos > 72) {
+ lpos = 8;
+ fprintf(fp, "\\\n\t");
+ }
+ fprintf(fp, "%s ", sp);
+ lpos += len + 1;
+ *cp = och;
+cont:
+ ;
+ }
+ if (lpos != 8)
+ putc('\n', fp);
+}
+
+do_cfiles(fp)
+ FILE *fp;
+{
+ register struct file_list *tp, *fl;
+ register int lpos, len;
+ char swapname[32];
+
+ fputs("CFILES=", fp);
+ lpos = 8;
+ for (tp = ftab; tp; tp = tp->f_next)
+ if (tp->f_type != INVISIBLE) {
+ len = strlen(tp->f_fn);
+ if (tp->f_fn[len - 1] != 'c')
+ continue;
+ if ((len = 3 + len) + lpos > 72) {
+ lpos = 8;
+ fputs("\\\n\t", fp);
+ }
+ fprintf(fp, "$S/%s ", tp->f_fn);
+ lpos += len + 1;
+ }
+ for (fl = conf_list; fl; fl = fl->f_next)
+ if (fl->f_type == SYSTEMSPEC) {
+ (void) sprintf(swapname, "swap%s.c", fl->f_fn);
+ if ((len = 3 + strlen(swapname)) + lpos > 72) {
+ lpos = 8;
+ fputs("\\\n\t", fp);
+ }
+ if (eq(fl->f_fn, "generic"))
+ fprintf(fp, "$S/%s/%s/%s ",
+ machinename, machinename, swapname);
+ else
+ fprintf(fp, "%s ", swapname);
+ lpos += len + 1;
+ }
+ if (lpos != 8)
+ putc('\n', fp);
+}
+
+char *
+tail(fn)
+ char *fn;
+{
+ register char *cp;
+
+ cp = rindex(fn, '/');
+ if (cp == 0)
+ return (fn);
+ return (cp+1);
+}
+
+/*
+ * Create the makerules for each file
+ * which is part of the system.
+ * Devices are processed with the special c2 option -i
+ * which avoids any problem areas with i/o addressing
+ * (e.g. for the VAX); assembler files are processed by as.
+ */
+do_rules(f)
+ FILE *f;
+{
+ register char *cp, *np, och, *tp;
+ register struct file_list *ftp;
+ char *special;
+
+ for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
+ if (ftp->f_type == INVISIBLE)
+ continue;
+ cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
+ och = *cp;
+ *cp = '\0';
+ if (och == 'o') {
+ fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np);
+ continue;
+ }
+ fprintf(f, "%so: $S/%s%c\n", tail(np), np, och);
+ tp = tail(np);
+ special = ftp->f_special;
+ if (special == 0) {
+ char *ftype;
+ static char cmd[128];
+
+ switch (ftp->f_type) {
+
+ case NORMAL:
+ ftype = "NORMAL";
+ break;
+
+ case DRIVER:
+ ftype = "DRIVER";
+ break;
+
+ case PROFILING:
+ if (!profiling)
+ continue;
+ ftype = "PROFILE";
+ break;
+
+ default:
+ printf("config: don't know rules for %s\n", np);
+ break;
+ }
+ (void)sprintf(cmd, "${%s_%c%s}", ftype, toupper(och),
+ ftp->f_flags & CONFIGDEP? "_C" : "");
+ special = cmd;
+ }
+ *cp = och;
+ fprintf(f, "\t%s\n\n", special);
+ }
+}
+
+/*
+ * Create the load strings
+ */
+do_load(f)
+ register FILE *f;
+{
+ register struct file_list *fl;
+ register int first;
+ struct file_list *do_systemspec();
+
+ for (first = 1, fl = conf_list; fl; first = 0)
+ fl = fl->f_type == SYSTEMSPEC ?
+ do_systemspec(f, fl, first) : fl->f_next;
+ fputs("all:", f);
+ for (fl = conf_list; fl; fl = fl->f_next)
+ if (fl->f_type == SYSTEMSPEC)
+ fprintf(f, " %s", fl->f_needs);
+ putc('\n', f);
+}
+
+struct file_list *
+do_systemspec(f, fl, first)
+ FILE *f;
+ register struct file_list *fl;
+ int first;
+{
+
+ fprintf(f, "%s: ${SYSTEM_DEP} swap%s.o", fl->f_needs, fl->f_fn);
+ if (first)
+ fprintf(f, " newvers");
+ fprintf(f, "\n\t${SYSTEM_LD_HEAD}\n");
+ fprintf(f, "\t${SYSTEM_LD} swap%s.o\n", fl->f_fn);
+ fprintf(f, "\t${SYSTEM_LD_TAIL}\n\n");
+ do_swapspec(f, fl->f_fn);
+ for (fl = fl->f_next; fl; fl = fl->f_next)
+ if (fl->f_type != SWAPSPEC)
+ break;
+ return (fl);
+}
+
+do_swapspec(f, name)
+ FILE *f;
+ register char *name;
+{
+
+ if (!eq(name, "generic"))
+ fprintf(f, "swap%s.o: swap%s.c\n", name, name);
+ else
+ fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n",
+ machinename, machinename);
+ fprintf(f, "\t${NORMAL_C}\n\n");
+}
+
+char *
+raise(str)
+ register char *str;
+{
+ register char *cp = str;
+
+ while (*str) {
+ if (islower(*str))
+ *str = toupper(*str);
+ str++;
+ }
+ return (cp);
+}
diff --git a/usr.sbin/config/mkswapconf.c b/usr.sbin/config/mkswapconf.c
new file mode 100644
index 0000000..e499973
--- /dev/null
+++ b/usr.sbin/config/mkswapconf.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkswapconf.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Build a swap configuration file.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+
+swapconf()
+{
+ register struct file_list *fl;
+ struct file_list *do_swap();
+
+ fl = conf_list;
+ while (fl) {
+ if (fl->f_type != SYSTEMSPEC) {
+ fl = fl->f_next;
+ continue;
+ }
+ fl = do_swap(fl);
+ }
+}
+
+struct file_list *
+do_swap(fl)
+ register struct file_list *fl;
+{
+ FILE *fp;
+ char swapname[80];
+ register struct file_list *swap;
+ dev_t dev;
+
+ if (eq(fl->f_fn, "generic")) {
+ fl = fl->f_next;
+ return (fl->f_next);
+ }
+ (void) sprintf(swapname, "swap%s.c", fl->f_fn);
+ fp = fopen(path(swapname), "w");
+ if (fp == 0) {
+ perror(path(swapname));
+ exit(1);
+ }
+ fprintf(fp, "#include \"sys/param.h\"\n");
+ fprintf(fp, "#include \"sys/conf.h\"\n");
+ fprintf(fp, "\n");
+ /*
+ * If there aren't any swap devices
+ * specified, just return, the error
+ * has already been noted.
+ */
+ swap = fl->f_next;
+ if (swap == 0 || swap->f_type != SWAPSPEC) {
+ (void) unlink(path(swapname));
+ fclose(fp);
+ return (swap);
+ }
+ fprintf(fp, "dev_t\trootdev = makedev(%d, %d);\n",
+ major(fl->f_rootdev), minor(fl->f_rootdev));
+ fprintf(fp, "dev_t\tdumpdev = makedev(%d, %d);\n",
+ major(fl->f_dumpdev), minor(fl->f_dumpdev));
+ fprintf(fp, "\n");
+ fprintf(fp, "struct\tswdevt swdevt[] = {\n");
+ do {
+ dev = swap->f_swapdev;
+ fprintf(fp, "\t{ makedev(%d, %d),\t%d,\t%d },\t/* %s */\n",
+ major(dev), minor(dev), swap->f_swapflag,
+ swap->f_swapsize, swap->f_fn);
+ swap = swap->f_next;
+ } while (swap && swap->f_type == SWAPSPEC);
+ fprintf(fp, "\t{ NODEV, 0, 0 }\n");
+ fprintf(fp, "};\n");
+ fclose(fp);
+ return (swap);
+}
+
+static int devtablenotread = 1;
+static struct devdescription {
+ char *dev_name;
+ int dev_major;
+ struct devdescription *dev_next;
+} *devtable;
+
+/*
+ * Given a device name specification figure out:
+ * major device number
+ * partition
+ * device name
+ * unit number
+ * This is a hack, but the system still thinks in
+ * terms of major/minor instead of string names.
+ */
+dev_t
+nametodev(name, defunit, defpartition)
+ char *name;
+ int defunit;
+ char defpartition;
+{
+ char *cp, partition;
+ int unit;
+ register struct devdescription *dp;
+
+ cp = name;
+ if (cp == 0) {
+ fprintf(stderr, "config: internal error, nametodev\n");
+ exit(1);
+ }
+ while (*cp && !isdigit(*cp))
+ cp++;
+ unit = *cp ? atoi(cp) : defunit;
+ if (unit < 0 || unit > 31) {
+ fprintf(stderr,
+"config: %s: invalid device specification, unit out of range\n", name);
+ unit = defunit; /* carry on more checking */
+ }
+ if (*cp) {
+ *cp++ = '\0';
+ while (*cp && isdigit(*cp))
+ cp++;
+ }
+ partition = *cp ? *cp : defpartition;
+ if (partition < 'a' || partition > 'h') {
+ fprintf(stderr,
+"config: %c: invalid device specification, bad partition\n", *cp);
+ partition = defpartition; /* carry on */
+ }
+ if (devtablenotread)
+ initdevtable();
+ for (dp = devtable; dp; dp = dp->dev_next)
+ if (eq(name, dp->dev_name))
+ break;
+ if (dp == 0) {
+ fprintf(stderr, "config: %s: unknown device\n", name);
+ return (NODEV);
+ }
+ return (makedev(dp->dev_major, (unit << 3) + (partition - 'a')));
+}
+
+char *
+devtoname(dev)
+ dev_t dev;
+{
+ char buf[80];
+ register struct devdescription *dp;
+
+ if (devtablenotread)
+ initdevtable();
+ for (dp = devtable; dp; dp = dp->dev_next)
+ if (major(dev) == dp->dev_major)
+ break;
+ if (dp == 0)
+ dp = devtable;
+ (void) sprintf(buf, "%s%d%c", dp->dev_name,
+ minor(dev) >> 3, (minor(dev) & 07) + 'a');
+ return (ns(buf));
+}
+
+initdevtable()
+{
+ char buf[BUFSIZ];
+ int maj;
+ register struct devdescription **dp = &devtable;
+ FILE *fp;
+
+ (void) sprintf(buf, "../conf/devices.%s", machinename);
+ fp = fopen(buf, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "config: can't open %s\n", buf);
+ exit(1);
+ }
+ while (fscanf(fp, "%s\t%d\n", buf, &maj) == 2) {
+ *dp = (struct devdescription *)malloc(sizeof (**dp));
+ (*dp)->dev_name = ns(buf);
+ (*dp)->dev_major = maj;
+ dp = &(*dp)->dev_next;
+ }
+ *dp = 0;
+ fclose(fp);
+ devtablenotread = 0;
+}
diff --git a/usr.sbin/config/mkubglue.c b/usr.sbin/config/mkubglue.c
new file mode 100644
index 0000000..7d2b3d4
--- /dev/null
+++ b/usr.sbin/config/mkubglue.c
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkubglue.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Make the uba interrupt file ubglue.s
+ */
+#include <stdio.h>
+#include "config.h"
+#include "y.tab.h"
+
+ubglue()
+{
+ register FILE *fp;
+ register struct device *dp, *mp;
+
+ fp = fopen(path("ubglue.s"), "w");
+ if (fp == 0) {
+ perror(path("ubglue.s"));
+ exit(1);
+ }
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != (struct device *)-1 &&
+ !eq(mp->d_name, "mba")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ dump_vec(fp, id->id, dp->d_unit);
+ break;
+ }
+ if (!strcmp(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ dump_std(fp);
+ for (dp = dtab; dp != 0; dp = dp->d_next) {
+ mp = dp->d_conn;
+ if (mp != 0 && mp != (struct device *)-1 &&
+ !eq(mp->d_name, "mba")) {
+ struct idlst *id, *id2;
+
+ for (id = dp->d_vec; id; id = id->id_next) {
+ for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
+ if (id2 == id) {
+ dump_intname(fp, id->id,
+ dp->d_unit);
+ break;
+ }
+ if (!strcmp(id->id, id2->id))
+ break;
+ }
+ }
+ }
+ }
+ dump_ctrs(fp);
+ (void) fclose(fp);
+}
+
+static int cntcnt = 0; /* number of interrupt counters allocated */
+
+/*
+ * print an interrupt vector
+ */
+dump_vec(fp, vector, number)
+ register FILE *fp;
+ char *vector;
+ int number;
+{
+ char nbuf[80];
+ register char *v = nbuf;
+
+ (void) sprintf(v, "%s%d", vector, number);
+ fprintf(fp, "\t.globl\t_X%s\n\t.align\t2\n_X%s:\n\tpushr\t$0x3f\n",
+ v, v);
+ fprintf(fp, "\tincl\t_fltintrcnt+(4*%d)\n", cntcnt++);
+ if (strncmp(vector, "dzx", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdzdma\n\n", number);
+ else if (strncmp(vector, "dpx", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdpxdma\n\n", number);
+ else if (strncmp(vector, "dpr", 3) == 0)
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdprdma\n\n", number);
+ else {
+ if (strncmp(vector, "uur", 3) == 0) {
+ fprintf(fp, "#ifdef UUDMA\n");
+ fprintf(fp, "\tmovl\t$%d,r0\n\tjsb\tuudma\n", number);
+ fprintf(fp, "#endif\n");
+ }
+ fprintf(fp, "\tpushl\t$%d\n", number);
+ fprintf(fp, "\tcalls\t$1,_%s\n\tpopr\t$0x3f\n", vector);
+ fprintf(fp, "\tincl\t_cnt+V_INTR\n\trei\n\n");
+ }
+}
+
+/*
+ * Start the interrupt name table with the names
+ * of the standard vectors not on the unibus.
+ * The number and order of these names should correspond
+ * with the definitions in scb.s.
+ */
+dump_std(fp)
+ register FILE *fp;
+{
+ fprintf(fp, "\n\t.globl\t_intrnames\n");
+ fprintf(fp, "\n\t.globl\t_eintrnames\n");
+ fprintf(fp, "\t.data\n");
+ fprintf(fp, "_intrnames:\n");
+ fprintf(fp, "\t.asciz\t\"clock\"\n");
+ fprintf(fp, "\t.asciz\t\"cnr\"\n");
+ fprintf(fp, "\t.asciz\t\"cnx\"\n");
+ fprintf(fp, "\t.asciz\t\"tur\"\n");
+ fprintf(fp, "\t.asciz\t\"tux\"\n");
+ fprintf(fp, "\t.asciz\t\"mba0\"\n");
+ fprintf(fp, "\t.asciz\t\"mba1\"\n");
+ fprintf(fp, "\t.asciz\t\"mba2\"\n");
+ fprintf(fp, "\t.asciz\t\"mba3\"\n");
+ fprintf(fp, "\t.asciz\t\"uba0\"\n");
+ fprintf(fp, "\t.asciz\t\"uba1\"\n");
+ fprintf(fp, "\t.asciz\t\"uba2\"\n");
+ fprintf(fp, "\t.asciz\t\"uba3\"\n");
+#define I_FIXED 13 /* number of names above */
+}
+
+dump_intname(fp, vector, number)
+ register FILE *fp;
+ char *vector;
+ int number;
+{
+ register char *cp = vector;
+
+ fprintf(fp, "\t.asciz\t\"");
+ /*
+ * Skip any "int" or "intr" in the name.
+ */
+ while (*cp)
+ if (cp[0] == 'i' && cp[1] == 'n' && cp[2] == 't') {
+ cp += 3;
+ if (*cp == 'r')
+ cp++;
+ } else {
+ putc(*cp, fp);
+ cp++;
+ }
+ fprintf(fp, "%d\"\n", number);
+}
+
+dump_ctrs(fp)
+ register FILE *fp;
+{
+ fprintf(fp, "_eintrnames:\n");
+ fprintf(fp, "\n\t.globl\t_intrcnt\n");
+ fprintf(fp, "\n\t.globl\t_eintrcnt\n");
+ fprintf(fp, "_intrcnt:\n", I_FIXED);
+ fprintf(fp, "\t.space\t4 * %d\n", I_FIXED);
+ fprintf(fp, "_fltintrcnt:\n", cntcnt);
+ fprintf(fp, "\t.space\t4 * %d\n", cntcnt);
+ fprintf(fp, "_eintrcnt:\n\n");
+ fprintf(fp, "\t.text\n");
+}
diff --git a/usr.sbin/dev_mkdb/Makefile b/usr.sbin/dev_mkdb/Makefile
new file mode 100644
index 0000000..29c24f4
--- /dev/null
+++ b/usr.sbin/dev_mkdb/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= dev_mkdb
+MAN8= dev_mkdb.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/dev_mkdb/dev_mkdb.8 b/usr.sbin/dev_mkdb/dev_mkdb.8
new file mode 100644
index 0000000..9369b2b
--- /dev/null
+++ b/usr.sbin/dev_mkdb/dev_mkdb.8
@@ -0,0 +1,81 @@
+.\" 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.
+.\"
+.\" @(#)dev_mkdb.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Os
+.Dt DEV_MKDB 8
+.Sh NAME
+.Nm dev_mkdb
+.Nd create
+.Pa /dev
+database
+.Sh SYNOPSIS
+.Nm dev_mkdb
+.Sh DESCRIPTION
+The
+.Nm dev_mkdb
+command creates a
+.Xr db 3
+hash access method database in
+.Dq Pa /var/run/dev.db
+which contains the names of all of the character and block special
+files in the
+.Dq Pa /dev
+directory, using the file type and the
+.Fa st_rdev
+field as the key.
+.Pp
+Keys are a structure containing a mode_t followed by a dev_t,
+with any padding zero'd out.
+The former is the type of the file (st_mode & S_IFMT),
+the latter is the st_rdev field.
+.Sh FILES
+.Bl -tag -width /var/run/dev.db -compact
+.It Pa /dev
+Device directory.
+.It Pa /var/run/dev.db
+Database file.
+.El
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr stat 2 ,
+.Xr db 3 ,
+.Xr devname 3 ,
+.Xr kvm_nlist 3 ,
+.Xr ttyname 3 ,
+.Xr kvm_mkdb 8
+.Sh HISTORY
+The
+.Nm dev_mkdb
+command appeared in
+.Bx 4.4 .
diff --git a/usr.sbin/dev_mkdb/dev_mkdb.c b/usr.sbin/dev_mkdb/dev_mkdb.c
new file mode 100644
index 0000000..682c041
--- /dev/null
+++ b/usr.sbin/dev_mkdb/dev_mkdb.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)dev_mkdb.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#undef DIRBLKSIZ
+#include <dirent.h>
+#include <nlist.h>
+#include <kvm.h>
+#include <db.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
+
+void err __P((const char *, ...));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register DIR *dirp;
+ register struct dirent *dp;
+ struct stat sb;
+ struct {
+ mode_t type;
+ dev_t dev;
+ } bkey;
+ DB *db;
+ DBT data, key;
+ int ch;
+ u_char buf[MAXNAMLEN + 1];
+ char dbtmp[MAXPATHLEN + 1], dbname[MAXPATHLEN + 1];
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch((char)ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ usage();
+
+ if (chdir(_PATH_DEV))
+ err("%s: %s", _PATH_DEV, strerror(errno));
+
+ dirp = opendir(".");
+
+ (void)snprintf(dbtmp, sizeof(dbtmp), "%sdev.tmp", _PATH_VARRUN);
+ (void)snprintf(dbname, sizeof(dbtmp), "%sdev.db", _PATH_VARRUN);
+ db = dbopen(dbtmp, O_CREAT|O_EXLOCK|O_RDWR|O_TRUNC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, DB_HASH, NULL);
+ if (db == NULL)
+ err("%s: %s", dbtmp, strerror(errno));
+
+ /*
+ * Keys are a mode_t followed by a dev_t. The former is the type of
+ * the file (mode & S_IFMT), the latter is the st_rdev field. Note
+ * that the structure may contain padding, so we have to clear it
+ * out here.
+ */
+ bzero(&bkey, sizeof(bkey));
+ key.data = &bkey;
+ key.size = sizeof(bkey);
+ data.data = buf;
+ while (dp = readdir(dirp)) {
+ if (lstat(dp->d_name, &sb)) {
+ (void)fprintf(stderr,
+ "dev_mkdb: %s: %s\n", dp->d_name, strerror(errno));
+ continue;
+ }
+
+ /* Create the key. */
+ if (S_ISCHR(sb.st_mode))
+ bkey.type = S_IFCHR;
+ else if (S_ISBLK(sb.st_mode))
+ bkey.type = S_IFBLK;
+ else
+ continue;
+ bkey.dev = sb.st_rdev;
+
+ /*
+ * Create the data; nul terminate the name so caller doesn't
+ * have to.
+ */
+ bcopy(dp->d_name, buf, dp->d_namlen);
+ buf[dp->d_namlen] = '\0';
+ data.size = dp->d_namlen + 1;
+ if ((db->put)(db, &key, &data, 0))
+ err("dbput %s: %s\n", dbtmp, strerror(errno));
+ }
+ (void)(db->close)(db);
+ if (rename(dbtmp, dbname))
+ err("rename %s to %s: %s", dbtmp, dbname, strerror(errno));
+ exit(0);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: dev_mkdb\n");
+ exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)fprintf(stderr, "dev_mkdb: ");
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)fprintf(stderr, "\n");
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/usr.sbin/diskpart/Makefile b/usr.sbin/diskpart/Makefile
new file mode 100644
index 0000000..3f24518
--- /dev/null
+++ b/usr.sbin/diskpart/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= diskpart
+MAN8= diskpart.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/diskpart/diskpart.8 b/usr.sbin/diskpart/diskpart.8
new file mode 100644
index 0000000..0b02de2
--- /dev/null
+++ b/usr.sbin/diskpart/diskpart.8
@@ -0,0 +1,143 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)diskpart.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt DISKPART 8
+.Os BSD 4
+.Sh NAME
+.Nm diskpart
+.Nd calculate default disk partition sizes
+.Sh SYNOPSIS
+.Nm diskpart
+.Op Fl p
+.Op Fl d
+.Op Fl s Ar size
+.Ar disk-type
+.Sh DESCRIPTION
+.Nm Diskpart
+is used to calculate the disk partition sizes based on the
+default rules used at Berkeley.
+.Pp
+Available options and operands:
+.Bl -tag -width Fl
+.It Fl p
+Tables suitable for inclusion in a device driver
+are produced.
+.It Fl d
+An entry suitable for inclusion in the disk
+description file
+.Pa /etc/disktab
+is generated; for example,
+.Xr disktab 5 .
+.It Fl s Ar size
+The size of the disk may be limited to
+.Ar size
+with the
+.Fl s
+option.
+.El
+.Pp
+On disks that use
+.Xr bad144 8
+type of
+bad-sector forwarding,
+space is normally left in the last partition on the disk
+for a bad sector forwarding table, although this space
+is not reflected in the tables produced. The space reserved
+is one track for the replicated copies of the table and
+sufficient tracks to hold a pool of 126 sectors to which bad sectors
+are mapped. For more information, see
+.Xr bad144 8 .
+The
+.Fl s
+option is intended for other controllers which reserve some space at the end
+of the disk for bad-sector replacements or other control areas,
+even if not a multiple of cylinders.
+.Pp
+The disk partition sizes are based on the total amount of
+space on the disk as given in the table below (all values
+are supplied in units of sectors). The
+.Ql c
+partition
+is, by convention, used to access the entire physical disk.
+The device driver tables include
+the space reserved for the bad sector forwarding table in the
+.Ql c
+partition;
+those used in the disktab and default formats exclude reserved tracks.
+In normal operation, either the
+.Ql g
+partition is used, or the
+.Ql d ,
+.Ql e ,
+and
+.Ql f
+partitions are used. The
+.Ql g
+and
+.Ql f
+partitions
+are variable-sized, occupying whatever space remains after allocation
+of the fixed sized partitions.
+If the disk is smaller than 20 Megabytes, then
+.Nm diskpart
+aborts with the message
+.Dq Li disk too small, calculate by hand .
+.Bl -column Partition 20-60\ MB 61-205\ MB 206-355\ MB 356+\ MB
+Partition 20-60 MB 61-205 MB 206-355 MB 356+ MB
+a 15884 15884 15884 15884
+b 10032 33440 33440 66880
+d 15884 15884 15884 15884
+e unused 55936 55936 307200
+h unused unused 291346 291346
+.El
+.Pp
+If an unknown disk type is specified,
+.Nm diskpart
+will prompt for the required disk geometry information.
+.Sh SEE ALSO
+.Xr disktab 5 ,
+.Xr bad144 8
+.Sh BUGS
+Most default partition sizes are based on historical artifacts
+(like the RP06), and may result in unsatisfactory layouts.
+.Pp
+When using the
+.Fl d
+flag, alternate disk names are not included
+in the output.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/diskpart/diskpart.c b/usr.sbin/diskpart/diskpart.c
new file mode 100644
index 0000000..c89d0f1
--- /dev/null
+++ b/usr.sbin/diskpart/diskpart.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)diskpart.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Program to calculate standard disk partition sizes.
+ */
+#include <sys/param.h>
+#define DKTYPENAMES
+#include <sys/disklabel.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define for_now /* show all of `c' partition for disklabel */
+#define NPARTITIONS 8
+#define PART(x) (x - 'a')
+
+/*
+ * Default partition sizes, where they exist.
+ */
+#define NDEFAULTS 4
+int defpart[NDEFAULTS][NPARTITIONS] = {
+ { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */
+ { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */
+ { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */
+ { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */
+};
+
+/*
+ * Each array defines a layout for a disk;
+ * that is, the collection of partitions totally
+ * covers the physical space on a disk.
+ */
+#define NLAYOUTS 3
+char layouts[NLAYOUTS][NPARTITIONS] = {
+ { 'a', 'b', 'h', 'g' },
+ { 'a', 'b', 'h', 'd', 'e', 'f' },
+ { 'c' },
+};
+
+/*
+ * Default disk block and disk block fragment
+ * sizes for each file system. Those file systems
+ * with zero block and frag sizes are special cases
+ * (e.g. swap areas or for access to the entire device).
+ */
+struct partition defparam[NPARTITIONS] = {
+ { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* a */
+ { 0, 0, 1024, FS_SWAP, 8, 0 }, /* b */
+ { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* c */
+ { 0, 0, 512, FS_UNUSED, 8, 0 }, /* d */
+ { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* e */
+ { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* f */
+ { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* g */
+ { 0, 0, 1024, FS_UNUSED, 8, 0 } /* h */
+};
+
+/*
+ * Each disk has some space reserved for a bad sector
+ * forwarding table. DEC standard 144 uses the first
+ * 5 even numbered sectors in the last track of the
+ * last cylinder for replicated storage of the bad sector
+ * table; another 126 sectors past this is needed as a
+ * pool of replacement sectors.
+ */
+int badsecttable = 126; /* # sectors */
+
+int pflag; /* print device driver partition tables */
+int dflag; /* print disktab entry */
+
+struct disklabel *promptfordisk();
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct disklabel *dp;
+ register int curcyl, spc, def, part, layout, j;
+ int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS];
+ int totsize = 0;
+ char *lp, *tyname;
+
+ argc--, argv++;
+ if (argc < 1) {
+ fprintf(stderr,
+ "usage: disktab [ -p ] [ -d ] [ -s size ] disk-type\n");
+ exit(1);
+ }
+ if (argc > 0 && strcmp(*argv, "-p") == 0) {
+ pflag++;
+ argc--, argv++;
+ }
+ if (argc > 0 && strcmp(*argv, "-d") == 0) {
+ dflag++;
+ argc--, argv++;
+ }
+ if (argc > 1 && strcmp(*argv, "-s") == 0) {
+ totsize = atoi(argv[1]);
+ argc += 2, argv += 2;
+ }
+ dp = getdiskbyname(*argv);
+ if (dp == NULL) {
+ if (isatty(0))
+ dp = promptfordisk(*argv);
+ if (dp == NULL) {
+ fprintf(stderr, "%s: unknown disk type\n", *argv);
+ exit(2);
+ }
+ } else {
+ if (dp->d_flags & D_REMOVABLE)
+ tyname = "removable";
+ else if (dp->d_flags & D_RAMDISK)
+ tyname = "simulated";
+ else
+ tyname = "winchester";
+ }
+ spc = dp->d_secpercyl;
+ /*
+ * Bad sector table contains one track for the replicated
+ * copies of the table and enough full tracks preceding
+ * the last track to hold the pool of free blocks to which
+ * bad sectors are mapped.
+ * If disk size was specified explicitly, use specified size.
+ */
+ if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT &&
+ totsize == 0) {
+ badsecttable = dp->d_nsectors +
+ roundup(badsecttable, dp->d_nsectors);
+ threshhold = howmany(spc, badsecttable);
+ } else {
+ badsecttable = 0;
+ threshhold = 0;
+ }
+ /*
+ * If disk size was specified, recompute number of cylinders
+ * that may be used, and set badsecttable to any remaining
+ * fraction of the last cylinder.
+ */
+ if (totsize != 0) {
+ dp->d_ncylinders = howmany(totsize, spc);
+ badsecttable = spc * dp->d_ncylinders - totsize;
+ }
+
+ /*
+ * Figure out if disk is large enough for
+ * expanded swap area and 'd', 'e', and 'f'
+ * partitions. Otherwise, use smaller defaults
+ * based on RK07.
+ */
+ for (def = 0; def < NDEFAULTS; def++) {
+ curcyl = 0;
+ for (part = PART('a'); part < NPARTITIONS; part++)
+ curcyl += howmany(defpart[def][part], spc);
+ if (curcyl < dp->d_ncylinders - threshhold)
+ break;
+ }
+ if (def >= NDEFAULTS) {
+ fprintf(stderr, "%s: disk too small, calculate by hand\n",
+ *argv);
+ exit(3);
+ }
+
+ /*
+ * Calculate number of cylinders allocated to each disk
+ * partition. We may waste a bit of space here, but it's
+ * in the interest of (very backward) compatibility
+ * (for mixed disk systems).
+ */
+ for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) {
+ numcyls[part] = 0;
+ if (defpart[def][part] != 0) {
+ numcyls[part] = howmany(defpart[def][part], spc);
+ curcyl += numcyls[part];
+ }
+ }
+ numcyls[PART('f')] = dp->d_ncylinders - curcyl;
+ numcyls[PART('g')] =
+ numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')];
+ numcyls[PART('c')] = dp->d_ncylinders;
+ defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable;
+ defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable;
+ defpart[def][PART('c')] = numcyls[PART('c')] * spc;
+#ifndef for_now
+ if (totsize || !pflag)
+#else
+ if (totsize)
+#endif
+ defpart[def][PART('c')] -= badsecttable;
+
+ /*
+ * Calculate starting cylinder number for each partition.
+ * Note the 'h' partition is physically located before the
+ * 'g' or 'd' partition. This is reflected in the layout
+ * arrays defined above.
+ */
+ for (layout = 0; layout < NLAYOUTS; layout++) {
+ curcyl = 0;
+ for (lp = layouts[layout]; *lp != 0; lp++) {
+ startcyl[PART(*lp)] = curcyl;
+ curcyl += numcyls[PART(*lp)];
+ }
+ }
+
+ if (pflag) {
+ printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS);
+ for (part = PART('a'); part < NPARTITIONS; part++) {
+ if (numcyls[part] == 0) {
+ printf("\t0,\t0,\n");
+ continue;
+ }
+ if (dp->d_type != DTYPE_MSCP) {
+ printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
+ defpart[def][part], startcyl[part],
+ 'A' + part, startcyl[part],
+ startcyl[part] + numcyls[part] - 1);
+ continue;
+ }
+ printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
+ defpart[def][part], spc * startcyl[part],
+ 'A' + part, spc * startcyl[part],
+ spc * startcyl[part] + defpart[def][part] - 1);
+ }
+ exit(0);
+ }
+ if (dflag) {
+ int nparts;
+
+ /*
+ * In case the disk is in the ``in-between'' range
+ * where the 'g' partition is smaller than the 'h'
+ * partition, reverse the frag sizes so the /usr partition
+ * is always set up with a frag size larger than the
+ * user's partition.
+ */
+ if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
+ int temp;
+
+ temp = defparam[PART('h')].p_fsize;
+ defparam[PART('h')].p_fsize =
+ defparam[PART('g')].p_fsize;
+ defparam[PART('g')].p_fsize = temp;
+ }
+ printf("%s:\\\n", dp->d_typename);
+ printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname,
+ dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
+ if (dp->d_secpercyl != dp->d_nsectors * dp->d_ntracks)
+ printf("sc#%d:", dp->d_secpercyl);
+ if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT)
+ printf("sf:");
+ printf("\\\n\t:dt=%s:", dktypenames[dp->d_type]);
+ for (part = NDDATA - 1; part >= 0; part--)
+ if (dp->d_drivedata[part])
+ break;
+ for (j = 0; j <= part; j++)
+ printf("d%d#%d:", j, dp->d_drivedata[j]);
+ printf("\\\n");
+ for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
+ if (defpart[def][part] != 0)
+ nparts++;
+ for (part = PART('a'); part < NPARTITIONS; part++) {
+ if (defpart[def][part] == 0)
+ continue;
+ printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
+ printf("o%c#%d:b%c#%d:f%c#%d:",
+ 'a' + part, spc * startcyl[part],
+ 'a' + part,
+ defparam[part].p_frag * defparam[part].p_fsize,
+ 'a' + part, defparam[part].p_fsize);
+ if (defparam[part].p_fstype == FS_SWAP)
+ printf("t%c=swap:", 'a' + part);
+ nparts--;
+ printf("%s\n", nparts > 0 ? "\\" : "");
+ }
+#ifdef for_now
+ defpart[def][PART('c')] -= badsecttable;
+ part = PART('c');
+ printf("#\t:p%c#%d:", 'a' + part, defpart[def][part]);
+ printf("o%c#%d:b%c#%d:f%c#%d:\n",
+ 'a' + part, spc * startcyl[part],
+ 'a' + part,
+ defparam[part].p_frag * defparam[part].p_fsize,
+ 'a' + part, defparam[part].p_fsize);
+#endif
+ exit(0);
+ }
+ printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
+ dp->d_typename, dp->d_nsectors, dp->d_ntracks,
+ dp->d_ncylinders);
+ printf("\n Partition\t Size\t Offset\t Range\n");
+ for (part = PART('a'); part < NPARTITIONS; part++) {
+ printf("\t%c\t", 'a' + part);
+ if (numcyls[part] == 0) {
+ printf(" unused\n");
+ continue;
+ }
+ printf("%7d\t%7d\t%4d - %d%s\n",
+ defpart[def][part], startcyl[part] * spc,
+ startcyl[part], startcyl[part] + numcyls[part] - 1,
+ defpart[def][part] % spc ? "*" : "");
+ }
+}
+
+struct disklabel disk;
+
+struct field {
+ char *f_name;
+ char *f_defaults;
+ u_long *f_location;
+} fields[] = {
+ { "sector size", "512", &disk.d_secsize },
+ { "#sectors/track", 0, &disk.d_nsectors },
+ { "#tracks/cylinder", 0, &disk.d_ntracks },
+ { "#cylinders", 0, &disk.d_ncylinders },
+ { 0, 0, 0 },
+};
+
+struct disklabel *
+promptfordisk(name)
+ char *name;
+{
+ register struct disklabel *dp = &disk;
+ register struct field *fp;
+ register i;
+ char buf[BUFSIZ], **tp, *cp, *gets();
+
+ strncpy(dp->d_typename, name, sizeof(dp->d_typename));
+ fprintf(stderr,
+ "%s: unknown disk type, want to supply parameters (y/n)? ",
+ name);
+ (void) gets(buf);
+ if (*buf != 'y')
+ return ((struct disklabel *)0);
+ for (;;) {
+ fprintf(stderr, "Disk/controller type (%s)? ", dktypenames[1]);
+ (void) gets(buf);
+ if (buf[0] == 0)
+ dp->d_type = 1;
+ else
+ dp->d_type = gettype(buf, dktypenames);
+ if (dp->d_type >= 0)
+ break;
+ fprintf(stderr, "%s: unrecognized controller type\n", buf);
+ fprintf(stderr, "use one of:\n", buf);
+ for (tp = dktypenames; *tp; tp++)
+ if (index(*tp, ' ') == 0)
+ fprintf(stderr, "\t%s\n", *tp);
+ }
+gettype:
+ dp->d_flags = 0;
+ fprintf(stderr, "type (winchester|removable|simulated)? ");
+ (void) gets(buf);
+ if (strcmp(buf, "removable") == 0)
+ dp->d_flags = D_REMOVABLE;
+ else if (strcmp(buf, "simulated") == 0)
+ dp->d_flags = D_RAMDISK;
+ else if (strcmp(buf, "winchester")) {
+ fprintf(stderr, "%s: bad disk type\n", buf);
+ goto gettype;
+ }
+ strncpy(dp->d_typename, buf, sizeof(dp->d_typename));
+ fprintf(stderr, "(type <cr> to get default value, if only one)\n");
+ if (dp->d_type == DTYPE_SMD)
+ fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ",
+ dp->d_typename);
+ (void) gets(buf);
+ if (*buf != 'n')
+ dp->d_flags |= D_BADSECT;
+ for (fp = fields; fp->f_name != NULL; fp++) {
+again:
+ fprintf(stderr, "%s ", fp->f_name);
+ if (fp->f_defaults != NULL)
+ fprintf(stderr, "(%s)", fp->f_defaults);
+ fprintf(stderr, "? ");
+ cp = gets(buf);
+ if (*cp == '\0') {
+ if (fp->f_defaults == NULL) {
+ fprintf(stderr, "no default value\n");
+ goto again;
+ }
+ cp = fp->f_defaults;
+ }
+ *fp->f_location = atol(cp);
+ if (*fp->f_location == 0) {
+ fprintf(stderr, "%s: bad value\n", cp);
+ goto again;
+ }
+ }
+ fprintf(stderr, "sectors/cylinder (%d)? ",
+ dp->d_nsectors * dp->d_ntracks);
+ (void) gets(buf);
+ if (buf[0] == 0)
+ dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks;
+ else
+ dp->d_secpercyl = atol(buf);
+ fprintf(stderr, "Drive-type-specific parameters, <cr> to terminate:\n");
+ for (i = 0; i < NDDATA; i++) {
+ fprintf(stderr, "d%d? ", i);
+ (void) gets(buf);
+ if (buf[0] == 0)
+ break;
+ dp->d_drivedata[i] = atol(buf);
+ }
+ return (dp);
+}
+
+gettype(t, names)
+ char *t;
+ char **names;
+{
+ register char **nm;
+
+ for (nm = names; *nm; nm++)
+ if (ustrcmp(t, *nm) == 0)
+ return (nm - names);
+ if (isdigit(*t))
+ return (atoi(t));
+ return (-1);
+}
+
+ustrcmp(s1, s2)
+ register char *s1, *s2;
+{
+#define lower(c) (islower(c) ? (c) : tolower(c))
+
+ for (; *s1; s1++, s2++) {
+ if (*s1 == *s2)
+ continue;
+ if (isalpha(*s1) && isalpha(*s2) &&
+ lower(*s1) == lower(*s2))
+ continue;
+ return (*s2 - *s1);
+ }
+ return (0);
+}
diff --git a/usr.sbin/edquota/Makefile b/usr.sbin/edquota/Makefile
new file mode 100644
index 0000000..38fa90c
--- /dev/null
+++ b/usr.sbin/edquota/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= edquota
+MAN8= edquota.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/edquota/edquota.8 b/usr.sbin/edquota/edquota.8
new file mode 100644
index 0000000..f5bf705
--- /dev/null
+++ b/usr.sbin/edquota/edquota.8
@@ -0,0 +1,150 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)edquota.8 8.1 (Berkeley) 6/6/93
+.\"
+.TH EDQUOTA 8 "June 6, 1993"
+.UC 5
+.SH NAME
+edquota \- edit user quotas
+.SH SYNOPSIS
+.B edquota
+[
+.I \-u
+] [
+.I \-p
+proto-username
+]
+username ...
+.br
+.B edquota
+.I \-g
+[
+.I \-p
+proto-groupname
+]
+groupname ...
+.br
+.B edquota
+.I -t
+[
+.I -u
+]
+.br
+.B edquota
+.I -t
+.I -g
+.br
+.SH DESCRIPTION
+.I Edquota
+is a quota editor.
+By default, or if the \fI-u\fP flag is specified,
+one or more users may be specified on the command line.
+For each user a temporary file is created
+with an ASCII representation of the current
+disk quotas for that user.
+The list of filesystems with user quotas is determined from
+.IR /etc/fstab .
+An editor is invoked on the ASCII file.
+The editor invoked is
+.IR vi (1)
+unless the environment variable EDITOR specifies otherwise.
+.PP
+The quotas may then be modified, new quotas added, etc.
+Setting a quota to zero indicates that no quota should be imposed.
+Setting a hard limit to one indicates that no allocations should
+be permitted.
+Setting a soft limit to one with a hard limit of zero
+indicates that allocations should be permitted on
+only a temporary basis (see \fI-t\fP below).
+The current usage information in the file is for informational purposes;
+only the hard and soft limits can be changed.
+.PP
+On leaving the editor,
+.I edquota
+reads the temporary file and modifies the binary
+quota files to reflect the changes made.
+.PP
+If the
+.B \-p
+option is specified,
+.I edquota
+will duplicate the quotas of the prototypical user
+specified for each user specified.
+This is the normal mechanism used to
+initialize quotas for groups of users.
+.PP
+If the \fI-g\fP flag is specified,
+.I edquota
+is invoked to edit the quotas of
+one or more groups specified on the command line.
+The \fI-p\fP flag can be specified in conjunction with
+the \fI-g\fP flag to specify a prototypical group
+to be duplicated among the listed set of groups.
+.PP
+Users are permitted to exceed their soft limits
+for a grace period that may be specified per filesystem.
+Once the grace period has expired,
+the soft limit is enforced as a hard limit.
+The default grace period for a filesystem is specified in
+.IR /usr/include/ufs/quota.h .
+The \fI-t\fP flag can be used to change the grace period.
+By default, or when invoked with the \fI-u\fP flag,
+the grace period is set for all the filesystems with user
+quotas specified in
+.IR /etc/fstab .
+When invoked with the \fI-g\fP flag the grace period is
+set for all the filesystems with group quotas specified in
+.IR /etc/fstab .
+The grace period may be specified in days, hours, minutes, or seconds.
+Setting a grace period to zero indicates that the default
+grace period should be imposed.
+Setting a grace period to one second indicates that no
+grace period should be granted.
+.PP
+Only the super-user may edit quotas.
+.SH FILES
+.DT
+\fIquota.user\fP at the filesystem root with user quotas
+.br
+\fIquota.group\fP at the filesystem root with group quotas
+.br
+/etc/fstab to find filesystem names and locations
+.SH SEE ALSO
+quota(1),
+quotactl(2),
+fstab(5),
+quotacheck(8), quotaon(8), repquota(8)
+.SH DIAGNOSTICS
+Various messages about inaccessible files; self-explanatory.
diff --git a/usr.sbin/edquota/edquota.c b/usr.sbin/edquota/edquota.c
new file mode 100644
index 0000000..3646720
--- /dev/null
+++ b/usr.sbin/edquota/edquota.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)edquota.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Disk quota editor.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <ufs/ufs/quota.h>
+#include <errno.h>
+#include <fstab.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "pathnames.h"
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+char *quotagroup = QUOTAGROUP;
+char tmpfil[] = _PATH_TMP;
+
+struct quotause {
+ struct quotause *next;
+ long flags;
+ struct dqblk dqblk;
+ char fsname[MAXPATHLEN + 1];
+ char qfname[1]; /* actually longer */
+} *getprivs();
+#define FOUND 0x01
+
+main(argc, argv)
+ register char **argv;
+ int argc;
+{
+ register struct quotause *qup, *protoprivs, *curprivs;
+ extern char *optarg;
+ extern int optind;
+ register long id, protoid;
+ register int quotatype, tmpfd;
+ char *protoname, ch;
+ int tflag = 0, pflag = 0;
+
+ if (argc < 2)
+ usage();
+ if (getuid()) {
+ fprintf(stderr, "edquota: permission denied\n");
+ exit(1);
+ }
+ quotatype = USRQUOTA;
+ while ((ch = getopt(argc, argv, "ugtp:")) != EOF) {
+ switch(ch) {
+ case 'p':
+ protoname = optarg;
+ pflag++;
+ break;
+ case 'g':
+ quotatype = GRPQUOTA;
+ break;
+ case 'u':
+ quotatype = USRQUOTA;
+ break;
+ case 't':
+ tflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (pflag) {
+ if ((protoid = getentry(protoname, quotatype)) == -1)
+ exit(1);
+ protoprivs = getprivs(protoid, quotatype);
+ for (qup = protoprivs; qup; qup = qup->next) {
+ qup->dqblk.dqb_btime = 0;
+ qup->dqblk.dqb_itime = 0;
+ }
+ while (argc-- > 0) {
+ if ((id = getentry(*argv++, quotatype)) < 0)
+ continue;
+ putprivs(id, quotatype, protoprivs);
+ }
+ exit(0);
+ }
+ tmpfd = mkstemp(tmpfil);
+ fchown(tmpfd, getuid(), getgid());
+ if (tflag) {
+ protoprivs = getprivs(0, quotatype);
+ if (writetimes(protoprivs, tmpfd, quotatype) == 0)
+ exit(1);
+ if (editit(tmpfil) && readtimes(protoprivs, tmpfd))
+ putprivs(0, quotatype, protoprivs);
+ freeprivs(protoprivs);
+ exit(0);
+ }
+ for ( ; argc > 0; argc--, argv++) {
+ if ((id = getentry(*argv, quotatype)) == -1)
+ continue;
+ curprivs = getprivs(id, quotatype);
+ if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)
+ continue;
+ if (editit(tmpfil) && readprivs(curprivs, tmpfd))
+ putprivs(id, quotatype, curprivs);
+ freeprivs(curprivs);
+ }
+ close(tmpfd);
+ unlink(tmpfil);
+ exit(0);
+}
+
+usage()
+{
+ fprintf(stderr, "%s%s%s%s",
+ "Usage: edquota [-u] [-p username] username ...\n",
+ "\tedquota -g [-p groupname] groupname ...\n",
+ "\tedquota [-u] -t\n", "\tedquota -g -t\n");
+ exit(1);
+}
+
+/*
+ * This routine converts a name for a particular quota type to
+ * an identifier. This routine must agree with the kernel routine
+ * getinoquota as to the interpretation of quota types.
+ */
+getentry(name, quotatype)
+ char *name;
+ int quotatype;
+{
+ struct passwd *pw;
+ struct group *gr;
+
+ if (alldigits(name))
+ return (atoi(name));
+ switch(quotatype) {
+ case USRQUOTA:
+ if (pw = getpwnam(name))
+ return (pw->pw_uid);
+ fprintf(stderr, "%s: no such user\n", name);
+ break;
+ case GRPQUOTA:
+ if (gr = getgrnam(name))
+ return (gr->gr_gid);
+ fprintf(stderr, "%s: no such group\n", name);
+ break;
+ default:
+ fprintf(stderr, "%d: unknown quota type\n", quotatype);
+ break;
+ }
+ sleep(1);
+ return (-1);
+}
+
+/*
+ * Collect the requested quota information.
+ */
+struct quotause *
+getprivs(id, quotatype)
+ register long id;
+ int quotatype;
+{
+ register struct fstab *fs;
+ register struct quotause *qup, *quptail;
+ struct quotause *quphead;
+ int qcmd, qupsize, fd;
+ char *qfpathname;
+ static int warned = 0;
+ extern int errno;
+
+ setfsent();
+ quphead = (struct quotause *)0;
+ qcmd = QCMD(Q_GETQUOTA, quotatype);
+ while (fs = getfsent()) {
+ if (strcmp(fs->fs_vfstype, "ufs"))
+ continue;
+ if (!hasquota(fs, quotatype, &qfpathname))
+ continue;
+ qupsize = sizeof(*qup) + strlen(qfpathname);
+ if ((qup = (struct quotause *)malloc(qupsize)) == NULL) {
+ fprintf(stderr, "edquota: out of memory\n");
+ exit(2);
+ }
+ if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
+ if (errno == EOPNOTSUPP && !warned) {
+ warned++;
+ fprintf(stderr, "Warning: %s\n",
+ "Quotas are not compiled into this kernel");
+ sleep(3);
+ }
+ if ((fd = open(qfpathname, O_RDONLY)) < 0) {
+ fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
+ if (fd < 0 && errno != ENOENT) {
+ perror(qfpathname);
+ free(qup);
+ continue;
+ }
+ fprintf(stderr, "Creating quota file %s\n",
+ qfpathname);
+ sleep(3);
+ (void) fchown(fd, getuid(),
+ getentry(quotagroup, GRPQUOTA));
+ (void) fchmod(fd, 0640);
+ }
+ lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
+ switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
+ case 0: /* EOF */
+ /*
+ * Convert implicit 0 quota (EOF)
+ * into an explicit one (zero'ed dqblk)
+ */
+ bzero((caddr_t)&qup->dqblk,
+ sizeof(struct dqblk));
+ break;
+
+ case sizeof(struct dqblk): /* OK */
+ break;
+
+ default: /* ERROR */
+ fprintf(stderr, "edquota: read error in ");
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ close(fd);
+ }
+ strcpy(qup->qfname, qfpathname);
+ strcpy(qup->fsname, fs->fs_file);
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ qup->next = 0;
+ }
+ endfsent();
+ return (quphead);
+}
+
+/*
+ * Store the requested quota information.
+ */
+putprivs(id, quotatype, quplist)
+ long id;
+ int quotatype;
+ struct quotause *quplist;
+{
+ register struct quotause *qup;
+ int qcmd, fd;
+
+ qcmd = QCMD(Q_SETQUOTA, quotatype);
+ for (qup = quplist; qup; qup = qup->next) {
+ if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0)
+ continue;
+ if ((fd = open(qup->qfname, O_WRONLY)) < 0) {
+ perror(qup->qfname);
+ } else {
+ lseek(fd, (long)id * (long)sizeof (struct dqblk), 0);
+ if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
+ sizeof (struct dqblk)) {
+ fprintf(stderr, "edquota: ");
+ perror(qup->qfname);
+ }
+ close(fd);
+ }
+ }
+}
+
+/*
+ * Take a list of priviledges and get it edited.
+ */
+editit(tmpfile)
+ char *tmpfile;
+{
+ long omask;
+ int pid, stat;
+ extern char *getenv();
+
+ omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
+ top:
+ if ((pid = fork()) < 0) {
+ extern errno;
+
+ if (errno == EPROCLIM) {
+ fprintf(stderr, "You have too many processes\n");
+ return(0);
+ }
+ if (errno == EAGAIN) {
+ sleep(1);
+ goto top;
+ }
+ perror("fork");
+ return (0);
+ }
+ if (pid == 0) {
+ register char *ed;
+
+ sigsetmask(omask);
+ setgid(getgid());
+ setuid(getuid());
+ if ((ed = getenv("EDITOR")) == (char *)0)
+ ed = _PATH_VI;
+ execlp(ed, ed, tmpfile, 0);
+ perror(ed);
+ exit(1);
+ }
+ waitpid(pid, &stat, 0);
+ sigsetmask(omask);
+ if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0)
+ return (0);
+ return (1);
+}
+
+/*
+ * Convert a quotause list to an ASCII file.
+ */
+writeprivs(quplist, outfd, name, quotatype)
+ struct quotause *quplist;
+ int outfd;
+ char *name;
+ int quotatype;
+{
+ register struct quotause *qup;
+ FILE *fd;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, L_SET);
+ if ((fd = fdopen(dup(outfd), "w")) == NULL) {
+ fprintf(stderr, "edquota: ");
+ perror(tmpfil);
+ exit(1);
+ }
+ fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name);
+ for (qup = quplist; qup; qup = qup->next) {
+ fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n",
+ qup->fsname, "blocks in use:",
+ dbtob(qup->dqblk.dqb_curblocks) / 1024,
+ dbtob(qup->dqblk.dqb_bsoftlimit) / 1024,
+ dbtob(qup->dqblk.dqb_bhardlimit) / 1024);
+ fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n",
+ "\tinodes in use:", qup->dqblk.dqb_curinodes,
+ qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit);
+ }
+ fclose(fd);
+ return (1);
+}
+
+/*
+ * Merge changes to an ASCII file into a quotause list.
+ */
+readprivs(quplist, infd)
+ struct quotause *quplist;
+ int infd;
+{
+ register struct quotause *qup;
+ FILE *fd;
+ int cnt;
+ register char *cp;
+ struct dqblk dqblk;
+ char *fsp, line1[BUFSIZ], line2[BUFSIZ];
+
+ lseek(infd, 0, L_SET);
+ fd = fdopen(dup(infd), "r");
+ if (fd == NULL) {
+ fprintf(stderr, "Can't re-read temp file!!\n");
+ return (0);
+ }
+ /*
+ * Discard title line, then read pairs of lines to process.
+ */
+ (void) fgets(line1, sizeof (line1), fd);
+ while (fgets(line1, sizeof (line1), fd) != NULL &&
+ fgets(line2, sizeof (line2), fd) != NULL) {
+ if ((fsp = strtok(line1, " \t:")) == NULL) {
+ fprintf(stderr, "%s: bad format\n", line1);
+ return (0);
+ }
+ if ((cp = strtok((char *)0, "\n")) == NULL) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp,
+ &fsp[strlen(fsp) + 1]);
+ return (0);
+ }
+ cnt = sscanf(cp,
+ " blocks in use: %d, limits (soft = %d, hard = %d)",
+ &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit,
+ &dqblk.dqb_bhardlimit);
+ if (cnt != 3) {
+ fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
+ return (0);
+ }
+ dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024);
+ dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024);
+ dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024);
+ if ((cp = strtok(line2, "\n")) == NULL) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
+ return (0);
+ }
+ cnt = sscanf(cp,
+ "\tinodes in use: %d, limits (soft = %d, hard = %d)",
+ &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit,
+ &dqblk.dqb_ihardlimit);
+ if (cnt != 3) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
+ return (0);
+ }
+ for (qup = quplist; qup; qup = qup->next) {
+ if (strcmp(fsp, qup->fsname))
+ continue;
+ /*
+ * Cause time limit to be reset when the quota
+ * is next used if previously had no soft limit
+ * or were under it, but now have a soft limit
+ * and are over it.
+ */
+ if (dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit &&
+ (qup->dqblk.dqb_bsoftlimit == 0 ||
+ qup->dqblk.dqb_curblocks <
+ qup->dqblk.dqb_bsoftlimit))
+ qup->dqblk.dqb_btime = 0;
+ if (dqblk.dqb_isoftlimit &&
+ qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit &&
+ (qup->dqblk.dqb_isoftlimit == 0 ||
+ qup->dqblk.dqb_curinodes <
+ qup->dqblk.dqb_isoftlimit))
+ qup->dqblk.dqb_itime = 0;
+ qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit;
+ qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit;
+ qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit;
+ qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit;
+ qup->flags |= FOUND;
+ if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks &&
+ dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes)
+ break;
+ fprintf(stderr,
+ "%s: cannot change current allocation\n", fsp);
+ break;
+ }
+ }
+ fclose(fd);
+ /*
+ * Disable quotas for any filesystems that have not been found.
+ */
+ for (qup = quplist; qup; qup = qup->next) {
+ if (qup->flags & FOUND) {
+ qup->flags &= ~FOUND;
+ continue;
+ }
+ qup->dqblk.dqb_bsoftlimit = 0;
+ qup->dqblk.dqb_bhardlimit = 0;
+ qup->dqblk.dqb_isoftlimit = 0;
+ qup->dqblk.dqb_ihardlimit = 0;
+ }
+ return (1);
+}
+
+/*
+ * Convert a quotause list to an ASCII file of grace times.
+ */
+writetimes(quplist, outfd, quotatype)
+ struct quotause *quplist;
+ int outfd;
+ int quotatype;
+{
+ register struct quotause *qup;
+ char *cvtstoa();
+ FILE *fd;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, L_SET);
+ if ((fd = fdopen(dup(outfd), "w")) == NULL) {
+ fprintf(stderr, "edquota: ");
+ perror(tmpfil);
+ exit(1);
+ }
+ fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n");
+ fprintf(fd, "Grace period before enforcing soft limits for %ss:\n",
+ qfextension[quotatype]);
+ for (qup = quplist; qup; qup = qup->next) {
+ fprintf(fd, "%s: block grace period: %s, ",
+ qup->fsname, cvtstoa(qup->dqblk.dqb_btime));
+ fprintf(fd, "file grace period: %s\n",
+ cvtstoa(qup->dqblk.dqb_itime));
+ }
+ fclose(fd);
+ return (1);
+}
+
+/*
+ * Merge changes of grace times in an ASCII file into a quotause list.
+ */
+readtimes(quplist, infd)
+ struct quotause *quplist;
+ int infd;
+{
+ register struct quotause *qup;
+ FILE *fd;
+ int cnt;
+ register char *cp;
+ time_t itime, btime, iseconds, bseconds;
+ char *fsp, bunits[10], iunits[10], line1[BUFSIZ];
+
+ lseek(infd, 0, L_SET);
+ fd = fdopen(dup(infd), "r");
+ if (fd == NULL) {
+ fprintf(stderr, "Can't re-read temp file!!\n");
+ return (0);
+ }
+ /*
+ * Discard two title lines, then read lines to process.
+ */
+ (void) fgets(line1, sizeof (line1), fd);
+ (void) fgets(line1, sizeof (line1), fd);
+ while (fgets(line1, sizeof (line1), fd) != NULL) {
+ if ((fsp = strtok(line1, " \t:")) == NULL) {
+ fprintf(stderr, "%s: bad format\n", line1);
+ return (0);
+ }
+ if ((cp = strtok((char *)0, "\n")) == NULL) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp,
+ &fsp[strlen(fsp) + 1]);
+ return (0);
+ }
+ cnt = sscanf(cp,
+ " block grace period: %d %s file grace period: %d %s",
+ &btime, bunits, &itime, iunits);
+ if (cnt != 4) {
+ fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
+ return (0);
+ }
+ if (cvtatos(btime, bunits, &bseconds) == 0)
+ return (0);
+ if (cvtatos(itime, iunits, &iseconds) == 0)
+ return (0);
+ for (qup = quplist; qup; qup = qup->next) {
+ if (strcmp(fsp, qup->fsname))
+ continue;
+ qup->dqblk.dqb_btime = bseconds;
+ qup->dqblk.dqb_itime = iseconds;
+ qup->flags |= FOUND;
+ break;
+ }
+ }
+ fclose(fd);
+ /*
+ * reset default grace periods for any filesystems
+ * that have not been found.
+ */
+ for (qup = quplist; qup; qup = qup->next) {
+ if (qup->flags & FOUND) {
+ qup->flags &= ~FOUND;
+ continue;
+ }
+ qup->dqblk.dqb_btime = 0;
+ qup->dqblk.dqb_itime = 0;
+ }
+ return (1);
+}
+
+/*
+ * Convert seconds to ASCII times.
+ */
+char *
+cvtstoa(time)
+ time_t time;
+{
+ static char buf[20];
+
+ if (time % (24 * 60 * 60) == 0) {
+ time /= 24 * 60 * 60;
+ sprintf(buf, "%d day%s", time, time == 1 ? "" : "s");
+ } else if (time % (60 * 60) == 0) {
+ time /= 60 * 60;
+ sprintf(buf, "%d hour%s", time, time == 1 ? "" : "s");
+ } else if (time % 60 == 0) {
+ time /= 60;
+ sprintf(buf, "%d minute%s", time, time == 1 ? "" : "s");
+ } else
+ sprintf(buf, "%d second%s", time, time == 1 ? "" : "s");
+ return (buf);
+}
+
+/*
+ * Convert ASCII input times to seconds.
+ */
+cvtatos(time, units, seconds)
+ time_t time;
+ char *units;
+ time_t *seconds;
+{
+
+ if (bcmp(units, "second", 6) == 0)
+ *seconds = time;
+ else if (bcmp(units, "minute", 6) == 0)
+ *seconds = time * 60;
+ else if (bcmp(units, "hour", 4) == 0)
+ *seconds = time * 60 * 60;
+ else if (bcmp(units, "day", 3) == 0)
+ *seconds = time * 24 * 60 * 60;
+ else {
+ printf("%s: bad units, specify %s\n", units,
+ "days, hours, minutes, or seconds");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Free a list of quotause structures.
+ */
+freeprivs(quplist)
+ struct quotause *quplist;
+{
+ register struct quotause *qup, *nextqup;
+
+ for (qup = quplist; qup; qup = nextqup) {
+ nextqup = qup->next;
+ free(qup);
+ }
+}
+
+/*
+ * Check whether a string is completely composed of digits.
+ */
+alldigits(s)
+ register char *s;
+{
+ register c;
+
+ c = *s++;
+ do {
+ if (!isdigit(c))
+ return (0);
+ } while (c = *s++);
+ return (1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
+ sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strcpy(buf, fs->fs_mntops);
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
diff --git a/usr.sbin/edquota/pathnames.h b/usr.sbin/edquota/pathnames.h
new file mode 100644
index 0000000..92546f7
--- /dev/null
+++ b/usr.sbin/edquota/pathnames.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#undef _PATH_TMP
+#define _PATH_TMP "/tmp/EdP.aXXXXX"
diff --git a/usr.sbin/eeprom/Makefile b/usr.sbin/eeprom/Makefile
new file mode 100644
index 0000000..389a137
--- /dev/null
+++ b/usr.sbin/eeprom/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= eeprom
+MAN8= eeprom.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/eeprom/eeprom.8 b/usr.sbin/eeprom/eeprom.8
new file mode 100644
index 0000000..07c3969
--- /dev/null
+++ b/usr.sbin/eeprom/eeprom.8
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This software was developed by the Computer Systems Engineering group
+.\" at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+.\" contributed to Berkeley.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)eeprom.8 8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt EEPROM 8
+.Os BSD 4.4
+.Sh NAME
+.Nm eeprom
+.Nd openprom control utility
+.Sh SYNOPSIS
+.Nm eeprom
+.Op Ar name Ar ...
+.Op Ar name=value Ar ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+is used to display
+and modify options fields in the SPARCstation openprom.
+.Pp
+When invoked with no arguments,
+.Nm
+display the values of all options. Otherwise, fields are displayed or
+set (in the order specified on the command line).
+.Sh FILES
+.Bl -tag -width /dev/openprom -compact
+.It Pa /dev/openprom
+the openprom device
+.El
+.Sh SEE ALSO
+.Xr openprom 4
+.Sh HISTORY
+The
+.Nm eeprom
+utility first appeared in 4.4BSD.
diff --git a/usr.sbin/eeprom/eeprom.c b/usr.sbin/eeprom/eeprom.c
new file mode 100644
index 0000000..2015fed
--- /dev/null
+++ b/usr.sbin/eeprom/eeprom.c
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)eeprom.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * eeprom - openprom control utility
+ *
+ * usage:
+ *
+ * eeprom [field] [field=value]
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <machine/openpromio.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pathnames.h"
+
+static char openprom[] = _PATH_OPENPROM;
+static char usage[] = "usage: %s [field] [field=value]\n";
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register char *cp;
+ register int i, op, fd, flags, status;
+ register struct opiocdesc *dp;
+ struct opiocdesc desc;
+ char buf[1024], buf2[sizeof(buf)];
+ char *prog, *name;
+
+ /* Determine simple program name for error messages */
+ if (cp = rindex(argv[0], '/'))
+ prog = cp + 1;
+ else
+ prog = argv[0];
+
+ /* Parse flags */
+ opterr = 0;
+ while ((op = getopt(argc, argv, "")) != EOF)
+ switch (op) {
+
+ default:
+ (void) fprintf(stderr, usage, prog);
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Determine flags and open device */
+ flags = O_RDONLY;
+ for (i = 0; i < argc; ++i)
+ if (index(argv[i], '=') != NULL) {
+ flags = O_RDWR;
+ break;
+ }
+ if ((fd = open(openprom, flags, 0)) < 0) {
+ fprintf(stderr, "%s: open %s: %s\n",
+ prog, openprom, strerror(errno));
+ exit(1);
+ }
+
+ dp = &desc;
+ bzero(dp, sizeof(*dp));
+ if (ioctl(fd, OPIOCGETOPTNODE, &dp->op_nodeid) < 0) {
+ fprintf(stderr, "%s: get optionsnode: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+
+ if (argc <= 0) {
+ /* Prime the pump with a zero length name */
+ dp->op_name = buf;
+ dp->op_name[0] = '\0';
+ dp->op_namelen = 0;
+ dp->op_buf = buf2;
+ for (;;) {
+ /* Get the next property name */
+ dp->op_buflen = sizeof(buf);
+ if (ioctl(fd, OPIOCNEXTPROP, dp) < 0) {
+ fprintf(stderr, "%s: get next: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+
+ /* Zero length name means we're done */
+ if (dp->op_buflen <= 0)
+ break;
+
+ /* Clever hack, swap buffers */
+ cp = dp->op_buf;
+ dp->op_buf = dp->op_name;
+ dp->op_name = cp;
+ dp->op_namelen = dp->op_buflen;
+
+ /* Get the value */
+ dp->op_buflen = sizeof(buf);
+ if (ioctl(fd, OPIOCGET, dp) < 0) {
+ fprintf(stderr, "%s: get \"%s\": %s\n",
+ prog, cp, strerror(errno));
+ exit(1);
+ }
+ printf("%.*s=%.*s\n", dp->op_namelen, dp->op_name,
+ dp->op_buflen, dp->op_buf);
+ }
+ exit(0);
+ }
+
+ status = 0;
+ for (i = 0; i < argc; ++i) {
+ dp->op_name = name = argv[i];
+ cp = index(name, '=');
+ if (cp) {
+ *cp++ = '\0';
+ dp->op_buf = cp;
+ dp->op_buflen = strlen(dp->op_buf);
+ } else {
+ dp->op_buf = buf;
+ dp->op_buflen = sizeof(buf);
+ }
+ dp->op_namelen = strlen(name);
+ if (ioctl(fd, cp ? OPIOCSET : OPIOCGET, dp) < 0) {
+ fprintf(stderr, "%s: %s \"%s\": %s\n",
+ prog, cp ? "set" : "get", name, strerror(errno));
+ status |= 1;
+ continue;
+ }
+
+ /* If setting an entry, we're done */
+ if (cp)
+ continue;
+ if (dp->op_buflen < 0) {
+ fprintf(stderr, "%s: \"%s\" not found\n", prog, name);
+ status |= 1;
+ continue;
+ }
+ if (dp->op_buflen >= sizeof(buf)) {
+ fprintf(stderr, "%s: \"%s\" truncated\n", prog, name);
+ status |= 1;
+ /* fall thorugh and print truncated value */
+ }
+ printf("%s=%.*s\n", name, dp->op_buflen, buf);
+ }
+
+ exit(status);
+}
diff --git a/usr.sbin/eeprom/pathnames.h b/usr.sbin/eeprom/pathnames.h
new file mode 100644
index 0000000..8df60ce
--- /dev/null
+++ b/usr.sbin/eeprom/pathnames.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#define _PATH_OPENPROM "/dev/openprom"
diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile
new file mode 100644
index 0000000..964b00d
--- /dev/null
+++ b/usr.sbin/inetd/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= inetd
+MAN8= inetd.0
+MLINKS= inetd.8 inetd.5
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/inetd/inetd.8 b/usr.sbin/inetd/inetd.8
new file mode 100644
index 0000000..5fe5711
--- /dev/null
+++ b/usr.sbin/inetd/inetd.8
@@ -0,0 +1,375 @@
+.\" Copyright (c) 1985, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)inetd.8 8.3 (Berkeley) 4/13/94
+.\"
+.Dd April 13, 1994
+.Dt INETD 8
+.Os BSD 4.4
+.Sh NAME
+.Nm inetd
+.Nd internet
+.Dq super-server
+.Sh SYNOPSIS
+.Nm inetd
+.Op Fl d
+.Op Fl R Ar rate
+.Op Ar configuration file
+.Sh DESCRIPTION
+The
+.Nm inetd
+program
+should be run at boot time by
+.Pa /etc/rc
+(see
+.Xr rc 8 ) .
+It then listens for connections on certain
+internet sockets. When a connection is found on one
+of its sockets, it decides what service the socket
+corresponds to, and invokes a program to service the request.
+The server program is invoked with the service socket
+as its standard input, output and error descriptors.
+After the program is
+finished,
+.Nm inetd
+continues to listen on the socket (except in some cases which
+will be described below). Essentially,
+.Nm inetd
+allows running one daemon to invoke several others,
+reducing load on the system.
+.Pp
+The options available for
+.Nm inetd:
+.Bl -tag -width Ds
+.It Fl d
+Turns on debugging.
+.It Fl R Ar rate
+Specifies the maximum number of times a service can be invoked
+in one minute; the default is 1000.
+.El
+.Pp
+Upon execution,
+.Nm inetd
+reads its configuration information from a configuration
+file which, by default, is
+.Pa /etc/inetd.conf .
+There must be an entry for each field of the configuration
+file, with entries for each field separated by a tab or
+a space. Comments are denoted by a ``#'' at the beginning
+of a line. There must be an entry for each field. The
+fields of the configuration file are as follows:
+.Pp
+.Bd -unfilled -offset indent -compact
+service name
+socket type
+protocol
+wait/nowait
+user
+server program
+server program arguments
+.Ed
+.Pp
+There are two types of services that
+.Nm inetd
+can start: standard and TCPMUX.
+A standard service has a well-known port assigned to it;
+it may be a service that implements an official Internet standard or is a
+BSD-specific service.
+As described in
+.Tn RFC 1078 ,
+TCPMUX services are nonstandard services that do not have a
+well-known port assigned to them.
+They are invoked from
+.Nm inetd
+when a program connects to the
+.Dq tcpmux
+well-known port and specifies
+the service name.
+This feature is useful for adding locally-developed servers.
+.Pp
+The
+.Em service-name
+entry is the name of a valid service in
+the file
+.Pa /etc/services .
+For
+.Dq internal
+services (discussed below), the service
+name
+.Em must
+be the official name of the service (that is, the first entry in
+.Pa /etc/services ) .
+For TCPMUX services, the value of the
+.Em service-name
+field consists of the string
+.Dq tcpmux
+followed by a slash and the
+locally-chosen service name.
+The service names listed in
+.Pa /etc/services
+and the name
+.Dq help
+are reserved.
+Try to choose unique names for your TCPMUX services by prefixing them with
+your organization's name and suffixing them with a version number.
+.Pp
+The
+.Em socket-type
+should be one of
+.Dq stream ,
+.Dq dgram ,
+.Dq raw ,
+.Dq rdm ,
+or
+.Dq seqpacket ,
+depending on whether the socket is a stream, datagram, raw,
+reliably delivered message, or sequenced packet socket.
+TCPMUX services must use
+.Dq stream .
+.Pp
+The
+.Em protocol
+must be a valid protocol as given in
+.Pa /etc/protocols .
+Examples might be
+.Dq tcp
+or
+.Dq udp .
+TCPMUX services must use
+.Dq tcp .
+.Pp
+The
+.Em wait/nowait
+entry specifies whether the server that is invoked by inetd will take over
+the socket associated with the service access point, and thus whether
+.Nm inetd
+should wait for the server to exit before listening for new service
+requests.
+Datagram servers must use
+.Dq wait ,
+as they are always invoked with the original datagram socket bound
+to the specified service address.
+These servers must read at least one datagram from the socket
+before exiting.
+If a datagram server connects
+to its peer, freeing the socket so
+.Nm inetd
+can received further messages on the socket, it is said to be
+a
+.Dq multi-threaded
+server;
+it should read one datagram from the socket and create a new socket
+connected to the peer.
+It should fork, and the parent should then exit
+to allow
+.Nm inetd
+to check for new service requests to spawn new servers.
+Datagram servers which process all incoming datagrams
+on a socket and eventually time out are said to be
+.Dq single-threaded .
+.Xr Comsat 8 ,
+.Pq Xr biff 1
+and
+.Xr talkd 8
+are both examples of the latter type of
+datagram server.
+.Xr Tftpd 8
+is an example of a multi-threaded datagram server.
+.Pp
+Servers using stream sockets generally are multi-threaded and
+use the
+.Dq nowait
+entry.
+Connection requests for these services are accepted by
+.Nm inetd ,
+and the server is given only the newly-accepted socket connected
+to a client of the service.
+Most stream-based services operate in this manner.
+Stream-based servers that use
+.Dq wait
+are started with the listening service socket, and must accept
+at least one connection request before exiting.
+Such a server would normally accept and process incoming connection
+requests until a timeout.
+TCPMUX services must use
+.Dq nowait .
+.Pp
+The
+.Em user
+entry should contain the user name of the user as whom the server
+should run. This allows for servers to be given less permission
+than root.
+.Pp
+The
+.Em server-program
+entry should contain the pathname of the program which is to be
+executed by
+.Nm inetd
+when a request is found on its socket. If
+.Nm inetd
+provides this service internally, this entry should
+be
+.Dq internal .
+.Pp
+The
+.Em server program arguments
+should be just as arguments
+normally are, starting with argv[0], which is the name of
+the program. If the service is provided internally, the
+word
+.Dq internal
+should take the place of this entry.
+.Pp
+The
+.Nm inetd
+program
+provides several
+.Dq trivial
+services internally by use of
+routines within itself. These services are
+.Dq echo ,
+.Dq discard ,
+.Dq chargen
+(character generator),
+.Dq daytime
+(human readable time), and
+.Dq time
+(machine readable time,
+in the form of the number of seconds since midnight, January
+1, 1900). All of these services are tcp based. For
+details of these services, consult the appropriate
+.Tn RFC
+from the Network Information Center.
+.Pp
+The
+.Nm inetd
+program
+rereads its configuration file when it receives a hangup signal,
+.Dv SIGHUP .
+Services may be added, deleted or modified when the configuration file
+is reread.
+.Sh TCPMUX
+.Pp
+.Tn RFC 1078
+describes the TCPMUX protocol:
+``A TCP client connects to a foreign host on TCP port 1. It sends the
+service name followed by a carriage-return line-feed <CRLF>. The
+service name is never case sensitive. The server replies with a
+single character indicating positive (+) or negative (\-)
+acknowledgment, immediately followed by an optional message of
+explanation, terminated with a <CRLF>. If the reply was positive,
+the selected protocol begins; otherwise the connection is closed.''
+The program is passed the TCP connection as file descriptors 0 and 1.
+.Pp
+If the TCPMUX service name begins with a ``+'',
+.Nm inetd
+returns the positive reply for the program.
+This allows you to invoke programs that use stdin/stdout
+without putting any special server code in them.
+.Pp
+The special service name
+.Dq help
+causes
+.Nm inetd
+to list TCPMUX services in
+.Pa inetd.conf .
+.Sh "EXAMPLES"
+.Pp
+Here are several example service entries for the various types of services:
+.Bd -literal
+ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
+ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd
+tcpmux/+date stream tcp nowait guest /bin/date date
+tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
+.Ed
+.Sh "ERROR MESSAGES"
+The
+.Nm inetd
+server
+logs error messages using
+.Xr syslog 3 .
+Important error messages and their explanations are:
+.Bd -literal
+\fIservice\fP/\fIprotocol\fP server failing (looping), service terminated.
+.Ed
+The number of requests for the specified service in the past minute
+exceeded the limit. The limit exists to prevent a broken program
+or a malicious user from swamping the system.
+This message may occur for several reasons:
+1) there are lots of hosts requesting the service within a short time period,
+2) a 'broken' client program is requesting the service too frequently,
+3) a malicious user is running a program to invoke the service in
+a 'denial of service' attack, or
+4) the invoked service program has an error that causes clients
+to retry quickly.
+Use the
+.Op Fl R
+option,
+as described above, to change the rate limit.
+Once the limit is reached, the service will be
+reenabled automatically in 10 minutes.
+.sp
+.Bd -literal
+\fIservice\fP/\fIprotocol\fP: No such user '\fIuser\fP', service ignored
+\fIservice\fP/\fIprotocol\fP: getpwnam: \fIuser\fP: No such user
+.Ed
+No entry for
+.Em user
+exists in the
+.Pa passwd
+file. The first message
+occurs when
+.Nm inetd
+(re)reads the configuration file. The second message occurs when the
+service is invoked.
+.sp
+.Bd -literal
+\fIservice\fP: can't set uid \fInumber\fP
+\fIservice\fP: can't set gid \fInumber\fP
+.Ed
+The user or group ID for the entry's
+.Em user
+is invalid.
+.Sh SEE ALSO
+.Xr comsat 8 ,
+.Xr fingerd 8 ,
+.Xr ftpd 8 ,
+.Xr rexecd 8 ,
+.Xr rlogind 8 ,
+.Xr rshd 8 ,
+.Xr telnetd 8 ,
+.Xr tftpd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+TCPMUX is based on code and documentation by Mark Lottor.
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
new file mode 100644
index 0000000..50dfb43
--- /dev/null
+++ b/usr.sbin/inetd/inetd.c
@@ -0,0 +1,1255 @@
+/*
+ * Copyright (c) 1983, 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94";
+#endif /* not lint */
+
+/*
+ * Inetd - Internet super-server
+ *
+ * This program invokes all internet services as needed. Connection-oriented
+ * services are invoked each time a connection is made, by creating a process.
+ * This process is passed the connection as file descriptor 0 and is expected
+ * to do a getpeername to find out the source host and port.
+ *
+ * Datagram oriented services are invoked when a datagram
+ * arrives; a process is created and passed a pending message
+ * on file descriptor 0. Datagram servers may either connect
+ * to their peer, freeing up the original socket for inetd
+ * to receive further messages on, or ``take over the socket'',
+ * processing all arriving datagrams and, eventually, timing
+ * out. The first type of server is said to be ``multi-threaded'';
+ * the second type of server ``single-threaded''.
+ *
+ * Inetd uses a configuration file which is read at startup
+ * and, possibly, at some later time in response to a hangup signal.
+ * The configuration file is ``free format'' with fields given in the
+ * order shown below. Continuation lines for an entry must being with
+ * a space or tab. All fields must be present in each entry.
+ *
+ * service name must be in /etc/services or must
+ * name a tcpmux service
+ * socket type stream/dgram/raw/rdm/seqpacket
+ * protocol must be in /etc/protocols
+ * wait/nowait single-threaded/multi-threaded
+ * user user to run daemon as
+ * server program full path name
+ * server program arguments maximum of MAXARGS (20)
+ *
+ * TCP services without official port numbers are handled with the
+ * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
+ * requests. When a connection is made from a foreign host, the service
+ * requested is passed to tcpmux, which looks it up in the servtab list
+ * and returns the proper entry for the service. Tcpmux returns a
+ * negative reply if the service doesn't exist, otherwise the invoked
+ * server is expected to return the positive reply if the service type in
+ * inetd.conf file has the prefix "tcpmux/". If the service type has the
+ * prefix "tcpmux/+", tcpmux will return the positive reply for the
+ * process; this is for compatibility with older server code, and also
+ * allows you to invoke programs that use stdin/stdout without putting any
+ * special server code in them. Services that use tcpmux are "nowait"
+ * because they do not have a well-known port and hence cannot listen
+ * for new requests.
+ *
+ * Comment lines are indicated by a `#' in column 1.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+#define TOOMANY 40 /* don't start more than TOOMANY */
+#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
+#define RETRYTIME (60*10) /* retry after bind or server fail */
+
+#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
+
+
+int debug = 0;
+int nsock, maxsock;
+fd_set allsock;
+int options;
+int timingout;
+int toomany = TOOMANY;
+struct servent *sp;
+
+struct servtab {
+ char *se_service; /* name of service */
+ int se_socktype; /* type of socket to use */
+ char *se_proto; /* protocol used */
+ short se_wait; /* single threaded server */
+ short se_checked; /* looked at during merge */
+ char *se_user; /* user name to run as */
+ struct biltin *se_bi; /* if built-in, description */
+ char *se_server; /* server program */
+#define MAXARGV 20
+ char *se_argv[MAXARGV+1]; /* program arguments */
+ int se_fd; /* open descriptor */
+ int se_type; /* type */
+ struct sockaddr_in se_ctrladdr;/* bound address */
+ int se_count; /* number started since se_time */
+ struct timeval se_time; /* start of se_count */
+ struct servtab *se_next;
+} *servtab;
+
+#define NORM_TYPE 0
+#define MUX_TYPE 1
+#define MUXPLUS_TYPE 2
+#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \
+ ((sep)->se_type == MUXPLUS_TYPE))
+#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
+
+
+void chargen_dg __P((int, struct servtab *));
+void chargen_stream __P((int, struct servtab *));
+void close_sep __P((struct servtab *));
+void config __P((int));
+void daytime_dg __P((int, struct servtab *));
+void daytime_stream __P((int, struct servtab *));
+void discard_dg __P((int, struct servtab *));
+void discard_stream __P((int, struct servtab *));
+void echo_dg __P((int, struct servtab *));
+void echo_stream __P((int, struct servtab *));
+void endconfig __P((void));
+struct servtab *enter __P((struct servtab *));
+void freeconfig __P((struct servtab *));
+struct servtab *getconfigent __P((void));
+void machtime_dg __P((int, struct servtab *));
+void machtime_stream __P((int, struct servtab *));
+char *newstr __P((char *));
+char *nextline __P((FILE *));
+void print_service __P((char *, struct servtab *));
+void reapchild __P((int));
+void retry __P((int));
+int setconfig __P((void));
+void setup __P((struct servtab *));
+char *sskip __P((char **));
+char *skip __P((char **));
+struct servtab *tcpmux __P((int));
+
+struct biltin {
+ char *bi_service; /* internally provided service name */
+ int bi_socktype; /* type of socket supported */
+ short bi_fork; /* 1 if should fork before call */
+ short bi_wait; /* 1 if should wait for child */
+ void (*bi_fn)(); /* function which performs it */
+} biltins[] = {
+ /* Echo received data */
+ { "echo", SOCK_STREAM, 1, 0, echo_stream },
+ { "echo", SOCK_DGRAM, 0, 0, echo_dg },
+
+ /* Internet /dev/null */
+ { "discard", SOCK_STREAM, 1, 0, discard_stream },
+ { "discard", SOCK_DGRAM, 0, 0, discard_dg },
+
+ /* Return 32 bit time since 1970 */
+ { "time", SOCK_STREAM, 0, 0, machtime_stream },
+ { "time", SOCK_DGRAM, 0, 0, machtime_dg },
+
+ /* Return human-readable time */
+ { "daytime", SOCK_STREAM, 0, 0, daytime_stream },
+ { "daytime", SOCK_DGRAM, 0, 0, daytime_dg },
+
+ /* Familiar character generator */
+ { "chargen", SOCK_STREAM, 1, 0, chargen_stream },
+ { "chargen", SOCK_DGRAM, 0, 0, chargen_dg },
+
+ { "tcpmux", SOCK_STREAM, 1, 0, (void (*)())tcpmux },
+
+ { NULL }
+};
+
+#define NUMINT (sizeof(intab) / sizeof(struct inent))
+char *CONFIG = _PATH_INETDCONF;
+char **Argv;
+char *LastArg;
+
+int
+main(argc, argv, envp)
+ int argc;
+ char *argv[], *envp[];
+{
+ struct servtab *sep;
+ struct passwd *pwd;
+ struct sigvec sv;
+ int tmpint, ch, dofork;
+ pid_t pid;
+ char buf[50];
+
+ Argv = argv;
+ if (envp == 0 || *envp == 0)
+ envp = argv;
+ while (*envp)
+ envp++;
+ LastArg = envp[-1] + strlen(envp[-1]);
+
+ openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+
+ while ((ch = getopt(argc, argv, "dR:")) != EOF)
+ switch(ch) {
+ case 'd':
+ debug = 1;
+ options |= SO_DEBUG;
+ break;
+ case 'R': { /* invocation rate */
+ char *p;
+
+ tmpint = strtol(optarg, &p, 0);
+ if (tmpint < 1 || *p)
+ syslog(LOG_ERR,
+ "-R %s: bad value for service invocation rate",
+ optarg);
+ else
+ toomany = tmpint;
+ break;
+ }
+ case '?':
+ default:
+ syslog(LOG_ERR,
+ "usage: inetd [-d] [-R rate] [conf-file]");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ CONFIG = argv[0];
+ if (debug == 0) {
+ daemon(0, 0);
+ }
+ memset(&sv, 0, sizeof(sv));
+ sv.sv_mask = SIGBLOCK;
+ sv.sv_handler = retry;
+ sigvec(SIGALRM, &sv, (struct sigvec *)0);
+ config(SIGHUP);
+ sv.sv_handler = config;
+ sigvec(SIGHUP, &sv, (struct sigvec *)0);
+ sv.sv_handler = reapchild;
+ sigvec(SIGCHLD, &sv, (struct sigvec *)0);
+
+ {
+ /* space for daemons to overwrite environment for ps */
+#define DUMMYSIZE 100
+ char dummy[DUMMYSIZE];
+
+ (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1);
+ dummy[DUMMYSIZE - 1] = '\0';
+ (void)setenv("inetd_dummy", dummy, 1);
+ }
+
+ for (;;) {
+ int n, ctrl;
+ fd_set readable;
+
+ if (nsock == 0) {
+ (void) sigblock(SIGBLOCK);
+ while (nsock == 0)
+ sigpause(0L);
+ (void) sigsetmask(0L);
+ }
+ readable = allsock;
+ if ((n = select(maxsock + 1, &readable, (fd_set *)0,
+ (fd_set *)0, (struct timeval *)0)) <= 0) {
+ if (n < 0 && errno != EINTR)
+ syslog(LOG_WARNING, "select: %m");
+ sleep(1);
+ continue;
+ }
+ for (sep = servtab; n && sep; sep = sep->se_next)
+ if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
+ n--;
+ if (debug)
+ fprintf(stderr, "someone wants %s\n",
+ sep->se_service);
+ if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+ ctrl = accept(sep->se_fd, (struct sockaddr *)0,
+ (int *)0);
+ if (debug)
+ fprintf(stderr, "accept, ctrl %d\n", ctrl);
+ if (ctrl < 0) {
+ if (errno != EINTR)
+ syslog(LOG_WARNING,
+ "accept (for %s): %m",
+ sep->se_service);
+ continue;
+ }
+ /*
+ * Call tcpmux to find the real service to exec.
+ */
+ if (sep->se_bi &&
+ sep->se_bi->bi_fn == (void (*)()) tcpmux) {
+ sep = tcpmux(ctrl);
+ if (sep == NULL) {
+ close(ctrl);
+ continue;
+ }
+ }
+ } else
+ ctrl = sep->se_fd;
+ (void) sigblock(SIGBLOCK);
+ pid = 0;
+ dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
+ if (dofork) {
+ if (sep->se_count++ == 0)
+ (void)gettimeofday(&sep->se_time,
+ (struct timezone *)0);
+ else if (sep->se_count >= toomany) {
+ struct timeval now;
+
+ (void)gettimeofday(&now, (struct timezone *)0);
+ if (now.tv_sec - sep->se_time.tv_sec >
+ CNT_INTVL) {
+ sep->se_time = now;
+ sep->se_count = 1;
+ } else {
+ syslog(LOG_ERR,
+ "%s/%s server failing (looping), service terminated",
+ sep->se_service, sep->se_proto);
+ close_sep(sep);
+ sigsetmask(0L);
+ if (!timingout) {
+ timingout = 1;
+ alarm(RETRYTIME);
+ }
+ continue;
+ }
+ }
+ pid = fork();
+ }
+ if (pid < 0) {
+ syslog(LOG_ERR, "fork: %m");
+ if (!sep->se_wait &&
+ sep->se_socktype == SOCK_STREAM)
+ close(ctrl);
+ sigsetmask(0L);
+ sleep(1);
+ continue;
+ }
+ if (pid && sep->se_wait) {
+ sep->se_wait = pid;
+ if (sep->se_fd >= 0) {
+ FD_CLR(sep->se_fd, &allsock);
+ nsock--;
+ }
+ }
+ sigsetmask(0L);
+ if (pid == 0) {
+ if (debug && dofork)
+ setsid();
+ if (dofork) {
+ if (debug)
+ fprintf(stderr, "+ Closing from %d\n",
+ maxsock);
+ for (tmpint = maxsock; tmpint > 2; tmpint--)
+ if (tmpint != ctrl)
+ close(tmpint);
+ }
+ if (sep->se_bi)
+ (*sep->se_bi->bi_fn)(ctrl, sep);
+ else {
+ if (debug)
+ fprintf(stderr, "%d execl %s\n",
+ getpid(), sep->se_server);
+ dup2(ctrl, 0);
+ close(ctrl);
+ dup2(0, 1);
+ dup2(0, 2);
+ if ((pwd = getpwnam(sep->se_user)) == NULL) {
+ syslog(LOG_ERR,
+ "%s/%s: %s: No such user",
+ sep->se_service, sep->se_proto,
+ sep->se_user);
+ if (sep->se_socktype != SOCK_STREAM)
+ recv(0, buf, sizeof (buf), 0);
+ _exit(1);
+ }
+ if (pwd->pw_uid) {
+ if (setgid(pwd->pw_gid) < 0) {
+ syslog(LOG_ERR,
+ "%s: can't set gid %d: %m",
+ sep->se_service, pwd->pw_gid);
+ _exit(1);
+ }
+ (void) initgroups(pwd->pw_name,
+ pwd->pw_gid);
+ if (setuid(pwd->pw_uid) < 0) {
+ syslog(LOG_ERR,
+ "%s: can't set uid %d: %m",
+ sep->se_service, pwd->pw_uid);
+ _exit(1);
+ }
+ }
+ execv(sep->se_server, sep->se_argv);
+ if (sep->se_socktype != SOCK_STREAM)
+ recv(0, buf, sizeof (buf), 0);
+ syslog(LOG_ERR,
+ "cannot execute %s: %m", sep->se_server);
+ _exit(1);
+ }
+ }
+ if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+ close(ctrl);
+ }
+ }
+}
+
+void
+reapchild(signo)
+ int signo;
+{
+ int status;
+ pid_t pid;
+ struct servtab *sep;
+
+ for (;;) {
+ pid = wait3(&status, WNOHANG, (struct rusage *)0);
+ if (pid <= 0)
+ break;
+ if (debug)
+ fprintf(stderr, "%d reaped, status %#x\n",
+ pid, status);
+ for (sep = servtab; sep; sep = sep->se_next)
+ if (sep->se_wait == pid) {
+ if (status)
+ syslog(LOG_WARNING,
+ "%s: exit status 0x%x",
+ sep->se_server, status);
+ if (debug)
+ fprintf(stderr, "restored %s, fd %d\n",
+ sep->se_service, sep->se_fd);
+ FD_SET(sep->se_fd, &allsock);
+ nsock++;
+ sep->se_wait = 1;
+ }
+ }
+}
+
+void
+config(signo)
+ int signo;
+{
+ struct servtab *sep, *cp, **sepp;
+ struct passwd *pwd;
+ long omask;
+
+ if (!setconfig()) {
+ syslog(LOG_ERR, "%s: %m", CONFIG);
+ return;
+ }
+ for (sep = servtab; sep; sep = sep->se_next)
+ sep->se_checked = 0;
+ while (cp = getconfigent()) {
+ if ((pwd = getpwnam(cp->se_user)) == NULL) {
+ syslog(LOG_ERR,
+ "%s/%s: No such user '%s', service ignored",
+ cp->se_service, cp->se_proto, cp->se_user);
+ continue;
+ }
+ for (sep = servtab; sep; sep = sep->se_next)
+ if (strcmp(sep->se_service, cp->se_service) == 0 &&
+ strcmp(sep->se_proto, cp->se_proto) == 0)
+ break;
+ if (sep != 0) {
+ int i;
+
+ omask = sigblock(SIGBLOCK);
+ /*
+ * sep->se_wait may be holding the pid of a daemon
+ * that we're waiting for. If so, don't overwrite
+ * it unless the config file explicitly says don't
+ * wait.
+ */
+ if (cp->se_bi == 0 &&
+ (sep->se_wait == 1 || cp->se_wait == 0))
+ sep->se_wait = cp->se_wait;
+#define SWAP(a, b) { char *c = a; a = b; b = c; }
+ if (cp->se_user)
+ SWAP(sep->se_user, cp->se_user);
+ if (cp->se_server)
+ SWAP(sep->se_server, cp->se_server);
+ for (i = 0; i < MAXARGV; i++)
+ SWAP(sep->se_argv[i], cp->se_argv[i]);
+ sigsetmask(omask);
+ freeconfig(cp);
+ if (debug)
+ print_service("REDO", sep);
+ } else {
+ sep = enter(cp);
+ if (debug)
+ print_service("ADD ", sep);
+ }
+ sep->se_checked = 1;
+ if (ISMUX(sep)) {
+ sep->se_fd = -1;
+ continue;
+ }
+ sp = getservbyname(sep->se_service, sep->se_proto);
+ if (sp == 0) {
+ syslog(LOG_ERR, "%s/%s: unknown service",
+ sep->se_service, sep->se_proto);
+ sep->se_checked = 0;
+ continue;
+ }
+ if (sp->s_port != sep->se_ctrladdr.sin_port) {
+ sep->se_ctrladdr.sin_family = AF_INET;
+ sep->se_ctrladdr.sin_port = sp->s_port;
+ if (sep->se_fd >= 0)
+ close_sep(sep);
+ }
+ if (sep->se_fd == -1)
+ setup(sep);
+ }
+ endconfig();
+ /*
+ * Purge anything not looked at above.
+ */
+ omask = sigblock(SIGBLOCK);
+ sepp = &servtab;
+ while (sep = *sepp) {
+ if (sep->se_checked) {
+ sepp = &sep->se_next;
+ continue;
+ }
+ *sepp = sep->se_next;
+ if (sep->se_fd >= 0)
+ close_sep(sep);
+ if (debug)
+ print_service("FREE", sep);
+ freeconfig(sep);
+ free((char *)sep);
+ }
+ (void) sigsetmask(omask);
+}
+
+void
+retry(signo)
+ int signo;
+{
+ struct servtab *sep;
+
+ timingout = 0;
+ for (sep = servtab; sep; sep = sep->se_next)
+ if (sep->se_fd == -1)
+ setup(sep);
+}
+
+void
+setup(sep)
+ struct servtab *sep;
+{
+ int on = 1;
+
+ if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
+ if (debug)
+ fprintf(stderr, "socket failed on %s/%s: %s\n",
+ sep->se_service, sep->se_proto,
+ strerror(errno));
+ syslog(LOG_ERR, "%s/%s: socket: %m",
+ sep->se_service, sep->se_proto);
+ return;
+ }
+#define turnon(fd, opt) \
+setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
+ if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
+ turnon(sep->se_fd, SO_DEBUG) < 0)
+ syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+ if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
+ syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
+#undef turnon
+ if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
+ sizeof (sep->se_ctrladdr)) < 0) {
+ if (debug)
+ fprintf(stderr, "bind failed on %s/%s: %s\n",
+ sep->se_service, sep->se_proto,
+ strerror(errno));
+ syslog(LOG_ERR, "%s/%s: bind: %m",
+ sep->se_service, sep->se_proto);
+ (void) close(sep->se_fd);
+ sep->se_fd = -1;
+ if (!timingout) {
+ timingout = 1;
+ alarm(RETRYTIME);
+ }
+ return;
+ }
+ if (sep->se_socktype == SOCK_STREAM)
+ listen(sep->se_fd, 10);
+ FD_SET(sep->se_fd, &allsock);
+ nsock++;
+ if (sep->se_fd > maxsock)
+ maxsock = sep->se_fd;
+ if (debug) {
+ fprintf(stderr, "registered %s on %d\n",
+ sep->se_server, sep->se_fd);
+ }
+}
+
+/*
+ * Finish with a service and its socket.
+ */
+void
+close_sep(sep)
+ struct servtab *sep;
+{
+ if (sep->se_fd >= 0) {
+ nsock--;
+ FD_CLR(sep->se_fd, &allsock);
+ (void) close(sep->se_fd);
+ sep->se_fd = -1;
+ }
+ sep->se_count = 0;
+ /*
+ * Don't keep the pid of this running deamon: when reapchild()
+ * reaps this pid, it would erroneously increment nsock.
+ */
+ if (sep->se_wait > 1)
+ sep->se_wait = 1;
+}
+
+struct servtab *
+enter(cp)
+ struct servtab *cp;
+{
+ struct servtab *sep;
+ long omask;
+
+ sep = (struct servtab *)malloc(sizeof (*sep));
+ if (sep == (struct servtab *)0) {
+ syslog(LOG_ERR, "Out of memory.");
+ exit(-1);
+ }
+ *sep = *cp;
+ sep->se_fd = -1;
+ omask = sigblock(SIGBLOCK);
+ sep->se_next = servtab;
+ servtab = sep;
+ sigsetmask(omask);
+ return (sep);
+}
+
+FILE *fconfig = NULL;
+struct servtab serv;
+char line[LINE_MAX];
+
+int
+setconfig()
+{
+
+ if (fconfig != NULL) {
+ fseek(fconfig, 0L, SEEK_SET);
+ return (1);
+ }
+ fconfig = fopen(CONFIG, "r");
+ return (fconfig != NULL);
+}
+
+void
+endconfig()
+{
+ if (fconfig) {
+ (void) fclose(fconfig);
+ fconfig = NULL;
+ }
+}
+
+struct servtab *
+getconfigent()
+{
+ struct servtab *sep = &serv;
+ int argc;
+ char *cp, *arg;
+ static char TCPMUX_TOKEN[] = "tcpmux/";
+#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
+
+more:
+ while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
+ ;
+ if (cp == NULL)
+ return ((struct servtab *)0);
+ /*
+ * clear the static buffer, since some fields (se_ctrladdr,
+ * for example) don't get initialized here.
+ */
+ memset((caddr_t)sep, 0, sizeof *sep);
+ arg = skip(&cp);
+ if (cp == NULL) {
+ /* got an empty line containing just blanks/tabs. */
+ goto more;
+ }
+ if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
+ char *c = arg + MUX_LEN;
+ if (*c == '+') {
+ sep->se_type = MUXPLUS_TYPE;
+ c++;
+ } else
+ sep->se_type = MUX_TYPE;
+ sep->se_service = newstr(c);
+ } else {
+ sep->se_service = newstr(arg);
+ sep->se_type = NORM_TYPE;
+ }
+ arg = sskip(&cp);
+ if (strcmp(arg, "stream") == 0)
+ sep->se_socktype = SOCK_STREAM;
+ else if (strcmp(arg, "dgram") == 0)
+ sep->se_socktype = SOCK_DGRAM;
+ else if (strcmp(arg, "rdm") == 0)
+ sep->se_socktype = SOCK_RDM;
+ else if (strcmp(arg, "seqpacket") == 0)
+ sep->se_socktype = SOCK_SEQPACKET;
+ else if (strcmp(arg, "raw") == 0)
+ sep->se_socktype = SOCK_RAW;
+ else
+ sep->se_socktype = -1;
+ sep->se_proto = newstr(sskip(&cp));
+ arg = sskip(&cp);
+ sep->se_wait = strcmp(arg, "wait") == 0;
+ if (ISMUX(sep)) {
+ /*
+ * Silently enforce "nowait" for TCPMUX services since
+ * they don't have an assigned port to listen on.
+ */
+ sep->se_wait = 0;
+
+ if (strcmp(sep->se_proto, "tcp")) {
+ syslog(LOG_ERR,
+ "%s: bad protocol for tcpmux service %s",
+ CONFIG, sep->se_service);
+ goto more;
+ }
+ if (sep->se_socktype != SOCK_STREAM) {
+ syslog(LOG_ERR,
+ "%s: bad socket type for tcpmux service %s",
+ CONFIG, sep->se_service);
+ goto more;
+ }
+ }
+ sep->se_user = newstr(sskip(&cp));
+ sep->se_server = newstr(sskip(&cp));
+ if (strcmp(sep->se_server, "internal") == 0) {
+ struct biltin *bi;
+
+ for (bi = biltins; bi->bi_service; bi++)
+ if (bi->bi_socktype == sep->se_socktype &&
+ strcmp(bi->bi_service, sep->se_service) == 0)
+ break;
+ if (bi->bi_service == 0) {
+ syslog(LOG_ERR, "internal service %s unknown",
+ sep->se_service);
+ goto more;
+ }
+ sep->se_bi = bi;
+ sep->se_wait = bi->bi_wait;
+ } else
+ sep->se_bi = NULL;
+ argc = 0;
+ for (arg = skip(&cp); cp; arg = skip(&cp))
+ if (argc < MAXARGV)
+ sep->se_argv[argc++] = newstr(arg);
+ while (argc <= MAXARGV)
+ sep->se_argv[argc++] = NULL;
+ return (sep);
+}
+
+void
+freeconfig(cp)
+ struct servtab *cp;
+{
+ int i;
+
+ if (cp->se_service)
+ free(cp->se_service);
+ if (cp->se_proto)
+ free(cp->se_proto);
+ if (cp->se_user)
+ free(cp->se_user);
+ if (cp->se_server)
+ free(cp->se_server);
+ for (i = 0; i < MAXARGV; i++)
+ if (cp->se_argv[i])
+ free(cp->se_argv[i]);
+}
+
+
+/*
+ * Safe skip - if skip returns null, log a syntax error in the
+ * configuration file and exit.
+ */
+char *
+sskip(cpp)
+ char **cpp;
+{
+ char *cp;
+
+ cp = skip(cpp);
+ if (cp == NULL) {
+ syslog(LOG_ERR, "%s: syntax error", CONFIG);
+ exit(-1);
+ }
+ return (cp);
+}
+
+char *
+skip(cpp)
+ char **cpp;
+{
+ char *cp = *cpp;
+ char *start;
+
+again:
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0') {
+ int c;
+
+ c = getc(fconfig);
+ (void) ungetc(c, fconfig);
+ if (c == ' ' || c == '\t')
+ if (cp = nextline(fconfig))
+ goto again;
+ *cpp = (char *)0;
+ return ((char *)0);
+ }
+ start = cp;
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ if (*cp != '\0')
+ *cp++ = '\0';
+ *cpp = cp;
+ return (start);
+}
+
+char *
+nextline(fd)
+ FILE *fd;
+{
+ char *cp;
+
+ if (fgets(line, sizeof (line), fd) == NULL)
+ return ((char *)0);
+ cp = strchr(line, '\n');
+ if (cp)
+ *cp = '\0';
+ return (line);
+}
+
+char *
+newstr(cp)
+ char *cp;
+{
+ if (cp = strdup(cp ? cp : ""))
+ return (cp);
+ syslog(LOG_ERR, "strdup: %m");
+ exit(-1);
+}
+
+void
+setproctitle(a, s)
+ char *a;
+ int s;
+{
+ int size;
+ char *cp;
+ struct sockaddr_in sin;
+ char buf[80];
+
+ cp = Argv[0];
+ size = sizeof(sin);
+ if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
+ (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
+ else
+ (void) sprintf(buf, "-%s", a);
+ strncpy(cp, buf, LastArg - cp);
+ cp += strlen(cp);
+ while (cp < LastArg)
+ *cp++ = ' ';
+}
+
+/*
+ * Internet services provided internally by inetd:
+ */
+#define BUFSIZE 8192
+
+/* ARGSUSED */
+void
+echo_stream(s, sep) /* Echo service -- echo data back */
+ int s;
+ struct servtab *sep;
+{
+ char buffer[BUFSIZE];
+ int i;
+
+ setproctitle(sep->se_service, s);
+ while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
+ write(s, buffer, i) > 0)
+ ;
+ exit(0);
+}
+
+/* ARGSUSED */
+void
+echo_dg(s, sep) /* Echo service -- echo data back */
+ int s;
+ struct servtab *sep;
+{
+ char buffer[BUFSIZE];
+ int i, size;
+ struct sockaddr sa;
+
+ size = sizeof(sa);
+ if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
+ return;
+ (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
+}
+
+/* ARGSUSED */
+void
+discard_stream(s, sep) /* Discard service -- ignore data */
+ int s;
+ struct servtab *sep;
+{
+ int ret;
+ char buffer[BUFSIZE];
+
+ setproctitle(sep->se_service, s);
+ while (1) {
+ while ((ret = read(s, buffer, sizeof(buffer))) > 0)
+ ;
+ if (ret == 0 || errno != EINTR)
+ break;
+ }
+ exit(0);
+}
+
+/* ARGSUSED */
+void
+discard_dg(s, sep) /* Discard service -- ignore data */
+ int s;
+ struct servtab *sep;
+{
+ char buffer[BUFSIZE];
+
+ (void) read(s, buffer, sizeof(buffer));
+}
+
+#include <ctype.h>
+#define LINESIZ 72
+char ring[128];
+char *endring;
+
+void
+initring()
+{
+ int i;
+
+ endring = ring;
+
+ for (i = 0; i <= 128; ++i)
+ if (isprint(i))
+ *endring++ = i;
+}
+
+/* ARGSUSED */
+void
+chargen_stream(s, sep) /* Character generator */
+ int s;
+ struct servtab *sep;
+{
+ int len;
+ char *rs, text[LINESIZ+2];
+
+ setproctitle(sep->se_service, s);
+
+ if (!endring) {
+ initring();
+ rs = ring;
+ }
+
+ text[LINESIZ] = '\r';
+ text[LINESIZ + 1] = '\n';
+ for (rs = ring;;) {
+ if ((len = endring - rs) >= LINESIZ)
+ memmove(text, rs, LINESIZ);
+ else {
+ memmove(text, rs, len);
+ memmove(text + len, ring, LINESIZ - len);
+ }
+ if (++rs == endring)
+ rs = ring;
+ if (write(s, text, sizeof(text)) != sizeof(text))
+ break;
+ }
+ exit(0);
+}
+
+/* ARGSUSED */
+void
+chargen_dg(s, sep) /* Character generator */
+ int s;
+ struct servtab *sep;
+{
+ struct sockaddr sa;
+ static char *rs;
+ int len, size;
+ char text[LINESIZ+2];
+
+ if (endring == 0) {
+ initring();
+ rs = ring;
+ }
+
+ size = sizeof(sa);
+ if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
+ return;
+
+ if ((len = endring - rs) >= LINESIZ)
+ memmove(text, rs, LINESIZ);
+ else {
+ memmove(text, rs, len);
+ memmove(text + len, ring, LINESIZ - len);
+ }
+ if (++rs == endring)
+ rs = ring;
+ text[LINESIZ] = '\r';
+ text[LINESIZ + 1] = '\n';
+ (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
+}
+
+/*
+ * Return a machine readable date and time, in the form of the
+ * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
+ * returns the number of seconds since midnight, Jan 1, 1970,
+ * we must add 2208988800 seconds to this figure to make up for
+ * some seventy years Bell Labs was asleep.
+ */
+
+long
+machtime()
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, (struct timezone *)0) < 0) {
+ if (debug)
+ fprintf(stderr, "Unable to get time of day\n");
+ return (0L);
+ }
+#define OFFSET ((u_long)25567 * 24*60*60)
+ return (htonl((long)(tv.tv_sec + OFFSET)));
+#undef OFFSET
+}
+
+/* ARGSUSED */
+void
+machtime_stream(s, sep)
+ int s;
+ struct servtab *sep;
+{
+ long result;
+
+ result = machtime();
+ (void) write(s, (char *) &result, sizeof(result));
+}
+
+/* ARGSUSED */
+void
+machtime_dg(s, sep)
+ int s;
+ struct servtab *sep;
+{
+ long result;
+ struct sockaddr sa;
+ int size;
+
+ size = sizeof(sa);
+ if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
+ return;
+ result = machtime();
+ (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
+}
+
+/* ARGSUSED */
+void
+daytime_stream(s, sep) /* Return human-readable time of day */
+ int s;
+ struct servtab *sep;
+{
+ char buffer[256];
+ time_t clock;
+
+ clock = time((time_t *) 0);
+
+ (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
+ (void) write(s, buffer, strlen(buffer));
+}
+
+/* ARGSUSED */
+void
+daytime_dg(s, sep) /* Return human-readable time of day */
+ int s;
+ struct servtab *sep;
+{
+ char buffer[256];
+ time_t clock;
+ struct sockaddr sa;
+ int size;
+
+ clock = time((time_t *) 0);
+
+ size = sizeof(sa);
+ if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
+ return;
+ (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
+ (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
+}
+
+/*
+ * print_service:
+ * Dump relevant information to stderr
+ */
+void
+print_service(action, sep)
+ char *action;
+ struct servtab *sep;
+{
+ fprintf(stderr,
+ "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
+ action, sep->se_service, sep->se_proto,
+ sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server);
+}
+
+/*
+ * Based on TCPMUX.C by Mark K. Lottor November 1988
+ * sri-nic::ps:<mkl>tcpmux.c
+ */
+
+
+static int /* # of characters upto \r,\n or \0 */
+getline(fd, buf, len)
+ int fd;
+ char *buf;
+ int len;
+{
+ int count = 0, n;
+
+ do {
+ n = read(fd, buf, len-count);
+ if (n == 0)
+ return (count);
+ if (n < 0)
+ return (-1);
+ while (--n >= 0) {
+ if (*buf == '\r' || *buf == '\n' || *buf == '\0')
+ return (count);
+ count++;
+ buf++;
+ }
+ } while (count < len);
+ return (count);
+}
+
+#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
+
+#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
+
+struct servtab *
+tcpmux(s)
+ int s;
+{
+ struct servtab *sep;
+ char service[MAX_SERV_LEN+1];
+ int len;
+
+ /* Get requested service name */
+ if ((len = getline(s, service, MAX_SERV_LEN)) < 0) {
+ strwrite(s, "-Error reading service name\r\n");
+ return (NULL);
+ }
+ service[len] = '\0';
+
+ if (debug)
+ fprintf(stderr, "tcpmux: someone wants %s\n", service);
+
+ /*
+ * Help is a required command, and lists available services,
+ * one per line.
+ */
+ if (!strcasecmp(service, "help")) {
+ for (sep = servtab; sep; sep = sep->se_next) {
+ if (!ISMUX(sep))
+ continue;
+ (void)write(s,sep->se_service,strlen(sep->se_service));
+ strwrite(s, "\r\n");
+ }
+ return (NULL);
+ }
+
+ /* Try matching a service in inetd.conf with the request */
+ for (sep = servtab; sep; sep = sep->se_next) {
+ if (!ISMUX(sep))
+ continue;
+ if (!strcasecmp(service, sep->se_service)) {
+ if (ISMUXPLUS(sep)) {
+ strwrite(s, "+Go\r\n");
+ }
+ return (sep);
+ }
+ }
+ strwrite(s, "-Service not available\r\n");
+ return (NULL);
+}
diff --git a/usr.sbin/inetd/pathnames.h b/usr.sbin/inetd/pathnames.h
new file mode 100644
index 0000000..e8ae3cd
--- /dev/null
+++ b/usr.sbin/inetd/pathnames.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#define _PATH_INETDCONF "/etc/inetd.conf"
diff --git a/usr.sbin/iostat/Makefile b/usr.sbin/iostat/Makefile
new file mode 100644
index 0000000..e9287e3
--- /dev/null
+++ b/usr.sbin/iostat/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= iostat
+CFLAGS+=-I/sys -I${.CURDIR}/../../usr.bin/vmstat
+MAN8= iostat.0
+DPADD= ${LIBKVM}
+LDADD= -lkvm
+BINGRP= kmem
+BINMODE=2555
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/iostat/iostat.8 b/usr.sbin/iostat/iostat.8
new file mode 100644
index 0000000..48ef627
--- /dev/null
+++ b/usr.sbin/iostat/iostat.8
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)iostat.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt IOSTAT 8
+.Os BSD 4
+.Sh NAME
+.Nm iostat
+.Nd report
+.Tn I/O
+statistics
+.Sh SYNOPSIS
+.Nm iostat
+.Op Fl c Ar count
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar wait
+.Op Ar drives
+.Sh DESCRIPTION
+.Nm Iostat
+displays kernel
+.Tn I/O
+statistics on terminal, disk and cpu
+operations.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl c
+Repeat the display
+.Ar count
+times.
+The first display is for the time since a reboot and each subsequent
+report is for the time period since the last display.
+If no
+.Ar wait
+interval is specified, the default is 1 second.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Dq Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the default
+.Dq Pa /vmunix .
+.It Fl w
+Pause
+.Ar wait
+seconds between each display.
+If no repeat
+.Ar count
+is specified, the default is infinity.
+.El
+.Pp
+.Nm Iostat
+displays its information in the following format:
+.Bl -tag -width flag
+.It tty
+.Bl -tag -width indent -compact
+.It tin
+characters read from terminals
+.It tout
+characters written to terminals
+.El
+.It disks
+Disk operations (this field is system dependent).
+The header of the field is the disk name and unit number.
+If more than four disk drives are configured in the system,
+.Nm iostat
+displays only the first four drives.
+To force
+.Nm iostat
+to display specific drives, their names may be supplied on the command
+line.
+.Pp
+.Bl -tag -width indent -compact
+.It sps
+sectors transferred per second
+.It tps
+transfers per second
+.It msps
+milliseconds per average seek (including implied
+seeks and rotational latency)
+.El
+.It cpu
+.Bl -tag -width indent -compact
+.It \&us
+% of cpu time in user mode
+.It \&ni
+% of cpu time in user mode running niced processes
+.It \&sy
+% of cpu time in system mode
+.It \&id
+% of cpu time in idle mode
+.El
+.El
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+Default kernel namelist.
+.It Pa /dev/kmem
+Default memory file.
+.El
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr nfsstat 1 ,
+.Xr \&ps 1 ,
+.Xr systat 1 ,
+.Xr vmstat 1 ,
+.Xr pstat 8
+.Pp
+The sections starting with ``Interpreting system activity'' in
+.%T "Installing and Operating 4.3BSD" .
diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c
new file mode 100644
index 0000000..a41cac4
--- /dev/null
+++ b/usr.sbin/iostat/iostat.c
@@ -0,0 +1,391 @@
+/*-
+ * Copyright (c) 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1986, 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)iostat.c 8.2 (Berkeley) 1/26/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/dkstat.h>
+
+#include <err.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct nlist namelist[] = {
+#define X_DK_TIME 0
+ { "_dk_time" },
+#define X_DK_XFER 1
+ { "_dk_xfer" },
+#define X_DK_WDS 2
+ { "_dk_wds" },
+#define X_TK_NIN 3
+ { "_tk_nin" },
+#define X_TK_NOUT 4
+ { "_tk_nout" },
+#define X_DK_SEEK 5
+ { "_dk_seek" },
+#define X_CP_TIME 6
+ { "_cp_time" },
+#define X_DK_WPMS 7
+ { "_dk_wpms" },
+#define X_HZ 8
+ { "_hz" },
+#define X_STATHZ 9
+ { "_stathz" },
+#define X_DK_NDRIVE 10
+ { "_dk_ndrive" },
+#define X_END 10
+#if defined(hp300) || defined(luna68k)
+#define X_HPDINIT (X_END+1)
+ { "_hp_dinit" },
+#endif
+#ifdef mips
+#define X_SCSI_DINIT (X_END+1)
+ { "_scsi_dinit" },
+#endif
+#ifdef tahoe
+#define X_VBDINIT (X_END+1)
+ { "_vbdinit" },
+#endif
+#ifdef vax
+ { "_mbdinit" },
+#define X_MBDINIT (X_END+1)
+ { "_ubdinit" },
+#define X_UBDINIT (X_END+2)
+#endif
+ { NULL },
+};
+
+struct _disk {
+ long cp_time[CPUSTATES];
+ long *dk_time;
+ long *dk_wds;
+ long *dk_seek;
+ long *dk_xfer;
+ long tk_nin;
+ long tk_nout;
+} cur, last;
+
+kvm_t *kd;
+double etime;
+long *dk_wpms;
+int dk_ndrive, *dr_select, hz, kmemfd, ndrives;
+char **dr_name;
+
+#define nlread(x, v) \
+ kvm_read(kd, namelist[x].n_value, &(v), sizeof(v))
+
+#include "names.c" /* XXX */
+
+void cpustats __P((void));
+void dkstats __P((void));
+void phdr __P((int));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int i;
+ long tmp;
+ int ch, hdrcnt, reps, interval, stathz, ndrives;
+ char **cp, *memf, *nlistf, buf[30];
+ char errbuf[_POSIX2_LINE_MAX];
+
+ interval = reps = 0;
+ nlistf = memf = NULL;
+ while ((ch = getopt(argc, argv, "c:M:N:w:")) != EOF)
+ switch(ch) {
+ case 'c':
+ if ((reps = atoi(optarg)) <= 0)
+ errx(1, "repetition count <= 0.");
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'w':
+ if ((interval = atoi(optarg)) <= 0)
+ errx(1, "interval <= 0.");
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ if (nlistf != NULL || memf != NULL)
+ setgid(getgid());
+
+ kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ if (kd == 0)
+ errx(1, "kvm_openfiles: %s", errbuf);
+ if (kvm_nlist(kd, namelist) == -1)
+ errx(1, "kvm_nlist: %s", kvm_geterr(kd));
+ if (namelist[X_DK_NDRIVE].n_type == 0)
+ errx(1, "dk_ndrive not found in namelist");
+ (void)nlread(X_DK_NDRIVE, dk_ndrive);
+ if (dk_ndrive <= 0)
+ errx(1, "invalid dk_ndrive %d\n", dk_ndrive);
+
+ cur.dk_time = calloc(dk_ndrive, sizeof(long));
+ cur.dk_wds = calloc(dk_ndrive, sizeof(long));
+ cur.dk_seek = calloc(dk_ndrive, sizeof(long));
+ cur.dk_xfer = calloc(dk_ndrive, sizeof(long));
+ last.dk_time = calloc(dk_ndrive, sizeof(long));
+ last.dk_wds = calloc(dk_ndrive, sizeof(long));
+ last.dk_seek = calloc(dk_ndrive, sizeof(long));
+ last.dk_xfer = calloc(dk_ndrive, sizeof(long));
+ dr_select = calloc(dk_ndrive, sizeof(int));
+ dr_name = calloc(dk_ndrive, sizeof(char *));
+ dk_wpms = calloc(dk_ndrive, sizeof(long));
+
+ for (i = 0; i < dk_ndrive; i++) {
+ (void)sprintf(buf, "dk%d", i);
+ dr_name[i] = strdup(buf);
+ }
+ if (!read_names())
+ exit(1);
+ (void)nlread(X_HZ, hz);
+ (void)nlread(X_STATHZ, stathz);
+ if (stathz)
+ hz = stathz;
+ (void)kvm_read(kd, namelist[X_DK_WPMS].n_value, dk_wpms,
+ dk_ndrive * sizeof(dk_wpms));
+
+ /*
+ * Choose drives to be displayed. Priority goes to (in order) drives
+ * supplied as arguments and default drives. If everything isn't
+ * filled in and there are drives not taken care of, display the first
+ * few that fit.
+ *
+ * The backward compatibility #ifdefs permit the syntax:
+ * iostat [ drives ] [ interval [ count ] ]
+ */
+#define BACKWARD_COMPATIBILITY
+ for (ndrives = 0; *argv; ++argv) {
+#ifdef BACKWARD_COMPATIBILITY
+ if (isdigit(**argv))
+ break;
+#endif
+ for (i = 0; i < dk_ndrive; i++) {
+ if (strcmp(dr_name[i], *argv))
+ continue;
+ dr_select[i] = 1;
+ ++ndrives;
+ }
+ }
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ interval = atoi(*argv);
+ if (*++argv)
+ reps = atoi(*argv);
+ }
+#endif
+
+ if (interval) {
+ if (!reps)
+ reps = -1;
+ } else
+ if (reps)
+ interval = 1;
+
+ for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+ if (dr_select[i] || dk_wpms[i] == 0)
+ continue;
+ for (cp = defdrives; *cp; cp++)
+ if (strcmp(dr_name[i], *cp) == 0) {
+ dr_select[i] = 1;
+ ++ndrives;
+ break;
+ }
+ }
+ for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+ if (dr_select[i])
+ continue;
+ dr_select[i] = 1;
+ ++ndrives;
+ }
+
+ (void)signal(SIGCONT, phdr);
+
+ for (hdrcnt = 1;;) {
+ if (!--hdrcnt) {
+ phdr(0);
+ hdrcnt = 20;
+ }
+ (void)kvm_read(kd, namelist[X_DK_TIME].n_value,
+ cur.dk_time, dk_ndrive * sizeof(long));
+ (void)kvm_read(kd, namelist[X_DK_XFER].n_value,
+ cur.dk_xfer, dk_ndrive * sizeof(long));
+ (void)kvm_read(kd, namelist[X_DK_WDS].n_value,
+ cur.dk_wds, dk_ndrive * sizeof(long));
+ (void)kvm_read(kd, namelist[X_DK_SEEK].n_value,
+ cur.dk_seek, dk_ndrive * sizeof(long));
+ (void)kvm_read(kd, namelist[X_TK_NIN].n_value,
+ &cur.tk_nin, sizeof(cur.tk_nin));
+ (void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
+ &cur.tk_nout, sizeof(cur.tk_nout));
+ (void)kvm_read(kd, namelist[X_CP_TIME].n_value,
+ cur.cp_time, sizeof(cur.cp_time));
+ for (i = 0; i < dk_ndrive; i++) {
+ if (!dr_select[i])
+ continue;
+#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp
+ X(dk_xfer);
+ X(dk_seek);
+ X(dk_wds);
+ X(dk_time);
+ }
+ tmp = cur.tk_nin;
+ cur.tk_nin -= last.tk_nin;
+ last.tk_nin = tmp;
+ tmp = cur.tk_nout;
+ cur.tk_nout -= last.tk_nout;
+ last.tk_nout = tmp;
+ etime = 0;
+ for (i = 0; i < CPUSTATES; i++) {
+ X(cp_time);
+ etime += cur.cp_time[i];
+ }
+ if (etime == 0.0)
+ etime = 1.0;
+ etime /= (float)hz;
+ (void)printf("%4.0f%5.0f",
+ cur.tk_nin / etime, cur.tk_nout / etime);
+ dkstats();
+ cpustats();
+ (void)printf("\n");
+ (void)fflush(stdout);
+
+ if (reps >= 0 && --reps <= 0)
+ break;
+ (void)sleep(interval);
+ }
+ exit(0);
+}
+
+/* ARGUSED */
+void
+phdr(signo)
+ int signo;
+{
+ register int i;
+
+ (void)printf(" tty");
+ for (i = 0; i < dk_ndrive; i++)
+ if (dr_select[i])
+ (void)printf(" %3.3s ", dr_name[i]);
+ (void)printf(" cpu\n tin tout");
+ for (i = 0; i < dk_ndrive; i++)
+ if (dr_select[i])
+ (void)printf(" sps tps msps ");
+ (void)printf(" us ni sy id\n");
+}
+
+void
+dkstats()
+{
+ register int dn;
+ double atime, itime, msps, words, xtime;
+
+ for (dn = 0; dn < dk_ndrive; ++dn) {
+ if (!dr_select[dn])
+ continue;
+ words = cur.dk_wds[dn] * 32; /* words xfer'd */
+ (void)printf("%4.0f", /* sectors */
+ words / (DEV_BSIZE / 2) / etime);
+
+ (void)printf("%4.0f", cur.dk_xfer[dn] / etime);
+
+ if (dk_wpms[dn] && cur.dk_xfer[dn]) {
+ atime = cur.dk_time[dn]; /* ticks disk busy */
+ atime /= (float)hz; /* ticks to seconds */
+ xtime = words / dk_wpms[dn]; /* transfer time */
+ itime = atime - xtime; /* time not xfer'ing */
+ if (itime < 0)
+ msps = 0;
+ else
+ msps = itime * 1000 / cur.dk_xfer[dn];
+ } else
+ msps = 0;
+ (void)printf("%5.1f ", msps);
+ }
+}
+
+void
+cpustats()
+{
+ register int state;
+ double time;
+
+ time = 0;
+ for (state = 0; state < CPUSTATES; ++state)
+ time += cur.cp_time[state];
+ for (state = 0; state < CPUSTATES; ++state)
+ (void)printf("%3.0f",
+ 100. * cur.cp_time[state] / (time ? time : 1));
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
+ exit(1);
+}
diff --git a/usr.sbin/kgmon/Makefile b/usr.sbin/kgmon/Makefile
new file mode 100644
index 0000000..e0ef616
--- /dev/null
+++ b/usr.sbin/kgmon/Makefile
@@ -0,0 +1,14 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= kgmon
+MAN8= kgmon.0
+DPADD= ${LIBKVM}
+LDADD= -lkvm
+#
+# This program may safely be run setuid-root to allow non-root
+# users to start, stop, and reset profiling buffers.
+#
+#BINOWN=root
+#BINMODE=4555
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/kgmon/kgmon.8 b/usr.sbin/kgmon/kgmon.8
new file mode 100644
index 0000000..060ed2e
--- /dev/null
+++ b/usr.sbin/kgmon/kgmon.8
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)kgmon.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt KGMON 8
+.Os BSD 4.2
+.Sh NAME
+.Nm kgmon
+.Nd generate a dump of the operating system's profile buffers
+.Sh SYNOPSIS
+.Nm kgmon
+.Op Fl bhpr
+.Op Fl M core
+.Op Fl N system
+.Sh DESCRIPTION
+.Nm Kgmon
+is a tool used when profiling the operating system.
+When no arguments are supplied,
+.Nm kgmon
+indicates the state of operating system profiling as running,
+off, or not configured.
+(see
+.Xr config 8 )
+If the
+.Fl p
+flag is specified,
+.Nm kgmon
+extracts profile data from the operating system and produces a
+.Pa gmon.out
+file suitable for later analysis by
+.Xr gprof 1 .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl b
+Resume the collection of profile data.
+.It Fl h
+Stop the collection of profile data.
+.It Fl p
+Dump the contents of the profile buffers into a
+.Pa gmon.out
+file.
+.It Fl r
+Reset all the profile buffers.
+If the
+.Fl p
+flag is also specified, the
+.Pa gmon.out
+file is generated before the buffers are reset.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default ``/dev/kmem''.
+.It Fl N
+Extract the name list from the specified system instead of the
+default ``/vmunix''.
+.El
+.Pp
+If neither
+.Fl b
+nor
+.Fl h
+is specified, the state of profiling collection remains unchanged.
+For example, if the
+.Fl p
+flag is specified and profile data is being collected,
+profiling will be momentarily suspended,
+the operating system profile buffers will be dumped,
+and profiling will be immediately resumed.
+.Sh FILES
+.Bl -tag -width /dev/kmemx -compact
+.It Pa /vmunix
+the default system
+.It Pa /dev/kmem
+the default memory
+.El
+.Sh SEE ALSO
+.Xr gprof 1 ,
+.Xr config 8
+.Sh DIAGNOSTICS
+Users with only read permission on
+.Pa /dev/kmem
+cannot change the state
+of profiling collection.
+They can get a
+.Pa gmon.out
+file with the warning that the data may be
+inconsistent if profiling is in progress.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/kgmon/kgmon.c b/usr.sbin/kgmon/kgmon.c
new file mode 100644
index 0000000..1265ce2
--- /dev/null
+++ b/usr.sbin/kgmon/kgmon.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/sysctl.h>
+#include <sys/gmon.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <nlist.h>
+#include <ctype.h>
+#include <paths.h>
+
+struct nlist nl[] = {
+#define N_GMONPARAM 0
+ { "__gmonparam" },
+#define N_PROFHZ 1
+ { "_profhz" },
+ 0,
+};
+
+struct kvmvars {
+ kvm_t *kd;
+ struct gmonparam gpm;
+};
+
+int bflag, hflag, kflag, rflag, pflag;
+int debug = 0;
+void setprof __P((struct kvmvars *kvp, int state));
+void dumpstate __P((struct kvmvars *kvp));
+void reset __P((struct kvmvars *kvp));
+
+int
+main(int argc, char **argv)
+{
+ extern char *optarg;
+ extern int optind;
+ int ch, mode, disp, accessmode;
+ struct kvmvars kvmvars;
+ char *system, *kmemf;
+
+ seteuid(getuid());
+ kmemf = NULL;
+ system = NULL;
+ while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {
+ switch((char)ch) {
+
+ case 'M':
+ kmemf = optarg;
+ kflag = 1;
+ break;
+
+ case 'N':
+ system = optarg;
+ break;
+
+ case 'b':
+ bflag = 1;
+ break;
+
+ case 'h':
+ hflag = 1;
+ break;
+
+ case 'p':
+ pflag = 1;
+ break;
+
+ case 'r':
+ rflag = 1;
+ break;
+
+ default:
+ (void)fprintf(stderr,
+ "usage: kgmon [-bhrp] [-M core] [-N system]\n");
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ system = *argv;
+ if (*++argv) {
+ kmemf = *argv;
+ ++kflag;
+ }
+ }
+#endif
+ if (system == NULL)
+ system = _PATH_UNIX;
+ accessmode = openfiles(system, kmemf, &kvmvars);
+ mode = getprof(&kvmvars);
+ if (hflag)
+ disp = GMON_PROF_OFF;
+ else if (bflag)
+ disp = GMON_PROF_ON;
+ else
+ disp = mode;
+ if (pflag)
+ dumpstate(&kvmvars);
+ if (rflag)
+ reset(&kvmvars);
+ if (accessmode == O_RDWR)
+ setprof(&kvmvars, disp);
+ (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n",
+ disp == GMON_PROF_OFF ? "off" : "running");
+ return (0);
+}
+
+/*
+ * Check that profiling is enabled and open any ncessary files.
+ */
+openfiles(system, kmemf, kvp)
+ char *system;
+ char *kmemf;
+ struct kvmvars *kvp;
+{
+ int mib[3], state, size, openmode;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ if (!kflag) {
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROF;
+ mib[2] = GPROF_STATE;
+ size = sizeof state;
+ if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
+ (void)fprintf(stderr,
+ "kgmon: profiling not defined in kernel.\n");
+ exit(20);
+ }
+ if (!(bflag || hflag || rflag ||
+ (pflag && state == GMON_PROF_ON)))
+ return (O_RDONLY);
+ (void)seteuid(0);
+ if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)
+ return (O_RDWR);
+ (void)seteuid(getuid());
+ kern_readonly(state);
+ return (O_RDONLY);
+ }
+ openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
+ kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);
+ if (kvp->kd == NULL) {
+ if (openmode == O_RDWR) {
+ openmode = O_RDONLY;
+ kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY,
+ errbuf);
+ }
+ if (kvp->kd == NULL) {
+ (void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n",
+ errbuf);
+ exit(2);
+ }
+ kern_readonly(GMON_PROF_ON);
+ }
+ if (kvm_nlist(kvp->kd, nl) < 0) {
+ (void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
+ exit(3);
+ }
+ if (!nl[N_GMONPARAM].n_value) {
+ (void)fprintf(stderr,
+ "kgmon: profiling not defined in kernel.\n");
+ exit(20);
+ }
+ return (openmode);
+}
+
+/*
+ * Suppress options that require a writable kernel.
+ */
+kern_readonly(mode)
+ int mode;
+{
+
+ (void)fprintf(stderr, "kgmon: kernel read-only: ");
+ if (pflag && mode == GMON_PROF_ON)
+ (void)fprintf(stderr, "data may be inconsistent\n");
+ if (rflag)
+ (void)fprintf(stderr, "-r supressed\n");
+ if (bflag)
+ (void)fprintf(stderr, "-b supressed\n");
+ if (hflag)
+ (void)fprintf(stderr, "-h supressed\n");
+ rflag = bflag = hflag = 0;
+}
+
+/*
+ * Get the state of kernel profiling.
+ */
+getprof(kvp)
+ struct kvmvars *kvp;
+{
+ int mib[3], size;
+
+ if (kflag) {
+ size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm,
+ sizeof kvp->gpm);
+ } else {
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROF;
+ mib[2] = GPROF_GMONPARAM;
+ size = sizeof kvp->gpm;
+ if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0)
+ size = 0;
+ }
+ if (size != sizeof kvp->gpm) {
+ (void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n",
+ kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+ exit (4);
+ }
+ return (kvp->gpm.state);
+}
+
+/*
+ * Enable or disable kernel profiling according to the state variable.
+ */
+void
+setprof(kvp, state)
+ struct kvmvars *kvp;
+ int state;
+{
+ struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
+ int mib[3], sz, oldstate;
+
+ sz = sizeof(state);
+ if (!kflag) {
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROF;
+ mib[2] = GPROF_STATE;
+ if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0)
+ goto bad;
+ if (oldstate == state)
+ return;
+ (void)seteuid(0);
+ if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) {
+ (void)seteuid(getuid());
+ return;
+ }
+ (void)seteuid(getuid());
+ } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz)
+ == sz)
+ return;
+bad:
+ (void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n",
+ state == GMON_PROF_OFF ? "off" : "on");
+}
+
+/*
+ * Build the gmon.out file.
+ */
+void
+dumpstate(kvp)
+ struct kvmvars *kvp;
+{
+ register FILE *fp;
+ struct rawarc rawarc;
+ struct tostruct *tos;
+ u_long frompc, addr;
+ u_short *froms, *tickbuf;
+ int mib[3], i;
+ struct gmonhdr h;
+ int fromindex, endfrom, toindex;
+
+ setprof(kvp, GMON_PROF_OFF);
+ fp = fopen("gmon.out", "w");
+ if (fp == 0) {
+ perror("gmon.out");
+ return;
+ }
+
+ /*
+ * Build the gmon header and write it to a file.
+ */
+ bzero(&h, sizeof(h));
+ h.lpc = kvp->gpm.lowpc;
+ h.hpc = kvp->gpm.highpc;
+ h.ncnt = kvp->gpm.kcountsize + sizeof(h);
+ h.version = GMONVERSION;
+ h.profrate = getprofhz(kvp);
+ fwrite((char *)&h, sizeof(h), 1, fp);
+
+ /*
+ * Write out the tick buffer.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROF;
+ if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) {
+ fprintf(stderr, "kgmon: cannot allocate kcount space\n");
+ exit (5);
+ }
+ if (kflag) {
+ i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf,
+ kvp->gpm.kcountsize);
+ } else {
+ mib[2] = GPROF_COUNT;
+ i = kvp->gpm.kcountsize;
+ if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0)
+ i = 0;
+ }
+ if (i != kvp->gpm.kcountsize) {
+ (void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s",
+ kvp->gpm.kcountsize, i,
+ kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+ exit(6);
+ }
+ if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) {
+ perror("kgmon: writing tocks to gmon.out");
+ exit(7);
+ }
+ free(tickbuf);
+
+ /*
+ * Write out the arc info.
+ */
+ if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) {
+ fprintf(stderr, "kgmon: cannot allocate froms space\n");
+ exit (8);
+ }
+ if (kflag) {
+ i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms,
+ kvp->gpm.fromssize);
+ } else {
+ mib[2] = GPROF_FROMS;
+ i = kvp->gpm.fromssize;
+ if (sysctl(mib, 3, froms, &i, NULL, 0) < 0)
+ i = 0;
+ }
+ if (i != kvp->gpm.fromssize) {
+ (void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s",
+ kvp->gpm.fromssize, i,
+ kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+ exit(9);
+ }
+ if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) {
+ fprintf(stderr, "kgmon: cannot allocate tos space\n");
+ exit(10);
+ }
+ if (kflag) {
+ i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos,
+ kvp->gpm.tossize);
+ } else {
+ mib[2] = GPROF_TOS;
+ i = kvp->gpm.tossize;
+ if (sysctl(mib, 3, tos, &i, NULL, 0) < 0)
+ i = 0;
+ }
+ if (i != kvp->gpm.tossize) {
+ (void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s",
+ kvp->gpm.tossize, i,
+ kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+ exit(11);
+ }
+ if (debug)
+ (void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n",
+ kvp->gpm.lowpc, kvp->gpm.textsize);
+ endfrom = kvp->gpm.fromssize / sizeof(*froms);
+ for (fromindex = 0; fromindex < endfrom; ++fromindex) {
+ if (froms[fromindex] == 0)
+ continue;
+ frompc = (u_long)kvp->gpm.lowpc +
+ (fromindex * kvp->gpm.hashfraction * sizeof(*froms));
+ for (toindex = froms[fromindex]; toindex != 0;
+ toindex = tos[toindex].link) {
+ if (debug)
+ (void)fprintf(stderr,
+ "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
+ "kgmon", frompc, tos[toindex].selfpc,
+ tos[toindex].count);
+ rawarc.raw_frompc = frompc;
+ rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
+ rawarc.raw_count = tos[toindex].count;
+ fwrite((char *)&rawarc, sizeof(rawarc), 1, fp);
+ }
+ }
+ fclose(fp);
+}
+
+/*
+ * Get the profiling rate.
+ */
+int
+getprofhz(kvp)
+ struct kvmvars *kvp;
+{
+ int mib[2], size, profrate;
+ struct clockinfo clockrate;
+
+ if (kflag) {
+ profrate = 1;
+ if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate,
+ sizeof profrate) != sizeof profrate)
+ (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
+ kvm_geterr(kvp->kd));
+ return (profrate);
+ }
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CLOCKRATE;
+ clockrate.profhz = 1;
+ size = sizeof clockrate;
+ if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0)
+ (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
+ strerror(errno));
+ return (clockrate.profhz);
+}
+
+/*
+ * Reset the kernel profiling date structures.
+ */
+void
+reset(kvp)
+ struct kvmvars *kvp;
+{
+ char *zbuf;
+ u_long biggest;
+ int mib[3];
+
+ setprof(kvp, GMON_PROF_OFF);
+
+ biggest = kvp->gpm.kcountsize;
+ if (kvp->gpm.fromssize > biggest)
+ biggest = kvp->gpm.fromssize;
+ if (kvp->gpm.tossize > biggest)
+ biggest = kvp->gpm.tossize;
+ if ((zbuf = (char *)malloc(biggest)) == NULL) {
+ fprintf(stderr, "kgmon: cannot allocate zbuf space\n");
+ exit(12);
+ }
+ bzero(zbuf, biggest);
+ if (kflag) {
+ if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
+ kvp->gpm.kcountsize) != kvp->gpm.kcountsize) {
+ (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
+ kvm_geterr(kvp->kd));
+ exit(13);
+ }
+ if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
+ kvp->gpm.fromssize) != kvp->gpm.fromssize) {
+ (void)fprintf(stderr, "kgmon: froms zero: %s\n",
+ kvm_geterr(kvp->kd));
+ exit(14);
+ }
+ if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
+ kvp->gpm.tossize) != kvp->gpm.tossize) {
+ (void)fprintf(stderr, "kgmon: tos zero: %s\n",
+ kvm_geterr(kvp->kd));
+ exit(15);
+ }
+ return;
+ }
+ (void)seteuid(0);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROF;
+ mib[2] = GPROF_COUNT;
+ if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) {
+ (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
+ strerror(errno));
+ exit(13);
+ }
+ mib[2] = GPROF_FROMS;
+ if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) {
+ (void)fprintf(stderr, "kgmon: froms zero: %s\n",
+ strerror(errno));
+ exit(14);
+ }
+ mib[2] = GPROF_TOS;
+ if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) {
+ (void)fprintf(stderr, "kgmon: tos zero: %s\n",
+ strerror(errno));
+ exit(15);
+ }
+ (void)seteuid(getuid());
+ free(zbuf);
+}
diff --git a/usr.sbin/kvm_mkdb/Makefile b/usr.sbin/kvm_mkdb/Makefile
new file mode 100644
index 0000000..ea2b883
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= kvm_mkdb
+SRCS= kvm_mkdb.c nlist.c testdb.c
+MAN8= kvm_mkdb.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/kvm_mkdb/extern.h b/usr.sbin/kvm_mkdb/extern.h
new file mode 100644
index 0000000..6d72268
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/extern.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+void create_knlist __P((char *, DB *));
+void error __P((char *));
+int testdb __P(());
diff --git a/usr.sbin/kvm_mkdb/kvm_mkdb.8 b/usr.sbin/kvm_mkdb/kvm_mkdb.8
new file mode 100644
index 0000000..d9dcbf9
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/kvm_mkdb.8
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)kvm_mkdb.8 8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt KVM_MKDB 8
+.Os
+.Sh NAME
+.Nm kvm_mkdb
+.Nd create kernel database
+.Sh SYNOPSIS
+.Nm kvm_mkdb
+.Op file
+.Sh DESCRIPTION
+.Nm Kvm_mkdb
+creates a database in
+.Pa /var/db
+containing information about the specified file.
+If no file is specified,
+.Pa /vmunix
+is used by default.
+The file is named ``kvm_filename.db'', where ``filename'' is the
+name of the file read.
+Various library routines consult this database.
+The only information currently stored is the kernel namelist, which is
+used by the
+.Xr kvm_nlist 3
+function, however, in the future the database may contain other static
+information about the current system.
+.Sh FILES
+.Bl -tag -width /var/db/kvm_vmunix.db -compact
+.It Pa /vmunix
+.It Pa /var/db/kvm_vmunix.db
+.El
+.Sh SEE ALSO
+.Xr kvm_nlist 3
+.Sh HISTORY
+The
+.Nm kvm_mkdb
+utility first appeared in 4.4BSD.
diff --git a/usr.sbin/kvm_mkdb/kvm_mkdb.c b/usr.sbin/kvm_mkdb/kvm_mkdb.c
new file mode 100644
index 0000000..f80b109
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/kvm_mkdb.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)kvm_mkdb.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "extern.h"
+
+static void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ DB *db;
+ int ch;
+ char *p, *nlistpath, *nlistname, dbtemp[MAXPATHLEN], dbname[MAXPATHLEN];
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ usage();
+
+ /* If the existing db file matches the currently running kernel, exit */
+ if (testdb())
+ exit(0);
+
+#define basename(cp) ((p = rindex((cp), '/')) != NULL ? p + 1 : (cp))
+ nlistpath = argc > 0 ? argv[0] : _PATH_UNIX;
+ nlistname = basename(nlistpath);
+
+ (void)snprintf(dbtemp, sizeof(dbtemp), "%skvm_%s.tmp",
+ _PATH_VARDB, nlistname);
+ (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db",
+ _PATH_VARDB, nlistname);
+ (void)umask(0);
+ db = dbopen(dbtemp, O_CREAT | O_EXLOCK | O_TRUNC | O_RDWR,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, DB_HASH, NULL);
+ if (db == NULL)
+ err(1, "%s", dbtemp);
+ create_knlist(nlistpath, db);
+ if (db->close(db))
+ err(1, "%s", dbtemp);
+ if (rename(dbtemp, dbname))
+ err(1, "rename %s to %s", dbtemp, dbname);
+ exit(0);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: kvm_mkdb [file]\n");
+ exit(1);
+}
diff --git a/usr.sbin/kvm_mkdb/nlist.c b/usr.sbin/kvm_mkdb/nlist.c
new file mode 100644
index 0000000..ad31a1a
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/nlist.c
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <a.out.h>
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+typedef struct nlist NLIST;
+#define _strx n_un.n_strx
+#define _name n_un.n_name
+
+#define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE))
+
+static void badread __P((int, char *));
+
+static char *kfile;
+
+void
+create_knlist(name, db)
+ char *name;
+ DB *db;
+{
+ register int nsyms;
+ struct exec ebuf;
+ FILE *fp;
+ NLIST nbuf;
+ DBT data, key;
+ int fd, nr, strsize;
+ char *strtab, buf[1024];
+
+ kfile = name;
+ if ((fd = open(name, O_RDONLY, 0)) < 0)
+ err(1, "%s", name);
+
+ /* Read in exec structure. */
+ nr = read(fd, &ebuf, sizeof(struct exec));
+ if (nr != sizeof(struct exec))
+ badfmt("no exec header");
+
+ /* Check magic number and symbol count. */
+ if (N_BADMAG(ebuf))
+ badfmt("bad magic number");
+ if (!ebuf.a_syms)
+ badfmt("stripped");
+
+ /* Seek to string table. */
+ if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1)
+ badfmt("corrupted string table");
+
+ /* Read in the size of the symbol table. */
+ nr = read(fd, (char *)&strsize, sizeof(strsize));
+ if (nr != sizeof(strsize))
+ badread(nr, "no symbol table");
+
+ /* Read in the string table. */
+ strsize -= sizeof(strsize);
+ if (!(strtab = malloc(strsize)))
+ err(1, NULL);
+ if ((nr = read(fd, strtab, strsize)) != strsize)
+ badread(nr, "corrupted symbol table");
+
+ /* Seek to symbol table. */
+ if (!(fp = fdopen(fd, "r")))
+ err(1, "%s", name);
+ if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1)
+ err(1, "%s", name);
+
+ data.data = (u_char *)&nbuf;
+ data.size = sizeof(NLIST);
+
+ /* Read each symbol and enter it into the database. */
+ nsyms = ebuf.a_syms / sizeof(struct nlist);
+ while (nsyms--) {
+ if (fread((char *)&nbuf, sizeof (NLIST), 1, fp) != 1) {
+ if (feof(fp))
+ badfmt("corrupted symbol table");
+ err(1, "%s", name);
+ }
+ if (!nbuf._strx || nbuf.n_type&N_STAB)
+ continue;
+
+ key.data = (u_char *)strtab + nbuf._strx - sizeof(long);
+ key.size = strlen((char *)key.data);
+ if (db->put(db, &key, &data, 0))
+ err(1, "record enter");
+
+ if (strcmp((char *)key.data, VRS_SYM) == 0) {
+ long cur_off, voff;
+#ifndef KERNTEXTOFF
+#define KERNTEXTOFF KERNBASE
+#endif
+ /*
+ * Calculate offset relative to a normal (non-kernel)
+ * a.out. KERNTEXTOFF is where the kernel is really
+ * loaded; N_TXTADDR is where a normal file is loaded.
+ * From there, locate file offset in text or data.
+ */
+ voff = nbuf.n_value - KERNTEXTOFF + N_TXTADDR(ebuf);
+ if ((nbuf.n_type & N_TYPE) == N_TEXT)
+ voff += N_TXTOFF(ebuf) - N_TXTADDR(ebuf);
+ else
+ voff += N_DATOFF(ebuf) - N_DATADDR(ebuf);
+ cur_off = ftell(fp);
+ if (fseek(fp, voff, SEEK_SET) == -1)
+ badfmt("corrupted string table");
+
+ /*
+ * Read version string up to, and including newline.
+ * This code assumes that a newline terminates the
+ * version line.
+ */
+ if (fgets(buf, sizeof(buf), fp) == NULL)
+ badfmt("corrupted string table");
+
+ key.data = (u_char *)VRS_KEY;
+ key.size = sizeof(VRS_KEY) - 1;
+ data.data = (u_char *)buf;
+ data.size = strlen(buf);
+ if (db->put(db, &key, &data, 0))
+ err(1, "record enter");
+
+ /* Restore to original values. */
+ data.data = (u_char *)&nbuf;
+ data.size = sizeof(NLIST);
+ if (fseek(fp, cur_off, SEEK_SET) == -1)
+ badfmt("corrupted string table");
+ }
+ }
+ (void)fclose(fp);
+}
+
+static void
+badread(nr, p)
+ int nr;
+ char *p;
+{
+ if (nr < 0)
+ err(1, "%s", kfile);
+ badfmt(p);
+}
diff --git a/usr.sbin/kvm_mkdb/testdb.c b/usr.sbin/kvm_mkdb/testdb.c
new file mode 100644
index 0000000..f4f3bf0
--- /dev/null
+++ b/usr.sbin/kvm_mkdb/testdb.c
@@ -0,0 +1,113 @@
+/*-
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)testdb.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <limits.h>
+#include <kvm.h>
+#include <db.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <paths.h>
+
+#include "extern.h"
+
+/* Return true if the db file is valid, else false */
+int
+testdb()
+{
+ register DB *db;
+ register int cc, kd, ret, dbversionlen;
+ register char *cp, *uf;
+ DBT rec;
+ struct nlist nitem;
+ char dbname[MAXPATHLEN], dbversion[_POSIX2_LINE_MAX];
+ char kversion[_POSIX2_LINE_MAX];
+
+ ret = 0;
+ db = NULL;
+
+ if ((kd = open(_PATH_KMEM, O_RDONLY, 0)) < 0)
+ goto close;
+
+ uf = _PATH_UNIX;
+ if ((cp = rindex(uf, '/')) != 0)
+ uf = cp + 1;
+ (void) snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
+ if ((db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+ goto close;
+
+ /* Read the version out of the database */
+ rec.data = VRS_KEY;
+ rec.size = sizeof(VRS_KEY) - 1;
+ if ((db->get)(db, &rec, &rec, 0))
+ goto close;
+ if (rec.data == 0 || rec.size > sizeof(dbversion))
+ goto close;
+ bcopy(rec.data, dbversion, rec.size);
+ dbversionlen = rec.size;
+
+ /* Read version string from kernel memory */
+ rec.data = VRS_SYM;
+ rec.size = sizeof(VRS_SYM) - 1;
+ if ((db->get)(db, &rec, &rec, 0))
+ goto close;
+ if (rec.data == 0 || rec.size != sizeof(struct nlist))
+ goto close;
+ bcopy(rec.data, &nitem, sizeof(nitem));
+ /*
+ * Theoretically possible for lseek to be seeking to -1. Not
+ * that it's something to lie awake nights about, however.
+ */
+ errno = 0;
+ if (lseek(kd, (off_t)nitem.n_value, SEEK_SET) == -1 && errno != 0)
+ goto close;
+ cc = read(kd, kversion, sizeof(kversion));
+ if (cc < 0 || cc != sizeof(kversion))
+ goto close;
+
+ /* If they match, we win */
+ ret = bcmp(dbversion, kversion, dbversionlen) == 0;
+
+close: if (kd >= 0)
+ (void)close(kd);
+ if (db)
+ (void)(db->close)(db);
+ return (ret);
+}
diff --git a/usr.sbin/lpr/Makefile b/usr.sbin/lpr/Makefile
new file mode 100644
index 0000000..9b4d7d2
--- /dev/null
+++ b/usr.sbin/lpr/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+SUBDIR= lpc lpd lpq lpr lprm lptest pac filters
+
+.include <bsd.subdir.mk>
+
diff --git a/usr.sbin/lpr/SMM.doc/0.t b/usr.sbin/lpr/SMM.doc/0.t
new file mode 100644
index 0000000..65ecd4e
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/0.t
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)0.t 8.1 (Berkeley) 6/8/93
+.\"
+.if n .ND
+.TL
+4.3BSD Line Printer Spooler Manual
+.EH 'SMM:7-%''4.3BSD Line Printer Spooler Manual'
+.OH '4.3BSD Line Printer Spooler Manual''SMM:7-%'
+.AU
+Ralph Campbell
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.AB
+.FS
+* UNIX is a trademark of Bell Laboratories.
+.FE
+This document describes the structure and installation procedure
+for the line printer spooling system
+developed for the 4.3BSD version
+of the UNIX* operating system.
+.de D?
+.ie \\n(.$>1 Revised \\$1 \\$2 \\$3
+.el DRAFT of \n(mo/\n(dy/\n(yr
+..
+.sp 2
+.LP
+.D? June 8, 1993
+.AE
+.de IR
+\fI\\$1\fP\\$2
+..
+.de DT
+.TA 8 16 24 32 40 48 56 64 72 80
+..
diff --git a/usr.sbin/lpr/SMM.doc/1.t b/usr.sbin/lpr/SMM.doc/1.t
new file mode 100644
index 0000000..1d34e9e
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/1.t
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)1.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Overview
+.PP
+The line printer system supports:
+.IP \(bu 3
+multiple printers,
+.IP \(bu 3
+multiple spooling queues,
+.IP \(bu 3
+both local and remote
+printers, and
+.IP \(bu 3
+printers attached via serial lines that require
+line initialization such as the baud rate.
+.LP
+Raster output devices
+such as a Varian or Versatec, and laser printers such as an Imagen,
+are also supported by the line printer system.
+.PP
+The line printer system consists mainly of the
+following files and commands:
+.DS
+.TS
+l l.
+/etc/printcap printer configuration and capability data base
+/usr/lib/lpd line printer daemon, does all the real work
+/usr/ucb/lpr program to enter a job in a printer queue
+/usr/ucb/lpq spooling queue examination program
+/usr/ucb/lprm program to delete jobs from a queue
+/etc/lpc program to administer printers and spooling queues
+/dev/printer socket on which lpd listens
+.TE
+.DE
+The file /etc/printcap is a master data base describing line
+printers directly attached to a machine and, also, printers
+accessible across a network. The manual page entry
+.IR printcap (5)
+provides the authoritative definition of
+the format of this data base, as well as
+specifying default values for important items
+such as the directory in which spooling is performed.
+This document introduces some of the
+information that may be placed
+.IR printcap .
diff --git a/usr.sbin/lpr/SMM.doc/2.t b/usr.sbin/lpr/SMM.doc/2.t
new file mode 100644
index 0000000..9da2ae2
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/2.t
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)2.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Commands
+.NH 2
+lpd \- line printer daemon
+.PP
+The program
+.IR lpd (8),
+usually invoked at boot time from the /etc/rc file, acts as
+a master server for coordinating and controlling
+the spooling queues configured in the printcap file.
+When
+.I lpd
+is started it makes a single pass through the
+.I printcap
+database restarting any printers that have jobs.
+In normal operation
+.I lpd
+listens for service requests on multiple sockets,
+one in the UNIX domain (named ``/dev/printer'') for
+local requests, and one in the Internet domain
+(under the ``printer'' service specification)
+for requests for printer access from off machine;
+see \fIsocket\fP\|(2) and \fIservices\fP\|(5)
+for more information on sockets and service
+specifications, respectively.
+.I Lpd
+spawns a copy of itself to process the request; the master daemon
+continues to listen for new requests.
+.PP
+Clients communicate with
+.I lpd
+using a simple transaction oriented protocol.
+Authentication of remote clients is done based
+on the ``privilege port'' scheme employed by
+\fIrshd\fP\|(8C) and \fIrcmd\fP\|(3X).
+The following table shows the requests
+understood by
+.IR lpd .
+In each request the first byte indicates the
+``meaning'' of the request, followed by the name
+of the printer to which it should be applied. Additional
+qualifiers may follow, depending on the request.
+.DS
+.TS
+l l.
+Request Interpretation
+_
+^Aprinter\en check the queue for jobs and print any found
+^Bprinter\en receive and queue a job from another machine
+^Cprinter [users ...] [jobs ...]\en return short list of current queue state
+^Dprinter [users ...] [jobs ...]\en return long list of current queue state
+^Eprinter person [users ...] [jobs ...]\en remove jobs from a queue
+.TE
+.DE
+.PP
+The \fIlpr\fP\|(1) command
+is used by users to enter a print job in a local queue and to notify
+the local
+.I lpd
+that there are new jobs in the spooling area.
+.I Lpd
+either schedules the job to be printed locally, or if
+printing remotely, attempts to forward
+the job to the appropriate machine.
+If the printer cannot be opened or the destination
+machine is unreachable, the job will remain queued until it is
+possible to complete the work.
+.NH 2
+lpq \- show line printer queue
+.PP
+The \fIlpq\fP\|(1)
+program works recursively backwards displaying the queue of the machine with
+the printer and then the queue(s) of the machine(s) that lead to it.
+.I Lpq
+has two forms of output: in the default, short, format it
+gives a single line of output per queued job; in the long
+format it shows the list of files, and their sizes, that
+comprise a job.
+.NH 2
+lprm \- remove jobs from a queue
+.PP
+The \fIlprm\fP\|(1) command deletes jobs from a spooling
+queue. If necessary, \fIlprm\fP will first kill off a
+running daemon that is servicing the queue and restart
+it after the required files are removed. When removing
+jobs destined for a remote printer, \fIlprm\fP acts
+similarly to \fIlpq\fP except it first checks locally
+for jobs to remove and then
+tries to remove files in queues off-machine.
+.NH 2
+lpc \- line printer control program
+.PP
+The
+.IR lpc (8)
+program is used by the system administrator to control the
+operation of the line printer system.
+For each line printer configured in /etc/printcap,
+.I lpc
+may be used to:
+.IP \(bu
+disable or enable a printer,
+.IP \(bu
+disable or enable a printer's spooling queue,
+.IP \(bu
+rearrange the order of jobs in a spooling queue,
+.IP \(bu
+find the status of printers, and their associated
+spooling queues and printer daemons.
diff --git a/usr.sbin/lpr/SMM.doc/3.t b/usr.sbin/lpr/SMM.doc/3.t
new file mode 100644
index 0000000..8c950a9
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/3.t
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)3.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Access control
+.PP
+The printer system maintains protected spooling areas so that
+users cannot circumvent printer accounting or
+remove files other than their own.
+The strategy used to maintain protected
+spooling areas is as follows:
+.IP \(bu 3
+The spooling area is writable only by a \fIdaemon\fP user
+and \fIdaemon\fP group.
+.IP \(bu 3
+The \fIlpr\fP program runs set-user-id to \fIroot\fP and
+set-group-id to group \fIdaemon\fP. The \fIroot\fP access permits
+reading any file required. Accessibility is verified
+with an \fIaccess\fP\|(2) call. The group ID
+is used in setting up proper ownership of files
+in the spooling area for \fIlprm\fP.
+.IP \(bu 3
+Control files in a spooling area are made with \fIdaemon\fP
+ownership and group ownership \fIdaemon\fP. Their mode is 0660.
+This insures control files are not modified by a user
+and that no user can remove files except through \fIlprm\fP.
+.IP \(bu 3
+The spooling programs,
+\fIlpd\fP, \fIlpq\fP, and \fIlprm\fP run set-user-id to \fIroot\fP
+and set-group-id to group \fIdaemon\fP to access spool files and printers.
+.IP \(bu 3
+The printer server, \fIlpd\fP,
+uses the same verification procedures as \fIrshd\fP\|(8C)
+in authenticating remote clients. The host on which a client
+resides must be present in the file /etc/hosts.equiv or /etc/hosts.lpd and
+the request message must come from a reserved port number.
+.PP
+In practice, none of \fIlpd\fP, \fIlpq\fP, or
+\fIlprm\fP would have to run as user \fIroot\fP if remote
+spooling were not supported. In previous incarnations of
+the printer system \fIlpd\fP ran set-user-id to \fIdaemon\fP,
+set-group-id to group \fIspooling\fP, and \fIlpq\fP and \fIlprm\fP ran
+set-group-id to group \fIspooling\fP.
diff --git a/usr.sbin/lpr/SMM.doc/4.t b/usr.sbin/lpr/SMM.doc/4.t
new file mode 100644
index 0000000..8800bc0
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/4.t
@@ -0,0 +1,206 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)4.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Setting up
+.PP
+The 4.3BSD release comes with the necessary programs
+installed and with the default line printer queue
+created. If the system must be modified, the
+makefile in the directory /usr/src/usr.lib/lpr
+should be used in recompiling and reinstalling
+the necessary programs.
+.PP
+The real work in setting up is to create the
+.I printcap
+file and any printer filters for printers not supported
+in the distribution system.
+.NH 2
+Creating a printcap file
+.PP
+The
+.I printcap
+database contains one or more entries per printer.
+A printer should have a separate spooling directory;
+otherwise, jobs will be printed on
+different printers depending on which printer daemon starts first.
+This section describes how to create entries for printers that do not
+conform to the default printer description (an LP-11 style interface to a
+standard, band printer).
+.NH 3
+Printers on serial lines
+.PP
+When a printer is connected via a serial communication line
+it must have the proper baud rate and terminal modes set.
+The following example is for a DecWriter III printer connected
+locally via a 1200 baud serial line.
+.DS
+.DT
+lp|LA-180 DecWriter III:\e
+ :lp=/dev/lp:br#1200:fs#06320:\e
+ :tr=\ef:of=/usr/lib/lpf:lf=/usr/adm/lpd-errs:
+.DE
+The
+.B lp
+entry specifies the file name to open for output. Here it could
+be left out since ``/dev/lp'' is the default.
+The
+.B br
+entry sets the baud rate for the tty line and the
+.B fs
+entry sets CRMOD, no parity, and XTABS (see \fItty\fP\|(4)).
+The
+.B tr
+entry indicates that a form-feed should be printed when the queue
+empties so the paper can be torn off without turning the printer off-line and
+pressing form feed.
+The
+.B of
+entry specifies the filter program
+.I lpf
+should be used for printing the files;
+more will be said about filters later.
+The last entry causes errors
+to be written to the file ``/usr/adm/lpd-errs''
+instead of the console. Most errors from \fIlpd\fP are logged using
+\fIsyslogd\fP\|(8) and will not be logged in the specified file. The
+filters should use \fIsyslogd\fP to report errors; only those that
+write to standard error output will end up with errors in the \fBlf\fP file.
+(Occasionally errors sent to standard error output have not appeared
+in the log file; the use of \fIsyslogd\fP is highly recommended.)
+.NH 3
+Remote printers
+.PP
+Printers that reside on remote hosts should have an empty
+.B lp
+entry.
+For example, the following printcap entry would send output to the printer
+named ``lp'' on the machine ``ucbvax''.
+.DS
+.DT
+lp|default line printer:\e
+ :lp=:rm=ucbvax:rp=lp:sd=/usr/spool/vaxlpd:
+.DE
+The
+.B rm
+entry is the name of the remote machine to connect to; this name must
+be a known host name for a machine on the network.
+The
+.B rp
+capability indicates
+the name of the printer on the remote machine is ``lp'';
+here it could be left out since this is the default value.
+The
+.B sd
+entry specifies ``/usr/spool/vaxlpd''
+as the spooling directory instead of the
+default value of ``/usr/spool/lpd''.
+.NH 2
+Output filters
+.PP
+Filters are used to handle device dependencies and to
+do accounting functions. The output filtering of
+.B of
+is used when accounting is
+not being done or when all text data must be passed through a filter.
+It is not intended to do accounting since it is started only once,
+all text files are filtered through it, and no provision is made for passing
+owners' login name, identifying the beginning and ending of jobs, etc.
+The other filters (if specified) are started for each file
+printed and do accounting if there is an
+.B af
+entry.
+If entries for both
+.B of
+and other filters are specified,
+the output filter is used only to print the banner page;
+it is then stopped to allow other filters access to the printer.
+An example of a printer that requires output filters
+is the Benson-Varian.
+.DS
+.DT
+va|varian|Benson-Varian:\e
+ :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e
+ :tf=/usr/lib/rvcat:mx#2000:pl#58:px=2112:py=1700:tr=\ef:
+.DE
+The
+.B tf
+entry specifies ``/usr/lib/rvcat'' as the filter to be
+used in printing \fItroff\fP\|(1) output.
+This filter is needed to set the device into print mode
+for text, and plot mode for printing
+.I troff
+files and raster images (see \fIva\fP\|(4V)).
+Note that the page length is set to 58 lines by the
+.B pl
+entry for 8.5" by 11" fan-fold paper.
+To enable accounting, the varian entry would be
+augmented with an
+.B af
+filter as shown below.
+.DS
+.DT
+va|varian|Benson-Varian:\e
+ :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e
+ :if=/usr/lib/vpf:tf=/usr/lib/rvcat:af=/usr/adm/vaacct:\e
+ :mx#2000:pl#58:px=2112:py=1700:tr=\ef:
+.DE
+.NH 2
+Access Control
+.PP
+Local access to printer queues is controlled with the
+.B rg
+printcap entry.
+.DS
+ :rg=lprgroup:
+.DE
+Users must be in the group
+.I lprgroup
+to submit jobs to the specified printer.
+The default is to allow all users access.
+Note that once the files are in the local queue, they can be printed
+locally or forwarded to another host depending on the configuration.
+.PP
+Remote access is controlled by listing the hosts in either the file
+/etc/hosts.equiv or /etc/hosts.lpd, one host per line. Note that
+.IR rsh (1)
+and
+.IR rlogin (1)
+use /etc/hosts.equiv to determine which hosts are equivalent for allowing logins
+without passwords. The file /etc/hosts.lpd is only used to control
+which hosts have line printer access.
+Remote access can be further restricted to only allow remote users with accounts
+on the local host to print jobs by using the \fBrs\fP printcap entry.
+.DS
+ :rs:
+.DE
diff --git a/usr.sbin/lpr/SMM.doc/5.t b/usr.sbin/lpr/SMM.doc/5.t
new file mode 100644
index 0000000..137a342
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/5.t
@@ -0,0 +1,116 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)5.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Output filter specifications
+.PP
+The filters supplied with 4.3BSD
+handle printing and accounting for most common
+line printers, the Benson-Varian, the wide (36") and
+narrow (11") Versatec printer/plotters. For other devices or accounting
+methods, it may be necessary to create a new filter.
+.PP
+Filters are spawned by \fIlpd\fP
+with their standard input the data to be printed, and standard output
+the printer. The standard error is attached to the
+.B lf
+file for logging errors or \fIsyslogd\fP may be used for logging errors.
+A filter must return a 0 exit
+code if there were no errors, 1 if the job should be reprinted,
+and 2 if the job should be thrown away.
+When \fIlprm\fP
+sends a kill signal to the \fIlpd\fP process controlling
+printing, it sends a SIGINT signal
+to all filters and descendents of filters.
+This signal can be trapped by filters that need
+to do cleanup operations such as
+deleting temporary files.
+.PP
+Arguments passed to a filter depend on its type.
+The
+.B of
+filter is called with the following arguments.
+.DS
+\fIfilter\fP \fB\-w\fPwidth \fB\-l\fPlength
+.DE
+The \fIwidth\fP and \fIlength\fP values come from the
+.B pw
+and
+.B pl
+entries in the printcap database.
+The
+.B if
+filter is passed the following parameters.
+.DS
+\fIfilter\fP [\|\fB\-c\fP\|] \fB\-w\fPwidth \fB\-l\fPlength \fB\-i\fPindent \fB\-n\fP login \fB\-h\fP host accounting_file
+.DE
+The
+.B \-c
+flag is optional, and only supplied when control characters
+are to be passed uninterpreted to the printer (when using the
+.B \-l
+option of
+.I lpr
+to print the file).
+The
+.B \-w
+and
+.B \-l
+parameters are the same as for the
+.B of
+filter.
+The
+.B \-n
+and
+.B \-h
+parameters specify the login name and host name of the job owner.
+The last argument is the name of the accounting file from
+.IR printcap .
+.PP
+All other filters are called with the following arguments:
+.DS
+\fIfilter\fP \fB\-x\fPwidth \fB\-y\fPlength \fB\-n\fP login \fB\-h\fP host accounting_file
+.DE
+The
+.B \-x
+and
+.B \-y
+options specify the horizontal and vertical page
+size in pixels (from the
+.B px
+and
+.B py
+entries in the printcap file).
+The rest of the arguments are the same as for the
+.B if
+filter.
diff --git a/usr.sbin/lpr/SMM.doc/6.t b/usr.sbin/lpr/SMM.doc/6.t
new file mode 100644
index 0000000..7087790
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/6.t
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)6.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Line printer Administration
+.PP
+The
+.I lpc
+program provides local control over line printer activity.
+The major commands and their intended use will be described.
+The command format and remaining commands are described in
+.IR lpc (8).
+.LP
+\fBabort\fP and \fBstart\fP
+.IP
+.I Abort
+terminates an active spooling daemon on the local host immediately and
+then disables printing (preventing new daemons from being started by
+.IR lpr ).
+This is normally used to forcibly restart a hung line printer daemon
+(i.e., \fIlpq\fP reports that there is a daemon present but nothing is
+happening). It does not remove any jobs from the queue
+(use the \fIlprm\fP command instead).
+.I Start
+enables printing and requests \fIlpd\fP to start printing jobs.
+.LP
+\fBenable\fP and \fBdisable\fP
+.IP
+\fIEnable\fP and \fIdisable\fP allow spooling in the local queue to be
+turned on/off.
+This will allow/prevent
+.I lpr
+from putting new jobs in the spool queue. It is frequently convenient
+to turn spooling off while testing new line printer filters since the
+.I root
+user can still use
+.I lpr
+to put jobs in the queue but no one else can.
+The other main use is to prevent users from putting jobs in the queue
+when the printer is expected to be unavailable for a long time.
+.LP
+\fBrestart\fP
+.IP
+.I Restart
+allows ordinary users to restart printer daemons when
+.I lpq
+reports that there is no daemon present.
+.LP
+\fBstop\fP
+.IP
+.I Stop
+halts a spooling daemon after the current job completes;
+this also disables printing. This is a clean way to shutdown a
+printer to do maintenance, etc. Note that users can still enter jobs in a
+spool queue while a printer is
+.IR stopped .
+.LP
+\fBtopq\fP
+.IP
+.I Topq
+places jobs at the top of a printer queue. This can be used
+to reorder high priority jobs since
+.I lpr
+only provides first-come-first-serve ordering of jobs.
diff --git a/usr.sbin/lpr/SMM.doc/7.t b/usr.sbin/lpr/SMM.doc/7.t
new file mode 100644
index 0000000..a6f6bea
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/7.t
@@ -0,0 +1,226 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)7.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Troubleshooting
+.PP
+There are several messages that may be generated by the
+the line printer system. This section
+categorizes the most common and explains the cause
+for their generation. Where the message implies a failure,
+directions are given to remedy the problem.
+.PP
+In the examples below, the name
+.I printer
+is the name of the printer from the
+.I printcap
+database.
+.NH 2
+LPR
+.SH
+lpr: \fIprinter\fP\|: unknown printer
+.IP
+The
+.I printer
+was not found in the
+.I printcap
+database. Usually this is a typing mistake; however, it may indicate
+a missing or incorrect entry in the /etc/printcap file.
+.SH
+lpr: \fIprinter\fP\|: jobs queued, but cannot start daemon.
+.IP
+The connection to
+.I lpd
+on the local machine failed.
+This usually means the printer server started at
+boot time has died or is hung. Check the local socket
+/dev/printer to be sure it still exists (if it does not exist,
+there is no
+.I lpd
+process running).
+Usually it is enough to get a super-user to type the following to
+restart
+.IR lpd .
+.DS
+% /usr/lib/lpd
+.DE
+You can also check the state of the master printer daemon with the following.
+.DS
+% ps l`cat /usr/spool/lpd.lock`
+.DE
+.IP
+Another possibility is that the
+.I lpr
+program is not set-user-id to \fIroot\fP, set-group-id to group \fIdaemon\fP.
+This can be checked with
+.DS
+% ls \-lg /usr/ucb/lpr
+.DE
+.SH
+lpr: \fIprinter\fP\|: printer queue is disabled
+.IP
+This means the queue was turned off with
+.DS
+% lpc disable \fIprinter\fP
+.DE
+to prevent
+.I lpr
+from putting files in the queue. This is normally
+done by the system manager when a printer is
+going to be down for a long time. The
+printer can be turned back on by a super-user with
+.IR lpc .
+.NH 2
+LPQ
+.SH
+waiting for \fIprinter\fP to become ready (offline ?)
+.IP
+The printer device could not be opened by the daemon.
+This can happen for several reasons,
+the most common is that the printer is turned off-line.
+This message can also be generated if the printer is out
+of paper, the paper is jammed, etc.
+The actual reason is dependent on the meaning
+of error codes returned by system device driver.
+Not all printers supply enough information
+to distinguish when a printer is off-line or having
+trouble (e.g. a printer connected through a serial line).
+Another possible cause of this message is
+some other process, such as an output filter,
+has an exclusive open on the device. Your only recourse
+here is to kill off the offending program(s) and
+restart the printer with
+.IR lpc .
+.SH
+\fIprinter\fP is ready and printing
+.IP
+The
+.I lpq
+program checks to see if a daemon process exists for
+.I printer
+and prints the file \fIstatus\fP located in the spooling directory.
+If the daemon is hung, a super user can use
+.I lpc
+to abort the current daemon and start a new one.
+.SH
+waiting for \fIhost\fP to come up
+.IP
+This implies there is a daemon trying to connect to the remote
+machine named
+.I host
+to send the files in the local queue.
+If the remote machine is up,
+.I lpd
+on the remote machine is probably dead or
+hung and should be restarted as mentioned for
+.IR lpr .
+.SH
+sending to \fIhost\fP
+.IP
+The files should be in the process of being transferred to the remote
+.IR host .
+If not, the local daemon should be aborted and started with
+.IR lpc .
+.SH
+Warning: \fIprinter\fP is down
+.IP
+The printer has been marked as being unavailable with
+.IR lpc .
+.SH
+Warning: no daemon present
+.IP
+The \fIlpd\fP process overseeing
+the spooling queue, as specified in the ``lock'' file
+in that directory, does not exist. This normally occurs
+only when the daemon has unexpectedly died.
+The error log file for the printer and the \fIsyslogd\fP logs
+should be checked for a
+diagnostic from the deceased process.
+To restart an \fIlpd\fP, use
+.DS
+% lpc restart \fIprinter\fP
+.DE
+.SH
+no space on remote; waiting for queue to drain
+.IP
+This implies that there is insufficient disk space on the remote.
+If the file is large enough, there will never be enough space on
+the remote (even after the queue on the remote is empty). The solution here
+is to move the spooling queue or make more free space on the remote.
+.NH 2
+LPRM
+.SH
+lprm: \fIprinter\fP\|: cannot restart printer daemon
+.IP
+This case is the same as when
+.I lpr
+prints that the daemon cannot be started.
+.NH 2
+LPD
+.PP
+The
+.I lpd
+program can log many different messages using \fIsyslogd\fP\|(8).
+Most of these messages are about files that can not
+be opened and usually imply that the
+.I printcap
+file or the protection modes of the files are
+incorrect. Files may also be inaccessible if people
+manually manipulate the line printer system (i.e. they
+bypass the
+.I lpr
+program).
+.PP
+In addition to messages generated by
+.IR lpd ,
+any of the filters that
+.I lpd
+spawns may log messages using \fIsyslogd\fP or to the error log file
+(the file specified in the \fBlf\fP entry in \fIprintcap\fP\|).
+.NH 2
+LPC
+.PP
+.SH
+couldn't start printer
+.IP
+This case is the same as when
+.I lpr
+reports that the daemon cannot be started.
+.SH
+cannot examine spool directory
+.IP
+Error messages beginning with ``cannot ...'' are usually because of
+incorrect ownership or protection mode of the lock file, spooling
+directory or the
+.I lpc
+program.
diff --git a/usr.sbin/lpr/SMM.doc/Makefile b/usr.sbin/lpr/SMM.doc/Makefile
new file mode 100644
index 0000000..1701c86
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/Makefile
@@ -0,0 +1,10 @@
+# @(#)Makefile 8.1 (Berkeley) 6/8/93
+
+DIR= smm/07.lpd
+SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t 7.t
+MACROS= -ms
+
+paper.ps: ${SRCS}
+ ${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
+
+.include <bsd.doc.mk>
diff --git a/usr.sbin/lpr/SMM.doc/spell.ok b/usr.sbin/lpr/SMM.doc/spell.ok
new file mode 100644
index 0000000..bf31319
--- /dev/null
+++ b/usr.sbin/lpr/SMM.doc/spell.ok
@@ -0,0 +1,70 @@
+Aprinter
+Bprinter
+CRMOD
+Cprinter
+DecWriter
+Dprinter
+Eprinter
+LPC
+LPD
+Lpd
+Manual''SMM:5
+SIGINT
+SMM:5
+Topq
+XTABS
+adm
+af
+br
+daemon
+daemons
+dev
+f:of
+fs
+hosts.equiv
+hosts.lpd
+lf
+lg
+lib
+lp:br
+lp:sd
+lpc
+lpd
+lpd.lock
+lpf
+lpf:lf
+lprgroup
+makefile
+mx
+offline
+pl
+printcap
+pw
+py
+rc
+rcmd
+rg
+rlogin
+rp
+rs
+rsh
+rshd
+rvcat
+rvcat:af
+rvcat:mx
+sd
+src
+syslogd
+tf
+topq
+ucb
+ucbvax
+ucbvax:rp
+usr.lib
+va0:sd
+vaacct
+vad:of
+varian
+vaxlpd
+vpf
+vpf:tf
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
new file mode 100644
index 0000000..49f7939
--- /dev/null
+++ b/usr.sbin/lpr/common_source/common.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)common.c 8.2 (Berkeley) 1/21/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "lp.h"
+#include "pathnames.h"
+
+/*
+ * Routines and data common to all the line printer functions.
+ */
+
+char *AF; /* accounting file */
+long BR; /* baud rate if lp is a tty */
+char *CF; /* name of cifplot filter (per job) */
+char *DF; /* name of tex filter (per job) */
+long DU; /* daeomon user-id */
+long FC; /* flags to clear if lp is a tty */
+char *FF; /* form feed string */
+long FS; /* flags to set if lp is a tty */
+char *GF; /* name of graph(1G) filter (per job) */
+long HL; /* print header last */
+char *IF; /* name of input filter (created per job) */
+char *LF; /* log file for error messages */
+char *LO; /* lock file name */
+char *LP; /* line printer device name */
+long MC; /* maximum number of copies allowed */
+long MX; /* maximum number of blocks to copy */
+char *NF; /* name of ditroff filter (per job) */
+char *OF; /* name of output filter (created once) */
+char *PF; /* name of vrast filter (per job) */
+long PL; /* page length */
+long PW; /* page width */
+long PX; /* page width in pixels */
+long PY; /* page length in pixels */
+char *RF; /* name of fortran text filter (per job) */
+char *RG; /* resricted group */
+char *RM; /* remote machine name */
+char *RP; /* remote printer name */
+long RS; /* restricted to those with local accounts */
+long RW; /* open LP for reading and writing */
+long SB; /* short banner instead of normal header */
+long SC; /* suppress multiple copies */
+char *SD; /* spool directory */
+long SF; /* suppress FF on each print job */
+long SH; /* suppress header page */
+char *ST; /* status file name */
+char *TF; /* name of troff filter (per job) */
+char *TR; /* trailer string to be output when Q empties */
+char *VF; /* name of vplot filter (per job) */
+long XC; /* flags to clear for local mode */
+long XS; /* flags to set for local mode */
+
+char line[BUFSIZ];
+char *bp; /* pointer into printcap buffer. */
+char *name; /* program name */
+char *printer; /* printer name */
+ /* host machine name */
+char host[MAXHOSTNAMELEN];
+char *from = host; /* client's machine name */
+int sendtorem; /* are we sending to a remote? */
+char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
+
+static int compar __P((const void *, const void *));
+
+/*
+ * Create a connection to the remote printer server.
+ * Most of this code comes from rcmd.c.
+ */
+int
+getport(rhost)
+ char *rhost;
+{
+ struct hostent *hp;
+ struct servent *sp;
+ struct sockaddr_in sin;
+ int s, timo = 1, lport = IPPORT_RESERVED - 1;
+ int err;
+
+ /*
+ * Get the host address and port number to connect to.
+ */
+ if (rhost == NULL)
+ fatal("no remote host to connect to");
+ hp = gethostbyname(rhost);
+ if (hp == NULL)
+ fatal("unknown host %s", rhost);
+ sp = getservbyname("printer", "tcp");
+ if (sp == NULL)
+ fatal("printer/tcp: unknown service");
+ bzero((char *)&sin, sizeof(sin));
+ bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
+ sin.sin_family = hp->h_addrtype;
+ sin.sin_port = sp->s_port;
+
+ /*
+ * Try connecting to the server.
+ */
+retry:
+ s = rresvport(&lport);
+ if (s < 0)
+ return(-1);
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ err = errno;
+ (void) close(s);
+ errno = err;
+ if (errno == EADDRINUSE) {
+ lport--;
+ goto retry;
+ }
+ if (errno == ECONNREFUSED && timo <= 16) {
+ sleep(timo);
+ timo *= 2;
+ goto retry;
+ }
+ return(-1);
+ }
+ return(s);
+}
+
+/*
+ * Getline reads a line from the control file cfp, removes tabs, converts
+ * new-line to null and leaves it in line.
+ * Returns 0 at EOF or the number of characters read.
+ */
+int
+getline(cfp)
+ FILE *cfp;
+{
+ register int linel = 0;
+ register char *lp = line;
+ register c;
+
+ while ((c = getc(cfp)) != '\n') {
+ if (c == EOF)
+ return(0);
+ if (c == '\t') {
+ do {
+ *lp++ = ' ';
+ linel++;
+ } while ((linel & 07) != 0);
+ continue;
+ }
+ *lp++ = c;
+ linel++;
+ }
+ *lp++ = '\0';
+ return(linel);
+}
+
+/*
+ * Scan the current directory and make a list of daemon files sorted by
+ * creation time.
+ * Return the number of entries and a pointer to the list.
+ */
+int
+getq(namelist)
+ struct queue *(*namelist[]);
+{
+ register struct dirent *d;
+ register struct queue *q, **queue;
+ register int nitems;
+ struct stat stbuf;
+ DIR *dirp;
+ int arraysz;
+
+ if ((dirp = opendir(SD)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stbuf) < 0)
+ goto errdone;
+
+ /*
+ * Estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stbuf.st_size / 24);
+ queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
+ if (queue == NULL)
+ goto errdone;
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
+ continue; /* daemon control files only */
+ if (stat(d->d_name, &stbuf) < 0)
+ continue; /* Doesn't exist */
+ q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
+ if (q == NULL)
+ goto errdone;
+ q->q_time = stbuf.st_mtime;
+ strcpy(q->q_name, d->d_name);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems > arraysz) {
+ queue = (struct queue **)realloc((char *)queue,
+ (stbuf.st_size/12) * sizeof(struct queue *));
+ if (queue == NULL)
+ goto errdone;
+ }
+ queue[nitems-1] = q;
+ }
+ closedir(dirp);
+ if (nitems)
+ qsort(queue, nitems, sizeof(struct queue *), compar);
+ *namelist = queue;
+ return(nitems);
+
+errdone:
+ closedir(dirp);
+ return(-1);
+}
+
+/*
+ * Compare modification times.
+ */
+static int
+compar(p1, p2)
+ const void *p1, *p2;
+{
+ if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
+ return(-1);
+ if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
+ return(1);
+ return(0);
+}
+
+/*
+ * Figure out whether the local machine is the same
+ * as the remote machine (RM) entry (if it exists).
+ */
+char *
+checkremote()
+{
+ char name[MAXHOSTNAMELEN];
+ register struct hostent *hp;
+ static char errbuf[128];
+
+ sendtorem = 0; /* assume printer is local */
+ if (RM != (char *)NULL) {
+ /* get the official name of the local host */
+ gethostname(name, sizeof(name));
+ name[sizeof(name)-1] = '\0';
+ hp = gethostbyname(name);
+ if (hp == (struct hostent *) NULL) {
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "unable to get official name for local machine %s",
+ name);
+ return errbuf;
+ } else (void) strcpy(name, hp->h_name);
+
+ /* get the official name of RM */
+ hp = gethostbyname(RM);
+ if (hp == (struct hostent *) NULL) {
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "unable to get official name for remote machine %s",
+ RM);
+ return errbuf;
+ }
+
+ /*
+ * if the two hosts are not the same,
+ * then the printer must be remote.
+ */
+ if (strcmp(name, hp->h_name) != 0)
+ sendtorem = 1;
+ }
+ return (char *)0;
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+fatal(const char *msg, ...)
+#else
+fatal(msg, va_alist)
+ char *msg;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, msg);
+#else
+ va_start(ap);
+#endif
+ if (from != host)
+ (void)printf("%s: ", host);
+ (void)printf("%s: ", name);
+ if (printer)
+ (void)printf("%s: ", printer);
+ (void)vprintf(msg, ap);
+ va_end(ap);
+ (void)putchar('\n');
+ exit(1);
+}
diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c
new file mode 100644
index 0000000..59d3cc9
--- /dev/null
+++ b/usr.sbin/lpr/common_source/displayq.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)displayq.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+
+/*
+ * Routines to display the state of the queue.
+ */
+#define JOBCOL 40 /* column for job # in -l format */
+#define OWNCOL 7 /* start of Owner column in normal */
+#define SIZCOL 62 /* start of Size column in normal */
+
+/*
+ * Stuff for handling job specifications
+ */
+extern int requ[]; /* job number of spool entries */
+extern int requests; /* # of spool requests */
+extern char *user[]; /* users to process */
+extern int users; /* # of users in user array */
+
+static int col; /* column on screen */
+static char current[40]; /* current file being printed */
+static char file[132]; /* print file name */
+static int first; /* first file in ``files'' column? */
+static int garbage; /* # of garbage cf files */
+static int lflag; /* long output option */
+static int rank; /* order to be printed (-1=none, 0=active) */
+static long totsize; /* total print job size in bytes */
+
+static char *head0 = "Rank Owner Job Files";
+static char *head1 = "Total Size\n";
+
+/*
+ * Display the current state of the queue. Format = 1 if long format.
+ */
+void
+displayq(format)
+ int format;
+{
+ register struct queue *q;
+ register int i, nitems, fd;
+ register char *cp;
+ struct queue **queue;
+ struct stat statb;
+ FILE *fp;
+
+ lflag = format;
+ totsize = 0;
+ rank = -1;
+ if ((i = cgetent(&bp, printcapdb, printer)) == -2)
+ fatal("can't open printer description file");
+ else if (i == -1)
+ fatal("unknown printer");
+ else if (i == -3)
+ fatal("potential reference loop detected in printcap file");
+ if (cgetstr(bp, "lp", &LP) < 0)
+ LP = _PATH_DEFDEVLP;
+ if (cgetstr(bp, "rp", &RP) < 0)
+ RP = DEFLP;
+ if (cgetstr(bp, "sd", &SD) < 0)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp,"lo", &LO) < 0)
+ LO = DEFLOCK;
+ if (cgetstr(bp, "st", &ST) < 0)
+ ST = DEFSTAT;
+ cgetstr(bp, "rm", &RM);
+ if (cp = checkremote())
+ printf("Warning: %s\n", cp);
+
+ /*
+ * Print out local queue
+ * Find all the control files in the spooling directory
+ */
+ if (chdir(SD) < 0)
+ fatal("cannot chdir to spooling directory");
+ if ((nitems = getq(&queue)) < 0)
+ fatal("cannot examine spooling area\n");
+ if (stat(LO, &statb) >= 0) {
+ if (statb.st_mode & 0100) {
+ if (sendtorem)
+ printf("%s: ", host);
+ printf("Warning: %s is down: ", printer);
+ fd = open(ST, O_RDONLY);
+ if (fd >= 0) {
+ (void) flock(fd, LOCK_SH);
+ while ((i = read(fd, line, sizeof(line))) > 0)
+ (void) fwrite(line, 1, i, stdout);
+ (void) close(fd); /* unlocks as well */
+ } else
+ putchar('\n');
+ }
+ if (statb.st_mode & 010) {
+ if (sendtorem)
+ printf("%s: ", host);
+ printf("Warning: %s queue is turned off\n", printer);
+ }
+ }
+
+ if (nitems) {
+ fp = fopen(LO, "r");
+ if (fp == NULL)
+ warn();
+ else {
+ /* get daemon pid */
+ cp = current;
+ while ((*cp = getc(fp)) != EOF && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ i = atoi(current);
+ if (i <= 0 || kill(i, 0) < 0)
+ warn();
+ else {
+ /* read current file name */
+ cp = current;
+ while ((*cp = getc(fp)) != EOF && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ /*
+ * Print the status file.
+ */
+ if (sendtorem)
+ printf("%s: ", host);
+ fd = open(ST, O_RDONLY);
+ if (fd >= 0) {
+ (void) flock(fd, LOCK_SH);
+ while ((i = read(fd, line, sizeof(line))) > 0)
+ (void) fwrite(line, 1, i, stdout);
+ (void) close(fd); /* unlocks as well */
+ } else
+ putchar('\n');
+ }
+ (void) fclose(fp);
+ }
+ /*
+ * Now, examine the control files and print out the jobs to
+ * be done for each user.
+ */
+ if (!lflag)
+ header();
+ for (i = 0; i < nitems; i++) {
+ q = queue[i];
+ inform(q->q_name);
+ free(q);
+ }
+ free(queue);
+ }
+ if (!sendtorem) {
+ if (nitems == 0)
+ puts("no entries");
+ return;
+ }
+
+ /*
+ * Print foreign queue
+ * Note that a file in transit may show up in either queue.
+ */
+ if (nitems)
+ putchar('\n');
+ (void) sprintf(line, "%c%s", format + '\3', RP);
+ cp = line;
+ for (i = 0; i < requests; i++) {
+ cp += strlen(cp);
+ (void) sprintf(cp, " %d", requ[i]);
+ }
+ for (i = 0; i < users; i++) {
+ cp += strlen(cp);
+ *cp++ = ' ';
+ (void) strcpy(cp, user[i]);
+ }
+ strcat(line, "\n");
+ fd = getport(RM);
+ if (fd < 0) {
+ if (from != host)
+ printf("%s: ", host);
+ printf("connection to %s is down\n", RM);
+ }
+ else {
+ i = strlen(line);
+ if (write(fd, line, i) != i)
+ fatal("Lost connection");
+ while ((i = read(fd, line, sizeof(line))) > 0)
+ (void) fwrite(line, 1, i, stdout);
+ (void) close(fd);
+ }
+}
+
+/*
+ * Print a warning message if there is no daemon present.
+ */
+void
+warn()
+{
+ if (sendtorem)
+ printf("\n%s: ", host);
+ puts("Warning: no daemon present");
+ current[0] = '\0';
+}
+
+/*
+ * Print the header for the short listing format
+ */
+void
+header()
+{
+ printf(head0);
+ col = strlen(head0)+1;
+ blankfill(SIZCOL);
+ printf(head1);
+}
+
+void
+inform(cf)
+ char *cf;
+{
+ register int j;
+ FILE *cfp;
+
+ /*
+ * There's a chance the control file has gone away
+ * in the meantime; if this is the case just keep going
+ */
+ if ((cfp = fopen(cf, "r")) == NULL)
+ return;
+
+ if (rank < 0)
+ rank = 0;
+ if (sendtorem || garbage || strcmp(cf, current))
+ rank++;
+ j = 0;
+ while (getline(cfp)) {
+ switch (line[0]) {
+ case 'P': /* Was this file specified in the user's list? */
+ if (!inlist(line+1, cf)) {
+ fclose(cfp);
+ return;
+ }
+ if (lflag) {
+ printf("\n%s: ", line+1);
+ col = strlen(line+1) + 2;
+ prank(rank);
+ blankfill(JOBCOL);
+ printf(" [job %s]\n", cf+3);
+ } else {
+ col = 0;
+ prank(rank);
+ blankfill(OWNCOL);
+ printf("%-10s %-3d ", line+1, atoi(cf+3));
+ col += 16;
+ first = 1;
+ }
+ continue;
+ default: /* some format specifer and file name? */
+ if (line[0] < 'a' || line[0] > 'z')
+ continue;
+ if (j == 0 || strcmp(file, line+1) != 0)
+ (void) strcpy(file, line+1);
+ j++;
+ continue;
+ case 'N':
+ show(line+1, file, j);
+ file[0] = '\0';
+ j = 0;
+ }
+ }
+ fclose(cfp);
+ if (!lflag) {
+ blankfill(SIZCOL);
+ printf("%ld bytes\n", totsize);
+ totsize = 0;
+ }
+}
+
+int
+inlist(name, file)
+ char *name, *file;
+{
+ register int *r, n;
+ register char **u, *cp;
+
+ if (users == 0 && requests == 0)
+ return(1);
+ /*
+ * Check to see if it's in the user list
+ */
+ for (u = user; u < &user[users]; u++)
+ if (!strcmp(*u, name))
+ return(1);
+ /*
+ * Check the request list
+ */
+ for (n = 0, cp = file+3; isdigit(*cp); )
+ n = n * 10 + (*cp++ - '0');
+ for (r = requ; r < &requ[requests]; r++)
+ if (*r == n && !strcmp(cp, from))
+ return(1);
+ return(0);
+}
+
+void
+show(nfile, file, copies)
+ register char *nfile, *file;
+ int copies;
+{
+ if (strcmp(nfile, " ") == 0)
+ nfile = "(standard input)";
+ if (lflag)
+ ldump(nfile, file, copies);
+ else
+ dump(nfile, file, copies);
+}
+
+/*
+ * Fill the line with blanks to the specified column
+ */
+void
+blankfill(n)
+ register int n;
+{
+ while (col++ < n)
+ putchar(' ');
+}
+
+/*
+ * Give the abbreviated dump of the file names
+ */
+void
+dump(nfile, file, copies)
+ char *nfile, *file;
+ int copies;
+{
+ register short n, fill;
+ struct stat lbuf;
+
+ /*
+ * Print as many files as will fit
+ * (leaving room for the total size)
+ */
+ fill = first ? 0 : 2; /* fill space for ``, '' */
+ if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
+ if (col < SIZCOL) {
+ printf(" ..."), col += 4;
+ blankfill(SIZCOL);
+ }
+ } else {
+ if (first)
+ first = 0;
+ else
+ printf(", ");
+ printf("%s", nfile);
+ col += n+fill;
+ }
+ if (*file && !stat(file, &lbuf))
+ totsize += copies * lbuf.st_size;
+}
+
+/*
+ * Print the long info about the file
+ */
+void
+ldump(nfile, file, copies)
+ char *nfile, *file;
+ int copies;
+{
+ struct stat lbuf;
+
+ putchar('\t');
+ if (copies > 1)
+ printf("%-2d copies of %-19s", copies, nfile);
+ else
+ printf("%-32s", nfile);
+ if (*file && !stat(file, &lbuf))
+ printf(" %qd bytes", lbuf.st_size);
+ else
+ printf(" ??? bytes");
+ putchar('\n');
+}
+
+/*
+ * Print the job's rank in the queue,
+ * update col for screen management
+ */
+void
+prank(n)
+ int n;
+{
+ char rline[100];
+ static char *r[] = {
+ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
+ };
+
+ if (n == 0) {
+ printf("active");
+ col += 6;
+ return;
+ }
+ if ((n/10)%10 == 1)
+ (void)snprintf(rline, sizeof(rline), "%dth", n);
+ else
+ (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]);
+ col += strlen(rline);
+ printf("%s", rline);
+}
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
new file mode 100644
index 0000000..6dd1bf0
--- /dev/null
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)lp.h 8.1 (Berkeley) 6/6/93
+ */
+
+
+/*
+ * Global definitions for the line printer system.
+ */
+
+extern char *AF; /* accounting file */
+extern long BR; /* baud rate if lp is a tty */
+extern char *CF; /* name of cifplot filter (per job) */
+extern char *DF; /* name of tex filter (per job) */
+extern long DU; /* daeomon user-id */
+extern long FC; /* flags to clear if lp is a tty */
+extern char *FF; /* form feed string */
+extern long FS; /* flags to set if lp is a tty */
+extern char *GF; /* name of graph(1G) filter (per job) */
+extern long HL; /* print header last */
+extern char *IF; /* name of input filter (created per job) */
+extern char *LF; /* log file for error messages */
+extern char *LO; /* lock file name */
+extern char *LP; /* line printer device name */
+extern long MC; /* maximum number of copies allowed */
+extern long MX; /* maximum number of blocks to copy */
+extern char *NF; /* name of ditroff(1) filter (per job) */
+extern char *OF; /* name of output filter (created once) */
+extern long PL; /* page length */
+extern long PW; /* page width */
+extern long PX; /* page width in pixels */
+extern long PY; /* page length in pixels */
+extern char *RF; /* name of fortran text filter (per job) */
+extern char *RG; /* restricted group */
+extern char *RM; /* remote machine name */
+extern char *RP; /* remote printer name */
+extern long RS; /* restricted to those with local accounts */
+extern long RW; /* open LP for reading and writing */
+extern long SB; /* short banner instead of normal header */
+extern long SC; /* suppress multiple copies */
+extern char *SD; /* spool directory */
+extern long SF; /* suppress FF on each print job */
+extern long SH; /* suppress header page */
+extern char *ST; /* status file name */
+extern char *TF; /* name of troff(1) filter (per job) */
+extern char *TR; /* trailer string to be output when Q empties */
+extern char *VF; /* name of raster filter (per job) */
+extern long XC; /* flags to clear for local mode */
+extern long XS; /* flags to set for local mode */
+
+extern char line[BUFSIZ];
+extern char *bp; /* pointer into printcap buffer */
+extern char *name; /* program name */
+extern char *printer; /* printer name */
+ /* host machine name */
+extern char host[MAXHOSTNAMELEN];
+extern char *from; /* client's machine name */
+extern int sendtorem; /* are we sending to a remote? */
+extern char *printcapdb[]; /* printcap database array */
+/*
+ * Structure used for building a sorted list of control files.
+ */
+struct queue {
+ time_t q_time; /* modification time */
+ char q_name[MAXNAMLEN+1]; /* control file name */
+};
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+struct dirent;
+
+void blankfill __P((int));
+char *checkremote __P((void));
+int chk __P((char *));
+void displayq __P((int));
+void dump __P((char *, char *, int));
+void fatal __P((const char *, ...));
+int getline __P((FILE *));
+int getport __P((char *));
+int getq __P((struct queue *(*[])));
+void header __P((void));
+void inform __P((char *));
+int inlist __P((char *, char *));
+int iscf __P((struct dirent *));
+int isowner __P((char *, char *));
+void ldump __P((char *, char *, int));
+int lockchk __P((char *));
+void prank __P((int));
+void process __P((char *));
+void rmjob __P((void));
+void rmremote __P((void));
+void show __P((char *, char *, int));
+int startdaemon __P((char *));
+void warn __P((void));
+__END_DECLS
diff --git a/usr.sbin/lpr/common_source/lp.local.h b/usr.sbin/lpr/common_source/lp.local.h
new file mode 100644
index 0000000..837fd2f
--- /dev/null
+++ b/usr.sbin/lpr/common_source/lp.local.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)lp.local.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Possibly, local parameters to the spooling system
+ */
+
+/*
+ * Defaults for line printer capabilities data base
+ */
+#define DEFLP "lp"
+#define DEFLOCK "lock"
+#define DEFSTAT "status"
+#define DEFMX 1000
+#define DEFMAXCOPIES 0
+#define DEFFF "\f"
+#define DEFWIDTH 132
+#define DEFLENGTH 66
+#define DEFUID 1
+
+/*
+ * When files are created in the spooling area, they are normally
+ * readable only by their owner and the spooling group. If you
+ * want otherwise, change this mode.
+ */
+#define FILMOD 0660
+
+/*
+ * Printer is assumed to support LINELEN (for block chars)
+ * and background character (blank) is a space
+ */
+#define LINELEN 132
+#define BACKGND ' '
+
+#define HEIGHT 9 /* height of characters */
+#define WIDTH 8 /* width of characters */
+#define DROP 3 /* offset to drop characters with descenders */
+
+/*
+ * Define TERMCAP if the terminal capabilites are to be used for lpq.
+ */
+#define TERMCAP
+
+/*
+ * Maximum number of user and job requests for lpq and lprm.
+ */
+#define MAXUSERS 50
+#define MAXREQUESTS 50
diff --git a/usr.sbin/lpr/common_source/pathnames.h b/usr.sbin/lpr/common_source/pathnames.h
new file mode 100644
index 0000000..5c07cdb
--- /dev/null
+++ b/usr.sbin/lpr/common_source/pathnames.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#define _PATH_DEFDEVLP "/dev/lp"
+#define _PATH_DEFSPOOL "/var/spool/output/lpd"
+#define _PATH_HOSTSEQUIV "/etc/hosts.equiv"
+#define _PATH_HOSTSLPD "/etc/hosts.lpd"
+#define _PATH_MASTERLOCK "/var/spool/output/lpd.lock"
+#define _PATH_PR "/usr/bin/pr"
+#define _PATH_PRINTCAP "/etc/printcap"
+#define _PATH_SOCKETNAME "/var/run/printer"
+#define _PATH_VFONT "/usr/libdata/vfont/"
+#define _PATH_VFONTB "/usr/libdata/vfont/B"
+#define _PATH_VFONTI "/usr/libdata/vfont/I"
+#define _PATH_VFONTR "/usr/libdata/vfont/R"
+#define _PATH_VFONTS "/usr/libdata/vfont/S"
diff --git a/usr.sbin/lpr/common_source/printcap.c b/usr.sbin/lpr/common_source/printcap.c
new file mode 100644
index 0000000..627d2ce
--- /dev/null
+++ b/usr.sbin/lpr/common_source/printcap.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)printcap.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lp.h"
+#include "pathnames.h"
+
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+#define MAXHOP 32 /* max number of tc= indirections */
+
+/*
+ * termcap - routines for dealing with the terminal capability data base
+ *
+ * BUG: Should use a "last" pointer in tbuf, so that searching
+ * for capabilities alphabetically would not be a n**2/2
+ * process when large numbers of capabilities are given.
+ * Note: If we add a last pointer now we will screw up the
+ * tc capability. We really should compile termcap.
+ *
+ * Essentially all the work here is scanning and decoding escapes
+ * in string capabilities. We don't use stdio because the editor
+ * doesn't, and because living w/o it is not hard.
+ */
+
+#define PRINTCAP
+
+#ifdef PRINTCAP
+#define tgetent pgetent
+#define tskip pskip
+#define tgetstr pgetstr
+#define tdecode pdecode
+#define tgetnum pgetnum
+#define tgetflag pgetflag
+#define tdecode pdecode
+#define tnchktc pnchktc
+#define tnamatch pnamatch
+#define V6
+#endif
+
+static FILE *pfp = NULL; /* printcap data base file pointer */
+static char *tbuf;
+static int hopcount; /* detect infinite loops in termcap, init 0 */
+
+static char *tskip __P((char *));
+static char *tskip __P((char *bp));
+static char *tdecode __P((char *, char **));
+
+/*
+ * Similar to tgetent except it returns the next enrty instead of
+ * doing a lookup.
+ */
+int
+getprent(bp)
+ register char *bp;
+{
+ register int c, skip = 0;
+
+ if (pfp == NULL && (pfp = fopen(_PATH_PRINTCAP, "r")) == NULL)
+ return(-1);
+ tbuf = bp;
+ for (;;) {
+ switch (c = getc(pfp)) {
+ case EOF:
+ fclose(pfp);
+ pfp = NULL;
+ return(0);
+ case '\n':
+ if (bp == tbuf) {
+ skip = 0;
+ continue;
+ }
+ if (bp[-1] == '\\') {
+ bp--;
+ continue;
+ }
+ *bp = '\0';
+ return(1);
+ case '#':
+ if (bp == tbuf)
+ skip++;
+ default:
+ if (skip)
+ continue;
+ if (bp >= tbuf+BUFSIZ) {
+ write(2, "Termcap entry too long\n", 23);
+ *bp = '\0';
+ return(1);
+ }
+ *bp++ = c;
+ }
+ }
+}
+
+void
+endprent()
+{
+ if (pfp != NULL)
+ fclose(pfp);
+}
+
+/*
+ * Get an entry for terminal name in buffer bp,
+ * from the termcap file. Parse is very rudimentary;
+ * we just notice escaped newlines.
+ */
+int
+tgetent(bp, name)
+ char *bp, *name;
+{
+ register char *cp;
+ register int c;
+ register int i = 0, cnt = 0;
+ char ibuf[BUFSIZ];
+ int tf;
+
+ tbuf = bp;
+ tf = 0;
+#ifndef V6
+ cp = getenv("TERMCAP");
+ /*
+ * TERMCAP can have one of two things in it. It can be the
+ * name of a file to use instead of /etc/termcap. In this
+ * case it better start with a "/". Or it can be an entry to
+ * use so we don't have to read the file. In this case it
+ * has to already have the newlines crunched out.
+ */
+ if (cp && *cp) {
+ if (*cp!='/') {
+ cp2 = getenv("TERM");
+ if (cp2==(char *) 0 || strcmp(name,cp2)==0) {
+ strcpy(bp,cp);
+ return(tnchktc());
+ } else {
+ tf = open(_PATH_PRINTCAP, 0);
+ }
+ } else
+ tf = open(cp, 0);
+ }
+ if (tf==0)
+ tf = open(_PATH_PRINTCAP, 0);
+#else
+ tf = open(_PATH_PRINTCAP, 0);
+#endif
+ if (tf < 0)
+ return (-1);
+ for (;;) {
+ cp = bp;
+ for (;;) {
+ if (i == cnt) {
+ cnt = read(tf, ibuf, BUFSIZ);
+ if (cnt <= 0) {
+ close(tf);
+ return (0);
+ }
+ i = 0;
+ }
+ c = ibuf[i++];
+ if (c == '\n') {
+ if (cp > bp && cp[-1] == '\\'){
+ cp--;
+ continue;
+ }
+ break;
+ }
+ if (cp >= bp+BUFSIZ) {
+ write(2,"Termcap entry too long\n", 23);
+ break;
+ } else
+ *cp++ = c;
+ }
+ *cp = 0;
+
+ /*
+ * The real work for the match.
+ */
+ if (tnamatch(name)) {
+ close(tf);
+ return(tnchktc());
+ }
+ }
+}
+
+/*
+ * tnchktc: check the last entry, see if it's tc=xxx. If so,
+ * recursively find xxx and append that entry (minus the names)
+ * to take the place of the tc=xxx entry. This allows termcap
+ * entries to say "like an HP2621 but doesn't turn on the labels".
+ * Note that this works because of the left to right scan.
+ */
+int
+tnchktc()
+{
+ register char *p, *q;
+ char tcname[16]; /* name of similar terminal */
+ char tcbuf[BUFSIZ];
+ char *holdtbuf = tbuf;
+ int l;
+
+ p = tbuf + strlen(tbuf) - 2; /* before the last colon */
+ while (*--p != ':')
+ if (p<tbuf) {
+ write(2, "Bad termcap entry\n", 18);
+ return (0);
+ }
+ p++;
+ /* p now points to beginning of last field */
+ if (p[0] != 't' || p[1] != 'c')
+ return(1);
+ strcpy(tcname,p+3);
+ q = tcname;
+ while (q && *q != ':')
+ q++;
+ *q = 0;
+ if (++hopcount > MAXHOP) {
+ write(2, "Infinite tc= loop\n", 18);
+ return (0);
+ }
+ if (tgetent(tcbuf, tcname) != 1)
+ return(0);
+ for (q=tcbuf; *q != ':'; q++)
+ ;
+ l = p - holdtbuf + strlen(q);
+ if (l > BUFSIZ) {
+ write(2, "Termcap entry too long\n", 23);
+ q[BUFSIZ - (p-tbuf)] = 0;
+ }
+ strcpy(p, q+1);
+ tbuf = holdtbuf;
+ return(1);
+}
+
+/*
+ * Tnamatch deals with name matching. The first field of the termcap
+ * entry is a sequence of names separated by |'s, so we compare
+ * against each such name. The normal : terminator after the last
+ * name (before the first field) stops us.
+ */
+int
+tnamatch(np)
+ char *np;
+{
+ register char *Np, *Bp;
+
+ Bp = tbuf;
+ if (*Bp == '#')
+ return(0);
+ for (;;) {
+ for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
+ continue;
+ if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
+ return (1);
+ while (*Bp && *Bp != ':' && *Bp != '|')
+ Bp++;
+ if (*Bp == 0 || *Bp == ':')
+ return (0);
+ Bp++;
+ }
+}
+
+/*
+ * Skip to the next field. Notice that this is very dumb, not
+ * knowing about \: escapes or any such. If necessary, :'s can be put
+ * into the termcap file in octal.
+ */
+static char *
+tskip(bp)
+ register char *bp;
+{
+
+ while (*bp && *bp != ':')
+ bp++;
+ if (*bp == ':')
+ bp++;
+ return (bp);
+}
+
+/*
+ * Return the (numeric) option id.
+ * Numeric options look like
+ * li#80
+ * i.e. the option string is separated from the numeric value by
+ * a # character. If the option is not found we return -1.
+ * Note that we handle octal numbers beginning with 0.
+ */
+int
+tgetnum(id)
+ char *id;
+{
+ register int i, base;
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (*bp == 0)
+ return (-1);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(-1);
+ if (*bp != '#')
+ continue;
+ bp++;
+ base = 10;
+ if (*bp == '0')
+ base = 8;
+ i = 0;
+ while (isdigit(*bp))
+ i *= base, i += *bp++ - '0';
+ return (i);
+ }
+}
+
+/*
+ * Handle a flag option.
+ * Flag options are given "naked", i.e. followed by a : or the end
+ * of the buffer. Return 1 if we find the option, or 0 if it is
+ * not given.
+ */
+int
+tgetflag(id)
+ char *id;
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (!*bp)
+ return (0);
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (!*bp || *bp == ':')
+ return (1);
+ else if (*bp == '@')
+ return(0);
+ }
+ }
+}
+
+/*
+ * Get a string valued option.
+ * These are given as
+ * cl=^Z
+ * Much decoding is done on the strings, and the strings are
+ * placed in area, which is a ref parameter which is updated.
+ * No checking on area overflow.
+ */
+char *
+tgetstr(id, area)
+ char *id, **area;
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (!*bp)
+ return (0);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(0);
+ if (*bp != '=')
+ continue;
+ bp++;
+ return (tdecode(bp, area));
+ }
+}
+
+/*
+ * Tdecode does the grung work to decode the
+ * string capability escapes.
+ */
+static char *
+tdecode(str, area)
+ register char *str;
+ char **area;
+{
+ register char *cp;
+ register int c;
+ register char *dp;
+ int i;
+
+ cp = *area;
+ while ((c = *str++) && c != ':') {
+ switch (c) {
+
+ case '^':
+ c = *str++ & 037;
+ break;
+
+ case '\\':
+ dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
+ c = *str++;
+nextc:
+ if (*dp++ == c) {
+ c = *dp++;
+ break;
+ }
+ dp++;
+ if (*dp)
+ goto nextc;
+ if (isdigit(c)) {
+ c -= '0', i = 2;
+ do
+ c <<= 3, c |= *str++ - '0';
+ while (--i && isdigit(*str));
+ }
+ break;
+ }
+ *cp++ = c;
+ }
+ *cp++ = 0;
+ str = *area;
+ *area = cp;
+ return (str);
+}
+
diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c
new file mode 100644
index 0000000..74a94d8
--- /dev/null
+++ b/usr.sbin/lpr/common_source/rmjob.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)rmjob.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+
+/*
+ * rmjob - remove the specified jobs from the queue.
+ */
+
+/*
+ * Stuff for handling lprm specifications
+ */
+extern char *user[]; /* users to process */
+extern int users; /* # of users in user array */
+extern int requ[]; /* job number of spool entries */
+extern int requests; /* # of spool requests */
+extern char *person; /* name of person doing lprm */
+
+static char root[] = "root";
+static int all = 0; /* eliminate all files (root only) */
+static int cur_daemon; /* daemon's pid */
+static char current[40]; /* active control file name */
+
+void
+rmjob()
+{
+ register int i, nitems;
+ int assasinated = 0;
+ struct dirent **files;
+ char *cp;
+
+ if ((i = cgetent(&bp, printcapdb, printer)) == -2)
+ fatal("can't open printer description file");
+ else if (i == -1)
+ fatal("unknown printer");
+ else if (i == -3)
+ fatal("potential reference loop detected in printcap file");
+ if (cgetstr(bp, "lp", &LP) < 0)
+ LP = _PATH_DEFDEVLP;
+ if (cgetstr(bp, "rp", &RP) < 0)
+ RP = DEFLP;
+ if (cgetstr(bp, "sd", &SD) < 0)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp,"lo", &LO) < 0)
+ LO = DEFLOCK;
+ cgetstr(bp, "rm", &RM);
+ if (cp = checkremote())
+ printf("Warning: %s\n", cp);
+
+ /*
+ * If the format was `lprm -' and the user isn't the super-user,
+ * then fake things to look like he said `lprm user'.
+ */
+ if (users < 0) {
+ if (getuid() == 0)
+ all = 1; /* all files in local queue */
+ else {
+ user[0] = person;
+ users = 1;
+ }
+ }
+ if (!strcmp(person, "-all")) {
+ if (from == host)
+ fatal("The login name \"-all\" is reserved");
+ all = 1; /* all those from 'from' */
+ person = root;
+ }
+
+ if (chdir(SD) < 0)
+ fatal("cannot chdir to spool directory");
+ if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
+ fatal("cannot access spool directory");
+
+ if (nitems) {
+ /*
+ * Check for an active printer daemon (in which case we
+ * kill it if it is reading our file) then remove stuff
+ * (after which we have to restart the daemon).
+ */
+ if (lockchk(LO) && chk(current)) {
+ assasinated = kill(cur_daemon, SIGINT) == 0;
+ if (!assasinated)
+ fatal("cannot kill printer daemon");
+ }
+ /*
+ * process the files
+ */
+ for (i = 0; i < nitems; i++)
+ process(files[i]->d_name);
+ }
+ rmremote();
+ /*
+ * Restart the printer daemon if it was killed
+ */
+ if (assasinated && !startdaemon(printer))
+ fatal("cannot restart printer daemon\n");
+ exit(0);
+}
+
+/*
+ * Process a lock file: collect the pid of the active
+ * daemon and the file name of the active spool entry.
+ * Return boolean indicating existence of a lock file.
+ */
+int
+lockchk(s)
+ char *s;
+{
+ register FILE *fp;
+ register int i, n;
+
+ if ((fp = fopen(s, "r")) == NULL)
+ if (errno == EACCES)
+ fatal("can't access lock file");
+ else
+ return(0);
+ if (!getline(fp)) {
+ (void) fclose(fp);
+ return(0); /* no daemon present */
+ }
+ cur_daemon = atoi(line);
+ if (kill(cur_daemon, 0) < 0) {
+ (void) fclose(fp);
+ return(0); /* no daemon present */
+ }
+ for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) {
+ if (i > 5) {
+ n = 1;
+ break;
+ }
+ sleep(i);
+ }
+ current[n-1] = '\0';
+ (void) fclose(fp);
+ return(1);
+}
+
+/*
+ * Process a control file.
+ */
+void
+process(file)
+ char *file;
+{
+ FILE *cfp;
+
+ if (!chk(file))
+ return;
+ if ((cfp = fopen(file, "r")) == NULL)
+ fatal("cannot open %s", file);
+ while (getline(cfp)) {
+ switch (line[0]) {
+ case 'U': /* unlink associated files */
+ if (from != host)
+ printf("%s: ", host);
+ printf(unlink(line+1) ? "cannot dequeue %s\n" :
+ "%s dequeued\n", line+1);
+ }
+ }
+ (void) fclose(cfp);
+ if (from != host)
+ printf("%s: ", host);
+ printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file);
+}
+
+/*
+ * Do the dirty work in checking
+ */
+int
+chk(file)
+ char *file;
+{
+ register int *r, n;
+ register char **u, *cp;
+ FILE *cfp;
+
+ /*
+ * Check for valid cf file name (mostly checking current).
+ */
+ if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
+ return(0);
+
+ if (all && (from == host || !strcmp(from, file+6)))
+ return(1);
+
+ /*
+ * get the owner's name from the control file.
+ */
+ if ((cfp = fopen(file, "r")) == NULL)
+ return(0);
+ while (getline(cfp)) {
+ if (line[0] == 'P')
+ break;
+ }
+ (void) fclose(cfp);
+ if (line[0] != 'P')
+ return(0);
+
+ if (users == 0 && requests == 0)
+ return(!strcmp(file, current) && isowner(line+1, file));
+ /*
+ * Check the request list
+ */
+ for (n = 0, cp = file+3; isdigit(*cp); )
+ n = n * 10 + (*cp++ - '0');
+ for (r = requ; r < &requ[requests]; r++)
+ if (*r == n && isowner(line+1, file))
+ return(1);
+ /*
+ * Check to see if it's in the user list
+ */
+ for (u = user; u < &user[users]; u++)
+ if (!strcmp(*u, line+1) && isowner(line+1, file))
+ return(1);
+ return(0);
+}
+
+/*
+ * If root is removing a file on the local machine, allow it.
+ * If root is removing a file from a remote machine, only allow
+ * files sent from the remote machine to be removed.
+ * Normal users can only remove the file from where it was sent.
+ */
+int
+isowner(owner, file)
+ char *owner, *file;
+{
+ if (!strcmp(person, root) && (from == host || !strcmp(from, file+6)))
+ return(1);
+ if (!strcmp(person, owner) && !strcmp(from, file+6))
+ return(1);
+ if (from != host)
+ printf("%s: ", host);
+ printf("%s: Permission denied\n", file);
+ return(0);
+}
+
+/*
+ * Check to see if we are sending files to a remote machine. If we are,
+ * then try removing files on the remote machine.
+ */
+void
+rmremote()
+{
+ register char *cp;
+ register int i, rem;
+ char buf[BUFSIZ];
+
+ if (!sendtorem)
+ return; /* not sending to a remote machine */
+
+ /*
+ * Flush stdout so the user can see what has been deleted
+ * while we wait (possibly) for the connection.
+ */
+ fflush(stdout);
+
+ (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person);
+ cp = buf;
+ for (i = 0; i < users; i++) {
+ cp += strlen(cp);
+ *cp++ = ' ';
+ strcpy(cp, user[i]);
+ }
+ for (i = 0; i < requests; i++) {
+ cp += strlen(cp);
+ (void) sprintf(cp, " %d", requ[i]);
+ }
+ strcat(cp, "\n");
+ rem = getport(RM);
+ if (rem < 0) {
+ if (from != host)
+ printf("%s: ", host);
+ printf("connection to %s is down\n", RM);
+ } else {
+ i = strlen(buf);
+ if (write(rem, buf, i) != i)
+ fatal("Lost connection");
+ while ((i = read(rem, buf, sizeof(buf))) > 0)
+ (void) fwrite(buf, 1, i, stdout);
+ (void) close(rem);
+ }
+}
+
+/*
+ * Return 1 if the filename begins with 'cf'
+ */
+int
+iscf(d)
+ struct dirent *d;
+{
+ return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
+}
diff --git a/usr.sbin/lpr/common_source/startdaemon.c b/usr.sbin/lpr/common_source/startdaemon.c
new file mode 100644
index 0000000..237769e
--- /dev/null
+++ b/usr.sbin/lpr/common_source/startdaemon.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94";
+#endif /* not lint */
+
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "lp.h"
+#include "pathnames.h"
+
+static void perr __P((char *));
+
+/*
+ * Tell the printer daemon that there are new files in the spool directory.
+ */
+
+int
+startdaemon(printer)
+ char *printer;
+{
+ struct sockaddr_un un;
+ register int s, n;
+ char buf[BUFSIZ];
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ perr("socket");
+ return(0);
+ }
+ memset(&un, 0, sizeof(un));
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, _PATH_SOCKETNAME);
+#ifndef SUN_LEN
+#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
+#endif
+ if (connect(s, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
+ perr("connect");
+ (void) close(s);
+ return(0);
+ }
+ (void) sprintf(buf, "\1%s\n", printer);
+ n = strlen(buf);
+ if (write(s, buf, n) != n) {
+ perr("write");
+ (void) close(s);
+ return(0);
+ }
+ if (read(s, buf, 1) == 1) {
+ if (buf[0] == '\0') { /* everything is OK */
+ (void) close(s);
+ return(1);
+ }
+ putchar(buf[0]);
+ }
+ while ((n = read(s, buf, sizeof(buf))) > 0)
+ fwrite(buf, 1, n, stdout);
+ (void) close(s);
+ return(0);
+}
+
+static void
+perr(msg)
+ char *msg;
+{
+ extern char *name;
+
+ (void)printf("%s: %s: %s\n", name, msg, strerror(errno));
+}
diff --git a/usr.sbin/lpr/filters/Makefile b/usr.sbin/lpr/filters/Makefile
new file mode 100644
index 0000000..c9d5c4f
--- /dev/null
+++ b/usr.sbin/lpr/filters/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lpf
+NOMAN= noman
+BINDIR= /usr/libexec/lpr
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/filters/lpf.c b/usr.sbin/lpr/filters/lpf.c
new file mode 100644
index 0000000..5335f31
--- /dev/null
+++ b/usr.sbin/lpr/filters/lpf.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * filter which reads the output of nroff and converts lines
+ * with ^H's to overwritten lines. Thus this works like 'ul'
+ * but is much better: it can handle more than 2 overwrites
+ * and it is written with some style.
+ * modified by kls to use register references instead of arrays
+ * to try to gain a little speed.
+ */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define MAXWIDTH 132
+#define MAXREP 10
+
+char buf[MAXREP][MAXWIDTH];
+int maxcol[MAXREP] = {-1};
+int lineno;
+int width = 132; /* default line length */
+int length = 66; /* page length */
+int indent; /* indentation length */
+int npages = 1;
+int literal; /* print control characters */
+char *name; /* user's login name */
+char *host; /* user's machine name */
+char *acctfile; /* accounting information file */
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register FILE *p = stdin, *o = stdout;
+ register int i, col;
+ register char *cp;
+ int done, linedone, maxrep;
+ char ch, *limit;
+
+ while (--argc) {
+ if (*(cp = *++argv) == '-') {
+ switch (cp[1]) {
+ case 'n':
+ argc--;
+ name = *++argv;
+ break;
+
+ case 'h':
+ argc--;
+ host = *++argv;
+ break;
+
+ case 'w':
+ if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
+ width = i;
+ break;
+
+ case 'l':
+ length = atoi(&cp[2]);
+ break;
+
+ case 'i':
+ indent = atoi(&cp[2]);
+ break;
+
+ case 'c': /* Print control chars */
+ literal++;
+ break;
+ }
+ } else
+ acctfile = cp;
+ }
+
+ for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
+ done = 0;
+
+ while (!done) {
+ col = indent;
+ maxrep = -1;
+ linedone = 0;
+ while (!linedone) {
+ switch (ch = getc(p)) {
+ case EOF:
+ linedone = done = 1;
+ ch = '\n';
+ break;
+
+ case '\f':
+ lineno = length;
+ case '\n':
+ if (maxrep < 0)
+ maxrep = 0;
+ linedone = 1;
+ break;
+
+ case '\b':
+ if (--col < indent)
+ col = indent;
+ break;
+
+ case '\r':
+ col = indent;
+ break;
+
+ case '\t':
+ col = ((col - indent) | 07) + indent + 1;
+ break;
+
+ case '\031':
+ /*
+ * lpd needs to use a different filter to
+ * print data so stop what we are doing and
+ * wait for lpd to restart us.
+ */
+ if ((ch = getchar()) == '\1') {
+ fflush(stdout);
+ kill(getpid(), SIGSTOP);
+ break;
+ } else {
+ ungetc(ch, stdin);
+ ch = '\031';
+ }
+
+ default:
+ if (col >= width || !literal && ch < ' ') {
+ col++;
+ break;
+ }
+ cp = &buf[0][col];
+ for (i = 0; i < MAXREP; i++) {
+ if (i > maxrep)
+ maxrep = i;
+ if (*cp == ' ') {
+ *cp = ch;
+ if (col > maxcol[i])
+ maxcol[i] = col;
+ break;
+ }
+ cp += MAXWIDTH;
+ }
+ col++;
+ break;
+ }
+ }
+
+ /* print out lines */
+ for (i = 0; i <= maxrep; i++) {
+ for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
+ putc(*cp, o);
+ *cp++ = ' ';
+ }
+ if (i < maxrep)
+ putc('\r', o);
+ else
+ putc(ch, o);
+ if (++lineno >= length) {
+ fflush(o);
+ npages++;
+ lineno = 0;
+ }
+ maxcol[i] = -1;
+ }
+ }
+ if (lineno) { /* be sure to end on a page boundary */
+ putchar('\f');
+ npages++;
+ }
+ if (name && acctfile && access(acctfile, 02) >= 0 &&
+ freopen(acctfile, "a", stdout) != NULL) {
+ printf("%7.2f\t%s:%s\n", (float)npages, host, name);
+ }
+ exit(0);
+}
diff --git a/usr.sbin/lpr/lpc/Makefile b/usr.sbin/lpr/lpc/Makefile
new file mode 100644
index 0000000..10a3d69
--- /dev/null
+++ b/usr.sbin/lpr/lpc/Makefile
@@ -0,0 +1,12 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lpc
+CFLAGS+=-I${.CURDIR}/../common_source
+MAN8= lpc.0
+SRCS= lpc.c cmds.c cmdtab.c startdaemon.c common.c
+BINGRP= daemon
+BINMODE=2555
+.PATH: ${.CURDIR}/../common_source
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c
new file mode 100644
index 0000000..7c2b6fe
--- /dev/null
+++ b/usr.sbin/lpr/lpc/cmds.c
@@ -0,0 +1,1107 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * lpc -- line printer control program -- commands:
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "lpc.h"
+#include "extern.h"
+#include "pathnames.h"
+
+static void abortpr __P((int));
+static void cleanpr __P((void));
+static void disablepr __P((void));
+static int doarg __P((char *));
+static int doselect __P((struct dirent *));
+static void enablepr __P((void));
+static void prstat __P((void));
+static void putmsg __P((int, char **));
+static int sortq __P((const void *, const void *));
+static void startpr __P((int));
+static void stoppr __P((void));
+static int touch __P((struct queue *));
+static void unlinkf __P((char *));
+static void upstat __P((char *));
+
+/*
+ * kill an existing daemon and disable printing.
+ */
+void
+doabort(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: abort {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ abortpr(1);
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+ abortpr(1);
+ }
+}
+
+static void
+abortpr(dis)
+ int dis;
+{
+ register FILE *fp;
+ struct stat stbuf;
+ int pid, fd;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ (void) sprintf(line, "%s/%s", SD, LO);
+ printf("%s:\n", printer);
+
+ /*
+ * Turn on the owner execute bit of the lock file to disable printing.
+ */
+ if (dis) {
+ if (stat(line, &stbuf) >= 0) {
+ if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
+ printf("\tcannot disable printing\n");
+ else {
+ upstat("printing disabled\n");
+ printf("\tprinting disabled\n");
+ }
+ } else if (errno == ENOENT) {
+ if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
+ printf("\tcannot create lock file\n");
+ else {
+ (void) close(fd);
+ upstat("printing disabled\n");
+ printf("\tprinting disabled\n");
+ printf("\tno daemon to abort\n");
+ }
+ return;
+ } else {
+ printf("\tcannot stat lock file\n");
+ return;
+ }
+ }
+ /*
+ * Kill the current daemon to stop printing now.
+ */
+ if ((fp = fopen(line, "r")) == NULL) {
+ printf("\tcannot open lock file\n");
+ return;
+ }
+ if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
+ (void) fclose(fp); /* unlocks as well */
+ printf("\tno daemon to abort\n");
+ return;
+ }
+ (void) fclose(fp);
+ if (kill(pid = atoi(line), SIGTERM) < 0)
+ printf("\tWarning: daemon (pid %d) not killed\n", pid);
+ else
+ printf("\tdaemon (pid %d) killed\n", pid);
+}
+
+/*
+ * Write a message into the status file.
+ */
+static void
+upstat(msg)
+ char *msg;
+{
+ register int fd;
+ char statfile[BUFSIZ];
+
+ if (cgetstr(bp, "st", &ST) == -1)
+ ST = DEFSTAT;
+ (void) sprintf(statfile, "%s/%s", SD, ST);
+ umask(0);
+ fd = open(statfile, O_WRONLY|O_CREAT, 0664);
+ if (fd < 0 || flock(fd, LOCK_EX) < 0) {
+ printf("\tcannot create status file\n");
+ return;
+ }
+ (void) ftruncate(fd, 0);
+ if (msg == (char *)NULL)
+ (void) write(fd, "\n", 1);
+ else
+ (void) write(fd, msg, strlen(msg));
+ (void) close(fd);
+}
+
+/*
+ * Remove all spool files and temporaries from the spooling area.
+ */
+void
+clean(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: clean {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ cleanpr();
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ cleanpr();
+ }
+}
+
+static int
+doselect(d)
+ struct dirent *d;
+{
+ int c = d->d_name[0];
+
+ if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
+ return(1);
+ return(0);
+}
+
+/*
+ * Comparison routine for scandir. Sort by job number and machine, then
+ * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
+ */
+static int
+sortq(a, b)
+ const void *a, *b;
+{
+ struct dirent **d1, **d2;
+ int c1, c2;
+
+ d1 = (struct dirent **)a;
+ d2 = (struct dirent **)b;
+ if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))
+ return(c1);
+ c1 = (*d1)->d_name[0];
+ c2 = (*d2)->d_name[0];
+ if (c1 == c2)
+ return((*d1)->d_name[2] - (*d2)->d_name[2]);
+ if (c1 == 'c')
+ return(-1);
+ if (c1 == 'd' || c2 == 'c')
+ return(1);
+ return(-1);
+}
+
+/*
+ * Remove incomplete jobs from spooling area.
+ */
+static void
+cleanpr()
+{
+ register int i, n;
+ register char *cp, *cp1, *lp;
+ struct dirent **queue;
+ int nitems;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ printf("%s:\n", printer);
+
+ for (lp = line, cp = SD; *lp++ = *cp++; )
+ ;
+ lp[-1] = '/';
+
+ nitems = scandir(SD, &queue, doselect, sortq);
+ if (nitems < 0) {
+ printf("\tcannot examine spool directory\n");
+ return;
+ }
+ if (nitems == 0)
+ return;
+ i = 0;
+ do {
+ cp = queue[i]->d_name;
+ if (*cp == 'c') {
+ n = 0;
+ while (i + 1 < nitems) {
+ cp1 = queue[i + 1]->d_name;
+ if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
+ break;
+ i++;
+ n++;
+ }
+ if (n == 0) {
+ strcpy(lp, cp);
+ unlinkf(line);
+ }
+ } else {
+ /*
+ * Must be a df with no cf (otherwise, it would have
+ * been skipped above) or a tf file (which can always
+ * be removed).
+ */
+ strcpy(lp, cp);
+ unlinkf(line);
+ }
+ } while (++i < nitems);
+}
+
+static void
+unlinkf(name)
+ char *name;
+{
+ if (unlink(name) < 0)
+ printf("\tcannot remove %s\n", name);
+ else
+ printf("\tremoved %s\n", name);
+}
+
+/*
+ * Enable queuing to the printer (allow lpr's).
+ */
+void
+enable(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: enable {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ enablepr();
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ enablepr();
+ }
+}
+
+static void
+enablepr()
+{
+ struct stat stbuf;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ (void) sprintf(line, "%s/%s", SD, LO);
+ printf("%s:\n", printer);
+
+ /*
+ * Turn off the group execute bit of the lock file to enable queuing.
+ */
+ if (stat(line, &stbuf) >= 0) {
+ if (chmod(line, stbuf.st_mode & 0767) < 0)
+ printf("\tcannot enable queuing\n");
+ else
+ printf("\tqueuing enabled\n");
+ }
+}
+
+/*
+ * Disable queuing.
+ */
+void
+disable(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: disable {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ disablepr();
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ disablepr();
+ }
+}
+
+static void
+disablepr()
+{
+ register int fd;
+ struct stat stbuf;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ (void) sprintf(line, "%s/%s", SD, LO);
+ printf("%s:\n", printer);
+ /*
+ * Turn on the group execute bit of the lock file to disable queuing.
+ */
+ if (stat(line, &stbuf) >= 0) {
+ if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
+ printf("\tcannot disable queuing\n");
+ else
+ printf("\tqueuing disabled\n");
+ } else if (errno == ENOENT) {
+ if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
+ printf("\tcannot create lock file\n");
+ else {
+ (void) close(fd);
+ printf("\tqueuing disabled\n");
+ }
+ return;
+ } else
+ printf("\tcannot stat lock file\n");
+}
+
+/*
+ * Disable queuing and printing and put a message into the status file
+ * (reason for being down).
+ */
+void
+down(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: down {all | printer} [message ...]\n");
+ return;
+ }
+ if (!strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ putmsg(argc - 2, argv + 2);
+ }
+ return;
+ }
+ printer = argv[1];
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ return;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ return;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ putmsg(argc - 2, argv + 2);
+}
+
+static void
+putmsg(argc, argv)
+ int argc;
+ char **argv;
+{
+ register int fd;
+ register char *cp1, *cp2;
+ char buf[1024];
+ struct stat stbuf;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ if (cgetstr(bp, "st", &ST) == -1)
+ ST = DEFSTAT;
+ printf("%s:\n", printer);
+ /*
+ * Turn on the group execute bit of the lock file to disable queuing and
+ * turn on the owner execute bit of the lock file to disable printing.
+ */
+ (void) sprintf(line, "%s/%s", SD, LO);
+ if (stat(line, &stbuf) >= 0) {
+ if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
+ printf("\tcannot disable queuing\n");
+ else
+ printf("\tprinter and queuing disabled\n");
+ } else if (errno == ENOENT) {
+ if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
+ printf("\tcannot create lock file\n");
+ else {
+ (void) close(fd);
+ printf("\tprinter and queuing disabled\n");
+ }
+ return;
+ } else
+ printf("\tcannot stat lock file\n");
+ /*
+ * Write the message into the status file.
+ */
+ (void) sprintf(line, "%s/%s", SD, ST);
+ fd = open(line, O_WRONLY|O_CREAT, 0664);
+ if (fd < 0 || flock(fd, LOCK_EX) < 0) {
+ printf("\tcannot create status file\n");
+ return;
+ }
+ (void) ftruncate(fd, 0);
+ if (argc <= 0) {
+ (void) write(fd, "\n", 1);
+ (void) close(fd);
+ return;
+ }
+ cp1 = buf;
+ while (--argc >= 0) {
+ cp2 = *argv++;
+ while (*cp1++ = *cp2++)
+ ;
+ cp1[-1] = ' ';
+ }
+ cp1[-1] = '\n';
+ *cp1 = '\0';
+ (void) write(fd, buf, strlen(buf));
+ (void) close(fd);
+}
+
+/*
+ * Exit lpc
+ */
+void
+quit(argc, argv)
+ int argc;
+ char *argv[];
+{
+ exit(0);
+}
+
+/*
+ * Kill and restart the daemon.
+ */
+void
+restart(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: restart {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ abortpr(0);
+ startpr(0);
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ abortpr(0);
+ startpr(0);
+ }
+}
+
+/*
+ * Enable printing on the specified printer and startup the daemon.
+ */
+void
+startcmd(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: start {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ startpr(1);
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ startpr(1);
+ }
+}
+
+static void
+startpr(enable)
+ int enable;
+{
+ struct stat stbuf;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ (void) sprintf(line, "%s/%s", SD, LO);
+ printf("%s:\n", printer);
+
+ /*
+ * Turn off the owner execute bit of the lock file to enable printing.
+ */
+ if (enable && stat(line, &stbuf) >= 0) {
+ if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
+ printf("\tcannot enable printing\n");
+ else
+ printf("\tprinting enabled\n");
+ }
+ if (!startdaemon(printer))
+ printf("\tcouldn't start daemon\n");
+ else
+ printf("\tdaemon started\n");
+}
+
+/*
+ * Print the status of each queue listed or all the queues.
+ */
+void
+status(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ prstat();
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ prstat();
+ }
+}
+
+/*
+ * Print the status of the printer queue.
+ */
+static void
+prstat()
+{
+ struct stat stbuf;
+ register int fd, i;
+ register struct dirent *dp;
+ DIR *dirp;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ if (cgetstr(bp, "st", &ST) == -1)
+ ST = DEFSTAT;
+ printf("%s:\n", printer);
+ (void) sprintf(line, "%s/%s", SD, LO);
+ if (stat(line, &stbuf) >= 0) {
+ printf("\tqueuing is %s\n",
+ (stbuf.st_mode & 010) ? "disabled" : "enabled");
+ printf("\tprinting is %s\n",
+ (stbuf.st_mode & 0100) ? "disabled" : "enabled");
+ } else {
+ printf("\tqueuing is enabled\n");
+ printf("\tprinting is enabled\n");
+ }
+ if ((dirp = opendir(SD)) == NULL) {
+ printf("\tcannot examine spool directory\n");
+ return;
+ }
+ i = 0;
+ while ((dp = readdir(dirp)) != NULL) {
+ if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
+ i++;
+ }
+ closedir(dirp);
+ if (i == 0)
+ printf("\tno entries\n");
+ else if (i == 1)
+ printf("\t1 entry in spool area\n");
+ else
+ printf("\t%d entries in spool area\n", i);
+ fd = open(line, O_RDONLY);
+ if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
+ (void) close(fd); /* unlocks as well */
+ printf("\tno daemon present\n");
+ return;
+ }
+ (void) close(fd);
+ putchar('\t');
+ (void) sprintf(line, "%s/%s", SD, ST);
+ fd = open(line, O_RDONLY);
+ if (fd >= 0) {
+ (void) flock(fd, LOCK_SH);
+ while ((i = read(fd, line, sizeof(line))) > 0)
+ (void) fwrite(line, 1, i, stdout);
+ (void) close(fd); /* unlocks as well */
+ }
+}
+
+/*
+ * Stop the specified daemon after completing the current job and disable
+ * printing.
+ */
+void
+stop(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: stop {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ stoppr();
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ stoppr();
+ }
+}
+
+static void
+stoppr()
+{
+ register int fd;
+ struct stat stbuf;
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ (void) sprintf(line, "%s/%s", SD, LO);
+ printf("%s:\n", printer);
+
+ /*
+ * Turn on the owner execute bit of the lock file to disable printing.
+ */
+ if (stat(line, &stbuf) >= 0) {
+ if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
+ printf("\tcannot disable printing\n");
+ else {
+ upstat("printing disabled\n");
+ printf("\tprinting disabled\n");
+ }
+ } else if (errno == ENOENT) {
+ if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
+ printf("\tcannot create lock file\n");
+ else {
+ (void) close(fd);
+ upstat("printing disabled\n");
+ printf("\tprinting disabled\n");
+ }
+ } else
+ printf("\tcannot stat lock file\n");
+}
+
+struct queue **queue;
+int nitems;
+time_t mtime;
+
+/*
+ * Put the specified jobs at the top of printer queue.
+ */
+void
+topq(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int i;
+ struct stat stbuf;
+ int status, changed;
+
+ if (argc < 3) {
+ printf("Usage: topq printer [jobnum ...] [user ...]\n");
+ return;
+ }
+
+ --argc;
+ printer = *++argv;
+ status = cgetent(&bp, printcapdb, printer);
+ if (status == -2) {
+ printf("cannot open printer description file\n");
+ return;
+ } else if (status == -1) {
+ printf("%s: unknown printer\n", printer);
+ return;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ printf("%s:\n", printer);
+
+ if (chdir(SD) < 0) {
+ printf("\tcannot chdir to %s\n", SD);
+ return;
+ }
+ nitems = getq(&queue);
+ if (nitems == 0)
+ return;
+ changed = 0;
+ mtime = queue[0]->q_time;
+ for (i = argc; --i; ) {
+ if (doarg(argv[i]) == 0) {
+ printf("\tjob %s is not in the queue\n", argv[i]);
+ continue;
+ } else
+ changed++;
+ }
+ for (i = 0; i < nitems; i++)
+ free(queue[i]);
+ free(queue);
+ if (!changed) {
+ printf("\tqueue order unchanged\n");
+ return;
+ }
+ /*
+ * Turn on the public execute bit of the lock file to
+ * get lpd to rebuild the queue after the current job.
+ */
+ if (changed && stat(LO, &stbuf) >= 0)
+ (void) chmod(LO, (stbuf.st_mode & 0777) | 01);
+}
+
+/*
+ * Reposition the job by changing the modification time of
+ * the control file.
+ */
+static int
+touch(q)
+ struct queue *q;
+{
+ struct timeval tvp[2];
+
+ tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
+ tvp[0].tv_usec = tvp[1].tv_usec = 0;
+ return(utimes(q->q_name, tvp));
+}
+
+/*
+ * Checks if specified job name is in the printer's queue.
+ * Returns: negative (-1) if argument name is not in the queue.
+ */
+static int
+doarg(job)
+ char *job;
+{
+ register struct queue **qq;
+ register int jobnum, n;
+ register char *cp, *machine;
+ int cnt = 0;
+ FILE *fp;
+
+ /*
+ * Look for a job item consisting of system name, colon, number
+ * (example: ucbarpa:114)
+ */
+ if ((cp = index(job, ':')) != NULL) {
+ machine = job;
+ *cp++ = '\0';
+ job = cp;
+ } else
+ machine = NULL;
+
+ /*
+ * Check for job specified by number (example: 112 or 235ucbarpa).
+ */
+ if (isdigit(*job)) {
+ jobnum = 0;
+ do
+ jobnum = jobnum * 10 + (*job++ - '0');
+ while (isdigit(*job));
+ for (qq = queue + nitems; --qq >= queue; ) {
+ n = 0;
+ for (cp = (*qq)->q_name+3; isdigit(*cp); )
+ n = n * 10 + (*cp++ - '0');
+ if (jobnum != n)
+ continue;
+ if (*job && strcmp(job, cp) != 0)
+ continue;
+ if (machine != NULL && strcmp(machine, cp) != 0)
+ continue;
+ if (touch(*qq) == 0) {
+ printf("\tmoved %s\n", (*qq)->q_name);
+ cnt++;
+ }
+ }
+ return(cnt);
+ }
+ /*
+ * Process item consisting of owner's name (example: henry).
+ */
+ for (qq = queue + nitems; --qq >= queue; ) {
+ if ((fp = fopen((*qq)->q_name, "r")) == NULL)
+ continue;
+ while (getline(fp) > 0)
+ if (line[0] == 'P')
+ break;
+ (void) fclose(fp);
+ if (line[0] != 'P' || strcmp(job, line+1) != 0)
+ continue;
+ if (touch(*qq) == 0) {
+ printf("\tmoved %s\n", (*qq)->q_name);
+ cnt++;
+ }
+ }
+ return(cnt);
+}
+
+/*
+ * Enable everything and start printer (undo `down').
+ */
+void
+up(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int c, status;
+ register char *cp1, *cp2;
+ char prbuf[100];
+
+ if (argc == 1) {
+ printf("Usage: up {all | printer ...}\n");
+ return;
+ }
+ if (argc == 2 && !strcmp(argv[1], "all")) {
+ printer = prbuf;
+ while (cgetnext(&bp, printcapdb) > 0) {
+ cp1 = prbuf;
+ cp2 = bp;
+ while ((c = *cp2++) && c != '|' && c != ':')
+ *cp1++ = c;
+ *cp1 = '\0';
+ startpr(2);
+ }
+ return;
+ }
+ while (--argc) {
+ printer = *++argv;
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ printf("cannot open printer description file\n");
+ continue;
+ } else if (status == -1) {
+ printf("unknown printer %s\n", printer);
+ continue;
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ startpr(2);
+ }
+}
diff --git a/usr.sbin/lpr/lpc/cmdtab.c b/usr.sbin/lpr/lpc/cmdtab.c
new file mode 100644
index 0000000..7619791
--- /dev/null
+++ b/usr.sbin/lpr/lpc/cmdtab.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+
+#include "lpc.h"
+#include "extern.h"
+
+/*
+ * lpc -- command tables
+ */
+char aborthelp[] = "terminate a spooling daemon immediately and disable printing";
+char cleanhelp[] = "remove cruft files from a queue";
+char enablehelp[] = "turn a spooling queue on";
+char disablehelp[] = "turn a spooling queue off";
+char downhelp[] = "do a 'stop' followed by 'disable' and put a message in status";
+char helphelp[] = "get help on commands";
+char quithelp[] = "exit lpc";
+char restarthelp[] = "kill (if possible) and restart a spooling daemon";
+char starthelp[] = "enable printing and start a spooling daemon";
+char statushelp[] = "show status of daemon and queue";
+char stophelp[] = "stop a spooling daemon after current job completes and disable printing";
+char topqhelp[] = "put job at top of printer queue";
+char uphelp[] = "enable everything and restart spooling daemon";
+
+struct cmd cmdtab[] = {
+ { "abort", aborthelp, doabort, 1 },
+ { "clean", cleanhelp, clean, 1 },
+ { "enable", enablehelp, enable, 1 },
+ { "exit", quithelp, quit, 0 },
+ { "disable", disablehelp, disable, 1 },
+ { "down", downhelp, down, 1 },
+ { "help", helphelp, help, 0 },
+ { "quit", quithelp, quit, 0 },
+ { "restart", restarthelp, restart, 0 },
+ { "start", starthelp, startcmd, 1 },
+ { "status", statushelp, status, 0 },
+ { "stop", stophelp, stop, 1 },
+ { "topq", topqhelp, topq, 1 },
+ { "up", uphelp, up, 1 },
+ { "?", helphelp, help, 0 },
+ { 0 },
+};
+
+int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]);
diff --git a/usr.sbin/lpr/lpc/extern.h b/usr.sbin/lpr/lpc/extern.h
new file mode 100644
index 0000000..1b807b1
--- /dev/null
+++ b/usr.sbin/lpr/lpc/extern.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+
+#include <sys/cdefs.h>
+
+
+__BEGIN_DECLS
+void clean __P((int, char **));
+void disable __P((int, char **));
+void doabort __P((int, char **));
+void down __P((int, char **));
+void enable __P((int, char **));
+void help __P((int, char **));
+void quit __P((int, char **));
+void restart __P((int, char **));
+void startcmd __P((int, char **));
+void status __P((int, char **));
+void stop __P((int, char **));
+void topq __P((int, char **));
+void up __P((int, char **));
+__END_DECLS
+
+extern int NCMDS;
+extern struct cmd cmdtab[];
diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8
new file mode 100644
index 0000000..a786adc
--- /dev/null
+++ b/usr.sbin/lpr/lpc/lpc.8
@@ -0,0 +1,174 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)lpc.8 8.3 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt LPC 8
+.Os BSD 4.2
+.Sh NAME
+.Nm lpc
+.Nd line printer control program
+.Sh SYNOPSIS
+.Nm lpc
+.Oo
+.Ar command
+.Op Ar argument ...
+.Oc
+.Sh DESCRIPTION
+.Nm Lpc
+is used by the system administrator to control the
+operation of the line printer system.
+For each line printer configured in
+.Pa /etc/printcap ,
+.Nm lpc
+may be used to:
+.Bl -bullet -offset indent
+.It
+disable or enable a printer,
+.It
+disable or enable a printer's spooling queue,
+.It
+rearrange the order of jobs in a spooling queue,
+.It
+find the status of printers, and their associated
+spooling queues and printer daemons.
+.El
+.Pp
+Without any arguments,
+.Nm lpc
+will prompt for commands from the standard input.
+If arguments are supplied,
+.Nm lpc
+interprets the first argument as a command and the remaining
+arguments as parameters to the command. The standard input
+may be redirected causing
+.Nm lpc
+to read commands from file.
+Commands may be abbreviated;
+the following is the list of recognized commands.
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic \&? No [ command ... ]
+.It Ic help No [ command ... ]
+Print a short description of each command specified in the argument list,
+or, if no argument is given, a list of the recognized commands.
+.Pp
+.It Ic abort No {\ all\ |\ printer\ }
+Terminate an active spooling daemon on the local host immediately and
+then disable printing (preventing new daemons from being started by
+.Xr lpr )
+for the specified printers.
+.Pp
+.It Ic clean No {\ all\ |\ printer\ }
+Remove any temporary files, data files, and control files that cannot
+be printed (i.e., do not form a complete printer job)
+from the specified printer queue(s) on the local machine.
+.Pp
+.It Ic disable No {\ all\ |\ printer\ }
+Turn the specified printer queues off. This prevents new
+printer jobs from being entered into the queue by
+.Xr lpr .
+.Pp
+.It Ic down No {\ all\ |\ printer\ } message ...
+Turn the specified printer queue off, disable printing and put
+.Em message
+in the printer status file. The message doesn't need to be quoted, the
+remaining arguments are treated like
+.Xr echo 1 .
+This is normally used to take a printer down and let others know why
+.Xr lpq 1
+will indicate the printer is down and print the status message).
+.Pp
+.It Ic enable No {\ all\ |\ printer\ }
+Enable spooling on the local queue for the listed printers.
+This will allow
+.Xr lpr 1
+to put new jobs in the spool queue.
+.Pp
+.It Ic exit
+.It Ic quit
+Exit from lpc.
+.Pp
+.It Ic restart No {\ all\ |\ printer\ }
+Attempt to start a new printer daemon.
+This is useful when some abnormal condition causes the daemon to
+die unexpectedly, leaving jobs in the queue.
+.Xr Lpq
+will report that there is no daemon present when this condition occurs.
+If the user is the super-user,
+try to abort the current daemon first (i.e., kill and restart a stuck daemon).
+.Pp
+.It Ic start No {\ all\ |\ printer\ }
+Enable printing and start a spooling daemon for the listed printers.
+.Pp
+.It Ic status No {\ all\ |\ printer\ }
+Display the status of daemons and queues on the local machine.
+.Pp
+.It Ic stop No {\ all\ |\ printer\ }
+Stop a spooling daemon after the current job completes and disable
+printing.
+.Pp
+.It Ic topq No printer\ [\ jobnum\ ...\ ]\ [\ user\ ...\ ]
+Place the jobs in the order listed at the top of the printer queue.
+.Pp
+.It Ic up No {\ all\ |\ printer\ }
+Enable everything and start a new printer daemon. Undoes the effects of
+.Ic down .
+.Sh FILES
+.Bl -tag -width /var/spool/*/lockx -compact
+.It Pa /etc/printcap
+printer description file
+.It Pa /var/spool/*
+spool directories
+.It Pa /var/spool/*/lock
+lock file for queue control
+.El
+.Sh SEE ALSO
+.Xr lpd 8 ,
+.Xr lpr 1 ,
+.Xr lpq 1 ,
+.Xr lprm 1 ,
+.Xr printcap 5
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy "?Ambiguous command"
+abbreviation matches more than one command
+.It Sy "?Invalid command"
+no match was found
+.It Sy "?Privileged command"
+command can be executed by root only
+.El
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c
new file mode 100644
index 0000000..01cfc12
--- /dev/null
+++ b/usr.sbin/lpr/lpc/lpc.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpc.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <dirent.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lp.h"
+#include "lpc.h"
+#include "extern.h"
+
+/*
+ * lpc -- line printer control program
+ */
+
+int fromatty;
+
+char cmdline[200];
+int margc;
+char *margv[20];
+int top;
+
+jmp_buf toplevel;
+
+static void cmdscanner __P((int));
+static struct cmd *getcmd __P((char *));
+static void intr __P((int));
+static void makeargv __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct cmd *c;
+
+ name = argv[0];
+ openlog("lpd", 0, LOG_LPR);
+
+ if (--argc > 0) {
+ c = getcmd(*++argv);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ exit(1);
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ exit(1);
+ }
+ if (c->c_priv && getuid()) {
+ printf("?Privileged command\n");
+ exit(1);
+ }
+ (*c->c_handler)(argc, argv);
+ exit(0);
+ }
+ fromatty = isatty(fileno(stdin));
+ top = setjmp(toplevel) == 0;
+ if (top)
+ signal(SIGINT, intr);
+ for (;;) {
+ cmdscanner(top);
+ top = 1;
+ }
+}
+
+static void
+intr(signo)
+ int signo;
+{
+ if (!fromatty)
+ exit(0);
+ longjmp(toplevel, 1);
+}
+
+/*
+ * Command parser.
+ */
+static void
+cmdscanner(top)
+ int top;
+{
+ register struct cmd *c;
+
+ if (!top)
+ putchar('\n');
+ for (;;) {
+ if (fromatty) {
+ printf("lpc> ");
+ fflush(stdout);
+ }
+ if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
+ quit(0, NULL);
+ if (cmdline[0] == 0 || cmdline[0] == '\n')
+ break;
+ makeargv();
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->c_priv && getuid()) {
+ printf("?Privileged command\n");
+ continue;
+ }
+ (*c->c_handler)(margc, margv);
+ }
+ longjmp(toplevel, 0);
+}
+
+struct cmd *
+getcmd(name)
+ register char *name;
+{
+ register char *p, *q;
+ register struct cmd *c, *found;
+ register int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; p = c->c_name; c++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return(c);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return((struct cmd *)-1);
+ return(found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+static void
+makeargv()
+{
+ register char *cp;
+ register char **argp = margv;
+
+ margc = 0;
+ for (cp = cmdline; *cp;) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *cp++ = '\0';
+ }
+ *argp++ = 0;
+}
+
+#define HELPINDENT (sizeof ("directory"))
+
+/*
+ * Help command.
+ */
+void
+help(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct cmd *c;
+
+ if (argc == 1) {
+ register int i, j, w;
+ int columns, width = 0, lines;
+ extern int NCMDS;
+
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c->c_name; c++) {
+ int len = strlen(c->c_name);
+
+ if (len > width)
+ width = len;
+ }
+ width = (width + 8) &~ 7;
+ columns = 80 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < columns; j++) {
+ c = cmdtab + j * lines + i;
+ if (c->c_name)
+ printf("%s", c->c_name);
+ if (c + lines >= &cmdtab[NCMDS]) {
+ printf("\n");
+ break;
+ }
+ w = strlen(c->c_name);
+ while (w < width) {
+ w = (w + 8) &~ 7;
+ putchar('\t');
+ }
+ }
+ }
+ return;
+ }
+ while (--argc > 0) {
+ register char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%-*s\t%s\n", HELPINDENT,
+ c->c_name, c->c_help);
+ }
+}
diff --git a/usr.sbin/lpr/lpc/lpc.h b/usr.sbin/lpr/lpc/lpc.h
new file mode 100644
index 0000000..5e71203
--- /dev/null
+++ b/usr.sbin/lpr/lpc/lpc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)lpc.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Line printer control program.
+ */
+struct cmd {
+ char *c_name; /* command name */
+ char *c_help; /* help message */
+ /* routine to do the work */
+ void (*c_handler) __P((int, char *[]));
+ int c_priv; /* privileged command */
+};
diff --git a/usr.sbin/lpr/lpd/Makefile b/usr.sbin/lpr/lpd/Makefile
new file mode 100644
index 0000000..da95bac
--- /dev/null
+++ b/usr.sbin/lpr/lpd/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lpd
+CFLAGS+=-I${.CURDIR}/../common_source
+MAN8= lpd.0
+SRCS= lpd.c printjob.c recvjob.c displayq.c rmjob.c startdaemon.c \
+ lpdchar.c common.c
+.PATH: ${.CURDIR}/../common_source
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpd/extern.h b/usr.sbin/lpr/lpd/extern.h
new file mode 100644
index 0000000..64dec12
--- /dev/null
+++ b/usr.sbin/lpr/lpd/extern.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/cdefs.h>
+
+void printjob __P((void));
+void recvjob __P((void));
diff --git a/usr.sbin/lpr/lpd/lpd.8 b/usr.sbin/lpr/lpd/lpd.8
new file mode 100644
index 0000000..1e4677f
--- /dev/null
+++ b/usr.sbin/lpr/lpd/lpd.8
@@ -0,0 +1,249 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)lpd.8 8.3 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt LPD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm lpd
+.Nd line printer spooler daemon
+.Sh SYNOPSIS
+.Nm lpd
+.Op Fl l
+.Op Ar port#
+.Sh DESCRIPTION
+.Nm Lpd
+is the line printer daemon (spool area handler) and is normally invoked
+at boot time from the
+.Xr rc 8
+file. It makes a single pass through the
+.Xr printcap 5
+file to find out about the existing printers and
+prints any files left after a crash. It then uses the system calls
+.Xr listen 2
+and
+.Xr accept 2
+to receive requests to print files in the queue,
+transfer files to the spooling area, display the queue,
+or remove jobs from the queue. In each case, it forks a child to handle
+the request so the parent can continue to listen for more requests.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl l
+The
+.Fl l
+flag causes
+.Nm lpd
+to log valid requests received from the network. This can be useful
+for debugging purposes.
+.It Ar "port#"
+The Internet port number used to rendezvous
+with other processes is normally obtained with
+.Xr getservbyname 3
+but can be changed with the
+.Ar port#
+argument.
+.El
+.Pp
+Access control is provided by two means. First, all requests must come from
+one of the machines listed in the file
+.Pa /etc/hosts.equiv
+or
+.Pa /etc/hosts.lpd .
+Second, if the
+.Li rs
+capability is specified in the
+.Xr printcap
+entry for the printer being accessed,
+.Em lpr
+requests will only be honored for those users with accounts on the
+machine with the printer.
+.Pp
+The file
+.Em minfree
+in each spool directory contains the number of disk blocks to leave free
+so that the line printer queue won't completely fill the disk.
+The
+.Em minfree
+file can be edited with your favorite text editor.
+.Pp
+The daemon begins processing files
+after it has successfully set the lock for exclusive
+access (described a bit later),
+and scans the spool directory
+for files beginning with
+.Em cf .
+Lines in each
+.Em cf
+file specify files to be printed or non-printing actions to be
+performed. Each such line begins with a key character
+to specify what to do with the remainder of the line.
+.Bl -tag -width Ds
+.It J
+Job Name. String to be used for the job name on the burst page.
+.It C
+Classification. String to be used for the classification line
+on the burst page.
+.It L
+Literal. The line contains identification info from
+the password file and causes the banner page to be printed.
+.It T
+Title. String to be used as the title for
+.Xr pr 1 .
+.It H
+Host Name. Name of the machine where
+.Xr lpr
+was invoked.
+.It P
+Person. Login name of the person who invoked
+.Xr lpr .
+This is used to verify ownership by
+.Xr lprm .
+.It M
+Send mail to the specified user when the current print job completes.
+.It f
+Formatted File. Name of a file to print which is already formatted.
+.It l
+Like ``f'' but passes control characters and does not make page breaks.
+.It p
+Name of a file to print using
+.Xr pr 1
+as a filter.
+.It t
+Troff File. The file contains
+.Xr troff 1
+output (cat phototypesetter commands).
+.It n
+Ditroff File. The file contains device independent troff
+output.
+.It r
+DVI File. The file contains
+.Tn Tex l
+output
+DVI format from Standford.
+.It g
+Graph File. The file contains data produced by
+.Xr plot 3 .
+.It c
+Cifplot File. The file contains data produced by
+.Em cifplot .
+.It v
+The file contains a raster image.
+.It r
+The file contains text data with
+FORTRAN carriage control characters.
+.It \&1
+Troff Font R. Name of the font file to use instead of the default.
+.It \&2
+Troff Font I. Name of the font file to use instead of the default.
+.It \&3
+Troff Font B. Name of the font file to use instead of the default.
+.It \&4
+Troff Font S. Name of the font file to use instead of the default.
+.It W
+Width. Changes the page width (in characters) used by
+.Xr pr 1
+and the text filters.
+.It I
+Indent. The number of characters to indent the output by (in ascii).
+.It U
+Unlink. Name of file to remove upon completion of printing.
+.It N
+File name. The name of the file which is being printed, or a blank
+for the standard input (when
+.Xr lpr
+is invoked in a pipeline).
+.El
+.Pp
+If a file cannot be opened, a message will be logged via
+.Xr syslog 3
+using the
+.Em LOG_LPR
+facility.
+.Nm Lpd
+will try up to 20 times
+to reopen a file it expects to be there, after which it will
+skip the file to be printed.
+.Pp
+.Nm Lpd
+uses
+.Xr flock 2
+to provide exclusive access to the lock file and to prevent multiple
+daemons from becoming active simultaneously. If the daemon should be killed
+or die unexpectedly, the lock file need not be removed.
+The lock file is kept in a readable
+.Tn ASCII
+form
+and contains two lines.
+The first is the process id of the daemon and the second is the control
+file name of the current job being printed. The second line is updated to
+reflect the current status of
+.Nm lpd
+for the programs
+.Xr lpq 1
+and
+.Xr lprm 1 .
+.Sh FILES
+.Bl -tag -width "/var/spool/*/minfree" -compact
+.It Pa /etc/printcap
+printer description file
+.It Pa /var/spool/*
+spool directories
+.It Pa /var/spool/*/minfree
+minimum free space to leave
+.It Pa /dev/lp*
+line printer devices
+.It Pa /dev/printer
+socket for local requests
+.It Pa /etc/hosts.equiv
+lists machine names allowed printer access
+.It Pa /etc/hosts.lpd
+lists machine names allowed printer access,
+but not under same administrative control.
+.El
+.Sh SEE ALSO
+.Xr lpc 8 ,
+.Xr pac 1 ,
+.Xr lpr 1 ,
+.Xr lpq 1 ,
+.Xr lprm 1 ,
+.Xr syslog 3 ,
+.Xr printcap 5
+.Rs
+.%T "4.2 BSD Line Printer Spooler Manual"
+.Re
+.Sh HISTORY
+An
+.Nm
+daemon appeared in Version 6 AT&T UNIX.
diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c
new file mode 100644
index 0000000..aaf72b7
--- /dev/null
+++ b/usr.sbin/lpr/lpd/lpd.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpd.c 8.4 (Berkeley) 4/17/94";
+#endif /* not lint */
+
+/*
+ * lpd -- line printer daemon.
+ *
+ * Listen for a connection and perform the requested operation.
+ * Operations are:
+ * \1printer\n
+ * check the queue for jobs and print any found.
+ * \2printer\n
+ * receive a job from another machine and queue it.
+ * \3printer [users ...] [jobs ...]\n
+ * return the current state of the queue (short form).
+ * \4printer [users ...] [jobs ...]\n
+ * return the current state of the queue (long form).
+ * \5printer person [users ...] [jobs ...]\n
+ * remove jobs from the queue.
+ *
+ * Strategy to maintain protected spooling area:
+ * 1. Spooling area is writable only by daemon and spooling group
+ * 2. lpr runs setuid root and setgrp spooling group; it uses
+ * root to access any file it wants (verifying things before
+ * with an access call) and group id to know how it should
+ * set up ownership of files in the spooling area.
+ * 3. Files in spooling area are owned by root, group spooling
+ * group, with mode 660.
+ * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
+ * access files and printer. Users can't get to anything
+ * w/o help of lpq and lprm programs.
+ */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+
+#include <netdb.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+#include "extern.h"
+
+int lflag; /* log requests flag */
+int from_remote; /* from remote socket */
+
+static void reapchild __P((int));
+static void mcleanup __P((int));
+static void doit __P((void));
+static void startup __P((void));
+static void chkhost __P((struct sockaddr_in *));
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int f, funix, finet, options, fromlen;
+ fd_set defreadfds;
+ struct sockaddr_un un, fromunix;
+ struct sockaddr_in sin, frominet;
+ int omask, lfd;
+
+ options = 0;
+ gethostname(host, sizeof(host));
+ name = argv[0];
+
+ while (--argc > 0) {
+ argv++;
+ if (argv[0][0] == '-')
+ switch (argv[0][1]) {
+ case 'd':
+ options |= SO_DEBUG;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ }
+ }
+
+#ifndef DEBUG
+ /*
+ * Set up standard environment by detaching from the parent.
+ */
+ daemon(0, 0);
+#endif
+
+ openlog("lpd", LOG_PID, LOG_LPR);
+ syslog(LOG_INFO, "restarted");
+ (void) umask(0);
+ lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
+ if (lfd < 0) {
+ syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
+ exit(1);
+ }
+ if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
+ if (errno == EWOULDBLOCK) /* active deamon present */
+ exit(0);
+ syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
+ exit(1);
+ }
+ ftruncate(lfd, 0);
+ /*
+ * write process id for others to know
+ */
+ sprintf(line, "%u\n", getpid());
+ f = strlen(line);
+ if (write(lfd, line, f) != f) {
+ syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
+ exit(1);
+ }
+ signal(SIGCHLD, reapchild);
+ /*
+ * Restart all the printers.
+ */
+ startup();
+ (void) unlink(_PATH_SOCKETNAME);
+ funix = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (funix < 0) {
+ syslog(LOG_ERR, "socket: %m");
+ exit(1);
+ }
+#define mask(s) (1 << ((s) - 1))
+ omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
+ signal(SIGHUP, mcleanup);
+ signal(SIGINT, mcleanup);
+ signal(SIGQUIT, mcleanup);
+ signal(SIGTERM, mcleanup);
+ memset(&un, 0, sizeof(un));
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, _PATH_SOCKETNAME);
+#ifndef SUN_LEN
+#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
+#endif
+ if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
+ syslog(LOG_ERR, "ubind: %m");
+ exit(1);
+ }
+ sigsetmask(omask);
+ FD_ZERO(&defreadfds);
+ FD_SET(funix, &defreadfds);
+ listen(funix, 5);
+ finet = socket(AF_INET, SOCK_STREAM, 0);
+ if (finet >= 0) {
+ struct servent *sp;
+
+ if (options & SO_DEBUG)
+ if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
+ syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+ mcleanup(0);
+ }
+ sp = getservbyname("printer", "tcp");
+ if (sp == NULL) {
+ syslog(LOG_ERR, "printer/tcp: unknown service");
+ mcleanup(0);
+ }
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = sp->s_port;
+ if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ mcleanup(0);
+ }
+ FD_SET(finet, &defreadfds);
+ listen(finet, 5);
+ }
+ /*
+ * Main loop: accept, do a request, continue.
+ */
+ memset(&frominet, 0, sizeof(frominet));
+ memset(&fromunix, 0, sizeof(fromunix));
+ for (;;) {
+ int domain, nfds, s;
+ fd_set readfds;
+
+ FD_COPY(&defreadfds, &readfds);
+ nfds = select(20, &readfds, 0, 0, 0);
+ if (nfds <= 0) {
+ if (nfds < 0 && errno != EINTR)
+ syslog(LOG_WARNING, "select: %m");
+ continue;
+ }
+ if (FD_ISSET(funix, &readfds)) {
+ domain = AF_UNIX, fromlen = sizeof(fromunix);
+ s = accept(funix,
+ (struct sockaddr *)&fromunix, &fromlen);
+ } else /* if (FD_ISSET(finet, &readfds)) */ {
+ domain = AF_INET, fromlen = sizeof(frominet);
+ s = accept(finet,
+ (struct sockaddr *)&frominet, &fromlen);
+ }
+ if (s < 0) {
+ if (errno != EINTR)
+ syslog(LOG_WARNING, "accept: %m");
+ continue;
+ }
+ if (fork() == 0) {
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ (void) close(funix);
+ (void) close(finet);
+ dup2(s, 1);
+ (void) close(s);
+ if (domain == AF_INET) {
+ from_remote = 1;
+ chkhost(&frominet);
+ } else
+ from_remote = 0;
+ doit();
+ exit(0);
+ }
+ (void) close(s);
+ }
+}
+
+static void
+reapchild(signo)
+ int signo;
+{
+ union wait status;
+
+ while (wait3((int *)&status, WNOHANG, 0) > 0)
+ ;
+}
+
+static void
+mcleanup(signo)
+ int signo;
+{
+ if (lflag)
+ syslog(LOG_INFO, "exiting");
+ unlink(_PATH_SOCKETNAME);
+ exit(0);
+}
+
+/*
+ * Stuff for handling job specifications
+ */
+char *user[MAXUSERS]; /* users to process */
+int users; /* # of users in user array */
+int requ[MAXREQUESTS]; /* job number of spool entries */
+int requests; /* # of spool requests */
+char *person; /* name of person doing lprm */
+
+char fromb[MAXHOSTNAMELEN]; /* buffer for client's machine name */
+char cbuf[BUFSIZ]; /* command line buffer */
+char *cmdnames[] = {
+ "null",
+ "printjob",
+ "recvjob",
+ "displayq short",
+ "displayq long",
+ "rmjob"
+};
+
+static void
+doit()
+{
+ register char *cp;
+ register int n;
+
+ for (;;) {
+ cp = cbuf;
+ do {
+ if (cp >= &cbuf[sizeof(cbuf) - 1])
+ fatal("Command line too long");
+ if ((n = read(1, cp, 1)) != 1) {
+ if (n < 0)
+ fatal("Lost connection");
+ return;
+ }
+ } while (*cp++ != '\n');
+ *--cp = '\0';
+ cp = cbuf;
+ if (lflag) {
+ if (*cp >= '\1' && *cp <= '\5')
+ syslog(LOG_INFO, "%s requests %s %s",
+ from, cmdnames[*cp], cp+1);
+ else
+ syslog(LOG_INFO, "bad request (%d) from %s",
+ *cp, from);
+ }
+ switch (*cp++) {
+ case '\1': /* check the queue and print any jobs there */
+ printer = cp;
+ printjob();
+ break;
+ case '\2': /* receive files to be queued */
+ if (!from_remote) {
+ syslog(LOG_INFO, "illegal request (%d)", *cp);
+ exit(1);
+ }
+ printer = cp;
+ recvjob();
+ break;
+ case '\3': /* display the queue (short form) */
+ case '\4': /* display the queue (long form) */
+ printer = cp;
+ while (*cp) {
+ if (*cp != ' ') {
+ cp++;
+ continue;
+ }
+ *cp++ = '\0';
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ if (isdigit(*cp)) {
+ if (requests >= MAXREQUESTS)
+ fatal("Too many requests");
+ requ[requests++] = atoi(cp);
+ } else {
+ if (users >= MAXUSERS)
+ fatal("Too many users");
+ user[users++] = cp;
+ }
+ }
+ displayq(cbuf[0] - '\3');
+ exit(0);
+ case '\5': /* remove a job from the queue */
+ if (!from_remote) {
+ syslog(LOG_INFO, "illegal request (%d)", *cp);
+ exit(1);
+ }
+ printer = cp;
+ while (*cp && *cp != ' ')
+ cp++;
+ if (!*cp)
+ break;
+ *cp++ = '\0';
+ person = cp;
+ while (*cp) {
+ if (*cp != ' ') {
+ cp++;
+ continue;
+ }
+ *cp++ = '\0';
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ if (isdigit(*cp)) {
+ if (requests >= MAXREQUESTS)
+ fatal("Too many requests");
+ requ[requests++] = atoi(cp);
+ } else {
+ if (users >= MAXUSERS)
+ fatal("Too many users");
+ user[users++] = cp;
+ }
+ }
+ rmjob();
+ break;
+ }
+ fatal("Illegal service request");
+ }
+}
+
+/*
+ * Make a pass through the printcap database and start printing any
+ * files left from the last time the machine went down.
+ */
+static void
+startup()
+{
+ char *buf;
+ register char *cp;
+ int pid;
+
+ /*
+ * Restart the daemons.
+ */
+ while (cgetnext(&buf, printcapdb) > 0) {
+ for (cp = buf; *cp; cp++)
+ if (*cp == '|' || *cp == ':') {
+ *cp = '\0';
+ break;
+ }
+ if ((pid = fork()) < 0) {
+ syslog(LOG_WARNING, "startup: cannot fork");
+ mcleanup(0);
+ }
+ if (!pid) {
+ printer = buf;
+ cgetclose();
+ printjob();
+ }
+ }
+}
+
+#define DUMMY ":nobody::"
+
+/*
+ * Check to see if the from host has access to the line printer.
+ */
+static void
+chkhost(f)
+ struct sockaddr_in *f;
+{
+ register struct hostent *hp;
+ register FILE *hostf;
+ int first = 1;
+ extern char *inet_ntoa();
+
+ f->sin_port = ntohs(f->sin_port);
+ if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
+ fatal("Malformed from address");
+
+ /* Need real hostname for temporary filenames */
+ hp = gethostbyaddr((char *)&f->sin_addr,
+ sizeof(struct in_addr), f->sin_family);
+ if (hp == NULL)
+ fatal("Host name for your address (%s) unknown",
+ inet_ntoa(f->sin_addr));
+
+ (void) strncpy(fromb, hp->h_name, sizeof(fromb));
+ from[sizeof(fromb) - 1] = '\0';
+ from = fromb;
+
+ hostf = fopen(_PATH_HOSTSEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser(hostf, f->sin_addr.s_addr,
+ DUMMY, DUMMY) == 0) {
+ (void) fclose(hostf);
+ return;
+ }
+ (void) fclose(hostf);
+ }
+ if (first == 1) {
+ first = 0;
+ hostf = fopen(_PATH_HOSTSLPD, "r");
+ goto again;
+ }
+ fatal("Your host does not have line printer access");
+ /*NOTREACHED*/
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/usr.sbin/lpr/lpd/lpdchar.c b/usr.sbin/lpr/lpd/lpdchar.c
new file mode 100644
index 0000000..4a4f5da
--- /dev/null
+++ b/usr.sbin/lpr/lpd/lpdchar.c
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Character set for line printer daemon
+ */
+#include "lp.local.h"
+
+#define c_______ 0
+#define c______1 01
+#define c_____1_ 02
+#define c____1__ 04
+#define c____11_ 06
+#define c___1___ 010
+#define c___1__1 011
+#define c___1_1_ 012
+#define c___11__ 014
+#define c__1____ 020
+#define c__1__1_ 022
+#define c__1_1__ 024
+#define c__11___ 030
+#define c__111__ 034
+#define c__111_1 035
+#define c__1111_ 036
+#define c__11111 037
+#define c_1_____ 040
+#define c_1____1 041
+#define c_1___1_ 042
+#define c_1__1__ 044
+#define c_1_1___ 050
+#define c_1_1__1 051
+#define c_1_1_1_ 052
+#define c_11____ 060
+#define c_11_11_ 066
+#define c_111___ 070
+#define c_111__1 071
+#define c_111_1_ 072
+#define c_1111__ 074
+#define c_1111_1 075
+#define c_11111_ 076
+#define c_111111 077
+#define c1______ 0100
+#define c1_____1 0101
+#define c1____1_ 0102
+#define c1____11 0103
+#define c1___1__ 0104
+#define c1___1_1 0105
+#define c1___11_ 0106
+#define c1__1___ 0110
+#define c1__1__1 0111
+#define c1__11_1 0115
+#define c1__1111 0117
+#define c1_1____ 0120
+#define c1_1___1 0121
+#define c1_1_1_1 0125
+#define c1_1_11_ 0126
+#define c1_111__ 0134
+#define c1_1111_ 0136
+#define c11____1 0141
+#define c11___1_ 0142
+#define c11___11 0143
+#define c11_1___ 0150
+#define c11_1__1 0151
+#define c111_11_ 0166
+#define c1111___ 0170
+#define c11111__ 0174
+#define c111111_ 0176
+#define c1111111 0177
+
+char scnkey[][HEIGHT] = /* this is relatively easy to modify */
+ /* just look: */
+{
+ { c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* */
+
+ { c__11___,
+ c__11___,
+ c__11___,
+ c__11___,
+ c__11___,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___ }, /* ! */
+
+ { c_1__1__,
+ c_1__1__,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* " */
+
+ { c_______,
+ c__1_1__,
+ c__1_1__,
+ c1111111,
+ c__1_1__,
+ c1111111,
+ c__1_1__,
+ c__1_1__,
+ c_______ }, /* # */
+
+ { c___1___,
+ c_11111_,
+ c1__1__1,
+ c1__1___,
+ c_11111_,
+ c___1__1,
+ c1__1__1,
+ c_11111_,
+ c___1___ }, /* $ */
+
+ { c_1_____,
+ c1_1___1,
+ c_1___1_,
+ c____1__,
+ c___1___,
+ c__1____,
+ c_1___1_,
+ c1___1_1,
+ c_____1_ }, /* % */
+
+ { c_11____,
+ c1__1___,
+ c1___1__,
+ c_1_1___,
+ c__1____,
+ c_1_1__1,
+ c1___11_,
+ c1___11_,
+ c_111__1 }, /* & */
+
+ { c___11__,
+ c___11__,
+ c___1___,
+ c__1____,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* ' */
+
+ { c____1__,
+ c___1___,
+ c__1____,
+ c__1____,
+ c__1____,
+ c__1____,
+ c__1____,
+ c___1___,
+ c____1__ }, /* ( */
+
+ { c__1____,
+ c___1___,
+ c____1__,
+ c____1__,
+ c____1__,
+ c____1__,
+ c____1__,
+ c___1___,
+ c__1____ }, /* ) */
+
+ { c_______,
+ c___1___,
+ c1__1__1,
+ c_1_1_1_,
+ c__111__,
+ c_1_1_1_,
+ c1__1__1,
+ c___1___,
+ c_______ }, /* * */
+
+ { c_______,
+ c___1___,
+ c___1___,
+ c___1___,
+ c1111111,
+ c___1___,
+ c___1___,
+ c___1___,
+ c_______ }, /* + */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___,
+ c__1____,
+ c_1_____,
+ c_______ }, /* , */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_______,
+ c1111111,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* - */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___ }, /* . */
+
+ { c_______,
+ c______1,
+ c_____1_,
+ c____1__,
+ c___1___,
+ c__1____,
+ c_1_____,
+ c1______,
+ c_______ }, /* / */
+
+ { c_11111_,
+ c1_____1,
+ c1____11,
+ c1___1_1,
+ c1__1__1,
+ c1_1___1,
+ c11____1,
+ c1_____1,
+ c_11111_ }, /* 0 */
+
+ { c___1___,
+ c__11___,
+ c_1_1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c_11111_ }, /* 1 */
+
+ { c_11111_,
+ c1_____1,
+ c______1,
+ c_____1_,
+ c__111__,
+ c_1_____,
+ c1______,
+ c1______,
+ c1111111 }, /* 2 */
+
+ { c_11111_,
+ c1_____1,
+ c______1,
+ c______1,
+ c__1111_,
+ c______1,
+ c______1,
+ c1_____1,
+ c_11111_ }, /* 3 */
+
+ { c_____1_,
+ c____11_,
+ c___1_1_,
+ c__1__1_,
+ c_1___1_,
+ c1____1_,
+ c1111111,
+ c_____1_,
+ c_____1_ }, /* 4 */
+
+ { c1111111,
+ c1______,
+ c1______,
+ c11111__,
+ c_____1_,
+ c______1,
+ c______1,
+ c1____1_,
+ c_1111__ }, /* 5 */
+
+ { c__1111_,
+ c_1_____,
+ c1______,
+ c1______,
+ c1_1111_,
+ c11____1,
+ c1_____1,
+ c1_____1,
+ c_11111_ }, /* 6 */
+
+ { c1111111,
+ c1_____1,
+ c_____1_,
+ c____1__,
+ c___1___,
+ c__1____,
+ c__1____,
+ c__1____,
+ c__1____ }, /* 7 */
+
+ { c_11111_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_11111_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_11111_ }, /* 8 */
+
+ { c_11111_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_111111,
+ c______1,
+ c______1,
+ c1_____1,
+ c_1111__ }, /* 9 */
+
+ { c_______,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___ }, /* : */
+
+
+ { c__11___,
+ c__11___,
+ c_______,
+ c_______,
+ c__11___,
+ c__11___,
+ c__1____,
+ c_1_____,
+ c_______ }, /* ; */
+
+ { c____1__,
+ c___1___,
+ c__1____,
+ c_1_____,
+ c1______,
+ c_1_____,
+ c__1____,
+ c___1___,
+ c____1__ }, /* < */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1111111,
+ c_______,
+ c1111111,
+ c_______,
+ c_______,
+ c_______ }, /* = */
+
+ { c__1____,
+ c___1___,
+ c____1__,
+ c_____1_,
+ c______1,
+ c_____1_,
+ c____1__,
+ c___1___,
+ c__1____ }, /* > */
+
+ { c__1111_,
+ c_1____1,
+ c_1____1,
+ c______1,
+ c____11_,
+ c___1___,
+ c___1___,
+ c_______,
+ c___1___ }, /* ? */
+
+ { c__1111_,
+ c_1____1,
+ c1__11_1,
+ c1_1_1_1,
+ c1_1_1_1,
+ c1_1111_,
+ c1______,
+ c_1____1,
+ c__1111_ }, /* @ */
+
+ { c__111__,
+ c_1___1_,
+ c1_____1,
+ c1_____1,
+ c1111111,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1 }, /* A */
+
+ { c111111_,
+ c_1____1,
+ c_1____1,
+ c_1____1,
+ c_11111_,
+ c_1____1,
+ c_1____1,
+ c_1____1,
+ c111111_ }, /* B */
+
+ { c__1111_,
+ c_1____1,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c_1____1,
+ c__1111_ }, /* C */
+
+ { c11111__,
+ c_1___1_,
+ c_1____1,
+ c_1____1,
+ c_1____1,
+ c_1____1,
+ c_1____1,
+ c_1___1_,
+ c11111__ }, /* D */
+
+ { c1111111,
+ c1______,
+ c1______,
+ c1______,
+ c111111_,
+ c1______,
+ c1______,
+ c1______,
+ c1111111 }, /* E */
+
+ { c1111111,
+ c1______,
+ c1______,
+ c1______,
+ c111111_,
+ c1______,
+ c1______,
+ c1______,
+ c1______ }, /* F */
+
+ { c__1111_,
+ c_1____1,
+ c1______,
+ c1______,
+ c1______,
+ c1__1111,
+ c1_____1,
+ c_1____1,
+ c__1111_ }, /* G */
+
+ { c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1111111,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1 }, /* H */
+
+ { c_11111_,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c_11111_ }, /* I */
+
+ { c__11111,
+ c____1__,
+ c____1__,
+ c____1__,
+ c____1__,
+ c____1__,
+ c____1__,
+ c1___1__,
+ c_111___ }, /* J */
+
+ { c1_____1,
+ c1____1_,
+ c1___1__,
+ c1__1___,
+ c1_1____,
+ c11_1___,
+ c1___1__,
+ c1____1_,
+ c1_____1 }, /* K */
+
+ { c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1______,
+ c1111111 }, /* L */
+
+ { c1_____1,
+ c11___11,
+ c1_1_1_1,
+ c1__1__1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1 }, /* M */
+
+ { c1_____1,
+ c11____1,
+ c1_1___1,
+ c1__1__1,
+ c1___1_1,
+ c1____11,
+ c1_____1,
+ c1_____1,
+ c1_____1 }, /* N */
+
+ { c__111__,
+ c_1___1_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_1___1_,
+ c__111__ }, /* O */
+
+ { c111111_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c111111_,
+ c1______,
+ c1______,
+ c1______,
+ c1______ }, /* P */
+
+ { c__111__,
+ c_1___1_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1__1__1,
+ c1___1_1,
+ c_1___1_,
+ c__111_1 }, /* Q */
+
+ { c111111_,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c111111_,
+ c1__1___,
+ c1___1__,
+ c1____1_,
+ c1_____1 }, /* R */
+
+ { c_11111_,
+ c1_____1,
+ c1______,
+ c1______,
+ c_11111_,
+ c______1,
+ c______1,
+ c1_____1,
+ c_11111_ }, /* S */
+
+ { c1111111,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___ }, /* T */
+
+ { c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_11111_ }, /* U */
+
+ { c1_____1,
+ c1_____1,
+ c1_____1,
+ c_1___1_,
+ c_1___1_,
+ c__1_1__,
+ c__1_1__,
+ c___1___,
+ c___1___ }, /* V */
+
+ { c1_____1,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c1__1__1,
+ c1__1__1,
+ c1_1_1_1,
+ c11___11,
+ c1_____1 }, /* W */
+
+ { c1_____1,
+ c1_____1,
+ c_1___1_,
+ c__1_1__,
+ c___1___,
+ c__1_1__,
+ c_1___1_,
+ c1_____1,
+ c1_____1 }, /* X */
+
+ { c1_____1,
+ c1_____1,
+ c_1___1_,
+ c__1_1__,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___ }, /* Y */
+
+ { c1111111,
+ c______1,
+ c_____1_,
+ c____1__,
+ c___1___,
+ c__1____,
+ c_1_____,
+ c1______,
+ c1111111 }, /* Z */
+
+ { c_1111__,
+ c_1_____,
+ c_1_____,
+ c_1_____,
+ c_1_____,
+ c_1_____,
+ c_1_____,
+ c_1_____,
+ c_1111__ }, /* [ */
+
+ { c_______,
+ c1______,
+ c_1_____,
+ c__1____,
+ c___1___,
+ c____1__,
+ c_____1_,
+ c______1,
+ c_______ }, /* \ */
+
+ { c__1111_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c__1111_ }, /* ] */
+
+ { c___1___,
+ c__1_1__,
+ c_1___1_,
+ c1_____1,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* ^ */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c1111111,
+ c_______ }, /* _ */
+
+ { c__11___,
+ c__11___,
+ c___1___,
+ c____1__,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* ` */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_1111__,
+ c_____1_,
+ c_11111_,
+ c1_____1,
+ c1____11,
+ c_1111_1 }, /* a */
+
+ { c1______,
+ c1______,
+ c1______,
+ c1_111__,
+ c11___1_,
+ c1_____1,
+ c1_____1,
+ c11___1_,
+ c1_111__ }, /* b */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_1111__,
+ c1____1_,
+ c1______,
+ c1______,
+ c1____1_,
+ c_1111__ }, /* c */
+
+ { c_____1_,
+ c_____1_,
+ c_____1_,
+ c_111_1_,
+ c1___11_,
+ c1____1_,
+ c1____1_,
+ c1___11_,
+ c_111_1_ }, /* d */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_1111__,
+ c1____1_,
+ c111111_,
+ c1______,
+ c1____1_,
+ c_1111__ }, /* e */
+
+ { c___11__,
+ c__1__1_,
+ c__1____,
+ c__1____,
+ c11111__,
+ c__1____,
+ c__1____,
+ c__1____,
+ c__1____ }, /* f */
+
+ { c_111_1_,
+ c1___11_,
+ c1____1_,
+ c1____1_,
+ c1___11_,
+ c_111_1_,
+ c_____1_,
+ c1____1_,
+ c_1111__ }, /* g */
+
+ { c1______,
+ c1______,
+ c1______,
+ c1_111__,
+ c11___1_,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1____1_ }, /* h */
+
+ { c_______,
+ c___1___,
+ c_______,
+ c__11___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c__111__ }, /* i */
+
+ { c____11_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_____1_,
+ c_1___1_,
+ c__111__ }, /* j */
+
+ { c1______,
+ c1______,
+ c1______,
+ c1___1__,
+ c1__1___,
+ c1_1____,
+ c11_1___,
+ c1___1__,
+ c1____1_ }, /* k */
+
+ { c__11___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c__111__ }, /* l */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1_1_11_,
+ c11_1__1,
+ c1__1__1,
+ c1__1__1,
+ c1__1__1,
+ c1__1__1 }, /* m */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1_111__,
+ c11___1_,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1____1_ }, /* n */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_1111__,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c_1111__ }, /* o */
+
+ { c1_111__,
+ c11___1_,
+ c1____1_,
+ c1____1_,
+ c11___1_,
+ c1_111__,
+ c1______,
+ c1______,
+ c1______ }, /* p */
+
+ { c_111_1_,
+ c1___11_,
+ c1____1_,
+ c1____1_,
+ c1___11_,
+ c_111_1_,
+ c_____1_,
+ c_____1_,
+ c_____1_ }, /* q */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1_111__,
+ c11___1_,
+ c1______,
+ c1______,
+ c1______,
+ c1______ }, /* r */
+
+ { c_______,
+ c_______,
+ c_______,
+ c_1111__,
+ c1____1_,
+ c_11____,
+ c___11__,
+ c1____1_,
+ c_1111__ }, /* s */
+
+ { c_______,
+ c__1____,
+ c__1____,
+ c11111__,
+ c__1____,
+ c__1____,
+ c__1____,
+ c__1__1_,
+ c___11__ }, /* t */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1___11_,
+ c_111_1_ }, /* u */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1_____1,
+ c1_____1,
+ c1_____1,
+ c_1___1_,
+ c__1_1__,
+ c___1___ }, /* v */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1_____1,
+ c1__1__1,
+ c1__1__1,
+ c1__1__1,
+ c1__1__1,
+ c_11_11_ }, /* w */
+
+ { c_______,
+ c_______,
+ c_______,
+ c1____1_,
+ c_1__1__,
+ c__11___,
+ c__11___,
+ c_1__1__,
+ c1____1_ }, /* x */
+
+ { c1____1_,
+ c1____1_,
+ c1____1_,
+ c1____1_,
+ c1___11_,
+ c_111_1_,
+ c_____1_,
+ c1____1_,
+ c_1111__ }, /* y */
+
+ { c_______,
+ c_______,
+ c_______,
+ c111111_,
+ c____1__,
+ c___1___,
+ c__1____,
+ c_1_____,
+ c111111_ }, /* z */
+
+ { c___11__,
+ c__1____,
+ c__1____,
+ c__1____,
+ c_1_____,
+ c__1____,
+ c__1____,
+ c__1____,
+ c___11__ }, /* } */
+
+ { c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___,
+ c___1___ }, /* | */
+
+ { c__11___,
+ c____1__,
+ c____1__,
+ c____1__,
+ c_____1_,
+ c____1__,
+ c____1__,
+ c____1__,
+ c__11___ }, /* } */
+
+ { c_11____,
+ c1__1__1,
+ c____11_,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______,
+ c_______ }, /* ~ */
+
+ { c_1__1__,
+ c1__1__1,
+ c__1__1_,
+ c_1__1__,
+ c1__1__1,
+ c__1__1_,
+ c_1__1__,
+ c1__1__1,
+ c__1__1_ } /* rub-out */
+};
diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c
new file mode 100644
index 0000000..87c9352
--- /dev/null
+++ b/usr.sbin/lpr/lpd/printjob.c
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94";
+#endif /* not lint */
+
+
+/*
+ * printjob -- print jobs in the queue.
+ *
+ * NOTE: the lock file is used to pass information to lpq and lprm.
+ * it does not need to be removed because file locks are dynamic.
+ */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <pwd.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sgtty.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+#include "extern.h"
+
+#define DORETURN 0 /* absorb fork error */
+#define DOABORT 1 /* abort if dofork fails */
+
+/*
+ * Error tokens
+ */
+#define REPRINT -2
+#define ERROR -1
+#define OK 0
+#define FATALERR 1
+#define NOACCT 2
+#define FILTERERR 3
+#define ACCESS 4
+
+static dev_t fdev; /* device of file pointed to by symlink */
+static ino_t fino; /* inode of file pointed to by symlink */
+static FILE *cfp; /* control file */
+static int child; /* id of any filters */
+static int lfd; /* lock file descriptor */
+static int ofd; /* output filter file descriptor */
+static int ofilter; /* id of output filter, if any */
+static int pfd; /* prstatic inter file descriptor */
+static int pid; /* pid of lpd process */
+static int prchild; /* id of pr process */
+static int remote; /* true if sending files to remote */
+static char title[80]; /* ``pr'' title */
+static int tof; /* true if at top of form */
+
+static char class[32]; /* classification field */
+static char fromhost[32]; /* user's host machine */
+ /* indentation size in static characters */
+static char indent[10] = "-i0";
+static char jobname[100]; /* job or file name */
+static char length[10] = "-l"; /* page length in lines */
+static char logname[32]; /* user's login name */
+static char pxlength[10] = "-y"; /* page length in pixels */
+static char pxwidth[10] = "-x"; /* page width in pixels */
+static char tempfile[] = "errsXXXXXX"; /* file name for filter output */
+static char width[10] = "-w"; /* page width in static characters */
+
+static void abortpr __P((int));
+static void banner __P((char *, char *));
+static int dofork __P((int));
+static int dropit __P((int));
+static void init __P((void));
+static void openpr __P((void));
+static int print __P((int, char *));
+static int printit __P((char *));
+static void pstatus __P((const char *, ...));
+static char response __P((void));
+static void scan_out __P((int, char *, int));
+static char *scnline __P((int, char *, int));
+static int sendfile __P((int, char *));
+static int sendit __P((char *));
+static void sendmail __P((char *, int));
+static void setty __P((void));
+
+void
+printjob()
+{
+ struct stat stb;
+ register struct queue *q, **qp;
+ struct queue **queue;
+ register int i, nitems;
+ long pidoff;
+ int count = 0;
+
+ init(); /* set up capabilities */
+ (void) write(1, "", 1); /* ack that daemon is started */
+ (void) close(2); /* set up log file */
+ if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
+ syslog(LOG_ERR, "%s: %m", LF);
+ (void) open(_PATH_DEVNULL, O_WRONLY);
+ }
+ setgid(getegid());
+ pid = getpid(); /* for use with lprm */
+ setpgrp(0, pid);
+ signal(SIGHUP, abortpr);
+ signal(SIGINT, abortpr);
+ signal(SIGQUIT, abortpr);
+ signal(SIGTERM, abortpr);
+
+ (void) mktemp(tempfile);
+
+ /*
+ * uses short form file names
+ */
+ if (chdir(SD) < 0) {
+ syslog(LOG_ERR, "%s: %m", SD);
+ exit(1);
+ }
+ if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
+ exit(0); /* printing disabled */
+ lfd = open(LO, O_WRONLY|O_CREAT, 0644);
+ if (lfd < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ exit(1);
+ }
+ if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
+ if (errno == EWOULDBLOCK) /* active deamon present */
+ exit(0);
+ syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ exit(1);
+ }
+ ftruncate(lfd, 0);
+ /*
+ * write process id for others to know
+ */
+ sprintf(line, "%u\n", pid);
+ pidoff = i = strlen(line);
+ if (write(lfd, line, i) != i) {
+ syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ exit(1);
+ }
+ /*
+ * search the spool directory for work and sort by queue order.
+ */
+ if ((nitems = getq(&queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ exit(1);
+ }
+ if (nitems == 0) /* no work to do */
+ exit(0);
+ if (stb.st_mode & 01) { /* reset queue flag */
+ if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ }
+ openpr(); /* open printer or remote */
+again:
+ /*
+ * we found something to do now do it --
+ * write the name of the current control file into the lock file
+ * so the spool queue program can tell what we're working on
+ */
+ for (qp = queue; nitems--; free((char *) q)) {
+ q = *qp++;
+ if (stat(q->q_name, &stb) < 0)
+ continue;
+ restart:
+ (void) lseek(lfd, (off_t)pidoff, 0);
+ (void) sprintf(line, "%s\n", q->q_name);
+ i = strlen(line);
+ if (write(lfd, line, i) != i)
+ syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ if (!remote)
+ i = printit(q->q_name);
+ else
+ i = sendit(q->q_name);
+ /*
+ * Check to see if we are supposed to stop printing or
+ * if we are to rebuild the queue.
+ */
+ if (fstat(lfd, &stb) == 0) {
+ /* stop printing before starting next job? */
+ if (stb.st_mode & 0100)
+ goto done;
+ /* rebuild queue (after lpc topq) */
+ if (stb.st_mode & 01) {
+ for (free((char *) q); nitems--; free((char *) q))
+ q = *qp++;
+ if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ syslog(LOG_WARNING, "%s: %s: %m",
+ printer, LO);
+ break;
+ }
+ }
+ if (i == OK) /* file ok and printed */
+ count++;
+ else if (i == REPRINT) { /* try reprinting the job */
+ syslog(LOG_INFO, "restarting %s", printer);
+ if (ofilter > 0) {
+ kill(ofilter, SIGCONT); /* to be sure */
+ (void) close(ofd);
+ while ((i = wait(0)) > 0 && i != ofilter)
+ ;
+ ofilter = 0;
+ }
+ (void) close(pfd); /* close printer */
+ if (ftruncate(lfd, pidoff) < 0)
+ syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
+ openpr(); /* try to reopen printer */
+ goto restart;
+ }
+ }
+ free((char *) queue);
+ /*
+ * search the spool directory for more work.
+ */
+ if ((nitems = getq(&queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ exit(1);
+ }
+ if (nitems == 0) { /* no more work to do */
+ done:
+ if (count > 0) { /* Files actually printed */
+ if (!SF && !tof)
+ (void) write(ofd, FF, strlen(FF));
+ if (TR != NULL) /* output trailer */
+ (void) write(ofd, TR, strlen(TR));
+ }
+ (void) unlink(tempfile);
+ exit(0);
+ }
+ goto again;
+}
+
+char fonts[4][50]; /* fonts for troff */
+
+char ifonts[4][40] = {
+ _PATH_VFONTR,
+ _PATH_VFONTI,
+ _PATH_VFONTB,
+ _PATH_VFONTS,
+};
+
+/*
+ * The remaining part is the reading of the control file (cf)
+ * and performing the various actions.
+ */
+static int
+printit(file)
+ char *file;
+{
+ register int i;
+ char *cp;
+ int bombed = OK;
+
+ /*
+ * open control file; ignore if no longer there.
+ */
+ if ((cfp = fopen(file, "r")) == NULL) {
+ syslog(LOG_INFO, "%s: %s: %m", printer, file);
+ return(OK);
+ }
+ /*
+ * Reset troff fonts.
+ */
+ for (i = 0; i < 4; i++)
+ strcpy(fonts[i], ifonts[i]);
+ sprintf(&width[2], "%d", PW);
+ strcpy(indent+2, "0");
+
+ /*
+ * read the control file for work to do
+ *
+ * file format -- first character in the line is a command
+ * rest of the line is the argument.
+ * valid commands are:
+ *
+ * S -- "stat info" for symbolic link protection
+ * J -- "job name" on banner page
+ * C -- "class name" on banner page
+ * L -- "literal" user's name to print on banner
+ * T -- "title" for pr
+ * H -- "host name" of machine where lpr was done
+ * P -- "person" user's login name
+ * I -- "indent" amount to indent output
+ * f -- "file name" name of text file to print
+ * l -- "file name" text file with control chars
+ * p -- "file name" text file to print with pr(1)
+ * t -- "file name" troff(1) file to print
+ * n -- "file name" ditroff(1) file to print
+ * d -- "file name" dvi file to print
+ * g -- "file name" plot(1G) file to print
+ * v -- "file name" plain raster file to print
+ * c -- "file name" cifplot file to print
+ * 1 -- "R font file" for troff
+ * 2 -- "I font file" for troff
+ * 3 -- "B font file" for troff
+ * 4 -- "S font file" for troff
+ * N -- "name" of file (used by lpq)
+ * U -- "unlink" name of file to remove
+ * (after we print it. (Pass 2 only)).
+ * M -- "mail" to user when done printing
+ *
+ * getline reads a line and expands tabs to blanks
+ */
+
+ /* pass 1 */
+
+ while (getline(cfp))
+ switch (line[0]) {
+ case 'H':
+ strcpy(fromhost, line+1);
+ if (class[0] == '\0')
+ strncpy(class, line+1, sizeof(class)-1);
+ continue;
+
+ case 'P':
+ strncpy(logname, line+1, sizeof(logname)-1);
+ if (RS) { /* restricted */
+ if (getpwnam(logname) == NULL) {
+ bombed = NOACCT;
+ sendmail(line+1, bombed);
+ goto pass2;
+ }
+ }
+ continue;
+
+ case 'S':
+ cp = line+1;
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + (*cp++ - '0');
+ fdev = i;
+ cp++;
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + (*cp++ - '0');
+ fino = i;
+ continue;
+
+ case 'J':
+ if (line[1] != '\0')
+ strncpy(jobname, line+1, sizeof(jobname)-1);
+ else
+ strcpy(jobname, " ");
+ continue;
+
+ case 'C':
+ if (line[1] != '\0')
+ strncpy(class, line+1, sizeof(class)-1);
+ else if (class[0] == '\0')
+ gethostname(class, sizeof(class));
+ continue;
+
+ case 'T': /* header title for pr */
+ strncpy(title, line+1, sizeof(title)-1);
+ continue;
+
+ case 'L': /* identification line */
+ if (!SH && !HL)
+ banner(line+1, jobname);
+ continue;
+
+ case '1': /* troff fonts */
+ case '2':
+ case '3':
+ case '4':
+ if (line[1] != '\0')
+ strcpy(fonts[line[0]-'1'], line+1);
+ continue;
+
+ case 'W': /* page width */
+ strncpy(width+2, line+1, sizeof(width)-3);
+ continue;
+
+ case 'I': /* indent amount */
+ strncpy(indent+2, line+1, sizeof(indent)-3);
+ continue;
+
+ default: /* some file to print */
+ switch (i = print(line[0], line+1)) {
+ case ERROR:
+ if (bombed == OK)
+ bombed = FATALERR;
+ break;
+ case REPRINT:
+ (void) fclose(cfp);
+ return(REPRINT);
+ case FILTERERR:
+ case ACCESS:
+ bombed = i;
+ sendmail(logname, bombed);
+ }
+ title[0] = '\0';
+ continue;
+
+ case 'N':
+ case 'U':
+ case 'M':
+ continue;
+ }
+
+ /* pass 2 */
+
+pass2:
+ fseek(cfp, 0L, 0);
+ while (getline(cfp))
+ switch (line[0]) {
+ case 'L': /* identification line */
+ if (!SH && HL)
+ banner(line+1, jobname);
+ continue;
+
+ case 'M':
+ if (bombed < NOACCT) /* already sent if >= NOACCT */
+ sendmail(line+1, bombed);
+ continue;
+
+ case 'U':
+ (void) unlink(line+1);
+ }
+ /*
+ * clean-up in case another control file exists
+ */
+ (void) fclose(cfp);
+ (void) unlink(file);
+ return(bombed == OK ? OK : ERROR);
+}
+
+/*
+ * Print a file.
+ * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
+ * Return -1 if a non-recoverable error occured,
+ * 2 if the filter detected some errors (but printed the job anyway),
+ * 1 if we should try to reprint this job and
+ * 0 if all is well.
+ * Note: all filters take stdin as the file, stdout as the printer,
+ * stderr as the log file, and must not ignore SIGINT.
+ */
+static int
+print(format, file)
+ int format;
+ char *file;
+{
+ register int n;
+ register char *prog;
+ int fi, fo;
+ FILE *fp;
+ char *av[15], buf[BUFSIZ];
+ int pid, p[2], stopped = 0;
+ union wait status;
+ struct stat stb;
+
+ if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0)
+ return(ERROR);
+ /*
+ * Check to see if data file is a symbolic link. If so, it should
+ * still point to the same file or someone is trying to print
+ * something he shouldn't.
+ */
+ if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
+ (stb.st_dev != fdev || stb.st_ino != fino))
+ return(ACCESS);
+ if (!SF && !tof) { /* start on a fresh page */
+ (void) write(ofd, FF, strlen(FF));
+ tof = 1;
+ }
+ if (IF == NULL && (format == 'f' || format == 'l')) {
+ tof = 0;
+ while ((n = read(fi, buf, BUFSIZ)) > 0)
+ if (write(ofd, buf, n) != n) {
+ (void) close(fi);
+ return(REPRINT);
+ }
+ (void) close(fi);
+ return(OK);
+ }
+ switch (format) {
+ case 'p': /* print file using 'pr' */
+ if (IF == NULL) { /* use output filter */
+ prog = _PATH_PR;
+ av[0] = "pr";
+ av[1] = width;
+ av[2] = length;
+ av[3] = "-h";
+ av[4] = *title ? title : " ";
+ av[5] = 0;
+ fo = ofd;
+ goto start;
+ }
+ pipe(p);
+ if ((prchild = dofork(DORETURN)) == 0) { /* child */
+ dup2(fi, 0); /* file is stdin */
+ dup2(p[1], 1); /* pipe is stdout */
+ for (n = 3; n < NOFILE; n++)
+ (void) close(n);
+ execl(_PATH_PR, "pr", width, length,
+ "-h", *title ? title : " ", 0);
+ syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
+ exit(2);
+ }
+ (void) close(p[1]); /* close output side */
+ (void) close(fi);
+ if (prchild < 0) {
+ prchild = 0;
+ (void) close(p[0]);
+ return(ERROR);
+ }
+ fi = p[0]; /* use pipe for input */
+ case 'f': /* print plain text file */
+ prog = IF;
+ av[1] = width;
+ av[2] = length;
+ av[3] = indent;
+ n = 4;
+ break;
+ case 'l': /* like 'f' but pass control characters */
+ prog = IF;
+ av[1] = "-c";
+ av[2] = width;
+ av[3] = length;
+ av[4] = indent;
+ n = 5;
+ break;
+ case 'r': /* print a fortran text file */
+ prog = RF;
+ av[1] = width;
+ av[2] = length;
+ n = 3;
+ break;
+ case 't': /* print troff output */
+ case 'n': /* print ditroff output */
+ case 'd': /* print tex output */
+ (void) unlink(".railmag");
+ if ((fo = creat(".railmag", FILMOD)) < 0) {
+ syslog(LOG_ERR, "%s: cannot create .railmag", printer);
+ (void) unlink(".railmag");
+ } else {
+ for (n = 0; n < 4; n++) {
+ if (fonts[n][0] != '/')
+ (void) write(fo, _PATH_VFONT,
+ sizeof(_PATH_VFONT) - 1);
+ (void) write(fo, fonts[n], strlen(fonts[n]));
+ (void) write(fo, "\n", 1);
+ }
+ (void) close(fo);
+ }
+ prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
+ av[1] = pxwidth;
+ av[2] = pxlength;
+ n = 3;
+ break;
+ case 'c': /* print cifplot output */
+ prog = CF;
+ av[1] = pxwidth;
+ av[2] = pxlength;
+ n = 3;
+ break;
+ case 'g': /* print plot(1G) output */
+ prog = GF;
+ av[1] = pxwidth;
+ av[2] = pxlength;
+ n = 3;
+ break;
+ case 'v': /* print raster output */
+ prog = VF;
+ av[1] = pxwidth;
+ av[2] = pxlength;
+ n = 3;
+ break;
+ default:
+ (void) close(fi);
+ syslog(LOG_ERR, "%s: illegal format character '%c'",
+ printer, format);
+ return(ERROR);
+ }
+ if ((av[0] = rindex(prog, '/')) != NULL)
+ av[0]++;
+ else
+ av[0] = prog;
+ av[n++] = "-n";
+ av[n++] = logname;
+ av[n++] = "-h";
+ av[n++] = fromhost;
+ av[n++] = AF;
+ av[n] = 0;
+ fo = pfd;
+ if (ofilter > 0) { /* stop output filter */
+ write(ofd, "\031\1", 2);
+ while ((pid =
+ wait3((int *)&status, WUNTRACED, 0)) > 0 && pid != ofilter)
+ ;
+ if (status.w_stopval != WSTOPPED) {
+ (void) close(fi);
+ syslog(LOG_WARNING, "%s: output filter died (%d)",
+ printer, status.w_retcode);
+ return(REPRINT);
+ }
+ stopped++;
+ }
+start:
+ if ((child = dofork(DORETURN)) == 0) { /* child */
+ dup2(fi, 0);
+ dup2(fo, 1);
+ n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ if (n >= 0)
+ dup2(n, 2);
+ for (n = 3; n < NOFILE; n++)
+ (void) close(n);
+ execv(prog, av);
+ syslog(LOG_ERR, "cannot execv %s", prog);
+ exit(2);
+ }
+ (void) close(fi);
+ if (child < 0)
+ status.w_retcode = 100;
+ else
+ while ((pid = wait((int *)&status)) > 0 && pid != child)
+ ;
+ child = 0;
+ prchild = 0;
+ if (stopped) { /* restart output filter */
+ if (kill(ofilter, SIGCONT) < 0) {
+ syslog(LOG_ERR, "cannot restart output filter");
+ exit(1);
+ }
+ }
+ tof = 0;
+
+ /* Copy filter output to "lf" logfile */
+ if (fp = fopen(tempfile, "r")) {
+ while (fgets(buf, sizeof(buf), fp))
+ fputs(buf, stderr);
+ fclose(fp);
+ }
+
+ if (!WIFEXITED(status)) {
+ syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
+ printer, format, status.w_termsig);
+ return(ERROR);
+ }
+ switch (status.w_retcode) {
+ case 0:
+ tof = 1;
+ return(OK);
+ case 1:
+ return(REPRINT);
+ default:
+ syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
+ printer, format, status.w_retcode);
+ case 2:
+ return(ERROR);
+ }
+}
+
+/*
+ * Send the daemon control file (cf) and any data files.
+ * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
+ * 0 if all is well.
+ */
+static int
+sendit(file)
+ char *file;
+{
+ register int i, err = OK;
+ char *cp, last[BUFSIZ];
+
+ /*
+ * open control file
+ */
+ if ((cfp = fopen(file, "r")) == NULL)
+ return(OK);
+ /*
+ * read the control file for work to do
+ *
+ * file format -- first character in the line is a command
+ * rest of the line is the argument.
+ * commands of interest are:
+ *
+ * a-z -- "file name" name of file to print
+ * U -- "unlink" name of file to remove
+ * (after we print it. (Pass 2 only)).
+ */
+
+ /*
+ * pass 1
+ */
+ while (getline(cfp)) {
+ again:
+ if (line[0] == 'S') {
+ cp = line+1;
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + (*cp++ - '0');
+ fdev = i;
+ cp++;
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + (*cp++ - '0');
+ fino = i;
+ continue;
+ }
+ if (line[0] >= 'a' && line[0] <= 'z') {
+ strcpy(last, line);
+ while (i = getline(cfp))
+ if (strcmp(last, line))
+ break;
+ switch (sendfile('\3', last+1)) {
+ case OK:
+ if (i)
+ goto again;
+ break;
+ case REPRINT:
+ (void) fclose(cfp);
+ return(REPRINT);
+ case ACCESS:
+ sendmail(logname, ACCESS);
+ case ERROR:
+ err = ERROR;
+ }
+ break;
+ }
+ }
+ if (err == OK && sendfile('\2', file) > 0) {
+ (void) fclose(cfp);
+ return(REPRINT);
+ }
+ /*
+ * pass 2
+ */
+ fseek(cfp, 0L, 0);
+ while (getline(cfp))
+ if (line[0] == 'U')
+ (void) unlink(line+1);
+ /*
+ * clean-up in case another control file exists
+ */
+ (void) fclose(cfp);
+ (void) unlink(file);
+ return(err);
+}
+
+/*
+ * Send a data file to the remote machine and spool it.
+ * Return positive if we should try resending.
+ */
+static int
+sendfile(type, file)
+ int type;
+ char *file;
+{
+ register int f, i, amt;
+ struct stat stb;
+ char buf[BUFSIZ];
+ int sizerr, resp;
+
+ if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
+ return(ERROR);
+ /*
+ * Check to see if data file is a symbolic link. If so, it should
+ * still point to the same file or someone is trying to print something
+ * he shouldn't.
+ */
+ if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 &&
+ (stb.st_dev != fdev || stb.st_ino != fino))
+ return(ACCESS);
+ (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file);
+ amt = strlen(buf);
+ for (i = 0; ; i++) {
+ if (write(pfd, buf, amt) != amt ||
+ (resp = response()) < 0 || resp == '\1') {
+ (void) close(f);
+ return(REPRINT);
+ } else if (resp == '\0')
+ break;
+ if (i == 0)
+ pstatus("no space on remote; waiting for queue to drain");
+ if (i == 10)
+ syslog(LOG_ALERT, "%s: can't send to %s; queue full",
+ printer, RM);
+ sleep(5 * 60);
+ }
+ if (i)
+ pstatus("sending to %s", RM);
+ sizerr = 0;
+ for (i = 0; i < stb.st_size; i += BUFSIZ) {
+ amt = BUFSIZ;
+ if (i + amt > stb.st_size)
+ amt = stb.st_size - i;
+ if (sizerr == 0 && read(f, buf, amt) != amt)
+ sizerr = 1;
+ if (write(pfd, buf, amt) != amt) {
+ (void) close(f);
+ return(REPRINT);
+ }
+ }
+
+
+
+
+ (void) close(f);
+ if (sizerr) {
+ syslog(LOG_INFO, "%s: %s: changed size", printer, file);
+ /* tell recvjob to ignore this file */
+ (void) write(pfd, "\1", 1);
+ return(ERROR);
+ }
+ if (write(pfd, "", 1) != 1 || response())
+ return(REPRINT);
+ return(OK);
+}
+
+/*
+ * Check to make sure there have been no errors and that both programs
+ * are in sync with eachother.
+ * Return non-zero if the connection was lost.
+ */
+static char
+response()
+{
+ char resp;
+
+ if (read(pfd, &resp, 1) != 1) {
+ syslog(LOG_INFO, "%s: lost connection", printer);
+ return(-1);
+ }
+ return(resp);
+}
+
+/*
+ * Banner printing stuff
+ */
+static void
+banner(name1, name2)
+ char *name1, *name2;
+{
+ time_t tvec;
+ extern char *ctime();
+
+ time(&tvec);
+ if (!SF && !tof)
+ (void) write(ofd, FF, strlen(FF));
+ if (SB) { /* short banner only */
+ if (class[0]) {
+ (void) write(ofd, class, strlen(class));
+ (void) write(ofd, ":", 1);
+ }
+ (void) write(ofd, name1, strlen(name1));
+ (void) write(ofd, " Job: ", 7);
+ (void) write(ofd, name2, strlen(name2));
+ (void) write(ofd, " Date: ", 8);
+ (void) write(ofd, ctime(&tvec), 24);
+ (void) write(ofd, "\n", 1);
+ } else { /* normal banner */
+ (void) write(ofd, "\n\n\n", 3);
+ scan_out(ofd, name1, '\0');
+ (void) write(ofd, "\n\n", 2);
+ scan_out(ofd, name2, '\0');
+ if (class[0]) {
+ (void) write(ofd,"\n\n\n",3);
+ scan_out(ofd, class, '\0');
+ }
+ (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15);
+ (void) write(ofd, name2, strlen(name2));
+ (void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
+ (void) write(ofd, ctime(&tvec), 24);
+ (void) write(ofd, "\n", 1);
+ }
+ if (!SF)
+ (void) write(ofd, FF, strlen(FF));
+ tof = 1;
+}
+
+static char *
+scnline(key, p, c)
+ register int key;
+ register char *p;
+ int c;
+{
+ register scnwidth;
+
+ for (scnwidth = WIDTH; --scnwidth;) {
+ key <<= 1;
+ *p++ = key & 0200 ? c : BACKGND;
+ }
+ return (p);
+}
+
+#define TRC(q) (((q)-' ')&0177)
+
+static void
+scan_out(scfd, scsp, dlm)
+ int scfd, dlm;
+ char *scsp;
+{
+ register char *strp;
+ register nchrs, j;
+ char outbuf[LINELEN+1], *sp, c, cc;
+ int d, scnhgt;
+ extern char scnkey[][HEIGHT]; /* in lpdchar.c */
+
+ for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
+ strp = &outbuf[0];
+ sp = scsp;
+ for (nchrs = 0; ; ) {
+ d = dropit(c = TRC(cc = *sp++));
+ if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
+ for (j = WIDTH; --j;)
+ *strp++ = BACKGND;
+ else
+ strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
+ if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
+ break;
+ *strp++ = BACKGND;
+ *strp++ = BACKGND;
+ }
+ while (*--strp == BACKGND && strp >= outbuf)
+ ;
+ strp++;
+ *strp++ = '\n';
+ (void) write(scfd, outbuf, strp-outbuf);
+ }
+}
+
+static int
+dropit(c)
+ int c;
+{
+ switch(c) {
+
+ case TRC('_'):
+ case TRC(';'):
+ case TRC(','):
+ case TRC('g'):
+ case TRC('j'):
+ case TRC('p'):
+ case TRC('q'):
+ case TRC('y'):
+ return (DROP);
+
+ default:
+ return (0);
+ }
+}
+
+/*
+ * sendmail ---
+ * tell people about job completion
+ */
+static void
+sendmail(user, bombed)
+ char *user;
+ int bombed;
+{
+ register int i;
+ int p[2], s;
+ register char *cp;
+ char buf[100];
+ struct stat stb;
+ FILE *fp;
+
+ pipe(p);
+ if ((s = dofork(DORETURN)) == 0) { /* child */
+ dup2(p[0], 0);
+ for (i = 3; i < NOFILE; i++)
+ (void) close(i);
+ if ((cp = rindex(_PATH_SENDMAIL, '/')) != NULL)
+ cp++;
+ else
+ cp = _PATH_SENDMAIL;
+ sprintf(buf, "%s@%s", user, fromhost);
+ execl(_PATH_SENDMAIL, cp, buf, 0);
+ exit(0);
+ } else if (s > 0) { /* parent */
+ dup2(p[1], 1);
+ printf("To: %s@%s\n", user, fromhost);
+ printf("Subject: printer job\n\n");
+ printf("Your printer job ");
+ if (*jobname)
+ printf("(%s) ", jobname);
+ switch (bombed) {
+ case OK:
+ printf("\ncompleted successfully\n");
+ break;
+ default:
+ case FATALERR:
+ printf("\ncould not be printed\n");
+ break;
+ case NOACCT:
+ printf("\ncould not be printed without an account on %s\n", host);
+ break;
+ case FILTERERR:
+ if (stat(tempfile, &stb) < 0 || stb.st_size == 0 ||
+ (fp = fopen(tempfile, "r")) == NULL) {
+ printf("\nwas printed but had some errors\n");
+ break;
+ }
+ printf("\nwas printed but had the following errors:\n");
+ while ((i = getc(fp)) != EOF)
+ putchar(i);
+ (void) fclose(fp);
+ break;
+ case ACCESS:
+ printf("\nwas not printed because it was not linked to the original file\n");
+ }
+ fflush(stdout);
+ (void) close(1);
+ }
+ (void) close(p[0]);
+ (void) close(p[1]);
+ wait(&s);
+}
+
+/*
+ * dofork - fork with retries on failure
+ */
+static int
+dofork(action)
+ int action;
+{
+ register int i, pid;
+
+ for (i = 0; i < 20; i++) {
+ if ((pid = fork()) < 0) {
+ sleep((unsigned)(i*i));
+ continue;
+ }
+ /*
+ * Child should run as daemon instead of root
+ */
+ if (pid == 0)
+ setuid(DU);
+ return(pid);
+ }
+ syslog(LOG_ERR, "can't fork");
+
+ switch (action) {
+ case DORETURN:
+ return (-1);
+ default:
+ syslog(LOG_ERR, "bad action (%d) to dofork", action);
+ /*FALL THRU*/
+ case DOABORT:
+ exit(1);
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * Kill child processes to abort current job.
+ */
+static void
+abortpr(signo)
+ int signo;
+{
+ (void) unlink(tempfile);
+ kill(0, SIGINT);
+ if (ofilter > 0)
+ kill(ofilter, SIGCONT);
+ while (wait(NULL) > 0)
+ ;
+ exit(0);
+}
+
+static void
+init()
+{
+ int status;
+ char *s;
+
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
+ syslog(LOG_ERR, "can't open printer description file");
+ exit(1);
+ } else if (status == -1) {
+ syslog(LOG_ERR, "unknown printer: %s", printer);
+ exit(1);
+ } else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ if (cgetstr(bp, "lp", &LP) == -1)
+ LP = _PATH_DEFDEVLP;
+ if (cgetstr(bp, "rp", &RP) == -1)
+ RP = DEFLP;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ if (cgetstr(bp, "st", &ST) == -1)
+ ST = DEFSTAT;
+ if (cgetstr(bp, "lf", &LF) == -1)
+ LF = _PATH_CONSOLE;
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetnum(bp, "du", &DU) < 0)
+ DU = DEFUID;
+ if (cgetstr(bp,"ff", &FF) == -1)
+ FF = DEFFF;
+ if (cgetnum(bp, "pw", &PW) < 0)
+ PW = DEFWIDTH;
+ sprintf(&width[2], "%d", PW);
+ if (cgetnum(bp, "pl", &PL) < 0)
+ PL = DEFLENGTH;
+ sprintf(&length[2], "%d", PL);
+ if (cgetnum(bp,"px", &PX) < 0)
+ PX = 0;
+ sprintf(&pxwidth[2], "%d", PX);
+ if (cgetnum(bp, "py", &PY) < 0)
+ PY = 0;
+ sprintf(&pxlength[2], "%d", PY);
+ cgetstr(bp, "rm", &RM);
+ if (s = checkremote())
+ syslog(LOG_WARNING, s);
+
+ cgetstr(bp, "af", &AF);
+ cgetstr(bp, "of", &OF);
+ cgetstr(bp, "if", &IF);
+ cgetstr(bp, "rf", &RF);
+ cgetstr(bp, "tf", &TF);
+ cgetstr(bp, "nf", &NF);
+ cgetstr(bp, "df", &DF);
+ cgetstr(bp, "gf", &GF);
+ cgetstr(bp, "vf", &VF);
+ cgetstr(bp, "cf", &CF);
+ cgetstr(bp, "tr", &TR);
+
+ RS = (cgetcap(bp, "rs", ':') != NULL);
+ SF = (cgetcap(bp, "sf", ':') != NULL);
+ SH = (cgetcap(bp, "sh", ':') != NULL);
+ SB = (cgetcap(bp, "sb", ':') != NULL);
+ HL = (cgetcap(bp, "hl", ':') != NULL);
+ RW = (cgetcap(bp, "rw", ':') != NULL);
+
+ cgetnum(bp, "br", &BR);
+ if (cgetnum(bp, "fc", &FC) < 0)
+ FC = 0;
+ if (cgetnum(bp, "fs", &FS) < 0)
+ FS = 0;
+ if (cgetnum(bp, "xc", &XC) < 0)
+ XC = 0;
+ if (cgetnum(bp, "xs", &XS) < 0)
+ XS = 0;
+
+ tof = (cgetcap(bp, "fo", ':') == NULL);
+}
+
+/*
+ * Acquire line printer or remote connection.
+ */
+static void
+openpr()
+{
+ register int i, n;
+ int resp;
+
+ if (!sendtorem && *LP) {
+ for (i = 1; ; i = i < 32 ? i << 1 : i) {
+ pfd = open(LP, RW ? O_RDWR : O_WRONLY);
+ if (pfd >= 0)
+ break;
+ if (errno == ENOENT) {
+ syslog(LOG_ERR, "%s: %m", LP);
+ exit(1);
+ }
+ if (i == 1)
+ pstatus("waiting for %s to become ready (offline ?)", printer);
+ sleep(i);
+ }
+ if (isatty(pfd))
+ setty();
+ pstatus("%s is ready and printing", printer);
+ } else if (RM != NULL) {
+ for (i = 1; ; i = i < 256 ? i << 1 : i) {
+ resp = -1;
+ pfd = getport(RM);
+ if (pfd >= 0) {
+ (void) sprintf(line, "\2%s\n", RP);
+ n = strlen(line);
+ if (write(pfd, line, n) == n &&
+ (resp = response()) == '\0')
+ break;
+ (void) close(pfd);
+ }
+ if (i == 1) {
+ if (resp < 0)
+ pstatus("waiting for %s to come up", RM);
+ else {
+ pstatus("waiting for queue to be enabled on %s", RM);
+ i = 256;
+ }
+ }
+ sleep(i);
+ }
+ pstatus("sending to %s", RM);
+ remote = 1;
+ } else {
+ syslog(LOG_ERR, "%s: no line printer device or host name",
+ printer);
+ exit(1);
+ }
+ /*
+ * Start up an output filter, if needed.
+ */
+ if (!remote && OF) {
+ int p[2];
+ char *cp;
+
+ pipe(p);
+ if ((ofilter = dofork(DOABORT)) == 0) { /* child */
+ dup2(p[0], 0); /* pipe is std in */
+ dup2(pfd, 1); /* printer is std out */
+ for (i = 3; i < NOFILE; i++)
+ (void) close(i);
+ if ((cp = rindex(OF, '/')) == NULL)
+ cp = OF;
+ else
+ cp++;
+ execl(OF, cp, width, length, 0);
+ syslog(LOG_ERR, "%s: %s: %m", printer, OF);
+ exit(1);
+ }
+ (void) close(p[0]); /* close input side */
+ ofd = p[1]; /* use pipe for output */
+ } else {
+ ofd = pfd;
+ ofilter = 0;
+ }
+}
+
+struct bauds {
+ int baud;
+ int speed;
+} bauds[] = {
+ 50, B50,
+ 75, B75,
+ 110, B110,
+ 134, B134,
+ 150, B150,
+ 200, B200,
+ 300, B300,
+ 600, B600,
+ 1200, B1200,
+ 1800, B1800,
+ 2400, B2400,
+ 4800, B4800,
+ 9600, B9600,
+ 19200, EXTA,
+ 38400, EXTB,
+ 0, 0
+};
+
+/*
+ * setup tty lines.
+ */
+static void
+setty()
+{
+ struct sgttyb ttybuf;
+ register struct bauds *bp;
+
+ if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
+ syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
+ exit(1);
+ }
+ if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
+ syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer);
+ exit(1);
+ }
+ if (BR > 0) {
+ for (bp = bauds; bp->baud; bp++)
+ if (BR == bp->baud)
+ break;
+ if (!bp->baud) {
+ syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
+ exit(1);
+ }
+ ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
+ }
+ ttybuf.sg_flags &= ~FC;
+ ttybuf.sg_flags |= FS;
+ if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
+ syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer);
+ exit(1);
+ }
+ if (XC) {
+ if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
+ syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer);
+ exit(1);
+ }
+ }
+ if (XS) {
+ if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
+ syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer);
+ exit(1);
+ }
+ }
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+pstatus(const char *msg, ...)
+#else
+pstatus(msg, va_alist)
+ char *msg;
+ va_dcl
+#endif
+{
+ register int fd;
+ char buf[BUFSIZ];
+ va_list ap;
+#if __STDC__
+ va_start(ap, msg);
+#else
+ va_start(ap);
+#endif
+
+ umask(0);
+ fd = open(ST, O_WRONLY|O_CREAT, 0664);
+ if (fd < 0 || flock(fd, LOCK_EX) < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", printer, ST);
+ exit(1);
+ }
+ ftruncate(fd, 0);
+ (void)vsnprintf(buf, sizeof(buf), msg, ap);
+ va_end(ap);
+ strcat(buf, "\n");
+ (void) write(fd, buf, strlen(buf));
+ (void) close(fd);
+}
diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c
new file mode 100644
index 0000000..67a6183
--- /dev/null
+++ b/usr.sbin/lpr/lpd/recvjob.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Receive printer jobs from the network, queue them and
+ * start the printer daemon.
+ */
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "extern.h"
+#include "pathnames.h"
+
+#define ack() (void) write(1, sp, 1);
+
+static char dfname[40]; /* data files */
+static int minfree; /* keep at least minfree blocks available */
+static char *sp = "";
+static char tfname[40]; /* tmp copy of cf before linking */
+
+static int chksize __P((int));
+static void frecverr __P((const char *, ...));
+static int noresponse __P((void));
+static void rcleanup __P((int));
+static int read_number __P((char *));
+static int readfile __P((char *, int));
+static int readjob __P((void));
+
+
+void
+recvjob()
+{
+ struct stat stb;
+ int status;
+
+ /*
+ * Perform lookup for printer name or abbreviation
+ */
+ if ((status = cgetent(&bp, printcapdb, printer)) == -2)
+ frecverr("cannot open printer description file");
+ else if (status == -1)
+ frecverr("unknown printer %s", printer);
+ else if (status == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ if (cgetstr(bp, "lf", &LF) == -1)
+ LF = _PATH_CONSOLE;
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+
+ (void) close(2); /* set up log file */
+ if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
+ syslog(LOG_ERR, "%s: %m", LF);
+ (void) open(_PATH_DEVNULL, O_WRONLY);
+ }
+
+ if (chdir(SD) < 0)
+ frecverr("%s: %s: %m", printer, SD);
+ if (stat(LO, &stb) == 0) {
+ if (stb.st_mode & 010) {
+ /* queue is disabled */
+ putchar('\1'); /* return error code */
+ exit(1);
+ }
+ } else if (stat(SD, &stb) < 0)
+ frecverr("%s: %s: %m", printer, SD);
+ minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
+ signal(SIGTERM, rcleanup);
+ signal(SIGPIPE, rcleanup);
+
+ if (readjob())
+ printjob();
+}
+
+/*
+ * Read printer jobs sent by lpd and copy them to the spooling directory.
+ * Return the number of jobs successfully transfered.
+ */
+static int
+readjob()
+{
+ register int size, nfiles;
+ register char *cp;
+
+ ack();
+ nfiles = 0;
+ for (;;) {
+ /*
+ * Read a command to tell us what to do
+ */
+ cp = line;
+ do {
+ if ((size = read(1, cp, 1)) != 1) {
+ if (size < 0)
+ frecverr("%s: Lost connection",printer);
+ return(nfiles);
+ }
+ } while (*cp++ != '\n');
+ *--cp = '\0';
+ cp = line;
+ switch (*cp++) {
+ case '\1': /* cleanup because data sent was bad */
+ rcleanup(0);
+ continue;
+
+ case '\2': /* read cf file */
+ size = 0;
+ while (*cp >= '0' && *cp <= '9')
+ size = size * 10 + (*cp++ - '0');
+ if (*cp++ != ' ')
+ break;
+ /*
+ * host name has been authenticated, we use our
+ * view of the host name since we may be passed
+ * something different than what gethostbyaddr()
+ * returns
+ */
+ strcpy(cp + 6, from);
+ strcpy(tfname, cp);
+ tfname[0] = 't';
+ if (!chksize(size)) {
+ (void) write(1, "\2", 1);
+ continue;
+ }
+ if (!readfile(tfname, size)) {
+ rcleanup(0);
+ continue;
+ }
+ if (link(tfname, cp) < 0)
+ frecverr("%s: %m", tfname);
+ (void) unlink(tfname);
+ tfname[0] = '\0';
+ nfiles++;
+ continue;
+
+ case '\3': /* read df file */
+ size = 0;
+ while (*cp >= '0' && *cp <= '9')
+ size = size * 10 + (*cp++ - '0');
+ if (*cp++ != ' ')
+ break;
+ if (!chksize(size)) {
+ (void) write(1, "\2", 1);
+ continue;
+ }
+ (void) strcpy(dfname, cp);
+ if (index(dfname, '/'))
+ frecverr("readjob: %s: illegal path name",
+ dfname);
+ (void) readfile(dfname, size);
+ continue;
+ }
+ frecverr("protocol screwup: %s", line);
+ }
+}
+
+/*
+ * Read files send by lpd and copy them to the spooling directory.
+ */
+static int
+readfile(file, size)
+ char *file;
+ int size;
+{
+ register char *cp;
+ char buf[BUFSIZ];
+ register int i, j, amt;
+ int fd, err;
+
+ fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
+ if (fd < 0)
+ frecverr("readfile: %s: illegal path name: %m", file);
+ ack();
+ err = 0;
+ for (i = 0; i < size; i += BUFSIZ) {
+ amt = BUFSIZ;
+ cp = buf;
+ if (i + amt > size)
+ amt = size - i;
+ do {
+ j = read(1, cp, amt);
+ if (j <= 0)
+ frecverr("Lost connection");
+ amt -= j;
+ cp += j;
+ } while (amt > 0);
+ amt = BUFSIZ;
+ if (i + amt > size)
+ amt = size - i;
+ if (write(fd, buf, amt) != amt) {
+ err++;
+ break;
+ }
+ }
+ (void) close(fd);
+ if (err)
+ frecverr("%s: write error", file);
+ if (noresponse()) { /* file sent had bad data in it */
+ (void) unlink(file);
+ return(0);
+ }
+ ack();
+ return(1);
+}
+
+static int
+noresponse()
+{
+ char resp;
+
+ if (read(1, &resp, 1) != 1)
+ frecverr("Lost connection");
+ if (resp == '\0')
+ return(0);
+ return(1);
+}
+
+/*
+ * Check to see if there is enough space on the disk for size bytes.
+ * 1 == OK, 0 == Not OK.
+ */
+static int
+chksize(size)
+ int size;
+{
+ int spacefree;
+ struct statfs sfb;
+
+ if (statfs(".", &sfb) < 0) {
+ syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
+ return (1);
+ }
+ spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
+ size = (size + 511) / 512;
+ if (minfree + size > spacefree)
+ return(0);
+ return(1);
+}
+
+static int
+read_number(fn)
+ char *fn;
+{
+ char lin[80];
+ register FILE *fp;
+
+ if ((fp = fopen(fn, "r")) == NULL)
+ return (0);
+ if (fgets(lin, 80, fp) == NULL) {
+ fclose(fp);
+ return (0);
+ }
+ fclose(fp);
+ return (atoi(lin));
+}
+
+/*
+ * Remove all the files associated with the current job being transfered.
+ */
+static void
+rcleanup(signo)
+ int signo;
+{
+ if (tfname[0])
+ (void) unlink(tfname);
+ if (dfname[0])
+ do {
+ do
+ (void) unlink(dfname);
+ while (dfname[2]-- != 'A');
+ dfname[2] = 'z';
+ } while (dfname[0]-- != 'd');
+ dfname[0] = '\0';
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+static void
+#if __STDC__
+frecverr(const char *msg, ...)
+#else
+frecverr(msg, va_alist)
+ char *msg;
+ va_dcl
+#endif
+{
+ extern char *fromb;
+ va_list ap;
+#if __STDC__
+ va_start(ap, msg);
+#else
+ va_start(ap);
+#endif
+ rcleanup(0);
+ syslog(LOG_ERR, "%s", fromb);
+ vsyslog(LOG_ERR, msg, ap);
+ va_end(ap);
+ putchar('\1'); /* return error code */
+ exit(1);
+}
diff --git a/usr.sbin/lpr/lpq/Makefile b/usr.sbin/lpr/lpq/Makefile
new file mode 100644
index 0000000..1c730c1
--- /dev/null
+++ b/usr.sbin/lpr/lpq/Makefile
@@ -0,0 +1,12 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lpq
+CFLAGS+=-I${.CURDIR}/../common_source
+SRCS= lpq.c displayq.c common.c
+BINOWN= root
+BINGRP= daemon
+BINMODE=6555
+BINDIR= /usr/bin
+.PATH: ${.CURDIR}/../common_source
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpq/lpq.1 b/usr.sbin/lpr/lpq/lpq.1
new file mode 100644
index 0000000..50e1474
--- /dev/null
+++ b/usr.sbin/lpr/lpq/lpq.1
@@ -0,0 +1,134 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)lpq.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt LPQ 1
+.Os BSD 4.2
+.Sh NAME
+.Nm lpq
+.Nd spool queue examination program
+.Sh SYNOPSIS
+.Nm lpq
+.Op Fl l
+.Op Fl P Ns Ar printer
+.Op job # ...
+.Op user ...
+.Sh DESCRIPTION
+.Nm Lpq
+examines the spooling area used by
+.Xr lpd 8
+for printing files on the line printer, and reports the status of the
+specified jobs or all jobs associated with a user.
+.Nm Lpq
+invoked
+without any arguments reports on any jobs currently in the queue.
+.Pp
+Options:
+.Pp
+.Bl -tag -width indent
+.It Fl P
+Specify a particular printer, otherwise the default
+line printer is used (or the value of the
+.Ev PRINTER
+variable in the
+environment). All other arguments supplied are interpreted as user
+names or job numbers to filter out only those jobs of interest.
+.It Fl l
+Information about each of the files comprising the job entry
+is printed.
+Normally, only as much information as will fit on one line is displayed.
+.El
+.Pp
+For each job submitted (i.e. invocation of
+.Xr lpr 1 )
+.Nm lpq
+reports the user's name, current rank in the queue, the
+names of files comprising the job, the job identifier (a number which
+may be supplied to
+.Xr lprm 1
+for removing a specific job), and the total size in bytes.
+Job ordering is dependent on
+the algorithm used to scan the spooling directory and is supposed
+to be
+.Tn FIFO
+(First in First Out).
+File names comprising a job may be unavailable
+(when
+.Xr lpr 1
+is used as a sink in a pipeline) in which case the file
+is indicated as ``(standard input)''.
+.Pp
+If
+.Nm lpq
+warns that there is no daemon present (i.e. due to some malfunction),
+the
+.Xr lpc 8
+command can be used to restart the printer daemon.
+.Sh ENVIRONMENT
+If the following environment variable exists, it is used by
+.Nm lpq :
+.Bl -tag -width PRINTER
+.It Ev PRINTER
+Specifies an alternate default printer.
+.El
+.Sh FILES
+.Bl -tag -width /usr/share/misc/termcap -compact
+.It Pa /etc/printcap
+To determine printer characteristics.
+.It Pa /var/spool/*
+The spooling directory, as determined from printcap.
+.It Pa /var/spool/*/cf*
+Control files specifying jobs.
+.It Pa /var/spool/*/lock
+The lock file to obtain the currently active job.
+.It Pa /usr/share/misc/termcap
+For manipulating the screen for repeated display.
+.El
+.Sh SEE ALSO
+.Xr lpr 1 ,
+.Xr lprm 1 ,
+.Xr lpc 8 ,
+.Xr lpd 8
+.Sh HISTORY
+.Nm Lpq
+appeared in
+.Bx 3 .
+.Sh BUGS
+Due to the dynamic nature of the information in the spooling directory
+.Nm lpq
+may report unreliably.
+Output formatting is sensitive to the line length of the terminal;
+this can results in widely spaced columns.
+.Sh DIAGNOSTICS
+Unable to open various files. The lock file being malformed. Garbage
+files when there is no daemon active, but files in the spooling directory.
diff --git a/usr.sbin/lpr/lpq/lpq.c b/usr.sbin/lpr/lpq/lpq.c
new file mode 100644
index 0000000..b091e8e
--- /dev/null
+++ b/usr.sbin/lpr/lpq/lpq.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpq.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Spool Queue examination program
+ *
+ * lpq [-l] [-Pprinter] [user...] [job...]
+ *
+ * -l long output
+ * -P used to identify printer as per lpr/lprm
+ */
+
+#include <sys/param.h>
+
+#include <syslog.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "lp.h"
+#include "lp.local.h"
+
+int requ[MAXREQUESTS]; /* job number of spool entries */
+int requests; /* # of spool requests */
+char *user[MAXUSERS]; /* users to process */
+int users; /* # of users in user array */
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ register int argc;
+ register char **argv;
+{
+ extern char *optarg;
+ extern int optind;
+ int ch, lflag; /* long output option */
+
+ name = *argv;
+ if (gethostname(host, sizeof(host))) {
+ perror("lpq: gethostname");
+ exit(1);
+ }
+ openlog("lpd", 0, LOG_LPR);
+
+ lflag = 0;
+ while ((ch = getopt(argc, argv, "lP:")) != EOF)
+ switch((char)ch) {
+ case 'l': /* long output */
+ ++lflag;
+ break;
+ case 'P': /* printer name */
+ printer = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
+ printer = DEFLP;
+
+ for (argc -= optind, argv += optind; argc; --argc, ++argv)
+ if (isdigit(argv[0][0])) {
+ if (requests >= MAXREQUESTS)
+ fatal("too many requests");
+ requ[requests++] = atoi(*argv);
+ }
+ else {
+ if (users >= MAXUSERS)
+ fatal("too many users");
+ user[users++] = *argv;
+ }
+
+ displayq(lflag);
+ exit(0);
+}
+
+void
+usage()
+{
+ puts("usage: lpq [-l] [-Pprinter] [user ...] [job ...]");
+ exit(1);
+}
diff --git a/usr.sbin/lpr/lpr/Makefile b/usr.sbin/lpr/lpr/Makefile
new file mode 100644
index 0000000..9a3cbfd
--- /dev/null
+++ b/usr.sbin/lpr/lpr/Makefile
@@ -0,0 +1,12 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lpr
+CFLAGS+=-I${.CURDIR}/../common_source
+SRCS= lpr.c startdaemon.c common.c
+BINOWN= root
+BINGRP= daemon
+BINMODE=6555
+BINDIR= /usr/bin
+.PATH: ${.CURDIR}/../common_source
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpr/lpr.1 b/usr.sbin/lpr/lpr/lpr.1
new file mode 100644
index 0000000..382d508
--- /dev/null
+++ b/usr.sbin/lpr/lpr/lpr.1
@@ -0,0 +1,256 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\" @(#)lpr.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt LPR 1
+.Os BSD 4
+.Sh NAME
+.Nm lpr
+.Nd off line print
+.Sh SYNOPSIS
+.Nm lpr
+.Op Fl P Ns Ar printer
+.Op Fl \&# Ns Ar num
+.Op Fl C Ar class
+.Op Fl J Ar job
+.Op Fl T Ar title
+.Op Fl U Ar user
+.Op Fl i Op Ar numcols
+.Op Fl 1234 Ar font
+.Op Fl w Ns Ar num
+.Op Fl cdfghlnmprstv
+.Op Ar name ...
+.Sh DESCRIPTION
+.Nm Lpr
+uses a spooling daemon to print the named files when facilities
+become available. If no names appear, the standard input is assumed.
+.Pp
+The following single letter options are used to notify the line printer
+spooler that the files are not standard text files. The spooling daemon will
+use the appropriate filters to print the data accordingly.
+.Bl -tag -width indent
+.It Fl c
+The files are assumed to contain data produced by
+.Xr cifplot 1
+.It Fl d
+The files are assumed to contain data from
+.Em tex
+.Pf ( Tn DVI
+format from Stanford).
+.It Fl f
+Use a filter which interprets the first character of each line as a
+standard
+.Tn FORTRAN
+carriage control character.
+.It Fl g
+The files are assumed to contain standard plot data as produced by the
+.Xr plot
+routines (see also
+.Xr plot
+for the filters used by the printer spooler).
+.It Fl l
+Use a filter which allows control characters to be printed and suppresses
+page breaks.
+.It Fl n
+The files are assumed to contain data from
+.Em ditroff
+(device independent troff).
+.It Fl p
+Use
+.Xr pr 1
+to format the files (equivalent to
+.Xr print ) .
+.It Fl t
+The files are assumed to contain data from
+.Xr troff 1
+(cat phototypesetter commands).
+.It Fl v
+The files are assumed to contain a raster image for devices like the
+Benson Varian.
+.El
+.Pp
+These options apply to the handling of
+the print job:
+.Bl -tag -width indent
+.It Fl P
+Force output to a specific printer. Normally,
+the default printer is used (site dependent), or the value of the
+environment variable
+.Ev PRINTER
+is used.
+.It Fl h
+Suppress the printing of the burst page.
+.It Fl m
+Send mail upon completion.
+.It Fl r
+Remove the file upon completion of spooling or upon completion of
+printing (with the
+.Fl s
+option).
+.It Fl s
+Use symbolic links. Usually files are copied to the spool directory.
+The
+.Fl s
+option will use
+.Xr symlink 2
+to link data files rather than trying to copy them so large files can be
+printed. This means the files should
+not be modified or removed until they have been printed.
+.El
+.Pp
+The remaining options apply to copies, the page display, and headers:
+.Bl -tag -width indent
+.It Fl \&# Ns Ar num
+The quantity
+.Ar num
+is the number of copies desired of each file named. For example,
+.Bd -literal -offset indent
+lpr \-#3 foo.c bar.c more.c
+.Ed
+would result in 3 copies of the file foo.c, followed by 3 copies
+of the file bar.c, etc. On the other hand,
+.Bd -literal -offset indent
+cat foo.c bar.c more.c \&| lpr \-#3
+.Ed
+.Pp
+will give three copies of the concatenation of the files. Often
+a site will disable this feature to encourage use of a photocopier
+instead.
+.It Xo
+.Fl Ns Oo Cm 1234 Oc Ar font
+.Xc
+Specifies a
+.Ar font
+to be mounted on font position
+.Ar i .
+The daemon
+will construct a
+.Li .railmag
+file referencing
+the font pathname.
+.It Fl C Ar class
+Job classification
+to use on the burst page. For example,
+.Bd -literal -offset indent
+lpr \-C EECS foo.c
+.Ed
+.Pp
+causes the system name (the name returned by
+.Xr hostname 1 )
+to be replaced on the burst page by
+.Tn EECS ,
+and the file foo.c to be printed.
+.It Fl J Ar job
+Job name to print on the burst page.
+Normally, the first file's name is used.
+.It Fl T Ar title
+Title name for
+.Xr pr 1 ,
+instead of the file name.
+.It Fl U Ar user
+User name to print on the burst page,
+also for accounting purposes.
+This option is only honored if the real user-id is daemon
+(or that specified in the printcap file instead of daemon),
+and is intended for those instances where print filters wish to requeue jobs.
+.It Fl i Op numcols
+The output is indented. If the next argument
+is numeric
+.Pq Ar numcols ,
+it is used as the number of blanks to be printed before each
+line; otherwise, 8 characters are printed.
+.It Fl w Ns Ar num
+Uses
+.Ar num
+as the page width for
+.Xr pr 1 .
+.El
+.Sh ENVIRONMENT
+If the following environment variable exists, it is used by
+.Nm lpr :
+.Bl -tag -width PRINTER
+.It Ev PRINTER
+Specifies an alternate default printer.
+.El
+.Sh FILES
+.Bl -tag -width /var/spool/output/*/tf* -compact
+.It Pa /etc/passwd
+Personal identification.
+.It Pa /etc/printcap
+Printer capabilities data base.
+.It Pa /usr/sbin/lpd*
+Line printer daemons.
+.It Pa /var/spool/output/*
+Directories used for spooling.
+.It Pa /var/spool/output/*/cf*
+Daemon control files.
+.It Pa /var/spool/output/*/df*
+Data files specified in "cf" files.
+.It Pa /var/spool/output/*/tf*
+Temporary copies of "cf" files.
+.El
+.Sh SEE ALSO
+.Xr lpq 1 ,
+.Xr lprm 1 ,
+.Xr pr 1 ,
+.Xr symlink 2 ,
+.Xr printcap 5 ,
+.Xr lpc 8 ,
+.Xr lpd 8
+.Sh HISTORY
+The
+.Nm lpr
+command appeared in
+.Bx 3 .
+.Sh DIAGNOSTICS
+If you try to spool too large a file, it will be truncated.
+.Nm Lpr
+will object to printing binary files.
+If a user other than root prints a file and spooling is disabled,
+.Nm lpr
+will print a message saying so and will not put jobs in the queue.
+If a connection to
+.Xr lpd 1
+on the local machine cannot be made,
+.Nm lpr
+will say that the daemon cannot be started.
+Diagnostics may be printed in the daemon's log file
+regarding missing spool files by
+.Xr lpd 1 .
+.Sh BUGS
+Fonts for
+.Xr troff 1
+and
+.Xr tex
+reside on the host with the printer. It is currently not possible to
+use local font libraries.
diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c
new file mode 100644
index 0000000..8e9c45f
--- /dev/null
+++ b/usr.sbin/lpr/lpr/lpr.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpr.c 8.3 (Berkeley) 3/30/94";
+#endif /* not lint */
+
+/*
+ * lpr -- off line print
+ *
+ * Allows multiple printers and printers on remote machines by
+ * using information from a printer data base.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <signal.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+
+static char *cfname; /* daemon control files, linked from tf's */
+static char *class = host; /* class title on header page */
+static char *dfname; /* data files */
+static char *fonts[4]; /* troff font names */
+static char format = 'f'; /* format char for printing files */
+static int hdr = 1; /* print header or not (default is yes) */
+static int iflag; /* indentation wanted */
+static int inchar; /* location to increment char in file names */
+static int indent; /* amount to indent */
+static char *jobname; /* job name on header page */
+static int mailflg; /* send mail */
+static int nact; /* number of jobs to act on */
+static int ncopies = 1; /* # of copies to make */
+static char *person; /* user name */
+static int qflag; /* q job, but don't exec daemon */
+static int rflag; /* remove files upon completion */
+static int sflag; /* symbolic link flag */
+static int tfd; /* control file descriptor */
+static char *tfname; /* tmp copy of cf before linking */
+static char *title; /* pr'ing title */
+static int userid; /* user id */
+static char *width; /* width for versatec printing */
+
+static struct stat statb;
+
+static void card __P((int, char *));
+static void chkprinter __P((char *));
+static void cleanup __P((int));
+static void copy __P((int, char []));
+static void fatal2 __P((const char *, ...));
+static char *itoa __P((int));
+static char *linked __P((char *));
+static char *lmktemp __P((char *, int, int));
+static void mktemps __P((void));
+static int nfile __P((char *));
+static int test __P((char *));
+
+void
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct passwd *pw;
+ struct group *gptr;
+ extern char *itoa();
+ register char *arg, *cp;
+ char buf[BUFSIZ];
+ int i, f;
+ struct stat stb;
+
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+ signal(SIGHUP, cleanup);
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, cleanup);
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+ signal(SIGQUIT, cleanup);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+ signal(SIGTERM, cleanup);
+
+ name = argv[0];
+ gethostname(host, sizeof (host));
+ openlog("lpd", 0, LOG_LPR);
+
+ while (argc > 1 && argv[1][0] == '-') {
+ argc--;
+ arg = *++argv;
+ switch (arg[1]) {
+
+ case 'P': /* specifiy printer name */
+ if (arg[2])
+ printer = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ printer = *++argv;
+ }
+ break;
+
+ case 'C': /* classification spec */
+ hdr++;
+ if (arg[2])
+ class = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ class = *++argv;
+ }
+ break;
+
+ case 'U': /* user name */
+ hdr++;
+ if (arg[2])
+ person = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ person = *++argv;
+ }
+ break;
+
+ case 'J': /* job name */
+ hdr++;
+ if (arg[2])
+ jobname = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ jobname = *++argv;
+ }
+ break;
+
+ case 'T': /* pr's title line */
+ if (arg[2])
+ title = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ title = *++argv;
+ }
+ break;
+
+ case 'l': /* literal output */
+ case 'p': /* print using ``pr'' */
+ case 't': /* print troff output (cat files) */
+ case 'n': /* print ditroff output */
+ case 'd': /* print tex output (dvi files) */
+ case 'g': /* print graph(1G) output */
+ case 'c': /* print cifplot output */
+ case 'v': /* print vplot output */
+ format = arg[1];
+ break;
+
+ case 'f': /* print fortran output */
+ format = 'r';
+ break;
+
+ case '4': /* troff fonts */
+ case '3':
+ case '2':
+ case '1':
+ if (argc > 1) {
+ argc--;
+ fonts[arg[1] - '1'] = *++argv;
+ }
+ break;
+
+ case 'w': /* versatec page width */
+ width = arg+2;
+ break;
+
+ case 'r': /* remove file when done */
+ rflag++;
+ break;
+
+ case 'm': /* send mail when done */
+ mailflg++;
+ break;
+
+ case 'h': /* toggle want of header page */
+ hdr = !hdr;
+ break;
+
+ case 's': /* try to link files */
+ sflag++;
+ break;
+
+ case 'q': /* just q job */
+ qflag++;
+ break;
+
+ case 'i': /* indent output */
+ iflag++;
+ indent = arg[2] ? atoi(&arg[2]) : 8;
+ break;
+
+ case '#': /* n copies */
+ if (isdigit(arg[2])) {
+ i = atoi(&arg[2]);
+ if (i > 0)
+ ncopies = i;
+ }
+ }
+ }
+ if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
+ printer = DEFLP;
+ chkprinter(printer);
+ if (SC && ncopies > 1)
+ fatal2("multiple copies are not allowed");
+ if (MC > 0 && ncopies > MC)
+ fatal2("only %d copies are allowed", MC);
+ /*
+ * Get the identity of the person doing the lpr using the same
+ * algorithm as lprm.
+ */
+ userid = getuid();
+ if (userid != DU || person == 0) {
+ if ((pw = getpwuid(userid)) == NULL)
+ fatal2("Who are you?");
+ person = pw->pw_name;
+ }
+ /*
+ * Check for restricted group access.
+ */
+ if (RG != NULL && userid != DU) {
+ if ((gptr = getgrnam(RG)) == NULL)
+ fatal2("Restricted group specified incorrectly");
+ if (gptr->gr_gid != getgid()) {
+ while (*gptr->gr_mem != NULL) {
+ if ((strcmp(person, *gptr->gr_mem)) == 0)
+ break;
+ gptr->gr_mem++;
+ }
+ if (*gptr->gr_mem == NULL)
+ fatal2("Not a member of the restricted group");
+ }
+ }
+ /*
+ * Check to make sure queuing is enabled if userid is not root.
+ */
+ (void) sprintf(buf, "%s/%s", SD, LO);
+ if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
+ fatal2("Printer queue is disabled");
+ /*
+ * Initialize the control file.
+ */
+ mktemps();
+ tfd = nfile(tfname);
+ (void) fchown(tfd, DU, -1); /* owned by daemon for protection */
+ card('H', host);
+ card('P', person);
+ if (hdr) {
+ if (jobname == NULL) {
+ if (argc == 1)
+ jobname = "stdin";
+ else
+ jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1];
+ }
+ card('J', jobname);
+ card('C', class);
+ card('L', person);
+ }
+ if (iflag)
+ card('I', itoa(indent));
+ if (mailflg)
+ card('M', person);
+ if (format == 't' || format == 'n' || format == 'd')
+ for (i = 0; i < 4; i++)
+ if (fonts[i] != NULL)
+ card('1'+i, fonts[i]);
+ if (width != NULL)
+ card('W', width);
+
+ /*
+ * Read the files and spool them.
+ */
+ if (argc == 1)
+ copy(0, " ");
+ else while (--argc) {
+ if ((f = test(arg = *++argv)) < 0)
+ continue; /* file unreasonable */
+
+ if (sflag && (cp = linked(arg)) != NULL) {
+ (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino);
+ card('S', buf);
+ if (format == 'p')
+ card('T', title ? title : arg);
+ for (i = 0; i < ncopies; i++)
+ card(format, &dfname[inchar-2]);
+ card('U', &dfname[inchar-2]);
+ if (f)
+ card('U', cp);
+ card('N', arg);
+ dfname[inchar]++;
+ nact++;
+ continue;
+ }
+ if (sflag)
+ printf("%s: %s: not linked, copying instead\n", name, arg);
+ if ((i = open(arg, O_RDONLY)) < 0) {
+ printf("%s: cannot open %s\n", name, arg);
+ continue;
+ }
+ copy(i, arg);
+ (void) close(i);
+ if (f && unlink(arg) < 0)
+ printf("%s: %s: not removed\n", name, arg);
+ }
+
+ if (nact) {
+ (void) close(tfd);
+ tfname[inchar]--;
+ /*
+ * Touch the control file to fix position in the queue.
+ */
+ if ((tfd = open(tfname, O_RDWR)) >= 0) {
+ char c;
+
+ if (read(tfd, &c, 1) == 1 &&
+ lseek(tfd, (off_t)0, 0) == 0 &&
+ write(tfd, &c, 1) != 1) {
+ printf("%s: cannot touch %s\n", name, tfname);
+ tfname[inchar]++;
+ cleanup(0);
+ }
+ (void) close(tfd);
+ }
+ if (link(tfname, cfname) < 0) {
+ printf("%s: cannot rename %s\n", name, cfname);
+ tfname[inchar]++;
+ cleanup(0);
+ }
+ unlink(tfname);
+ if (qflag) /* just q things up */
+ exit(0);
+ if (!startdaemon(printer))
+ printf("jobs queued, but cannot start daemon.\n");
+ exit(0);
+ }
+ cleanup(0);
+ /* NOTREACHED */
+}
+
+/*
+ * Create the file n and copy from file descriptor f.
+ */
+static void
+copy(f, n)
+ int f;
+ char n[];
+{
+ register int fd, i, nr, nc;
+ char buf[BUFSIZ];
+
+ if (format == 'p')
+ card('T', title ? title : n);
+ for (i = 0; i < ncopies; i++)
+ card(format, &dfname[inchar-2]);
+ card('U', &dfname[inchar-2]);
+ card('N', n);
+ fd = nfile(dfname);
+ nr = nc = 0;
+ while ((i = read(f, buf, BUFSIZ)) > 0) {
+ if (write(fd, buf, i) != i) {
+ printf("%s: %s: temp file write error\n", name, n);
+ break;
+ }
+ nc += i;
+ if (nc >= BUFSIZ) {
+ nc -= BUFSIZ;
+ nr++;
+ if (MX > 0 && nr > MX) {
+ printf("%s: %s: copy file is too large\n", name, n);
+ break;
+ }
+ }
+ }
+ (void) close(fd);
+ if (nc==0 && nr==0)
+ printf("%s: %s: empty input file\n", name, f ? n : "stdin");
+ else
+ nact++;
+}
+
+/*
+ * Try and link the file to dfname. Return a pointer to the full
+ * path name if successful.
+ */
+static char *
+linked(file)
+ register char *file;
+{
+ register char *cp;
+ static char buf[BUFSIZ];
+
+ if (*file != '/') {
+ if (getwd(buf) == NULL)
+ return(NULL);
+ while (file[0] == '.') {
+ switch (file[1]) {
+ case '/':
+ file += 2;
+ continue;
+ case '.':
+ if (file[2] == '/') {
+ if ((cp = rindex(buf, '/')) != NULL)
+ *cp = '\0';
+ file += 3;
+ continue;
+ }
+ }
+ break;
+ }
+ strcat(buf, "/");
+ strcat(buf, file);
+ file = buf;
+ }
+ return(symlink(file, dfname) ? NULL : file);
+}
+
+/*
+ * Put a line into the control file.
+ */
+static void
+card(c, p2)
+ register int c;
+ register char *p2;
+{
+ char buf[BUFSIZ];
+ register char *p1 = buf;
+ register int len = 2;
+
+ *p1++ = c;
+ while ((c = *p2++) != '\0') {
+ *p1++ = (c == '\n') ? ' ' : c;
+ len++;
+ }
+ *p1++ = '\n';
+ write(tfd, buf, len);
+}
+
+/*
+ * Create a new file in the spool directory.
+ */
+static int
+nfile(n)
+ char *n;
+{
+ register int f;
+ int oldumask = umask(0); /* should block signals */
+
+ f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD);
+ (void) umask(oldumask);
+ if (f < 0) {
+ printf("%s: cannot create %s\n", name, n);
+ cleanup(0);
+ }
+ if (fchown(f, userid, -1) < 0) {
+ printf("%s: cannot chown %s\n", name, n);
+ cleanup(0);
+ }
+ if (++n[inchar] > 'z') {
+ if (++n[inchar-2] == 't') {
+ printf("too many files - break up the job\n");
+ cleanup(0);
+ }
+ n[inchar] = 'A';
+ } else if (n[inchar] == '[')
+ n[inchar] = 'a';
+ return(f);
+}
+
+/*
+ * Cleanup after interrupts and errors.
+ */
+static void
+cleanup(signo)
+ int signo;
+{
+ register i;
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ i = inchar;
+ if (tfname)
+ do
+ unlink(tfname);
+ while (tfname[i]-- != 'A');
+ if (cfname)
+ do
+ unlink(cfname);
+ while (cfname[i]-- != 'A');
+ if (dfname)
+ do {
+ do
+ unlink(dfname);
+ while (dfname[i]-- != 'A');
+ dfname[i] = 'z';
+ } while (dfname[i-2]-- != 'd');
+ exit(1);
+}
+
+/*
+ * Test to see if this is a printable file.
+ * Return -1 if it is not, 0 if its printable, and 1 if
+ * we should remove it after printing.
+ */
+static int
+test(file)
+ char *file;
+{
+ struct exec execb;
+ register int fd;
+ register char *cp;
+
+ if (access(file, 4) < 0) {
+ printf("%s: cannot access %s\n", name, file);
+ return(-1);
+ }
+ if (stat(file, &statb) < 0) {
+ printf("%s: cannot stat %s\n", name, file);
+ return(-1);
+ }
+ if ((statb.st_mode & S_IFMT) == S_IFDIR) {
+ printf("%s: %s is a directory\n", name, file);
+ return(-1);
+ }
+ if (statb.st_size == 0) {
+ printf("%s: %s is an empty file\n", name, file);
+ return(-1);
+ }
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ printf("%s: cannot open %s\n", name, file);
+ return(-1);
+ }
+ if (read(fd, &execb, sizeof(execb)) == sizeof(execb) &&
+ !N_BADMAG(execb)) {
+ printf("%s: %s is an executable program", name, file);
+ goto error1;
+ }
+ (void) close(fd);
+ if (rflag) {
+ if ((cp = rindex(file, '/')) == NULL) {
+ if (access(".", 2) == 0)
+ return(1);
+ } else {
+ if (cp == file) {
+ fd = access("/", 2);
+ } else {
+ *cp = '\0';
+ fd = access(file, 2);
+ *cp = '/';
+ }
+ if (fd == 0)
+ return(1);
+ }
+ printf("%s: %s: is not removable by you\n", name, file);
+ }
+ return(0);
+
+error1:
+ printf(" and is unprintable\n");
+ (void) close(fd);
+ return(-1);
+}
+
+/*
+ * itoa - integer to string conversion
+ */
+static char *
+itoa(i)
+ register int i;
+{
+ static char b[10] = "########";
+ register char *p;
+
+ p = &b[8];
+ do
+ *p-- = i%10 + '0';
+ while (i /= 10);
+ return(++p);
+}
+
+/*
+ * Perform lookup for printer name or abbreviation --
+ */
+static void
+chkprinter(s)
+ char *s;
+{
+ int status;
+
+ if ((status = cgetent(&bp, printcapdb, s)) == -2)
+ fatal2("cannot open printer description file");
+ else if (status == -1)
+ fatal2("%s: unknown printer", s);
+ if (cgetstr(bp, "sd", &SD) == -1)
+ SD = _PATH_DEFSPOOL;
+ if (cgetstr(bp, "lo", &LO) == -1)
+ LO = DEFLOCK;
+ cgetstr(bp, "rg", &RG);
+ if (cgetnum(bp, "mx", &MX) < 0)
+ MX = DEFMX;
+ if (cgetnum(bp,"mc", &MC) < 0)
+ MC = DEFMAXCOPIES;
+ if (cgetnum(bp, "du", &DU) < 0)
+ DU = DEFUID;
+ SC = (cgetcap(bp, "sc", ':') != NULL);
+}
+
+/*
+ * Make the temp files.
+ */
+static void
+mktemps()
+{
+ register int len, fd, n;
+ register char *cp;
+ char buf[BUFSIZ];
+ char *lmktemp();
+
+ (void) sprintf(buf, "%s/.seq", SD);
+ if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
+ printf("%s: cannot create %s\n", name, buf);
+ exit(1);
+ }
+ if (flock(fd, LOCK_EX)) {
+ printf("%s: cannot lock %s\n", name, buf);
+ exit(1);
+ }
+ n = 0;
+ if ((len = read(fd, buf, sizeof(buf))) > 0) {
+ for (cp = buf; len--; ) {
+ if (*cp < '0' || *cp > '9')
+ break;
+ n = n * 10 + (*cp++ - '0');
+ }
+ }
+ len = strlen(SD) + strlen(host) + 8;
+ tfname = lmktemp("tf", n, len);
+ cfname = lmktemp("cf", n, len);
+ dfname = lmktemp("df", n, len);
+ inchar = strlen(SD) + 3;
+ n = (n + 1) % 1000;
+ (void) lseek(fd, (off_t)0, 0);
+ sprintf(buf, "%03d\n", n);
+ (void) write(fd, buf, strlen(buf));
+ (void) close(fd); /* unlocks as well */
+}
+
+/*
+ * Make a temp file name.
+ */
+static char *
+lmktemp(id, num, len)
+ char *id;
+ int num, len;
+{
+ register char *s;
+
+ if ((s = malloc(len)) == NULL)
+ fatal2("out of memory");
+ (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host);
+ return(s);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+static void
+#if __STDC__
+fatal2(const char *msg, ...)
+#else
+fatal2(msg, va_alist)
+ char *msg;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, msg);
+#else
+ va_start(ap);
+#endif
+ printf("%s: ", name);
+ vprintf(msg, ap);
+ putchar('\n');
+ va_end(ap);
+ exit(1);
+}
diff --git a/usr.sbin/lpr/lprm/Makefile b/usr.sbin/lpr/lprm/Makefile
new file mode 100644
index 0000000..d1362f5
--- /dev/null
+++ b/usr.sbin/lpr/lprm/Makefile
@@ -0,0 +1,12 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lprm
+CFLAGS+=-I${.CURDIR}/../common_source
+SRCS= lprm.c rmjob.c startdaemon.c common.c
+BINOWN= root
+BINGRP= daemon
+BINMODE=6555
+BINDIR= /usr/bin
+.PATH: ${.CURDIR}/../common_source
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lprm/lprm.1 b/usr.sbin/lpr/lprm/lprm.1
new file mode 100644
index 0000000..22309d1
--- /dev/null
+++ b/usr.sbin/lpr/lprm/lprm.1
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)lprm.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt LPRM 1
+.Os BSD 4.2
+.Sh NAME
+.Nm lprm
+.Nd remove jobs from the line printer spooling queue
+.Sh SYNOPSIS
+.Nm lprm
+.Op Fl P Ns Ar printer
+.Op Fl
+.Op job # ...
+.Op Ar user ...
+.Sh DESCRIPTION
+.Nm Lprm
+will remove a job, or jobs, from a printer's spool queue.
+Since the spooling directory is protected from users, using
+.Nm lprm
+is normally the only method by which a user may remove a job.
+The owner of a job is determined by the user's login name
+and host name on the machine where the
+.Xr lpr 1
+command was invoked.
+.Pp
+Options and arguments:
+.Bl -tag -width indent
+.It Fl P Ns Ar printer
+Specify the queue associated with a specific
+.Ar printer
+(otherwise the default printer is used).
+.It Fl
+If a single
+.Sq Fl
+is given,
+.Nm lprm
+will remove all jobs which a user
+owns. If the super-user employs this flag, the spool queue will
+be emptied entirely.
+.It Ar user
+Causes
+.Nm lprm
+to attempt to remove any jobs queued belonging to that user
+(or users). This form of invoking
+.Nm lprm
+is useful only to the super-user.
+.It Ar job\ \&#
+A user may dequeue an individual job by specifying its job number.
+This number may be obtained from the
+.Xr lpq 1
+program, e.g.
+.Pp
+.Bd -literal -offset indent
+\&% lpq \-l
+
+1st:ken [job #013ucbarpa]
+ (standard input) 100 bytes
+% lprm 13
+.Ed
+.El
+.Pp
+If neither arguments or options are given,
+.Nm Lprm
+will delete the currently active job if it is
+owned by the user who invoked
+.Nm lprm .
+.Pp
+.Nm Lprm
+announces the names of any files it removes and is silent if
+there are no jobs in the queue which match the request list.
+.Pp
+.Nm Lprm
+will kill off an active daemon, if necessary, before removing
+any spooling files. If a daemon is killed, a new one is
+automatically restarted upon completion of file removals.
+.Sh ENVIRONMENT
+If the following environment variable exists, it is utilized by
+.Nm lprm .
+.Bl -tag -width PRINTER
+.It Ev PRINTER
+If the environment variable
+.Ev PRINTER
+exists,
+and a printer has not been specified with the
+.Fl P
+option,
+the default printer is assumed from
+.Ev PRINTER .
+.El
+.Sh FILES
+.Bl -tag -width /var/spool/*/lock/ -compact
+.It Pa /etc/printcap
+Printer characteristics file.
+.It Pa /var/spool/*
+Spooling directories.
+.It Pa /var/spool/*/lock
+Lock file used to obtain the pid of the current
+daemon and the job number of the currently active job.
+.El
+.Sh SEE ALSO
+.Xr lpr 1 ,
+.Xr lpq 1 ,
+.Xr lpd 8
+.Sh DIAGNOSTICS
+``Permission denied" if the user tries to remove files other than his
+own.
+.Sh BUGS
+Since there are race conditions possible in the update of the lock file,
+the currently active job may be incorrectly identified.
+.Sh HISTORY
+The
+.Nm lprm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.sbin/lpr/lprm/lprm.c b/usr.sbin/lpr/lprm/lprm.c
new file mode 100644
index 0000000..20c4ee7
--- /dev/null
+++ b/usr.sbin/lpr/lprm/lprm.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * lprm - remove the current user's spool entry
+ *
+ * lprm [-] [[job #] [user] ...]
+ *
+ * Using information in the lock file, lprm will kill the
+ * currently active daemon (if necessary), remove the associated files,
+ * and startup a new daemon. Priviledged users may remove anyone's spool
+ * entries, otherwise one can only remove their own.
+ */
+
+#include <sys/param.h>
+
+#include <syslog.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "lp.h"
+#include "lp.local.h"
+
+/*
+ * Stuff for handling job specifications
+ */
+char *person; /* name of person doing lprm */
+int requ[MAXREQUESTS]; /* job number of spool entries */
+int requests; /* # of spool requests */
+char *user[MAXUSERS]; /* users to process */
+int users; /* # of users in user array */
+
+static char luser[16]; /* buffer for person */
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register char *arg;
+ struct passwd *p;
+
+ name = argv[0];
+ gethostname(host, sizeof(host));
+ openlog("lpd", 0, LOG_LPR);
+ if ((p = getpwuid(getuid())) == NULL)
+ fatal("Who are you?");
+ if (strlen(p->pw_name) >= sizeof(luser))
+ fatal("Your name is too long");
+ strcpy(luser, p->pw_name);
+ person = luser;
+ while (--argc) {
+ if ((arg = *++argv)[0] == '-')
+ switch (arg[1]) {
+ case 'P':
+ if (arg[2])
+ printer = &arg[2];
+ else if (argc > 1) {
+ argc--;
+ printer = *++argv;
+ }
+ break;
+ case '\0':
+ if (!users) {
+ users = -1;
+ break;
+ }
+ default:
+ usage();
+ }
+ else {
+ if (users < 0)
+ usage();
+ if (isdigit(arg[0])) {
+ if (requests >= MAXREQUESTS)
+ fatal("Too many requests");
+ requ[requests++] = atoi(arg);
+ } else {
+ if (users >= MAXUSERS)
+ fatal("Too many users");
+ user[users++] = arg;
+ }
+ }
+ }
+ if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
+ printer = DEFLP;
+
+ rmjob();
+ exit(0);
+}
+
+void
+usage()
+{
+ fprintf(stderr, "usage: lprm [-] [-Pprinter] [[job #] [user] ...]\n");
+ exit(2);
+}
diff --git a/usr.sbin/lpr/lptest/Makefile b/usr.sbin/lpr/lptest/Makefile
new file mode 100644
index 0000000..6ff8e7f
--- /dev/null
+++ b/usr.sbin/lpr/lptest/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= lptest
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lptest/lptest.1 b/usr.sbin/lpr/lptest/lptest.1
new file mode 100644
index 0000000..95b28f3
--- /dev/null
+++ b/usr.sbin/lpr/lptest/lptest.1
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1985, 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.
+.\"
+.\" @(#)lptest.1 8.2 (Berkeley) 12/30/93
+.\"
+.Dd December 30, 1993
+.Dt LPTEST 1
+.Os BSD 4.3
+.Sh NAME
+.Nm lptest
+.Nd generate lineprinter ripple pattern
+.Sh SYNOPSIS
+.Nm lptest
+.Op Ar length
+.Op Ar count
+.Sh DESCRIPTION
+.Nm Lptest
+writes the traditional "ripple test" pattern on standard output.
+In 96 lines,
+this pattern will print all 96 printable
+.Tn ASCII
+characters
+in each position.
+While originally created to test printers, it is quite
+useful for testing terminals,
+driving terminal ports for debugging purposes,
+or any other task where a quick supply of random data is needed.
+.Pp
+The
+.Ar length
+argument specifies the output line length if the default
+length of 79 is inappropriate.
+.Pp
+The
+.Ar count
+argument specifies the number of output lines to be generated if
+the default count of 200 is inappropriate.
+Note that if
+.Ar count
+is to be specified,
+.Ar length
+must be also be specified.
+.Sh HISTORY
+.Nm Lptest
+appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/lpr/lptest/lptest.c b/usr.sbin/lpr/lptest/lptest.c
new file mode 100644
index 0000000..5ce80b5
--- /dev/null
+++ b/usr.sbin/lpr/lptest/lptest.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lptest.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * lptest -- line printer test program (and other devices).
+ */
+void
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int len, count;
+ register i, j, fc, nc;
+ char outbuf[BUFSIZ];
+
+ setbuf(stdout, outbuf);
+ if (argc >= 2)
+ len = atoi(argv[1]);
+ else
+ len = 79;
+ if (argc >= 3)
+ count = atoi(argv[2]);
+ else
+ count = 200;
+ fc = ' ';
+ for (i = 0; i < count; i++) {
+ if (++fc == 0177)
+ fc = ' ';
+ nc = fc;
+ for (j = 0; j < len; j++) {
+ putchar(nc);
+ if (++nc == 0177)
+ nc = ' ';
+ }
+ putchar('\n');
+ }
+ (void) fflush(stdout);
+ exit(0);
+}
diff --git a/usr.sbin/lpr/pac/Makefile b/usr.sbin/lpr/pac/Makefile
new file mode 100644
index 0000000..70cea89
--- /dev/null
+++ b/usr.sbin/lpr/pac/Makefile
@@ -0,0 +1,10 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= pac
+CFLAGS+=-I${.CURDIR}/../common_source
+MAN8= pac.0
+SRCS= pac.c common.c
+.PATH: ${.CURDIR}/../common_source
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/pac/pac.8 b/usr.sbin/lpr/pac/pac.8
new file mode 100644
index 0000000..6e7ffc0
--- /dev/null
+++ b/usr.sbin/lpr/pac/pac.8
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pac.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PAC 8
+.Os BSD 4.2
+.Sh NAME
+.Nm pac
+.Nd printer/plotter accounting information
+.Sh SYNOPSIS
+.Nm pac
+.Op Fl P Ns Ar printer
+.Op Fl c
+.Op Fl m
+.Op Fl p Ns Ar price
+.Op Fl s
+.Op Fl r
+.Op Ar name ...
+.Sh DESCRIPTION
+.Nm Pac
+reads the printer/plotter accounting files, accumulating the number
+of pages (the usual case) or feet (for raster devices)
+of paper consumed by each user, and printing out
+how much each user consumed in pages or feet and dollars.
+.Pp
+Options and operands available:
+.Bl -tag -width PPprinter
+.It Fl P Ns Ar printer
+Accounting is done for the named printer.
+Normally, accounting is done for the default printer (site dependent) or
+the value of the environment variable
+.Ev PRINTER
+is used.
+.It Fl c
+flag causes the output to be sorted by cost; usually the
+output is sorted alphabetically by name.
+.It Fl m
+flag causes the host name to be ignored in the accounting file. This
+allows for a user on multiple machines to have all of his printing
+charges grouped together.
+.It Fl p Ns Ar price
+The value
+.Ar price
+is used for the cost in dollars instead of the default value of 0.02
+or the price specified in
+.Pa /etc/printcap .
+.It Fl r
+Reverse the sorting order.
+.It Fl s
+Accounting information is summarized on the
+summary accounting file; this summarization is necessary since on a
+busy system, the accounting file can grow by several lines per day.
+.It Ar names
+Statistics are only printed for user(s)
+.Ar name ;
+usually, statistics are printed for every user who has used any paper.
+.El
+.Sh FILES
+.Bl -tag -width /var/account/?_sum -compact
+.It Pa /var/account/?acct
+raw accounting files
+.It Pa /var/account/?_sum
+summary accounting files
+.It Pa /etc/printcap
+printer capability data base
+.El
+.Sh SEE ALSO
+.Xr printcap 5
+.Sh BUGS
+The relationship between the computed price and reality is
+as yet unknown.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c
new file mode 100644
index 0000000..af0c8cc
--- /dev/null
+++ b/usr.sbin/lpr/pac/pac.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Do Printer accounting summary.
+ * Currently, usage is
+ * pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...]
+ * to print the usage information for the named people.
+ */
+
+#include <sys/param.h>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "lp.h"
+#include "lp.local.h"
+
+static char *acctfile; /* accounting file (input data) */
+static int allflag = 1; /* Get stats on everybody */
+static int errs;
+static int hcount; /* Count of hash entries */
+static int mflag = 0; /* disregard machine names */
+static int pflag = 0; /* 1 if -p on cmd line */
+static float price = 0.02; /* cost per page (or what ever) */
+static long price100; /* per-page cost in 100th of a cent */
+static int reverse; /* Reverse sort order */
+static int sort; /* Sort by cost */
+static char *sumfile; /* summary file */
+static int summarize; /* Compress accounting file */
+
+/*
+ * Grossness follows:
+ * Names to be accumulated are hashed into the following
+ * table.
+ */
+
+#define HSHSIZE 97 /* Number of hash buckets */
+
+struct hent {
+ struct hent *h_link; /* Forward hash link */
+ char *h_name; /* Name of this user */
+ float h_feetpages; /* Feet or pages of paper */
+ int h_count; /* Number of runs */
+};
+
+static struct hent *hashtab[HSHSIZE]; /* Hash table proper */
+
+static void account __P((FILE *));
+static int any __P((int, char []));
+static int chkprinter __P((char *));
+static void dumpit __P((void));
+static int hash __P((char []));
+static struct hent *enter __P((char []));
+static struct hent *lookup __P((char []));
+static int qucmp __P((const void *, const void *));
+static void rewrite __P((void));
+
+void
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register FILE *acct;
+ register char *cp;
+
+ while (--argc) {
+ cp = *++argv;
+ if (*cp++ == '-') {
+ switch(*cp++) {
+ case 'P':
+ /*
+ * Printer name.
+ */
+ printer = cp;
+ continue;
+
+ case 'p':
+ /*
+ * get the price.
+ */
+ price = atof(cp);
+ pflag = 1;
+ continue;
+
+ case 's':
+ /*
+ * Summarize and compress accounting file.
+ */
+ summarize++;
+ continue;
+
+ case 'c':
+ /*
+ * Sort by cost.
+ */
+ sort++;
+ continue;
+
+ case 'm':
+ /*
+ * disregard machine names for each user
+ */
+ mflag = 1;
+ continue;
+
+ case 'r':
+ /*
+ * Reverse sorting order.
+ */
+ reverse++;
+ continue;
+
+ default:
+fprintf(stderr,
+ "usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n");
+ exit(1);
+ }
+ }
+ (void) enter(--cp);
+ allflag = 0;
+ }
+ if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
+ printer = DEFLP;
+ if (!chkprinter(printer)) {
+ printf("pac: unknown printer %s\n", printer);
+ exit(2);
+ }
+
+ if ((acct = fopen(acctfile, "r")) == NULL) {
+ perror(acctfile);
+ exit(1);
+ }
+ account(acct);
+ fclose(acct);
+ if ((acct = fopen(sumfile, "r")) != NULL) {
+ account(acct);
+ fclose(acct);
+ }
+ if (summarize)
+ rewrite();
+ else
+ dumpit();
+ exit(errs);
+}
+
+/*
+ * Read the entire accounting file, accumulating statistics
+ * for the users that we have in the hash table. If allflag
+ * is set, then just gather the facts on everyone.
+ * Note that we must accomodate both the active and summary file
+ * formats here.
+ * Host names are ignored if the -m flag is present.
+ */
+static void
+account(acct)
+ register FILE *acct;
+{
+ char linebuf[BUFSIZ];
+ double t;
+ register char *cp, *cp2;
+ register struct hent *hp;
+ register int ic;
+
+ while (fgets(linebuf, BUFSIZ, acct) != NULL) {
+ cp = linebuf;
+ while (any(*cp, " t\t"))
+ cp++;
+ t = atof(cp);
+ while (any(*cp, ".0123456789"))
+ cp++;
+ while (any(*cp, " \t"))
+ cp++;
+ for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
+ ;
+ ic = atoi(cp2);
+ *cp2 = '\0';
+ if (mflag && index(cp, ':'))
+ cp = index(cp, ':') + 1;
+ hp = lookup(cp);
+ if (hp == NULL) {
+ if (!allflag)
+ continue;
+ hp = enter(cp);
+ }
+ hp->h_feetpages += t;
+ if (ic)
+ hp->h_count += ic;
+ else
+ hp->h_count++;
+ }
+}
+
+/*
+ * Sort the hashed entries by name or footage
+ * and print it all out.
+ */
+static void
+dumpit()
+{
+ struct hent **base;
+ register struct hent *hp, **ap;
+ register int hno, c, runs;
+ float feet;
+
+ hp = hashtab[0];
+ hno = 1;
+ base = (struct hent **) calloc(sizeof hp, hcount);
+ for (ap = base, c = hcount; c--; ap++) {
+ while (hp == NULL)
+ hp = hashtab[hno++];
+ *ap = hp;
+ hp = hp->h_link;
+ }
+ qsort(base, hcount, sizeof hp, qucmp);
+ printf(" Login pages/feet runs price\n");
+ feet = 0.0;
+ runs = 0;
+ for (ap = base, c = hcount; c--; ap++) {
+ hp = *ap;
+ runs += hp->h_count;
+ feet += hp->h_feetpages;
+ printf("%-24s %7.2f %4d $%6.2f\n", hp->h_name,
+ hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
+ }
+ if (allflag) {
+ printf("\n");
+ printf("%-24s %7.2f %4d $%6.2f\n", "total", feet,
+ runs, feet * price);
+ }
+}
+
+/*
+ * Rewrite the summary file with the summary information we have accumulated.
+ */
+static void
+rewrite()
+{
+ register struct hent *hp;
+ register int i;
+ register FILE *acctf;
+
+ if ((acctf = fopen(sumfile, "w")) == NULL) {
+ perror(sumfile);
+ errs++;
+ return;
+ }
+ for (i = 0; i < HSHSIZE; i++) {
+ hp = hashtab[i];
+ while (hp != NULL) {
+ fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
+ hp->h_name, hp->h_count);
+ hp = hp->h_link;
+ }
+ }
+ fflush(acctf);
+ if (ferror(acctf)) {
+ perror(sumfile);
+ errs++;
+ }
+ fclose(acctf);
+ if ((acctf = fopen(acctfile, "w")) == NULL)
+ perror(acctfile);
+ else
+ fclose(acctf);
+}
+
+/*
+ * Hashing routines.
+ */
+
+/*
+ * Enter the name into the hash table and return the pointer allocated.
+ */
+
+static struct hent *
+enter(name)
+ char name[];
+{
+ register struct hent *hp;
+ register int h;
+
+ if ((hp = lookup(name)) != NULL)
+ return(hp);
+ h = hash(name);
+ hcount++;
+ hp = (struct hent *) calloc(sizeof *hp, 1);
+ hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1);
+ strcpy(hp->h_name, name);
+ hp->h_feetpages = 0.0;
+ hp->h_count = 0;
+ hp->h_link = hashtab[h];
+ hashtab[h] = hp;
+ return(hp);
+}
+
+/*
+ * Lookup a name in the hash table and return a pointer
+ * to it.
+ */
+
+static struct hent *
+lookup(name)
+ char name[];
+{
+ register int h;
+ register struct hent *hp;
+
+ h = hash(name);
+ for (hp = hashtab[h]; hp != NULL; hp = hp->h_link)
+ if (strcmp(hp->h_name, name) == 0)
+ return(hp);
+ return(NULL);
+}
+
+/*
+ * Hash the passed name and return the index in
+ * the hash table to begin the search.
+ */
+static int
+hash(name)
+ char name[];
+{
+ register int h;
+ register char *cp;
+
+ for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
+ ;
+ return((h & 0x7fffffff) % HSHSIZE);
+}
+
+/*
+ * Other stuff
+ */
+static int
+any(ch, str)
+ int ch;
+ char str[];
+{
+ register int c = ch;
+ register char *cp = str;
+
+ while (*cp)
+ if (*cp++ == c)
+ return(1);
+ return(0);
+}
+
+/*
+ * The qsort comparison routine.
+ * The comparison is ascii collating order
+ * or by feet of typesetter film, according to sort.
+ */
+static int
+qucmp(a, b)
+ const void *a, *b;
+{
+ register struct hent *h1, *h2;
+ register int r;
+
+ h1 = *(struct hent **)a;
+ h2 = *(struct hent **)b;
+ if (sort)
+ r = h1->h_feetpages < h2->h_feetpages ?
+ -1 : h1->h_feetpages > h2->h_feetpages;
+ else
+ r = strcmp(h1->h_name, h2->h_name);
+ return(reverse ? -r : r);
+}
+
+/*
+ * Perform lookup for printer name or abbreviation --
+ */
+static int
+chkprinter(s)
+ register char *s;
+{
+ int stat;
+
+ if ((stat = cgetent(&bp, printcapdb, s)) == -2) {
+ printf("pac: can't open printer description file\n");
+ exit(3);
+ } else if (stat == -1)
+ return(0);
+ else if (stat == -3)
+ fatal("potential reference loop detected in printcap file");
+
+ if (cgetstr(bp, "af", &acctfile) == -1) {
+ printf("accounting not enabled for printer %s\n", printer);
+ exit(2);
+ }
+ if (!pflag && (cgetnum(bp, "pc", &price100) == 0))
+ price = price100/10000.0;
+ sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
+ if (sumfile == NULL) {
+ perror("pac");
+ exit(1);
+ }
+ strcpy(sumfile, acctfile);
+ strcat(sumfile, "_sum");
+ return(1);
+}
diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile
new file mode 100644
index 0000000..fb8b424
--- /dev/null
+++ b/usr.sbin/mtree/Makefile
@@ -0,0 +1,8 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= mtree
+#CFLAGS+=-DDEBUG
+SRCS= compare.c crc.c create.c misc.c mtree.c spec.c verify.c
+.PATH: ${.CURDIR}/../../usr.bin/cksum
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/mtree/compare.c b/usr.sbin/mtree/compare.c
new file mode 100644
index 0000000..b258572
--- /dev/null
+++ b/usr.sbin/mtree/compare.c
@@ -0,0 +1,271 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include "mtree.h"
+#include "extern.h"
+
+extern int uflag;
+
+static char *ftype __P((u_int));
+
+#define INDENTNAMELEN 8
+#define LABEL \
+ if (!label++) { \
+ len = printf("%s: ", RP(p)); \
+ if (len > INDENTNAMELEN) { \
+ tab = "\t"; \
+ (void)printf("\n"); \
+ } else { \
+ tab = ""; \
+ (void)printf("%*s", INDENTNAMELEN - len, ""); \
+ } \
+ }
+
+int
+compare(name, s, p)
+ char *name;
+ register NODE *s;
+ register FTSENT *p;
+{
+ extern int uflag;
+ u_long len, val;
+ int fd, label;
+ char *cp, *tab;
+
+ label = 0;
+ switch(s->type) {
+ case F_BLOCK:
+ if (!S_ISBLK(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_CHAR:
+ if (!S_ISCHR(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_DIR:
+ if (!S_ISDIR(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_FIFO:
+ if (!S_ISFIFO(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_FILE:
+ if (!S_ISREG(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_LINK:
+ if (!S_ISLNK(p->fts_statp->st_mode))
+ goto typeerr;
+ break;
+ case F_SOCK:
+ if (!S_ISSOCK(p->fts_statp->st_mode)) {
+typeerr: LABEL;
+ (void)printf("\ttype (%s, %s)\n",
+ ftype(s->type), inotype(p->fts_statp->st_mode));
+ }
+ break;
+ }
+ /* Set the uid/gid first, then set the mode. */
+ if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
+ LABEL;
+ (void)printf("%suser (%u, %u",
+ tab, s->st_uid, p->fts_statp->st_uid);
+ if (uflag)
+ if (chown(p->fts_accpath, s->st_uid, -1))
+ (void)printf(", not modified: %s)\n",
+ strerror(errno));
+ else
+ (void)printf(", modified)\n");
+ else
+ (void)printf(")\n");
+ tab = "\t";
+ }
+ if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
+ LABEL;
+ (void)printf("%sgid (%u, %u",
+ tab, s->st_gid, p->fts_statp->st_gid);
+ if (uflag)
+ if (chown(p->fts_accpath, -1, s->st_gid))
+ (void)printf(", not modified: %s)\n",
+ strerror(errno));
+ else
+ (void)printf(", modified)\n");
+ else
+ (void)printf(")\n");
+ tab = "\t";
+ }
+ if (s->flags & F_MODE &&
+ s->st_mode != (p->fts_statp->st_mode & MBITS)) {
+ LABEL;
+ (void)printf("%spermissions (%#o, %#o",
+ tab, s->st_mode, p->fts_statp->st_mode & MBITS);
+ if (uflag)
+ if (chmod(p->fts_accpath, s->st_mode))
+ (void)printf(", not modified: %s)\n",
+ strerror(errno));
+ else
+ (void)printf(", modified)\n");
+ else
+ (void)printf(")\n");
+ tab = "\t";
+ }
+ if (s->flags & F_NLINK && s->type != F_DIR &&
+ s->st_nlink != p->fts_statp->st_nlink) {
+ LABEL;
+ (void)printf("%slink count (%u, %u)\n",
+ tab, s->st_nlink, p->fts_statp->st_nlink);
+ tab = "\t";
+ }
+ if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
+ LABEL;
+ (void)printf("%ssize (%qd, %qd)\n",
+ tab, s->st_size, p->fts_statp->st_size);
+ tab = "\t";
+ }
+ /*
+ * XXX
+ * Catches nano-second differences, but doesn't display them.
+ */
+ if (s->flags & F_TIME &&
+ s->st_mtimespec.ts_sec != p->fts_statp->st_mtimespec.ts_sec ||
+ s->st_mtimespec.ts_nsec != p->fts_statp->st_mtimespec.ts_nsec) {
+ LABEL;
+ (void)printf("%smodification time (%.24s, ",
+ tab, ctime(&s->st_mtimespec.ts_sec));
+ (void)printf("%.24s)\n",
+ ctime(&p->fts_statp->st_mtimespec.ts_sec));
+ tab = "\t";
+ }
+ if (s->flags & F_CKSUM)
+ if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
+ LABEL;
+ (void)printf("%scksum: %s: %s\n",
+ tab, p->fts_accpath, strerror(errno));
+ tab = "\t";
+ } else if (crc(fd, &val, &len)) {
+ (void)close(fd);
+ LABEL;
+ (void)printf("%scksum: %s: %s\n",
+ tab, p->fts_accpath, strerror(errno));
+ tab = "\t";
+ } else {
+ (void)close(fd);
+ if (s->cksum != val) {
+ LABEL;
+ (void)printf("%scksum (%lu, %lu)\n",
+ tab, s->cksum, val);
+ }
+ tab = "\t";
+ }
+ if (s->flags & F_SLINK && strcmp(cp = rlink(name), s->slink)) {
+ LABEL;
+ (void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink);
+ }
+ return (label);
+}
+
+char *
+inotype(type)
+ u_int type;
+{
+ switch(type & S_IFMT) {
+ case S_IFBLK:
+ return ("block");
+ case S_IFCHR:
+ return ("char");
+ case S_IFDIR:
+ return ("dir");
+ case S_IFIFO:
+ return ("fifo");
+ case S_IFREG:
+ return ("file");
+ case S_IFLNK:
+ return ("link");
+ case S_IFSOCK:
+ return ("socket");
+ default:
+ return ("unknown");
+ }
+ /* NOTREACHED */
+}
+
+static char *
+ftype(type)
+ u_int type;
+{
+ switch(type) {
+ case F_BLOCK:
+ return ("block");
+ case F_CHAR:
+ return ("char");
+ case F_DIR:
+ return ("dir");
+ case F_FIFO:
+ return ("fifo");
+ case F_FILE:
+ return ("file");
+ case F_LINK:
+ return ("link");
+ case F_SOCK:
+ return ("socket");
+ default:
+ return ("unknown");
+ }
+ /* NOTREACHED */
+}
+
+char *
+rlink(name)
+ char *name;
+{
+ static char lbuf[MAXPATHLEN];
+ register int len;
+
+ if ((len = readlink(name, lbuf, sizeof(lbuf))) == -1)
+ err("%s: %s", name, strerror(errno));
+ lbuf[len] = '\0';
+ return (lbuf);
+}
diff --git a/usr.sbin/mtree/create.c b/usr.sbin/mtree/create.c
new file mode 100644
index 0000000..9ce603e
--- /dev/null
+++ b/usr.sbin/mtree/create.c
@@ -0,0 +1,290 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "mtree.h"
+#include "extern.h"
+
+#define INDENTNAMELEN 15
+#define MAXLINELEN 80
+
+extern int crc_total, ftsoptions;
+extern int dflag, sflag;
+extern u_short keys;
+extern char fullpath[MAXPATHLEN];
+
+static gid_t gid;
+static uid_t uid;
+static mode_t mode;
+
+static int dsort __P((const FTSENT **, const FTSENT **));
+static void output __P((int *, const char *, ...));
+static int statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *));
+static void statf __P((FTSENT *));
+
+void
+cwalk()
+{
+ register FTS *t;
+ register FTSENT *p;
+ time_t clock;
+ char *argv[2], host[MAXHOSTNAMELEN];
+
+ (void)time(&clock);
+ (void)gethostname(host, sizeof(host));
+ (void)printf(
+ "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n#\t date: %s",
+ getlogin(), host, fullpath, ctime(&clock));
+
+ argv[0] = ".";
+ argv[1] = NULL;
+ if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
+ err("fts_open: %s", strerror(errno));
+ while (p = fts_read(t))
+ switch(p->fts_info) {
+ case FTS_D:
+ (void)printf("\n# %s\n", p->fts_path);
+ statd(t, p, &uid, &gid, &mode);
+ statf(p);
+ break;
+ case FTS_DP:
+ if (p->fts_level > 0)
+ (void)printf("# %s\n..\n\n", p->fts_path);
+ break;
+ case FTS_DNR:
+ case FTS_ERR:
+ case FTS_NS:
+ (void)fprintf(stderr,
+ "mtree: %s: %s\n", p->fts_path, strerror(errno));
+ break;
+ default:
+ if (!dflag)
+ statf(p);
+ break;
+
+ }
+ (void)fts_close(t);
+ if (sflag && keys & F_CKSUM)
+ (void)fprintf(stderr,
+ "mtree: %s checksum: %lu\n", fullpath, crc_total);
+}
+
+static void
+statf(p)
+ FTSENT *p;
+{
+ struct group *gr;
+ struct passwd *pw;
+ u_long len, val;
+ int fd, indent;
+
+ if (S_ISDIR(p->fts_statp->st_mode))
+ indent = printf("%s", p->fts_name);
+ else
+ indent = printf(" %s", p->fts_name);
+
+ if (indent > INDENTNAMELEN)
+ indent = MAXLINELEN;
+ else
+ indent += printf("%*s", INDENTNAMELEN - indent, "");
+
+ if (!S_ISREG(p->fts_statp->st_mode))
+ output(&indent, "type=%s", inotype(p->fts_statp->st_mode));
+ if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid)
+ if (keys & F_UNAME && (pw = getpwuid(p->fts_statp->st_uid)))
+ output(&indent, "uname=%s", pw->pw_name);
+ else /* if (keys & F_UID) */
+ output(&indent, "uid=%u", p->fts_statp->st_uid);
+ if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid)
+ if (keys & F_GNAME && (gr = getgrgid(p->fts_statp->st_gid)))
+ output(&indent, "gname=%s", gr->gr_name);
+ else /* if (keys & F_GID) */
+ output(&indent, "gid=%u", p->fts_statp->st_gid);
+ if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode)
+ output(&indent, "mode=%#o", p->fts_statp->st_mode & MBITS);
+ if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
+ output(&indent, "nlink=%u", p->fts_statp->st_nlink);
+ if (keys & F_SIZE)
+ output(&indent, "size=%qd", p->fts_statp->st_size);
+ if (keys & F_TIME)
+ output(&indent, "time=%ld.%ld",
+ p->fts_statp->st_mtimespec.ts_sec,
+ p->fts_statp->st_mtimespec.ts_nsec);
+ if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
+ if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
+ crc(fd, &val, &len))
+ err("%s: %s", p->fts_accpath, strerror(errno));
+ (void)close(fd);
+ output(&indent, "cksum=%lu", val);
+ }
+ if (keys & F_SLINK &&
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
+ output(&indent, "link=%s", rlink(p->fts_accpath));
+ (void)putchar('\n');
+}
+
+#define MAXGID 5000
+#define MAXUID 5000
+#define MAXMODE MBITS + 1
+
+static int
+statd(t, parent, puid, pgid, pmode)
+ FTS *t;
+ FTSENT *parent;
+ uid_t *puid;
+ gid_t *pgid;
+ mode_t *pmode;
+{
+ register FTSENT *p;
+ register gid_t sgid;
+ register uid_t suid;
+ register mode_t smode;
+ struct group *gr;
+ struct passwd *pw;
+ gid_t savegid;
+ uid_t saveuid;
+ mode_t savemode;
+ u_short maxgid, maxuid, maxmode, g[MAXGID], u[MAXUID], m[MAXMODE];
+
+ if ((p = fts_children(t, 0)) == NULL) {
+ if (errno)
+ err("%s: %s", RP(parent), strerror(errno));
+ return (1);
+ }
+
+ bzero(g, sizeof(g));
+ bzero(u, sizeof(u));
+ bzero(m, sizeof(m));
+
+ maxuid = maxgid = maxmode = 0;
+ for (; p; p = p->fts_link) {
+ smode = p->fts_statp->st_mode & MBITS;
+ if (smode < MAXMODE && ++m[smode] > maxmode) {
+ savemode = smode;
+ maxmode = m[smode];
+ }
+ sgid = p->fts_statp->st_gid;
+ if (sgid < MAXGID && ++g[sgid] > maxgid) {
+ savegid = sgid;
+ maxgid = g[sgid];
+ }
+ suid = p->fts_statp->st_uid;
+ if (suid < MAXUID && ++u[suid] > maxuid) {
+ saveuid = suid;
+ maxuid = u[suid];
+ }
+ }
+ (void)printf("/set type=file");
+ if (keys & F_GID)
+ (void)printf(" gid=%u", savegid);
+ if (keys & F_GNAME)
+ if ((gr = getgrgid(savegid)) != NULL)
+ (void)printf(" gname=%s", gr->gr_name);
+ else
+ (void)printf(" gid=%u", savegid);
+ if (keys & F_UNAME)
+ if ((pw = getpwuid(saveuid)) != NULL)
+ (void)printf(" uname=%s", pw->pw_name);
+ else
+ (void)printf(" uid=%u", saveuid);
+ if (keys & F_UID)
+ (void)printf(" uid=%u", saveuid);
+ if (keys & F_MODE)
+ (void)printf(" mode=%#o", savemode);
+ if (keys & F_NLINK)
+ (void)printf(" nlink=1");
+ (void)printf("\n");
+ *puid = saveuid;
+ *pgid = savegid;
+ *pmode = savemode;
+ return (0);
+}
+
+static int
+dsort(a, b)
+ const FTSENT **a, **b;
+{
+ if (S_ISDIR((*a)->fts_statp->st_mode)) {
+ if (!S_ISDIR((*b)->fts_statp->st_mode))
+ return (1);
+ } else if (S_ISDIR((*b)->fts_statp->st_mode))
+ return (-1);
+ return (strcmp((*a)->fts_name, (*b)->fts_name));
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+output(int *offset, const char *fmt, ...)
+#else
+output(offset, fmt, va_alist)
+ int *offset;
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+ char buf[1024];
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ if (*offset + strlen(buf) > MAXLINELEN - 3) {
+ (void)printf(" \\\n%*s", INDENTNAMELEN, "");
+ *offset = INDENTNAMELEN;
+ }
+ *offset += printf(" %s", buf) + 1;
+}
diff --git a/usr.sbin/mtree/extern.h b/usr.sbin/mtree/extern.h
new file mode 100644
index 0000000..72c5dbc
--- /dev/null
+++ b/usr.sbin/mtree/extern.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+int compare __P((char *, NODE *, FTSENT *));
+int crc __P((int, u_long *, u_long *));
+void cwalk __P((void));
+void err __P((const char *, ...));
+char *inotype __P((u_int));
+u_int parsekey __P((char *, int *));
+char *rlink __P((char *));
+NODE *spec __P((void));
+int verify __P((void));
diff --git a/usr.sbin/mtree/misc.c b/usr.sbin/mtree/misc.c
new file mode 100644
index 0000000..3169136
--- /dev/null
+++ b/usr.sbin/mtree/misc.c
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)misc.c 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+#include <stdio.h>
+#include "mtree.h"
+#include "extern.h"
+
+extern int lineno;
+
+typedef struct _key {
+ char *name; /* key name */
+ u_int val; /* value */
+
+#define NEEDVALUE 0x01
+ u_int flags;
+} KEY;
+
+/* NB: the following table must be sorted lexically. */
+static KEY keylist[] = {
+ "cksum", F_CKSUM, NEEDVALUE,
+ "gid", F_GID, NEEDVALUE,
+ "gname", F_GNAME, NEEDVALUE,
+ "ignore", F_IGN, 0,
+ "link", F_SLINK, NEEDVALUE,
+ "mode", F_MODE, NEEDVALUE,
+ "nlink", F_NLINK, NEEDVALUE,
+ "size", F_SIZE, NEEDVALUE,
+ "time", F_TIME, NEEDVALUE,
+ "type", F_TYPE, NEEDVALUE,
+ "uid", F_UID, NEEDVALUE,
+ "uname", F_UNAME, NEEDVALUE,
+};
+
+u_int
+parsekey(name, needvaluep)
+ char *name;
+ int *needvaluep;
+{
+ KEY *k, tmp;
+ int keycompare __P((const void *, const void *));
+
+ tmp.name = name;
+ k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
+ sizeof(KEY), keycompare);
+ if (k == NULL)
+ err("unknown keyword %s", name);
+
+ if (needvaluep)
+ *needvaluep = k->flags & NEEDVALUE ? 1 : 0;
+ return (k->val);
+}
+
+int
+keycompare(a, b)
+ const void *a, *b;
+{
+ return (strcmp(((KEY *)a)->name, ((KEY *)b)->name));
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)fprintf(stderr, "mtree: ");
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)fprintf(stderr, "\n");
+ if (lineno)
+ (void)fprintf(stderr,
+ "mtree: failed at line %d of the specification\n", lineno);
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/usr.sbin/mtree/mtree.8 b/usr.sbin/mtree/mtree.8
new file mode 100644
index 0000000..3c50f71
--- /dev/null
+++ b/usr.sbin/mtree/mtree.8
@@ -0,0 +1,249 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mtree.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt MTREE 8
+.Os
+.Sh NAME
+.Nm mtree
+.Nd map a directory hierarchy
+.Sh SYNOPSIS
+.Nm mtree
+.Op Fl cderux
+.Op Fl f Ar spec
+.Op Fl K Ar keywords
+.Op Fl k Ar keywords
+.Op Fl p Ar path
+.Op Fl s Ar seed
+.Sh DESCRIPTION
+The utility
+.Nm mtree
+compares the file hierarchy rooted in the current directory against a
+specification read from the standard input.
+Messages are written to the standard output for any files whose
+characteristics do not match the specifications, or which are
+missing from either the file hierarchy or the specification.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl c
+Print a specification for the file hierarchy to the standard output.
+.It Fl d
+Ignore everything except directory type files.
+.It Fl e
+Don't complain about files that are in the file hierarchy, but not in the
+specification.
+.It Fl f
+Read the specification from
+.Ar file ,
+instead of from the standard input.
+.It Fl K
+Add the specified (whitespace or comma separated) keywords to the current
+set of keywords.
+.It Fl k
+Use the ``type'' keyword plus the specified (whitespace or comma separated)
+keywords instead of the current set of keywords.
+.It Fl p
+Use the file hierarchy rooted in
+.Ar path ,
+instead of the current directory.
+.It Fl r
+Remove any files in the file hierarchy that are not described in the
+specification.
+.It Fl s
+Display a single checksum to the standard error output that represents all
+of the files for which the keyword
+.Cm cksum
+was specified.
+The checksum is seeded with the specified value.
+.It Fl u
+Modify the owner, group, and permissions of existing files to match
+the specification and create any missing directories.
+User, group, and permissions must all be specified for missing directories
+to be created.
+.It Fl x
+Don't descend below mount points in the file hierarchy.
+.El
+.Pp
+Specifications are mostly composed of ``keywords'', i.e. strings that
+that specify values relating to files.
+No keywords have default values, and if a keyword has no value set, no
+checks based on it are performed.
+.Pp
+Currently supported keywords are as follows:
+.Bl -tag -width Cm
+.It Cm cksum
+The checksum of the file using the default algorithm specified by
+the
+.Xr cksum 1
+utility.
+.It Cm ignore
+Ignore any file hierarchy below this file.
+.It Cm gid
+The file group as a numeric value.
+.It Cm gname
+The file group as a symbolic name.
+.It Cm mode
+The current file's permissions as a numeric (octal) or symbolic
+value.
+.It Cm nlink
+The number of hard links the file is expected to have.
+.It Cm uid
+The file owner as a numeric value.
+.It Cm uname
+The file group as a symbolic name.
+.It Cm size
+The size, in bytes, of the file.
+.It Cm link
+The file the symbolic link is expected to reference.
+.It Cm time
+The last modification time of the file.
+.It Cm type
+The type of the file; may be set to any one of the following:
+.sp
+.Bl -tag -width Cm -compact
+.It Cm block
+block special device
+.It Cm char
+character special device
+.It Cm dir
+directory
+.It Cm fifo
+fifo
+.It Cm file
+regular file
+.It Cm link
+symbolic link
+.It Cm socket
+socket
+.El
+.El
+.Pp
+The default set of keywords are
+.Cm gid ,
+.Cm mode ,
+.Cm nlink ,
+.Cm size ,
+.Cm slink ,
+.Cm time ,
+and
+.Cm uid .
+.Pp
+There are four types of lines in a specification.
+.Pp
+The first type of line sets a global value for a keyword, and consists of
+the string ``/set'' followed by whitespace, followed by sets of keyword/value
+pairs, separated by whitespace.
+Keyword/value pairs consist of a keyword, followed by an equals sign
+(``=''), followed by a value, without whitespace characters.
+Once a keyword has been set, its value remains unchanged until either
+reset or unset.
+.Pp
+The second type of line unsets keywords and consists of the string
+``/unset'', followed by whitespace, followed by one or more keywords,
+separated by whitespace.
+.Pp
+The third type of line is a file specification and consists of a file
+name, followed by whitespace, followed by zero or more whitespace
+separated keyword/value pairs.
+The file name may be preceded by whitespace characters.
+The file name may contain any of the standard file name matching
+characters (``['', ``]'', ``?'' or ``*''), in which case files
+in the hierarchy will be associated with the first pattern that
+they match.
+.Pp
+Each of the keyword/value pairs consist of a keyword, followed by an
+equals sign (``=''), followed by the keyword's value, without
+whitespace characters.
+These values override, without changing, the global value of the
+corresponding keyword.
+.Pp
+All paths are relative.
+Specifying a directory will cause subsequent files to be searched
+for in that directory hierarchy.
+Which brings us to the last type of line in a specification: a line
+containing only the string
+.Dq Nm \&..
+causes the current directory
+path to ascend one level.
+.Pp
+Empty lines and lines whose first non-whitespace character is a hash
+mark (``#'') are ignored.
+.Pp
+The
+.Nm mtree
+utility exits with a status of 0 on success, 1 if any error occurred,
+and 2 if the file hierarchy did not match the specification.
+.Sh EXAMPLES
+To detect system binaries that have been ``trojan horsed'', it is recommended
+that
+.Nm mtree
+be run on the file systems, and a copy of the results stored on a different
+machine, or, at least, in encrypted form.
+The seed for the
+.Fl s
+option should not be an obvious value and the final checksum should not be
+stored on-line under any circumstances!
+Then, periodically,
+.Nm mtree
+should be run against the on-line specifications and the final checksum
+compared with the previous value.
+While it is possible for the bad guys to change the on-line specifications
+to conform to their modified binaries, it shouldn't be possible for them
+to make it produce the same final checksum value.
+If the final checksum value changes, the off-line copies of the specification
+can be used to detect which of the binaries have actually been modified.
+.Pp
+The
+.Fl d
+and
+.Fl u
+options can be used in combination to create directory hierarchies
+for distributions and other such things.
+.Sh FILES
+.Bl -tag -width /etc/mtree -compact
+.It Pa /etc/mtree
+system specification directory
+.El
+.Sh SEE ALSO
+.Xr chmod 1 ,
+.Xr chown 1 ,
+.Xr chgrp 1 ,
+.Xr cksum 1 ,
+.Xr stat 2 ,
+.Xr fts 3 ,
+.Sh HISTORY
+The
+.Nm mtree
+utility appeared in
+.Bx 4.3 Reno .
diff --git a/usr.sbin/mtree/mtree.c b/usr.sbin/mtree/mtree.c
new file mode 100644
index 0000000..17857c5
--- /dev/null
+++ b/usr.sbin/mtree/mtree.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1989, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fts.h>
+#include "mtree.h"
+#include "extern.h"
+
+extern int crc_total;
+
+int ftsoptions = FTS_PHYSICAL;
+int cflag, dflag, eflag, rflag, sflag, uflag;
+u_short keys;
+char fullpath[MAXPATHLEN];
+
+static void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern int optind;
+ extern char *optarg;
+ int ch;
+ char *dir, *p;
+
+ dir = NULL;
+ keys = KEYDEFAULT;
+ while ((ch = getopt(argc, argv, "cdef:K:k:p:rs:ux")) != EOF)
+ switch((char)ch) {
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'e':
+ eflag = 1;
+ break;
+ case 'f':
+ if (!(freopen(optarg, "r", stdin)))
+ err("%s: %s", optarg, strerror(errno));
+ break;
+ case 'K':
+ while ((p = strsep(&optarg, " \t,")) != NULL)
+ if (*p != '\0')
+ keys |= parsekey(p, NULL);
+ break;
+ case 'k':
+ keys = F_TYPE;
+ while ((p = strsep(&optarg, " \t,")) != NULL)
+ if (*p != '\0')
+ keys |= parsekey(p, NULL);
+ break;
+ case 'p':
+ dir = optarg;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ crc_total = ~strtol(optarg, &p, 0);
+ if (*p)
+ err("illegal seed value -- %s", optarg);
+ case 'u':
+ uflag = 1;
+ break;
+ case 'x':
+ ftsoptions |= FTS_XDEV;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ usage();
+
+ if (dir && chdir(dir))
+ err("%s: %s", dir, strerror(errno));
+
+ if ((cflag || sflag) && !getwd(fullpath))
+ err("%s", fullpath);
+
+ if (cflag) {
+ cwalk();
+ exit(0);
+ }
+ exit(verify());
+}
+
+static void
+usage()
+{
+ (void)fprintf(stderr,
+"usage: mtree [-cderux] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n");
+ exit(1);
+}
diff --git a/usr.sbin/mtree/mtree.h b/usr.sbin/mtree/mtree.h
new file mode 100644
index 0000000..5583127
--- /dev/null
+++ b/usr.sbin/mtree/mtree.h
@@ -0,0 +1,88 @@
+/*-
+ * 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.
+ *
+ * @(#)mtree.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#define KEYDEFAULT \
+ (F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | F_TIME | F_UID)
+
+#define MISMATCHEXIT 2
+
+typedef struct _node {
+ struct _node *parent, *child; /* up, down */
+ struct _node *prev, *next; /* left, right */
+ off_t st_size; /* size */
+ struct timespec st_mtimespec; /* last modification time */
+ u_long cksum; /* check sum */
+ char *slink; /* symbolic link reference */
+ uid_t st_uid; /* uid */
+ gid_t st_gid; /* gid */
+#define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
+ mode_t st_mode; /* mode */
+ nlink_t st_nlink; /* link count */
+
+#define F_CKSUM 0x0001 /* check sum */
+#define F_DONE 0x0002 /* directory done */
+#define F_GID 0x0004 /* gid */
+#define F_GNAME 0x0008 /* group name */
+#define F_IGN 0x0010 /* ignore */
+#define F_MAGIC 0x0020 /* name has magic chars */
+#define F_MODE 0x0040 /* mode */
+#define F_NLINK 0x0080 /* number of links */
+#define F_SIZE 0x0100 /* size */
+#define F_SLINK 0x0200 /* link count */
+#define F_TIME 0x0400 /* modification time */
+#define F_TYPE 0x0800 /* file type */
+#define F_UID 0x1000 /* uid */
+#define F_UNAME 0x2000 /* user name */
+#define F_VISIT 0x4000 /* file visited */
+ u_short flags; /* items set */
+
+#define F_BLOCK 0x001 /* block special */
+#define F_CHAR 0x002 /* char special */
+#define F_DIR 0x004 /* directory */
+#define F_FIFO 0x008 /* fifo */
+#define F_FILE 0x010 /* regular file */
+#define F_LINK 0x020 /* symbolic link */
+#define F_SOCK 0x040 /* socket */
+ u_char type; /* file type */
+
+ char name[1]; /* file name (must be last) */
+} NODE;
+
+#define RP(p) \
+ ((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \
+ (p)->fts_path + 2 : (p)->fts_path)
diff --git a/usr.sbin/mtree/spec.c b/usr.sbin/mtree/spec.c
new file mode 100644
index 0000000..a50574f
--- /dev/null
+++ b/usr.sbin/mtree/spec.c
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)spec.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "mtree.h"
+#include "extern.h"
+
+int lineno; /* Current spec line number. */
+
+static void set __P((char *, NODE *));
+static void unset __P((char *, NODE *));
+
+NODE *
+spec()
+{
+ register NODE *centry, *last;
+ register char *p;
+ NODE ginfo, *root;
+ int c_cur, c_next;
+ char buf[2048];
+
+ root = NULL;
+ bzero(&ginfo, sizeof(ginfo));
+ c_cur = c_next = 0;
+ for (lineno = 1; fgets(buf, sizeof(buf), stdin);
+ ++lineno, c_cur = c_next, c_next = 0) {
+ /* Skip empty lines. */
+ if (buf[0] == '\n')
+ continue;
+
+ /* Find end of line. */
+ if ((p = index(buf, '\n')) == NULL)
+ err("line %d too long", lineno);
+
+ /* See if next line is continuation line. */
+ if (p[-1] == '\\') {
+ --p;
+ c_next = 1;
+ }
+
+ /* Null-terminate the line. */
+ *p = '\0';
+
+ /* Skip leading whitespace. */
+ for (p = buf; *p && isspace(*p); ++p);
+
+ /* If nothing but whitespace or comment char, continue. */
+ if (!*p || *p == '#')
+ continue;
+
+#ifdef DEBUG
+ (void)fprintf(stderr, "line %d: {%s}\n", lineno, p);
+#endif
+ if (c_cur) {
+ set(p, centry);
+ continue;
+ }
+
+ /* Grab file name, "$", "set", or "unset". */
+ if ((p = strtok(p, "\n\t ")) == NULL)
+ err("missing field");
+
+ if (p[0] == '/')
+ switch(p[1]) {
+ case 's':
+ if (strcmp(p + 1, "set"))
+ break;
+ set(NULL, &ginfo);
+ continue;
+ case 'u':
+ if (strcmp(p + 1, "unset"))
+ break;
+ unset(NULL, &ginfo);
+ continue;
+ }
+
+ if (index(p, '/'))
+ err("slash character in file name");
+
+ if (!strcmp(p, "..")) {
+ /* Don't go up, if haven't gone down. */
+ if (!root)
+ goto noparent;
+ if (last->type != F_DIR || last->flags & F_DONE) {
+ if (last == root)
+ goto noparent;
+ last = last->parent;
+ }
+ last->flags |= F_DONE;
+ continue;
+
+noparent: err("no parent node");
+ }
+
+ if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
+ err("%s", strerror(errno));
+ *centry = ginfo;
+ (void)strcpy(centry->name, p);
+#define MAGIC "?*["
+ if (strpbrk(p, MAGIC))
+ centry->flags |= F_MAGIC;
+ set(NULL, centry);
+
+ if (!root) {
+ last = root = centry;
+ root->parent = root;
+ } else if (last->type == F_DIR && !(last->flags & F_DONE)) {
+ centry->parent = last;
+ last = last->child = centry;
+ } else {
+ centry->parent = last->parent;
+ centry->prev = last;
+ last = last->next = centry;
+ }
+ }
+ return (root);
+}
+
+static void
+set(t, ip)
+ char *t;
+ register NODE *ip;
+{
+ register int type;
+ register char *kw, *val;
+ struct group *gr;
+ struct passwd *pw;
+ mode_t *m;
+ int value;
+ char *ep;
+
+ for (; kw = strtok(t, "= \t\n"); t = NULL) {
+ ip->flags |= type = parsekey(kw, &value);
+ if (value && (val = strtok(NULL, " \t\n")) == NULL)
+ err("missing value");
+ switch(type) {
+ case F_CKSUM:
+ ip->cksum = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid checksum %s", val);
+ break;
+ case F_GID:
+ ip->st_gid = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid gid %s", val);
+ break;
+ case F_GNAME:
+ if ((gr = getgrnam(val)) == NULL)
+ err("unknown group %s", val);
+ ip->st_gid = gr->gr_gid;
+ break;
+ case F_IGN:
+ /* just set flag bit */
+ break;
+ case F_MODE:
+ if ((m = setmode(val)) == NULL)
+ err("invalid file mode %s", val);
+ ip->st_mode = getmode(m, 0);
+ break;
+ case F_NLINK:
+ ip->st_nlink = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid link count %s", val);
+ break;
+ case F_SIZE:
+ ip->st_size = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid size %s", val);
+ break;
+ case F_SLINK:
+ if ((ip->slink = strdup(val)) == NULL)
+ err("%s", strerror(errno));
+ break;
+ case F_TIME:
+ ip->st_mtimespec.ts_sec = strtoul(val, &ep, 10);
+ if (*ep != '.')
+ err("invalid time %s", val);
+ val = ep + 1;
+ ip->st_mtimespec.ts_nsec = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid time %s", val);
+ break;
+ case F_TYPE:
+ switch(*val) {
+ case 'b':
+ if (!strcmp(val, "block"))
+ ip->type = F_BLOCK;
+ break;
+ case 'c':
+ if (!strcmp(val, "char"))
+ ip->type = F_CHAR;
+ break;
+ case 'd':
+ if (!strcmp(val, "dir"))
+ ip->type = F_DIR;
+ break;
+ case 'f':
+ if (!strcmp(val, "file"))
+ ip->type = F_FILE;
+ if (!strcmp(val, "fifo"))
+ ip->type = F_FIFO;
+ break;
+ case 'l':
+ if (!strcmp(val, "link"))
+ ip->type = F_LINK;
+ break;
+ case 's':
+ if (!strcmp(val, "socket"))
+ ip->type = F_SOCK;
+ break;
+ default:
+ err("unknown file type %s", val);
+ }
+ break;
+ case F_UID:
+ ip->st_uid = strtoul(val, &ep, 10);
+ if (*ep)
+ err("invalid uid %s", val);
+ break;
+ case F_UNAME:
+ if ((pw = getpwnam(val)) == NULL)
+ err("unknown user %s", val);
+ ip->st_uid = pw->pw_uid;
+ break;
+ }
+ }
+}
+
+static void
+unset(t, ip)
+ char *t;
+ register NODE *ip;
+{
+ register char *p;
+
+ while (p = strtok(t, "\n\t "))
+ ip->flags &= ~parsekey(p, NULL);
+}
diff --git a/usr.sbin/mtree/verify.c b/usr.sbin/mtree/verify.c
new file mode 100644
index 0000000..27d9b90
--- /dev/null
+++ b/usr.sbin/mtree/verify.c
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fts.h>
+#include <fnmatch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include "mtree.h"
+#include "extern.h"
+
+extern int crc_total, ftsoptions;
+extern int dflag, eflag, rflag, sflag, uflag;
+extern char fullpath[MAXPATHLEN];
+
+static NODE *root;
+static char path[MAXPATHLEN];
+
+static void miss __P((NODE *, char *));
+static int vwalk __P((void));
+
+int
+verify()
+{
+ int rval;
+
+ root = spec();
+ rval = vwalk();
+ miss(root, path);
+ return (rval);
+}
+
+static int
+vwalk()
+{
+ register FTS *t;
+ register FTSENT *p;
+ register NODE *ep, *level;
+ int ftsdepth, specdepth, rval;
+ char *argv[2];
+
+ argv[0] = ".";
+ argv[1] = NULL;
+ if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
+ err("fts_open: %s", strerror(errno));
+ level = root;
+ ftsdepth = specdepth = rval = 0;
+ while (p = fts_read(t)) {
+ switch(p->fts_info) {
+ case FTS_D:
+ ++ftsdepth;
+ break;
+ case FTS_DP:
+ --ftsdepth;
+ if (specdepth > ftsdepth) {
+ for (level = level->parent; level->prev;
+ level = level->prev);
+ --specdepth;
+ }
+ continue;
+ case FTS_DNR:
+ case FTS_ERR:
+ case FTS_NS:
+ (void)fprintf(stderr, "mtree: %s: %s\n",
+ RP(p), strerror(errno));
+ continue;
+ default:
+ if (dflag)
+ continue;
+ }
+
+ for (ep = level; ep; ep = ep->next)
+ if (ep->flags & F_MAGIC &&
+ !fnmatch(ep->name, p->fts_name, FNM_PATHNAME) ||
+ !strcmp(ep->name, p->fts_name)) {
+ ep->flags |= F_VISIT;
+ if (compare(ep->name, ep, p))
+ rval = MISMATCHEXIT;
+ if (ep->flags & F_IGN)
+ (void)fts_set(t, p, FTS_SKIP);
+ else if (ep->child && ep->type == F_DIR &&
+ p->fts_info == FTS_D) {
+ level = ep->child;
+ ++specdepth;
+ }
+ break;
+ }
+
+ if (ep)
+ continue;
+ if (!eflag) {
+ (void)printf("extra: %s", RP(p));
+ if (rflag) {
+ if (unlink(p->fts_accpath)) {
+ (void)printf(", not removed: %s",
+ strerror(errno));
+ } else
+ (void)printf(", removed");
+ }
+ (void)putchar('\n');
+ }
+ (void)fts_set(t, p, FTS_SKIP);
+ }
+ (void)fts_close(t);
+ if (sflag)
+ (void)fprintf(stderr,
+ "mtree: %s checksum: %lu\n", fullpath, crc_total);
+ return (rval);
+}
+
+static void
+miss(p, tail)
+ register NODE *p;
+ register char *tail;
+{
+ register int create;
+ register char *tp;
+
+ for (; p; p = p->next) {
+ if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
+ continue;
+ (void)strcpy(tail, p->name);
+ if (!(p->flags & F_VISIT))
+ (void)printf("missing: %s", path);
+ if (p->type != F_DIR) {
+ putchar('\n');
+ continue;
+ }
+
+ create = 0;
+ if (!(p->flags & F_VISIT) && uflag)
+ if (!(p->flags & (F_UID | F_UNAME)))
+ (void)printf(" (not created: user not specified)");
+ else if (!(p->flags & (F_GID | F_GNAME)))
+ (void)printf(" (not created: group not specified)");
+ else if (!(p->flags & F_MODE))
+ (void)printf(" (not created: mode not specified)");
+ else if (mkdir(path, S_IRWXU))
+ (void)printf(" (not created: %s)",
+ strerror(errno));
+ else {
+ create = 1;
+ (void)printf(" (created)");
+ }
+
+ if (!(p->flags & F_VISIT))
+ (void)putchar('\n');
+
+ for (tp = tail; *tp; ++tp);
+ *tp = '/';
+ miss(p->child, tp + 1);
+ *tp = '\0';
+
+ if (!create)
+ continue;
+ if (chown(path, p->st_uid, p->st_gid)) {
+ (void)printf("%s: user/group/mode not modified: %s\n",
+ path, strerror(errno));
+ continue;
+ }
+ if (chmod(path, p->st_mode))
+ (void)printf("%s: permissions not set: %s\n",
+ path, strerror(errno));
+ }
+}
diff --git a/usr.sbin/pstat/Makefile b/usr.sbin/pstat/Makefile
new file mode 100644
index 0000000..9969a64
--- /dev/null
+++ b/usr.sbin/pstat/Makefile
@@ -0,0 +1,10 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= pstat
+CFLAGS+=-I/sys
+BINGRP= kmem
+BINMODE=2555
+DPADD= ${LIBKVM}
+LDADD= -lkvm
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pstat/pstat.8 b/usr.sbin/pstat/pstat.8
new file mode 100644
index 0000000..95f3d86
--- /dev/null
+++ b/usr.sbin/pstat/pstat.8
@@ -0,0 +1,321 @@
+.\" Copyright (c) 1980, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" @(#)pstat.8 8.4 (Berkeley) 4/19/94
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)pstat.8 8.4 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt PSTAT 8
+.Os BSD 4
+.Sh NAME
+.Nm pstat
+.Nd display system data structures
+.Sh SYNOPSIS
+.Nm pstat
+.Op Fl Tfnstv
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Sh DESCRIPTION
+.Nm Pstat
+displays open file entry, swap space utilization,
+terminal state, and vnode data structures.
+If
+.Ar corefile
+is given, the information is sought there, otherwise
+in
+.Pa /dev/kmem .
+The required namelist is taken from
+.Pa /vmunix
+unless
+.Ar system
+is specified.
+The
+.Fl n
+option specifies that devices should be printed out by major/minor
+number rather than by name.
+.Pp
+Options are
+.Bl -tag -width indent
+.It Fl T
+Prints the number of used and free slots in the several system tables
+and is useful for checking to see how large system tables have become
+if the system is under heavy load.
+.It Fl f
+Print the open file table with these headings:
+.Bl -tag -width indent
+.It LOC
+The core location of this table entry.
+.It TYPE
+The type of object the file table entry points to.
+.It FLG
+Miscellaneous state variables encoded thus:
+.Bl -tag -width indent
+.It R
+open for reading
+.It W
+open for writing
+.It A
+open for appending
+.It S
+shared lock present
+.It X
+exclusive lock present
+.It I
+signal pgrp when data ready
+.El
+.It CNT
+Number of processes that know this open file.
+.It MSG
+Number of messages outstanding for this file.
+.It DATA
+The location of the vnode table entry or socket structure for this file.
+.It OFFSET
+The file offset (see
+.Xr lseek 2 ) .
+.El
+.It Fl s
+Print information about swap space usage on all the
+swap areas compiled into the kernel.
+The first column is the device name of the partition. The next column is
+the total space available in the partition. The
+.Ar Used
+column indicates the total blocks used so far; the
+.Ar Available
+column indicates how much space is remaining on each partition.
+The
+.Ar Capacity
+reports the percentage of space used.
+.Pp
+If more than one partition is configured into the system, totals for all
+of the statistics will be reported in the final line of the report.
+.It Fl t
+Print table for terminals
+with these headings:
+.Bl -tag -width indent
+.It RAW
+Number of characters in raw input queue.
+.It CAN
+Number of characters in canonicalized input queue.
+.It OUT
+Number of characters in putput queue.
+.It MODE
+See
+.Xr tty 4 .
+.It ADDR
+Physical device address.
+.It DEL
+Number of delimiters (newlines) in canonicalized input queue.
+.It COL
+Calculated column position of terminal.
+.It STATE
+Miscellaneous state variables encoded thus:
+.Bl -tag -width indent
+.It T
+delay timeout in progress
+.It W
+waiting for open to complete
+.It O
+open
+.It F
+outq has been flushed during DMA
+.It C
+carrier is on
+.It B
+busy doing output
+.It A
+process is awaiting output
+.It X
+open for exclusive use
+.It S
+output stopped
+.It H
+hangup on close
+.El
+.It PGRP
+Process group for which this is controlling terminal.
+.It DISC
+Line discipline; blank is old tty
+OTTYDISC
+or
+.Ql new tty
+for
+NTTYDISC
+or
+.Ql net
+for
+NETLDISC
+(see
+.Xr bk 4 ) .
+.El
+.It Fl v
+Print the active vnodes. Each group of vnodes corresponding
+to a particular filesystem is preceded by a two line header. The
+first line consists of the following:
+.Pp
+.Df I
+.No *** MOUNT Em fstype from
+on
+.Em on fsflags
+.De
+.Pp
+where
+.Em fstype
+is one of
+.Em ufs , nfs , mfs , or pc ;
+.Em from
+is the filesystem is mounted from;
+.Em on
+is the directory
+the filesystem is mounted on; and
+.Em fsflags
+is a list
+of optional flags applied to the mount (see
+.Xr mount 8 ) .
+.The second line is a header for the individual fields ,
+the first part of which are fixed, and the second part are filesystem
+type specific. The headers common to all vnodes are:
+.Bl -tag -width indent
+.It ADDR
+Location of this vnode.
+.It TYP
+File type.
+.It VFLAG
+.Pp
+A list of letters representing vnode flags:
+.Bl -tag -width indent
+.It R
+\- VROOT
+.It T
+\- VTEXT
+.It L
+\- VXLOCK
+.It W
+\- VXWANT
+.It E
+\- VEXLOCK
+.It S
+\- VSHLOCK
+.It T
+\- VLWAIT
+.It A
+\- VALIASED
+.It B
+\- VBWAIT
+.El
+.Pp
+.It USE
+The number of references to this vnode.
+.It HOLD
+The number of I/O buffers held by this vnode.
+.It FILEID
+The vnode fileid.
+In the case of
+.Em ufs
+this is the inode number.
+.It IFLAG
+Miscellaneous filesystem specific state variables encoded thus:
+.Bl -tag -width indent
+.It "For ufs:"
+.Pp
+.Bl -tag -width indent
+.It L
+locked
+.It U
+update time
+.Pq Xr fs 5
+must be corrected
+.It A
+access time must be corrected
+.It W
+wanted by another process (L flag is on)
+.It C
+changed time must be corrected
+.It S
+shared lock applied
+.It E
+exclusive lock applied
+.It Z
+someone waiting for a lock
+.It M
+contains modifications
+.It R
+has a rename in progress
+.El
+.It "For nfs:"
+.Bl -tag -width indent
+.It W
+waiting for I/O buffer flush to complete
+.It P
+I/O buffers being flushed
+.It M
+locally modified data exists
+.It E
+an earlier write failed
+.It X
+non-cacheable lease (nqnfs)
+.It O
+write lease (nqnfs)
+.It G
+lease was evicted (nqnfs)
+.El
+.El
+.It SIZ/RDEV
+Number of bytes in an ordinary file, or
+major and minor device of special file.
+.El
+.El
+.Sh FILES
+.Bl -tag -width /dev/kmemxxx -compact
+.It Pa /vmunix
+namelist
+.It Pa /dev/kmem
+default source of tables
+.El
+.Sh SEE ALSO
+.Xr iostat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr vmstat 1 ,
+.Xr stat 2 ,
+.Xr fs 5 ,
+.Rs
+.Rt Tn UNIX Rt Implementation ,
+.Ra K. Thompson
+.Re
+.Sh BUGS
+Swap statistics are reported for all swap partitions compiled into the kernel,
+regardless of whether those partitions are being used.
+.Pp
+Does not understand NFS swap servers.
+.Sh HISTORY
+The
+.Nm pstat
+command appeared in 4.0BSD.
diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c
new file mode 100644
index 0000000..0a3cdea
--- /dev/null
+++ b/usr.sbin/pstat/pstat.c
@@ -0,0 +1,1110 @@
+/*-
+ * Copyright (c) 1980, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1980, 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pstat.c 8.9 (Berkeley) 2/16/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
+#include <sys/map.h>
+#include <sys/ucred.h>
+#define KERNEL
+#include <sys/file.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#define NFS
+#include <sys/mount.h>
+#undef NFS
+#undef KERNEL
+#include <sys/stat.h>
+#include <nfs/nfsnode.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct nlist nl[] = {
+#define VM_SWAPMAP 0
+ { "_swapmap" }, /* list of free swap areas */
+#define VM_NSWAPMAP 1
+ { "_nswapmap" },/* size of the swap map */
+#define VM_SWDEVT 2
+ { "_swdevt" }, /* list of swap devices and sizes */
+#define VM_NSWAP 3
+ { "_nswap" }, /* size of largest swap device */
+#define VM_NSWDEV 4
+ { "_nswdev" }, /* number of swap devices */
+#define VM_DMMAX 5
+ { "_dmmax" }, /* maximum size of a swap block */
+#define V_MOUNTLIST 6
+ { "_mountlist" }, /* address of head of mount list. */
+#define V_NUMV 7
+ { "_numvnodes" },
+#define FNL_NFILE 8
+ {"_nfiles"},
+#define FNL_MAXFILE 9
+ {"_maxfiles"},
+#define NLMANDATORY FNL_MAXFILE /* names up to here are mandatory */
+#define VM_NISWAP NLMANDATORY + 1
+ { "_niswap" },
+#define VM_NISWDEV NLMANDATORY + 2
+ { "_niswdev" },
+#define SCONS NLMANDATORY + 3
+ { "_cons" },
+#define SPTY NLMANDATORY + 4
+ { "_pt_tty" },
+#define SNPTY NLMANDATORY + 5
+ { "_npty" },
+
+#ifdef hp300
+#define SDCA (SNPTY+1)
+ { "_dca_tty" },
+#define SNDCA (SNPTY+2)
+ { "_ndca" },
+#define SDCM (SNPTY+3)
+ { "_dcm_tty" },
+#define SNDCM (SNPTY+4)
+ { "_ndcm" },
+#define SDCL (SNPTY+5)
+ { "_dcl_tty" },
+#define SNDCL (SNPTY+6)
+ { "_ndcl" },
+#define SITE (SNPTY+7)
+ { "_ite_tty" },
+#define SNITE (SNPTY+8)
+ { "_nite" },
+#endif
+
+#ifdef mips
+#define SDC (SNPTY+1)
+ { "_dc_tty" },
+#define SNDC (SNPTY+2)
+ { "_dc_cnt" },
+#endif
+
+ { "" }
+};
+
+int usenumflag;
+int totalflag;
+char *nlistf = NULL;
+char *memf = NULL;
+kvm_t *kd;
+
+#define SVAR(var) __STRING(var) /* to force expansion */
+#define KGET(idx, var) \
+ KGET1(idx, &var, sizeof(var), SVAR(var))
+#define KGET1(idx, p, s, msg) \
+ KGET2(nl[idx].n_value, p, s, msg)
+#define KGET2(addr, p, s, msg) \
+ if (kvm_read(kd, (u_long)(addr), p, s) != s) \
+ warnx("cannot read %s: %s", msg, kvm_geterr(kd))
+#define KGETRET(addr, p, s, msg) \
+ if (kvm_read(kd, (u_long)(addr), p, s) != s) { \
+ warnx("cannot read %s: %s", msg, kvm_geterr(kd)); \
+ return (0); \
+ }
+
+void filemode __P((void));
+int getfiles __P((char **, int *));
+struct mount *
+ getmnt __P((struct mount *));
+struct e_vnode *
+ kinfo_vnodes __P((int *));
+struct e_vnode *
+ loadvnodes __P((int *));
+void mount_print __P((struct mount *));
+void nfs_header __P((void));
+int nfs_print __P((struct vnode *));
+void swapmode __P((void));
+void ttymode __P((void));
+void ttyprt __P((struct tty *, int));
+void ttytype __P((struct tty *, char *, int, int));
+void ufs_header __P((void));
+int ufs_print __P((struct vnode *));
+void usage __P((void));
+void vnode_header __P((void));
+void vnode_print __P((struct vnode *, struct vnode *));
+void vnodemode __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ int ch, i, quit, ret;
+ int fileflag, swapflag, ttyflag, vnodeflag;
+ char buf[_POSIX2_LINE_MAX];
+
+ fileflag = swapflag = ttyflag = vnodeflag = 0;
+ while ((ch = getopt(argc, argv, "TM:N:finstv")) != EOF)
+ switch (ch) {
+ case 'f':
+ fileflag = 1;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ usenumflag = 1;
+ break;
+ case 's':
+ swapflag = 1;
+ break;
+ case 'T':
+ totalflag = 1;
+ break;
+ case 't':
+ ttyflag = 1;
+ break;
+ case 'v':
+ case 'i': /* Backward compatibility. */
+ vnodeflag = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ if (nlistf != NULL || memf != NULL)
+ (void)setgid(getgid());
+
+ if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == 0)
+ errx(1, "kvm_openfiles: %s", buf);
+ if ((ret = kvm_nlist(kd, nl)) != 0) {
+ if (ret == -1)
+ errx(1, "kvm_nlist: %s", kvm_geterr(kd));
+ for (i = quit = 0; i <= NLMANDATORY; i++)
+ if (!nl[i].n_value) {
+ quit = 1;
+ warnx("undefined symbol: %s\n", nl[i].n_name);
+ }
+ if (quit)
+ exit(1);
+ }
+ if (!(fileflag | vnodeflag | ttyflag | swapflag | totalflag))
+ usage();
+ if (fileflag || totalflag)
+ filemode();
+ if (vnodeflag || totalflag)
+ vnodemode();
+ if (ttyflag)
+ ttymode();
+ if (swapflag || totalflag)
+ swapmode();
+ exit (0);
+}
+
+struct e_vnode {
+ struct vnode *avnode;
+ struct vnode vnode;
+};
+
+void
+vnodemode()
+{
+ register struct e_vnode *e_vnodebase, *endvnode, *evp;
+ register struct vnode *vp;
+ register struct mount *maddr, *mp;
+ int numvnodes;
+
+ e_vnodebase = loadvnodes(&numvnodes);
+ if (totalflag) {
+ (void)printf("%7d vnodes\n", numvnodes);
+ return;
+ }
+ endvnode = e_vnodebase + numvnodes;
+ (void)printf("%d active vnodes\n", numvnodes);
+
+
+#define ST mp->mnt_stat
+ maddr = NULL;
+ for (evp = e_vnodebase; evp < endvnode; evp++) {
+ vp = &evp->vnode;
+ if (vp->v_mount != maddr) {
+ /*
+ * New filesystem
+ */
+ if ((mp = getmnt(vp->v_mount)) == NULL)
+ continue;
+ maddr = vp->v_mount;
+ mount_print(mp);
+ vnode_header();
+ switch(ST.f_type) {
+ case MOUNT_UFS:
+ case MOUNT_MFS:
+ ufs_header();
+ break;
+ case MOUNT_NFS:
+ nfs_header();
+ break;
+ case MOUNT_NONE:
+ case MOUNT_MSDOS:
+ default:
+ break;
+ }
+ (void)printf("\n");
+ }
+ vnode_print(evp->avnode, vp);
+ switch(ST.f_type) {
+ case MOUNT_UFS:
+ case MOUNT_MFS:
+ ufs_print(vp);
+ break;
+ case MOUNT_NFS:
+ nfs_print(vp);
+ break;
+ case MOUNT_NONE:
+ case MOUNT_MSDOS:
+ default:
+ break;
+ }
+ (void)printf("\n");
+ }
+ free(e_vnodebase);
+}
+
+void
+vnode_header()
+{
+ (void)printf("ADDR TYP VFLAG USE HOLD");
+}
+
+void
+vnode_print(avnode, vp)
+ struct vnode *avnode;
+ struct vnode *vp;
+{
+ char *type, flags[16];
+ char *fp = flags;
+ register int flag;
+
+ /*
+ * set type
+ */
+ switch(vp->v_type) {
+ case VNON:
+ type = "non"; break;
+ case VREG:
+ type = "reg"; break;
+ case VDIR:
+ type = "dir"; break;
+ case VBLK:
+ type = "blk"; break;
+ case VCHR:
+ type = "chr"; break;
+ case VLNK:
+ type = "lnk"; break;
+ case VSOCK:
+ type = "soc"; break;
+ case VFIFO:
+ type = "fif"; break;
+ case VBAD:
+ type = "bad"; break;
+ default:
+ type = "unk"; break;
+ }
+ /*
+ * gather flags
+ */
+ flag = vp->v_flag;
+ if (flag & VROOT)
+ *fp++ = 'R';
+ if (flag & VTEXT)
+ *fp++ = 'T';
+ if (flag & VSYSTEM)
+ *fp++ = 'S';
+ if (flag & VXLOCK)
+ *fp++ = 'L';
+ if (flag & VXWANT)
+ *fp++ = 'W';
+ if (flag & VBWAIT)
+ *fp++ = 'B';
+ if (flag & VALIASED)
+ *fp++ = 'A';
+ if (flag == 0)
+ *fp++ = '-';
+ *fp = '\0';
+ (void)printf("%8x %s %5s %4d %4d",
+ avnode, type, flags, vp->v_usecount, vp->v_holdcnt);
+}
+
+void
+ufs_header()
+{
+ (void)printf(" FILEID IFLAG RDEV|SZ");
+}
+
+int
+ufs_print(vp)
+ struct vnode *vp;
+{
+ register int flag;
+ struct inode inode, *ip = &inode;
+ char flagbuf[16], *flags = flagbuf;
+ char *name;
+ mode_t type;
+
+ KGETRET(VTOI(vp), &inode, sizeof(struct inode), "vnode's inode");
+ flag = ip->i_flag;
+ if (flag & IN_LOCKED)
+ *flags++ = 'L';
+ if (flag & IN_WANTED)
+ *flags++ = 'W';
+ if (flag & IN_RENAME)
+ *flags++ = 'R';
+ if (flag & IN_UPDATE)
+ *flags++ = 'U';
+ if (flag & IN_ACCESS)
+ *flags++ = 'A';
+ if (flag & IN_CHANGE)
+ *flags++ = 'C';
+ if (flag & IN_MODIFIED)
+ *flags++ = 'M';
+ if (flag & IN_SHLOCK)
+ *flags++ = 'S';
+ if (flag & IN_EXLOCK)
+ *flags++ = 'E';
+ if (flag & IN_LWAIT)
+ *flags++ = 'Z';
+ if (flag == 0)
+ *flags++ = '-';
+ *flags = '\0';
+
+ (void)printf(" %6d %5s", ip->i_number, flagbuf);
+ type = ip->i_mode & S_IFMT;
+ if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
+ if (usenumflag || ((name = devname(ip->i_rdev, type)) == NULL))
+ (void)printf(" %2d,%-2d",
+ major(ip->i_rdev), minor(ip->i_rdev));
+ else
+ (void)printf(" %7s", name);
+ else
+ (void)printf(" %7qd", ip->i_size);
+ return (0);
+}
+
+void
+nfs_header()
+{
+ (void)printf(" FILEID NFLAG RDEV|SZ");
+}
+
+int
+nfs_print(vp)
+ struct vnode *vp;
+{
+ struct nfsnode nfsnode, *np = &nfsnode;
+ char flagbuf[16], *flags = flagbuf;
+ register int flag;
+ char *name;
+ mode_t type;
+
+ KGETRET(VTONFS(vp), &nfsnode, sizeof(nfsnode), "vnode's nfsnode");
+ flag = np->n_flag;
+ if (flag & NFLUSHWANT)
+ *flags++ = 'W';
+ if (flag & NFLUSHINPROG)
+ *flags++ = 'P';
+ if (flag & NMODIFIED)
+ *flags++ = 'M';
+ if (flag & NWRITEERR)
+ *flags++ = 'E';
+ if (flag & NQNFSNONCACHE)
+ *flags++ = 'X';
+ if (flag & NQNFSWRITE)
+ *flags++ = 'O';
+ if (flag & NQNFSEVICTED)
+ *flags++ = 'G';
+ if (flag == 0)
+ *flags++ = '-';
+ *flags = '\0';
+
+#define VT np->n_vattr
+ (void)printf(" %6d %5s", VT.va_fileid, flagbuf);
+ type = VT.va_mode & S_IFMT;
+ if (S_ISCHR(VT.va_mode) || S_ISBLK(VT.va_mode))
+ if (usenumflag || ((name = devname(VT.va_rdev, type)) == NULL))
+ (void)printf(" %2d,%-2d",
+ major(VT.va_rdev), minor(VT.va_rdev));
+ else
+ (void)printf(" %7s", name);
+ else
+ (void)printf(" %7qd", np->n_size);
+ return (0);
+}
+
+/*
+ * Given a pointer to a mount structure in kernel space,
+ * read it in and return a usable pointer to it.
+ */
+struct mount *
+getmnt(maddr)
+ struct mount *maddr;
+{
+ static struct mtab {
+ struct mtab *next;
+ struct mount *maddr;
+ struct mount mount;
+ } *mhead = NULL;
+ register struct mtab *mt;
+
+ for (mt = mhead; mt != NULL; mt = mt->next)
+ if (maddr == mt->maddr)
+ return (&mt->mount);
+ if ((mt = malloc(sizeof(struct mtab))) == NULL)
+ err(1, NULL);
+ KGETRET(maddr, &mt->mount, sizeof(struct mount), "mount table");
+ mt->maddr = maddr;
+ mt->next = mhead;
+ mhead = mt;
+ return (&mt->mount);
+}
+
+void
+mount_print(mp)
+ struct mount *mp;
+{
+ register int flags;
+ char *type;
+
+#define ST mp->mnt_stat
+ (void)printf("*** MOUNT ");
+ switch (ST.f_type) {
+ case MOUNT_NONE:
+ type = "none";
+ break;
+ case MOUNT_UFS:
+ type = "ufs";
+ break;
+ case MOUNT_NFS:
+ type = "nfs";
+ break;
+ case MOUNT_MFS:
+ type = "mfs";
+ break;
+ case MOUNT_MSDOS:
+ type = "pc";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ (void)printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname);
+ if (flags = mp->mnt_flag) {
+ char *comma = "(";
+
+ putchar(' ');
+ /* user visable flags */
+ if (flags & MNT_RDONLY) {
+ (void)printf("%srdonly", comma);
+ flags &= ~MNT_RDONLY;
+ comma = ",";
+ }
+ if (flags & MNT_SYNCHRONOUS) {
+ (void)printf("%ssynchronous", comma);
+ flags &= ~MNT_SYNCHRONOUS;
+ comma = ",";
+ }
+ if (flags & MNT_NOEXEC) {
+ (void)printf("%snoexec", comma);
+ flags &= ~MNT_NOEXEC;
+ comma = ",";
+ }
+ if (flags & MNT_NOSUID) {
+ (void)printf("%snosuid", comma);
+ flags &= ~MNT_NOSUID;
+ comma = ",";
+ }
+ if (flags & MNT_NODEV) {
+ (void)printf("%snodev", comma);
+ flags &= ~MNT_NODEV;
+ comma = ",";
+ }
+ if (flags & MNT_EXPORTED) {
+ (void)printf("%sexport", comma);
+ flags &= ~MNT_EXPORTED;
+ comma = ",";
+ }
+ if (flags & MNT_EXRDONLY) {
+ (void)printf("%sexrdonly", comma);
+ flags &= ~MNT_EXRDONLY;
+ comma = ",";
+ }
+ if (flags & MNT_LOCAL) {
+ (void)printf("%slocal", comma);
+ flags &= ~MNT_LOCAL;
+ comma = ",";
+ }
+ if (flags & MNT_QUOTA) {
+ (void)printf("%squota", comma);
+ flags &= ~MNT_QUOTA;
+ comma = ",";
+ }
+ /* filesystem control flags */
+ if (flags & MNT_UPDATE) {
+ (void)printf("%supdate", comma);
+ flags &= ~MNT_UPDATE;
+ comma = ",";
+ }
+ if (flags & MNT_MLOCK) {
+ (void)printf("%slock", comma);
+ flags &= ~MNT_MLOCK;
+ comma = ",";
+ }
+ if (flags & MNT_MWAIT) {
+ (void)printf("%swait", comma);
+ flags &= ~MNT_MWAIT;
+ comma = ",";
+ }
+ if (flags & MNT_MPBUSY) {
+ (void)printf("%sbusy", comma);
+ flags &= ~MNT_MPBUSY;
+ comma = ",";
+ }
+ if (flags & MNT_MPWANT) {
+ (void)printf("%swant", comma);
+ flags &= ~MNT_MPWANT;
+ comma = ",";
+ }
+ if (flags & MNT_UNMOUNT) {
+ (void)printf("%sunmount", comma);
+ flags &= ~MNT_UNMOUNT;
+ comma = ",";
+ }
+ if (flags)
+ (void)printf("%sunknown_flags:%x", comma, flags);
+ (void)printf(")");
+ }
+ (void)printf("\n");
+#undef ST
+}
+
+struct e_vnode *
+loadvnodes(avnodes)
+ int *avnodes;
+{
+ int mib[2];
+ size_t copysize;
+ struct e_vnode *vnodebase;
+
+ if (memf != NULL) {
+ /*
+ * do it by hand
+ */
+ return (kinfo_vnodes(avnodes));
+ }
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_VNODE;
+ if (sysctl(mib, 2, NULL, &copysize, NULL, 0) == -1)
+ err(1, "sysctl: KERN_VNODE");
+ if ((vnodebase = malloc(copysize)) == NULL)
+ err(1, NULL);
+ if (sysctl(mib, 2, vnodebase, &copysize, NULL, 0) == -1)
+ err(1, "sysctl: KERN_VNODE");
+ if (copysize % sizeof(struct e_vnode))
+ errx(1, "vnode size mismatch");
+ *avnodes = copysize / sizeof(struct e_vnode);
+
+ return (vnodebase);
+}
+
+/*
+ * simulate what a running kernel does in in kinfo_vnode
+ */
+struct e_vnode *
+kinfo_vnodes(avnodes)
+ int *avnodes;
+{
+ struct mntlist mountlist;
+ struct mount *mp, mount;
+ struct vnode *vp, vnode;
+ char *vbuf, *evbuf, *bp;
+ int num, numvnodes;
+
+#define VPTRSZ sizeof(struct vnode *)
+#define VNODESZ sizeof(struct vnode)
+
+ KGET(V_NUMV, numvnodes);
+ if ((vbuf = malloc((numvnodes + 20) * (VPTRSZ + VNODESZ))) == NULL)
+ err(1, NULL);
+ bp = vbuf;
+ evbuf = vbuf + (numvnodes + 20) * (VPTRSZ + VNODESZ);
+ KGET(V_MOUNTLIST, mountlist);
+ for (num = 0, mp = mountlist.tqh_first;
+ mp != NULL; mp = mp->mnt_list.tqe_next) {
+ KGET2(mp, &mount, sizeof(mount), "mount entry");
+ for (vp = mount.mnt_vnodelist.lh_first;
+ vp != NULL; vp = vp->v_mntvnodes.le_next) {
+ KGET2(vp, &vnode, sizeof(vnode), "vnode");
+ if ((bp + VPTRSZ + VNODESZ) > evbuf)
+ /* XXX - should realloc */
+ errx(1, "no more room for vnodes");
+ memmove(bp, &vp, VPTRSZ);
+ bp += VPTRSZ;
+ memmove(bp, &vnode, VNODESZ);
+ bp += VNODESZ;
+ num++;
+ }
+ }
+ *avnodes = num;
+ return ((struct e_vnode *)vbuf);
+}
+
+char hdr[]=" LINE RAW CAN OUT HWT LWT COL STATE SESS PGID DISC\n";
+int ttyspace = 128;
+
+void
+ttymode()
+{
+ struct tty *tty;
+
+ if ((tty = malloc(ttyspace * sizeof(*tty))) == NULL)
+ err(1, NULL);
+#ifndef hp300
+ (void)printf("1 console\n");
+ KGET(SCONS, *tty);
+ (void)printf(hdr);
+ ttyprt(&tty[0], 0);
+#endif
+#ifdef vax
+ if (nl[SNQD].n_type != 0)
+ qdss();
+ if (nl[SNDZ].n_type != 0)
+ ttytype(tty, "dz", SDZ, SNDZ);
+ if (nl[SNDH].n_type != 0)
+ ttytype(tty, "dh", SDH, SNDH);
+ if (nl[SNDMF].n_type != 0)
+ ttytype(tty, "dmf", SDMF, SNDMF);
+ if (nl[SNDHU].n_type != 0)
+ ttytype(tty, "dhu", SDHU, SNDHU);
+ if (nl[SNDMZ].n_type != 0)
+ ttytype(tty, "dmz", SDMZ, SNDMZ);
+#endif
+#ifdef tahoe
+ if (nl[SNVX].n_type != 0)
+ ttytype(tty, "vx", SVX, SNVX);
+ if (nl[SNMP].n_type != 0)
+ ttytype(tty, "mp", SMP, SNMP);
+#endif
+#ifdef hp300
+ if (nl[SNITE].n_type != 0)
+ ttytype(tty, "ite", SITE, SNITE);
+ if (nl[SNDCA].n_type != 0)
+ ttytype(tty, "dca", SDCA, SNDCA);
+ if (nl[SNDCM].n_type != 0)
+ ttytype(tty, "dcm", SDCM, SNDCM);
+ if (nl[SNDCL].n_type != 0)
+ ttytype(tty, "dcl", SDCL, SNDCL);
+#endif
+#ifdef mips
+ if (nl[SNDC].n_type != 0)
+ ttytype(tty, "dc", SDC, SNDC);
+#endif
+ if (nl[SNPTY].n_type != 0)
+ ttytype(tty, "pty", SPTY, SNPTY);
+}
+
+void
+ttytype(tty, name, type, number)
+ register struct tty *tty;
+ char *name;
+ int type, number;
+{
+ register struct tty *tp;
+ int ntty;
+
+ if (tty == NULL)
+ return;
+ KGET(number, ntty);
+ (void)printf("%d %s %s\n", ntty, name, (ntty == 1) ? "line" : "lines");
+ if (ntty > ttyspace) {
+ ttyspace = ntty;
+ if ((tty = realloc(tty, ttyspace * sizeof(*tty))) == 0)
+ err(1, NULL);
+ }
+ KGET1(type, tty, ntty * sizeof(struct tty), "tty structs");
+ (void)printf(hdr);
+ for (tp = tty; tp < &tty[ntty]; tp++)
+ ttyprt(tp, tp - tty);
+}
+
+struct {
+ int flag;
+ char val;
+} ttystates[] = {
+ { TS_WOPEN, 'W'},
+ { TS_ISOPEN, 'O'},
+ { TS_CARR_ON, 'C'},
+ { TS_TIMEOUT, 'T'},
+ { TS_FLUSH, 'F'},
+ { TS_BUSY, 'B'},
+ { TS_ASLEEP, 'A'},
+ { TS_XCLUDE, 'X'},
+ { TS_TTSTOP, 'S'},
+ { TS_TBLOCK, 'K'},
+ { TS_ASYNC, 'Y'},
+ { TS_BKSL, 'D'},
+ { TS_ERASE, 'E'},
+ { TS_LNCH, 'L'},
+ { TS_TYPEN, 'P'},
+ { TS_CNTTB, 'N'},
+ { 0, '\0'},
+};
+
+void
+ttyprt(tp, line)
+ register struct tty *tp;
+ int line;
+{
+ register int i, j;
+ pid_t pgid;
+ char *name, state[20];
+
+ if (usenumflag || tp->t_dev == 0 ||
+ (name = devname(tp->t_dev, S_IFCHR)) == NULL)
+ (void)printf("%7d ", line);
+ else
+ (void)printf("%7s ", name);
+ (void)printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc);
+ (void)printf("%3d %4d %3d %3d ", tp->t_outq.c_cc,
+ tp->t_hiwat, tp->t_lowat, tp->t_column);
+ for (i = j = 0; ttystates[i].flag; i++)
+ if (tp->t_state&ttystates[i].flag)
+ state[j++] = ttystates[i].val;
+ if (j == 0)
+ state[j++] = '-';
+ state[j] = '\0';
+ (void)printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE);
+ pgid = 0;
+ if (tp->t_pgrp != NULL)
+ KGET2(&tp->t_pgrp->pg_id, &pgid, sizeof(pid_t), "pgid");
+ (void)printf("%6d ", pgid);
+ switch (tp->t_line) {
+ case TTYDISC:
+ (void)printf("term\n");
+ break;
+ case TABLDISC:
+ (void)printf("tab\n");
+ break;
+ case SLIPDISC:
+ (void)printf("slip\n");
+ break;
+ default:
+ (void)printf("%d\n", tp->t_line);
+ break;
+ }
+}
+
+void
+filemode()
+{
+ register struct file *fp;
+ struct file *addr;
+ char *buf, flagbuf[16], *fbp;
+ int len, maxfile, nfile;
+ static char *dtypes[] = { "???", "inode", "socket" };
+
+ KGET(FNL_MAXFILE, maxfile);
+ if (totalflag) {
+ KGET(FNL_NFILE, nfile);
+ (void)printf("%3d/%3d files\n", nfile, maxfile);
+ return;
+ }
+ if (getfiles(&buf, &len) == -1)
+ return;
+ /*
+ * Getfiles returns in malloc'd memory a pointer to the first file
+ * structure, and then an array of file structs (whose addresses are
+ * derivable from the previous entry).
+ */
+ addr = *((struct file **)buf);
+ fp = (struct file *)(buf + sizeof(struct file *));
+ nfile = (len - sizeof(struct file *)) / sizeof(struct file);
+
+ (void)printf("%d/%d open files\n", nfile, maxfile);
+ (void)printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
+ for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) {
+ if ((unsigned)fp->f_type > DTYPE_SOCKET)
+ continue;
+ (void)printf("%x ", addr);
+ (void)printf("%-8.8s", dtypes[fp->f_type]);
+ fbp = flagbuf;
+ if (fp->f_flag & FREAD)
+ *fbp++ = 'R';
+ if (fp->f_flag & FWRITE)
+ *fbp++ = 'W';
+ if (fp->f_flag & FAPPEND)
+ *fbp++ = 'A';
+#ifdef FSHLOCK /* currently gone */
+ if (fp->f_flag & FSHLOCK)
+ *fbp++ = 'S';
+ if (fp->f_flag & FEXLOCK)
+ *fbp++ = 'X';
+#endif
+ if (fp->f_flag & FASYNC)
+ *fbp++ = 'I';
+ *fbp = '\0';
+ (void)printf("%6s %3d", flagbuf, fp->f_count);
+ (void)printf(" %3d", fp->f_msgcount);
+ (void)printf(" %8.1x", fp->f_data);
+ if (fp->f_offset < 0)
+ (void)printf(" %qx\n", fp->f_offset);
+ else
+ (void)printf(" %qd\n", fp->f_offset);
+ }
+ free(buf);
+}
+
+int
+getfiles(abuf, alen)
+ char **abuf;
+ int *alen;
+{
+ size_t len;
+ int mib[2];
+ char *buf;
+
+ /*
+ * XXX
+ * Add emulation of KINFO_FILE here.
+ */
+ if (memf != NULL)
+ errx(1, "files on dead kernel, not implemented\n");
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_FILE;
+ if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) {
+ warn("sysctl: KERN_FILE");
+ return (-1);
+ }
+ if ((buf = malloc(len)) == NULL)
+ err(1, NULL);
+ if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
+ warn("sysctl: KERN_FILE");
+ return (-1);
+ }
+ *abuf = buf;
+ *alen = len;
+ return (0);
+}
+
+/*
+ * swapmode is based on a program called swapinfo written
+ * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
+ */
+void
+swapmode()
+{
+ char *header;
+ int hlen, nswap, nswdev, dmmax, nswapmap, niswap, niswdev;
+ int s, e, div, i, l, avail, nfree, npfree, used;
+ struct swdevt *sw;
+ long blocksize, *perdev;
+ struct map *swapmap, *kswapmap;
+ struct mapent *mp;
+
+ KGET(VM_NSWAP, nswap);
+ KGET(VM_NSWDEV, nswdev);
+ KGET(VM_DMMAX, dmmax);
+ KGET(VM_NSWAPMAP, nswapmap);
+ KGET(VM_SWAPMAP, kswapmap); /* kernel `swapmap' is a pointer */
+ if ((sw = malloc(nswdev * sizeof(*sw))) == NULL ||
+ (perdev = malloc(nswdev * sizeof(*perdev))) == NULL ||
+ (mp = malloc(nswapmap * sizeof(*mp))) == NULL)
+ err(1, "malloc");
+ KGET1(VM_SWDEVT, sw, nswdev * sizeof(*sw), "swdevt");
+ KGET2((long)kswapmap, mp, nswapmap * sizeof(*mp), "swapmap");
+
+ /* Supports sequential swap */
+ if (nl[VM_NISWAP].n_value != 0) {
+ KGET(VM_NISWAP, niswap);
+ KGET(VM_NISWDEV, niswdev);
+ } else {
+ niswap = nswap;
+ niswdev = nswdev;
+ }
+
+ /* First entry in map is `struct map'; rest are mapent's. */
+ swapmap = (struct map *)mp;
+ if (nswapmap != swapmap->m_limit - (struct mapent *)kswapmap)
+ errx(1, "panic: nswapmap goof");
+
+ /* Count up swap space. */
+ nfree = 0;
+ memset(perdev, 0, nswdev * sizeof(*perdev));
+ for (mp++; mp->m_addr != 0; mp++) {
+ s = mp->m_addr; /* start of swap region */
+ e = mp->m_addr + mp->m_size; /* end of region */
+ nfree += mp->m_size;
+
+ /*
+ * Swap space is split up among the configured disks.
+ *
+ * For interleaved swap devices, the first dmmax blocks
+ * of swap space some from the first disk, the next dmmax
+ * blocks from the next, and so on up to niswap blocks.
+ *
+ * Sequential swap devices follow the interleaved devices
+ * (i.e. blocks starting at niswap) in the order in which
+ * they appear in the swdev table. The size of each device
+ * will be a multiple of dmmax.
+ *
+ * The list of free space joins adjacent free blocks,
+ * ignoring device boundries. If we want to keep track
+ * of this information per device, we'll just have to
+ * extract it ourselves. We know that dmmax-sized chunks
+ * cannot span device boundaries (interleaved or sequential)
+ * so we loop over such chunks assigning them to devices.
+ */
+ i = -1;
+ while (s < e) { /* XXX this is inefficient */
+ int bound = roundup(s+1, dmmax);
+
+ if (bound > e)
+ bound = e;
+ if (bound <= niswap) {
+ /* Interleaved swap chunk. */
+ if (i == -1)
+ i = (s / dmmax) % niswdev;
+ perdev[i] += bound - s;
+ if (++i >= niswdev)
+ i = 0;
+ } else {
+ /* Sequential swap chunk. */
+ if (i < niswdev) {
+ i = niswdev;
+ l = niswap + sw[i].sw_nblks;
+ }
+ while (s >= l) {
+ /* XXX don't die on bogus blocks */
+ if (i == nswdev-1)
+ break;
+ l += sw[++i].sw_nblks;
+ }
+ perdev[i] += bound - s;
+ }
+ s = bound;
+ }
+ }
+
+ header = getbsize(&hlen, &blocksize);
+ if (!totalflag)
+ (void)printf("%-11s %*s %8s %8s %8s %s\n",
+ "Device", hlen, header,
+ "Used", "Avail", "Capacity", "Type");
+ div = blocksize / 512;
+ avail = npfree = 0;
+ for (i = 0; i < nswdev; i++) {
+ int xsize, xfree;
+
+ if (!totalflag)
+ (void)printf("/dev/%-6s %*d ",
+ devname(sw[i].sw_dev, S_IFBLK),
+ hlen, sw[i].sw_nblks / div);
+
+ /*
+ * Don't report statistics for partitions which have not
+ * yet been activated via swapon(8).
+ */
+ if (!(sw[i].sw_flags & SW_FREED)) {
+ if (totalflag)
+ continue;
+ (void)printf(" *** not available for swapping ***\n");
+ continue;
+ }
+ xsize = sw[i].sw_nblks;
+ xfree = perdev[i];
+ used = xsize - xfree;
+ npfree++;
+ avail += xsize;
+ if (totalflag)
+ continue;
+ (void)printf("%8d %8d %5.0f%% %s\n",
+ used / div, xfree / div,
+ (double)used / (double)xsize * 100.0,
+ (sw[i].sw_flags & SW_SEQUENTIAL) ?
+ "Sequential" : "Interleaved");
+ }
+
+ /*
+ * If only one partition has been set up via swapon(8), we don't
+ * need to bother with totals.
+ */
+ used = avail - nfree;
+ if (totalflag) {
+ (void)printf("%dM/%dM swap space\n", used / 2048, avail / 2048);
+ return;
+ }
+ if (npfree > 1) {
+ (void)printf("%-11s %*d %8d %8d %5.0f%%\n",
+ "Total", hlen, avail / div, used / div, nfree / div,
+ (double)used / (double)avail * 100.0);
+ }
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: pstat -Tfnstv [system] [-M core] [-N system]\n");
+ exit(1);
+}
diff --git a/usr.sbin/pwd_mkdb/Makefile b/usr.sbin/pwd_mkdb/Makefile
new file mode 100644
index 0000000..f1e9020
--- /dev/null
+++ b/usr.sbin/pwd_mkdb/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= pwd_mkdb
+SRCS= pw_scan.c pwd_mkdb.c
+MAN8= pwd_mkdb.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pwd_mkdb/pw_scan.c b/usr.sbin/pwd_mkdb/pw_scan.c
new file mode 100644
index 0000000..3093ac2
--- /dev/null
+++ b/usr.sbin/pwd_mkdb/pw_scan.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+/*
+ * This module is used to "verify" password entries by chpass(1) and
+ * pwd_mkdb(8).
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+int
+pw_scan(bp, pw)
+ char *bp;
+ struct passwd *pw;
+{
+ long id;
+ int root;
+ char *p, *sh;
+
+ if (!(pw->pw_name = strsep(&bp, ":"))) /* login */
+ goto fmt;
+ root = !strcmp(pw->pw_name, "root");
+
+ if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */
+ goto fmt;
+
+ if (!(p = strsep(&bp, ":"))) /* uid */
+ goto fmt;
+ id = atol(p);
+ if (root && id) {
+ warnx("root uid should be 0");
+ return (0);
+ }
+ if (id > USHRT_MAX) {
+ warnx("%s > max uid value (%d)", p, USHRT_MAX);
+ return (0);
+ }
+ pw->pw_uid = id;
+
+ if (!(p = strsep(&bp, ":"))) /* gid */
+ goto fmt;
+ id = atol(p);
+ if (id > USHRT_MAX) {
+ warnx("%s > max gid value (%d)", p, USHRT_MAX);
+ return (0);
+ }
+ pw->pw_gid = id;
+
+ pw->pw_class = strsep(&bp, ":"); /* class */
+ if (!(p = strsep(&bp, ":"))) /* change */
+ goto fmt;
+ pw->pw_change = atol(p);
+ if (!(p = strsep(&bp, ":"))) /* expire */
+ goto fmt;
+ pw->pw_expire = atol(p);
+ pw->pw_gecos = strsep(&bp, ":"); /* gecos */
+ pw->pw_dir = strsep(&bp, ":"); /* directory */
+ if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */
+ goto fmt;
+
+ p = pw->pw_shell;
+ if (root && *p) /* empty == /bin/sh */
+ for (setusershell();;) {
+ if (!(sh = getusershell())) {
+ warnx("warning, unknown root shell");
+ break;
+ }
+ if (!strcmp(p, sh))
+ break;
+ }
+
+ if (p = strsep(&bp, ":")) { /* too many */
+fmt: warnx("corrupted entry");
+ return (0);
+ }
+ return (1);
+}
diff --git a/usr.sbin/pwd_mkdb/pw_scan.h b/usr.sbin/pwd_mkdb/pw_scan.h
new file mode 100644
index 0000000..d1d4bc1
--- /dev/null
+++ b/usr.sbin/pwd_mkdb/pw_scan.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94
+ */
+
+extern int pw_scan __P((char *, struct passwd *));
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.8 b/usr.sbin/pwd_mkdb/pwd_mkdb.8
new file mode 100644
index 0000000..01bc1c2
--- /dev/null
+++ b/usr.sbin/pwd_mkdb/pwd_mkdb.8
@@ -0,0 +1,128 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pwd_mkdb.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PWD_MKDB 8
+.Os
+.Sh NAME
+.Nm pwd_mkdb
+.Nd "generate the password databases"
+.Sh SYNOPSIS
+.Nm pwd_mkdb
+.Op Fl p
+.Ar file
+.Sh DESCRIPTION
+.Nm Pwd_mkdb
+creates
+.Xr db 3
+style secure and insecure databases for the specified file.
+These databases are then installed into
+.Dq Pa /etc/spwd.db
+and
+.Dq Pa /etc/pwd.db
+respectively.
+The file is installed into
+.Dq Pa /etc/master.passwd .
+The file must be in the correct format (see
+.Xr passwd 5 ) .
+It is important to note that the format used in this system is
+different from the historic Version 7 style format.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl p
+Create a Version 7 style password file and install it into
+.Dq Pa /etc/passwd .
+.El
+.Pp
+The two databases differ in that the secure version contains the user's
+encrypted password and the insecure version has an asterisk (``*'')
+.Pp
+The databases are used by the C library password routines (see
+.Xr getpwent 3 ) .
+.Pp
+.Nm Pwd_mkdb
+exits zero on success, non-zero on failure.
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /var/db/pwd.db
+The insecure password database file.
+.It Pa /var/db/pwd.db.tmp
+A temporary file.
+.It Pa /var/db/spwd.db
+The secure password database file.
+.It Pa /var/db/spwd.db.tmp
+A temporary file.
+.It Pa /etc/master.passwd
+The current password file.
+.It Pa /etc/passwd
+A Version 7 format password file.
+.El
+.Sh BUGS
+Because of the necessity for atomic update of the password files,
+.Nm pwd_mkdb
+uses
+.Xr rename 2
+to install them.
+This, however, requires that the file specified on the command line live
+on the same file system as the
+.Dq Pa /etc
+directory.
+.Pp
+There are the obvious races with multiple people running
+.Nm pwd_mkdb
+on different password files at the same time.
+The front-ends to
+.Nm pwd_mkdb ,
+.Xr chpass 1 ,
+.Xr passwd 1
+and
+.Xr vipw 8 ,
+handle the locking necessary to avoid this problem.
+.Sh COMPATIBILITY
+Previous versions of the system had a program similar to
+.Nm pwd_mkdb ,
+.Xr mkpasswd 8 ,
+which built
+.Xr dbm 3
+style databases for the password file but depended on the calling programs
+to install them.
+The program was renamed in order that previous users of the program
+not be surprised by the changes in functionality.
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr passwd 1 ,
+.Xr db 3 ,
+.Xr getpwent 3 ,
+.Xr passwd 5 ,
+.Xr vipw 8
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.c b/usr.sbin/pwd_mkdb/pwd_mkdb.c
new file mode 100644
index 0000000..7ccc91f
--- /dev/null
+++ b/usr.sbin/pwd_mkdb/pwd_mkdb.c
@@ -0,0 +1,387 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+#define INSECURE 1
+#define SECURE 2
+#define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#define PERM_SECURE (S_IRUSR|S_IWUSR)
+
+HASHINFO openinfo = {
+ 4096, /* bsize */
+ 32, /* ffactor */
+ 256, /* nelem */
+ 2048 * 1024, /* cachesize */
+ NULL, /* hash() */
+ 0 /* lorder */
+};
+
+static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
+static struct passwd pwd; /* password structure */
+static char *pname; /* password file name */
+
+void cleanup __P((void));
+void error __P((char *));
+void mv __P((char *, char *));
+int scan __P((FILE *, struct passwd *));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ DB *dp, *edp;
+ DBT data, key;
+ FILE *fp, *oldfp;
+ sigset_t set;
+ int ch, cnt, len, makeold, tfd;
+ char *p, *t;
+ char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
+
+ makeold = 0;
+ while ((ch = getopt(argc, argv, "pv")) != EOF)
+ switch(ch) {
+ case 'p': /* create V7 "file.orig" */
+ makeold = 1;
+ break;
+ case 'v': /* backward compatible */
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ /*
+ * This could be changed to allow the user to interrupt.
+ * Probably not worth the effort.
+ */
+ sigemptyset(&set);
+ sigaddset(&set, SIGTSTP);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGQUIT);
+ sigaddset(&set, SIGTERM);
+ (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+
+ /* We don't care what the user wants. */
+ (void)umask(0);
+
+ pname = *argv;
+ /* Open the original password file */
+ if (!(fp = fopen(pname, "r")))
+ error(pname);
+
+ /* Open the temporary insecure password database. */
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+ dp = dbopen(buf,
+ O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
+ if (dp == NULL)
+ error(buf);
+ clean = FILE_INSECURE;
+
+ /*
+ * Open file for old password file. Minor trickiness -- don't want to
+ * chance the file already existing, since someone (stupidly) might
+ * still be using this for permission checking. So, open it first and
+ * fdopen the resulting fd. The resulting file should be readable by
+ * everyone.
+ */
+ if (makeold) {
+ (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+ if ((tfd = open(buf,
+ O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
+ error(buf);
+ if ((oldfp = fdopen(tfd, "w")) == NULL)
+ error(buf);
+ clean = FILE_ORIG;
+ }
+
+ /*
+ * The databases actually contain three copies of the original data.
+ * Each password file entry is converted into a rough approximation
+ * of a ``struct passwd'', with the strings placed inline. This
+ * object is then stored as the data for three separate keys. The
+ * first key * is the pw_name field prepended by the _PW_KEYBYNAME
+ * character. The second key is the pw_uid field prepended by the
+ * _PW_KEYBYUID character. The third key is the line number in the
+ * original file prepended by the _PW_KEYBYNUM character. (The special
+ * characters are prepended to ensure that the keys do not collide.)
+ */
+ data.data = (u_char *)buf;
+ key.data = (u_char *)tbuf;
+ for (cnt = 1; scan(fp, &pwd); ++cnt) {
+#define COMPACT(e) t = e; while (*p++ = *t++);
+ /* Create insecure data. */
+ p = buf;
+ COMPACT(pwd.pw_name);
+ COMPACT("*");
+ memmove(p, &pwd.pw_uid, sizeof(int));
+ p += sizeof(int);
+ memmove(p, &pwd.pw_gid, sizeof(int));
+ p += sizeof(int);
+ memmove(p, &pwd.pw_change, sizeof(time_t));
+ p += sizeof(time_t);
+ COMPACT(pwd.pw_class);
+ COMPACT(pwd.pw_gecos);
+ COMPACT(pwd.pw_dir);
+ COMPACT(pwd.pw_shell);
+ memmove(p, &pwd.pw_expire, sizeof(time_t));
+ p += sizeof(time_t);
+ data.size = p - buf;
+
+ /* Store insecure by name. */
+ tbuf[0] = _PW_KEYBYNAME;
+ len = strlen(pwd.pw_name);
+ memmove(tbuf + 1, pwd.pw_name, len);
+ key.size = len + 1;
+ if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+
+ /* Store insecure by number. */
+ tbuf[0] = _PW_KEYBYNUM;
+ memmove(tbuf + 1, &cnt, sizeof(cnt));
+ key.size = sizeof(cnt) + 1;
+ if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+
+ /* Store insecure by uid. */
+ tbuf[0] = _PW_KEYBYUID;
+ memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
+ key.size = sizeof(pwd.pw_uid) + 1;
+ if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+
+ /* Create original format password file entry */
+ if (makeold)
+ (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
+ pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
+ pwd.pw_dir, pwd.pw_shell);
+ }
+ (void)(dp->close)(dp);
+ if (makeold) {
+ (void)fflush(oldfp);
+ (void)fclose(oldfp);
+ }
+
+ /* Open the temporary encrypted password database. */
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+ edp = dbopen(buf,
+ O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
+ if (!edp)
+ error(buf);
+ clean = FILE_SECURE;
+
+ rewind(fp);
+ for (cnt = 1; scan(fp, &pwd); ++cnt) {
+
+ /* Create secure data. */
+ p = buf;
+ COMPACT(pwd.pw_name);
+ COMPACT(pwd.pw_passwd);
+ memmove(p, &pwd.pw_uid, sizeof(int));
+ p += sizeof(int);
+ memmove(p, &pwd.pw_gid, sizeof(int));
+ p += sizeof(int);
+ memmove(p, &pwd.pw_change, sizeof(time_t));
+ p += sizeof(time_t);
+ COMPACT(pwd.pw_class);
+ COMPACT(pwd.pw_gecos);
+ COMPACT(pwd.pw_dir);
+ COMPACT(pwd.pw_shell);
+ memmove(p, &pwd.pw_expire, sizeof(time_t));
+ p += sizeof(time_t);
+ data.size = p - buf;
+
+ /* Store secure by name. */
+ tbuf[0] = _PW_KEYBYNAME;
+ len = strlen(pwd.pw_name);
+ memmove(tbuf + 1, pwd.pw_name, len);
+ key.size = len + 1;
+ if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+
+ /* Store secure by number. */
+ tbuf[0] = _PW_KEYBYNUM;
+ memmove(tbuf + 1, &cnt, sizeof(cnt));
+ key.size = sizeof(cnt) + 1;
+ if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+
+ /* Store secure by uid. */
+ tbuf[0] = _PW_KEYBYUID;
+ memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
+ key.size = sizeof(pwd.pw_uid) + 1;
+ if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+ error("put");
+ }
+
+ (void)(edp->close)(edp);
+
+ /* Set master.passwd permissions, in case caller forgot. */
+ (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
+ (void)fclose(fp);
+
+ /* Install as the real password files. */
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+ mv(buf, _PATH_MP_DB);
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+ mv(buf, _PATH_SMP_DB);
+ if (makeold) {
+ (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+ mv(buf, _PATH_PASSWD);
+ }
+ /*
+ * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
+ * all use flock(2) on it to block other incarnations of themselves.
+ * The rename means that everything is unlocked, as the original file
+ * can no longer be accessed.
+ */
+ mv(pname, _PATH_MASTERPASSWD);
+ exit(0);
+}
+
+int
+scan(fp, pw)
+ FILE *fp;
+ struct passwd *pw;
+{
+ static int lcnt;
+ static char line[LINE_MAX];
+ char *p;
+
+ if (!fgets(line, sizeof(line), fp))
+ return (0);
+ ++lcnt;
+ /*
+ * ``... if I swallow anything evil, put your fingers down my
+ * throat...''
+ * -- The Who
+ */
+ if (!(p = strchr(line, '\n'))) {
+ warnx("line too long");
+ goto fmt;
+
+ }
+ *p = '\0';
+ if (!pw_scan(line, pw)) {
+ warnx("at line #%d", lcnt);
+fmt: errno = EFTYPE; /* XXX */
+ error(pname);
+ }
+
+ return (1);
+}
+
+void
+mv(from, to)
+ char *from, *to;
+{
+ char buf[MAXPATHLEN];
+
+ if (rename(from, to)) {
+ int sverrno = errno;
+ (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
+ errno = sverrno;
+ error(buf);
+ }
+}
+
+void
+error(name)
+ char *name;
+{
+
+ warn(name);
+ cleanup();
+ exit(1);
+}
+
+void
+cleanup()
+{
+ char buf[MAXPATHLEN];
+
+ switch(clean) {
+ case FILE_ORIG:
+ (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+ (void)unlink(buf);
+ /* FALLTHROUGH */
+ case FILE_SECURE:
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+ (void)unlink(buf);
+ /* FALLTHROUGH */
+ case FILE_INSECURE:
+ (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+ (void)unlink(buf);
+ }
+}
+
+void
+usage()
+{
+
+ (void)fprintf(stderr, "usage: pwd_mkdb [-p] file\n");
+ exit(1);
+}
diff --git a/usr.sbin/quotaon/Makefile b/usr.sbin/quotaon/Makefile
new file mode 100644
index 0000000..b2f571b
--- /dev/null
+++ b/usr.sbin/quotaon/Makefile
@@ -0,0 +1,8 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= quotaon
+MAN8= quotaon.0
+MLINKS= quotaon.8 quotaoff.8
+LINKS= ${BINDIR}/quotaon ${BINDIR}/quotaoff
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/quotaon/quotaon.8 b/usr.sbin/quotaon/quotaon.8
new file mode 100644
index 0000000..8c68d76
--- /dev/null
+++ b/usr.sbin/quotaon/quotaon.8
@@ -0,0 +1,139 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)quotaon.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt QUOTAON 8
+.Os BSD 4.2
+.Sh NAME
+.Nm quotaon ,
+.Nm quotaoff
+.Nd turn filesystem quotas on and off
+.Sh SYNOPSIS
+.Nm quotaon
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm quotaon
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Nm quotaoff
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm quotaoff
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Sh DESCRIPTION
+.Nm Quotaon
+announces to the system that disk quotas should be enabled on one or more
+filesystems.
+.Nm Quotaoff
+announces to the system that the specified
+filesystems should have any disk quotas
+diskquotas turned off.
+The filesystems specified must have entries in
+.Pa /etc/fstab
+and be mounted.
+.Nm Quotaon
+expects each filesystem to have quota files named
+.Pa quota.user
+and
+.Pa quota.group
+which are located at the root of the associated file system.
+These defaults may be overridden in
+.Pa /etc/fstab .
+By default both user and group quotas are enabled.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+If the
+.Fl a
+flag is supplied in place of any filesystem names,
+.Nm quotaon Ns / Ns Nm quotaoff
+will enable/disable all the filesystems indicated in
+.Pa /etc/fstab
+to be read-write with disk quotas.
+By default only the types of quotas listed in
+.Pa /etc/fstab
+are enabled.
+.It Fl g
+Only group quotas listed in
+.Pa /etc/fstab
+should be enabled/disabled.
+.It Fl u
+Only user quotas listed in
+.Pa /etc/fstab
+should be enabled/disabled.
+.It Fl v
+Causes
+.Nm quotaon
+and
+.Nm quotaoff
+to print a message for each filesystem where quotas are turned on or off.
+.El
+.Pp
+Specifying both
+.Fl g
+and
+.Fl u
+is equivalent to the default.
+.Sh FILES
+.Bl -tag -width quota.group -compact
+.It Pa quota.user
+at the filesystem root with user quotas
+.It Pa quota.group
+at the filesystem root with group quotas
+.It Pa /etc/fstab
+filesystem table
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr fstab 5 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr repquota 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/quotaon/quotaon.c b/usr.sbin/quotaon/quotaon.c
new file mode 100644
index 0000000..8eabd27
--- /dev/null
+++ b/usr.sbin/quotaon/quotaon.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)quotaon.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Turn quota on/off for a filesystem.
+ */
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/mount.h>
+#include <ufs/ufs/quota.h>
+#include <stdio.h>
+#include <fstab.h>
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+
+int aflag; /* all file systems */
+int gflag; /* operate on group quotas */
+int uflag; /* operate on user quotas */
+int vflag; /* verbose */
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register struct fstab *fs;
+ char ch, *qfnp, *whoami, *rindex();
+ long argnum, done = 0;
+ int i, offmode = 0, errs = 0;
+ extern char *optarg;
+ extern int optind;
+
+ whoami = rindex(*argv, '/') + 1;
+ if (whoami == (char *)1)
+ whoami = *argv;
+ if (strcmp(whoami, "quotaoff") == 0)
+ offmode++;
+ else if (strcmp(whoami, "quotaon") != 0) {
+ fprintf(stderr, "Name must be quotaon or quotaoff not %s\n",
+ whoami);
+ exit(1);
+ }
+ while ((ch = getopt(argc, argv, "avug")) != EOF) {
+ switch(ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage(whoami);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc <= 0 && !aflag)
+ usage(whoami);
+ if (!gflag && !uflag) {
+ gflag++;
+ uflag++;
+ }
+ setfsent();
+ while ((fs = getfsent()) != NULL) {
+ if (strcmp(fs->fs_vfstype, "ufs") ||
+ strcmp(fs->fs_type, FSTAB_RW))
+ continue;
+ if (aflag) {
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
+ (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+ }
+ }
+ endfsent();
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not found in fstab\n",
+ argv[i]);
+ exit(errs);
+}
+
+usage(whoami)
+ char *whoami;
+{
+
+ fprintf(stderr, "Usage:\n\t%s [-g] [-u] [-v] -a\n", whoami);
+ fprintf(stderr, "\t%s [-g] [-u] [-v] filesys ...\n", whoami);
+ exit(1);
+}
+
+quotaonoff(fs, offmode, type, qfpathname)
+ register struct fstab *fs;
+ int offmode, type;
+ char *qfpathname;
+{
+
+ if (strcmp(fs->fs_file, "/") && readonly(fs))
+ return (1);
+ if (offmode) {
+ if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
+ fprintf(stderr, "quotaoff: ");
+ perror(fs->fs_file);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: quotas turned off\n", fs->fs_file);
+ return (0);
+ }
+ if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
+ fprintf(stderr, "quotaon: using %s on", qfpathname);
+ perror(fs->fs_file);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: %s quotas turned on\n", fs->fs_file,
+ qfextension[type]);
+ return (0);
+}
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+oneof(target, list, cnt)
+ register char *target, *list[];
+ int cnt;
+{
+ register int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
+ sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strcpy(buf, fs->fs_mntops);
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+
+/*
+ * Verify file system is mounted and not readonly.
+ */
+readonly(fs)
+ register struct fstab *fs;
+{
+ struct statfs fsbuf;
+
+ if (statfs(fs->fs_file, &fsbuf) < 0 ||
+ strcmp(fsbuf.f_mntonname, fs->fs_file) ||
+ strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
+ printf("%s: not mounted\n", fs->fs_file);
+ return (1);
+ }
+ if (fsbuf.f_flags & MNT_RDONLY) {
+ printf("%s: mounted read-only\n", fs->fs_file);
+ return (1);
+ }
+ return (0);
+}
diff --git a/usr.sbin/repquota/Makefile b/usr.sbin/repquota/Makefile
new file mode 100644
index 0000000..9330509
--- /dev/null
+++ b/usr.sbin/repquota/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= repquota
+MAN8= repquota.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/repquota/repquota.8 b/usr.sbin/repquota/repquota.8
new file mode 100644
index 0000000..6fba8e1
--- /dev/null
+++ b/usr.sbin/repquota/repquota.8
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the 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.
+.\"
+.\" @(#)repquota.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt REPQUOTA 8
+.Os BSD 4.2
+.Sh NAME
+.Nm repquota
+.Nd summarize quotas for a file system
+.Sh SYNOPSIS
+.Nm repquota
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm repquota
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Sh DESCRIPTION
+.Nm Repquota
+prints a summary of the disk usage and quotas for the
+specified file systems.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+Print the quotas of all the filesystems listed in
+.Pa /etc/fstab .
+.It Fl g
+Print only group quotas (the default is to print both
+group and user quotas if they exist).
+.It Fl u
+Print only user quotas (the default is to print both
+group and user quotas if they exist).
+.It Fl v
+Print a header line before printing each filesystem quotas.
+.El
+.Pp
+For each user or group, the current
+number files and amount of space (in kilobytes) is
+printed, along with any quotas created with
+.Xr edquota 8 .
+.Pp
+Only members of the operator group or the super-user may
+use this command.
+.Sh FILES
+.Bl -tag -width quota.group -compact
+.It Pa quota.user
+at the filesystem root with user quotas
+.It Pa quota.group
+at the filesystem root with group quotas
+.It Pa /etc/fstab
+for file system names and locations
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr fstab 5 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr quotaon 8
+.Sh DIAGNOSTICS
+Various messages about inaccessible files; self-explanatory.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/repquota/repquota.c b/usr.sbin/repquota/repquota.c
new file mode 100644
index 0000000..29989eb
--- /dev/null
+++ b/usr.sbin/repquota/repquota.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)repquota.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Quota report
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ufs/ufs/quota.h>
+#include <fstab.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <errno.h>
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+
+struct fileusage {
+ struct fileusage *fu_next;
+ struct dqblk fu_dqblk;
+ u_long fu_id;
+ char fu_name[1];
+ /* actually bigger */
+};
+#define FUHASH 1024 /* must be power of two */
+struct fileusage *fuhead[MAXQUOTAS][FUHASH];
+struct fileusage *lookup();
+struct fileusage *addid();
+u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
+
+int vflag; /* verbose */
+int aflag; /* all file systems */
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register struct fstab *fs;
+ register struct passwd *pw;
+ register struct group *gr;
+ int gflag = 0, uflag = 0, errs = 0;
+ long i, argnum, done = 0;
+ extern char *optarg;
+ extern int optind;
+ char ch, *qfnp;
+
+ while ((ch = getopt(argc, argv, "aguv")) != EOF) {
+ switch(ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0 && !aflag)
+ usage();
+ if (!gflag && !uflag) {
+ if (aflag)
+ gflag++;
+ uflag++;
+ }
+ if (gflag) {
+ setgrent();
+ while ((gr = getgrent()) != 0)
+ (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
+ endgrent();
+ }
+ if (uflag) {
+ setpwent();
+ while ((pw = getpwent()) != 0)
+ (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
+ endpwent();
+ }
+ setfsent();
+ while ((fs = getfsent()) != NULL) {
+ if (strcmp(fs->fs_vfstype, "ufs"))
+ continue;
+ if (aflag) {
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += repquota(fs, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += repquota(fs, USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
+ (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += repquota(fs, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += repquota(fs, USRQUOTA, qfnp);
+ }
+ }
+ endfsent();
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not found in fstab\n", argv[i]);
+ exit(errs);
+}
+
+usage()
+{
+ fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
+ "repquota [-v] [-g] [-u] -a",
+ "repquota [-v] [-g] [-u] filesys ...");
+ exit(1);
+}
+
+repquota(fs, type, qfpathname)
+ register struct fstab *fs;
+ int type;
+ char *qfpathname;
+{
+ register struct fileusage *fup;
+ FILE *qf;
+ u_long id;
+ struct dqblk dqbuf;
+ char *timeprt();
+ static struct dqblk zerodqblk;
+ static int warned = 0;
+ static int multiple = 0;
+ extern int errno;
+
+ if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
+ errno == EOPNOTSUPP && !warned && vflag) {
+ warned++;
+ fprintf(stdout,
+ "*** Warning: Quotas are not compiled into this kernel\n");
+ }
+ if (multiple++)
+ printf("\n");
+ if (vflag)
+ fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
+ qfextension[type], fs->fs_file, fs->fs_spec);
+ if ((qf = fopen(qfpathname, "r")) == NULL) {
+ perror(qfpathname);
+ return (1);
+ }
+ for (id = 0; ; id++) {
+ fread(&dqbuf, sizeof(struct dqblk), 1, qf);
+ if (feof(qf))
+ break;
+ if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
+ continue;
+ if ((fup = lookup(id, type)) == 0)
+ fup = addid(id, type, (char *)0);
+ fup->fu_dqblk = dqbuf;
+ }
+ fclose(qf);
+ printf(" Block limits File limits\n");
+ printf("User used soft hard grace used soft hard grace\n");
+ for (id = 0; id <= highid[type]; id++) {
+ fup = lookup(id, type);
+ if (fup == 0)
+ continue;
+ if (fup->fu_dqblk.dqb_curinodes == 0 &&
+ fup->fu_dqblk.dqb_curblocks == 0)
+ continue;
+ printf("%-10s", fup->fu_name);
+ printf("%c%c%8d%8d%8d%7s",
+ fup->fu_dqblk.dqb_bsoftlimit &&
+ fup->fu_dqblk.dqb_curblocks >=
+ fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
+ fup->fu_dqblk.dqb_isoftlimit &&
+ fup->fu_dqblk.dqb_curinodes >=
+ fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
+ dbtob(fup->fu_dqblk.dqb_curblocks) / 1024,
+ dbtob(fup->fu_dqblk.dqb_bsoftlimit) / 1024,
+ dbtob(fup->fu_dqblk.dqb_bhardlimit) / 1024,
+ fup->fu_dqblk.dqb_bsoftlimit &&
+ fup->fu_dqblk.dqb_curblocks >=
+ fup->fu_dqblk.dqb_bsoftlimit ?
+ timeprt(fup->fu_dqblk.dqb_btime) : "");
+ printf(" %6d%6d%6d%7s\n",
+ fup->fu_dqblk.dqb_curinodes,
+ fup->fu_dqblk.dqb_isoftlimit,
+ fup->fu_dqblk.dqb_ihardlimit,
+ fup->fu_dqblk.dqb_isoftlimit &&
+ fup->fu_dqblk.dqb_curinodes >=
+ fup->fu_dqblk.dqb_isoftlimit ?
+ timeprt(fup->fu_dqblk.dqb_itime) : "");
+ fup->fu_dqblk = zerodqblk;
+ }
+ return (0);
+}
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+oneof(target, list, cnt)
+ register char *target, *list[];
+ int cnt;
+{
+ register int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
+ sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strcpy(buf, fs->fs_mntops);
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+
+/*
+ * Routines to manage the file usage table.
+ *
+ * Lookup an id of a specific type.
+ */
+struct fileusage *
+lookup(id, type)
+ u_long id;
+ int type;
+{
+ register struct fileusage *fup;
+
+ for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
+ if (fup->fu_id == id)
+ return (fup);
+ return ((struct fileusage *)0);
+}
+
+/*
+ * Add a new file usage id if it does not already exist.
+ */
+struct fileusage *
+addid(id, type, name)
+ u_long id;
+ int type;
+ char *name;
+{
+ struct fileusage *fup, **fhp;
+ int len;
+ extern char *calloc();
+
+ if (fup = lookup(id, type))
+ return (fup);
+ if (name)
+ len = strlen(name);
+ else
+ len = 10;
+ if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) {
+ fprintf(stderr, "out of memory for fileusage structures\n");
+ exit(1);
+ }
+ fhp = &fuhead[type][id & (FUHASH - 1)];
+ fup->fu_next = *fhp;
+ *fhp = fup;
+ fup->fu_id = id;
+ if (id > highid[type])
+ highid[type] = id;
+ if (name) {
+ bcopy(name, fup->fu_name, len + 1);
+ } else {
+ sprintf(fup->fu_name, "%u", id);
+ }
+ return (fup);
+}
+
+/*
+ * Calculate the grace period and return a printable string for it.
+ */
+char *
+timeprt(seconds)
+ time_t seconds;
+{
+ time_t hours, minutes;
+ static char buf[20];
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ if (now > seconds)
+ return ("none");
+ seconds -= now;
+ minutes = (seconds + 30) / 60;
+ hours = (minutes + 30) / 60;
+ if (hours >= 36) {
+ sprintf(buf, "%ddays", (hours + 12) / 24);
+ return (buf);
+ }
+ if (minutes >= 60) {
+ sprintf(buf, "%2d:%d", minutes / 60, minutes % 60);
+ return (buf);
+ }
+ sprintf(buf, "%2d", minutes);
+ return (buf);
+}
diff --git a/usr.sbin/rmt/Makefile b/usr.sbin/rmt/Makefile
new file mode 100644
index 0000000..c55ae71
--- /dev/null
+++ b/usr.sbin/rmt/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= rmt
+MAN8= rmt.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/rmt/rmt.8 b/usr.sbin/rmt/rmt.8
new file mode 100644
index 0000000..fae5628
--- /dev/null
+++ b/usr.sbin/rmt/rmt.8
@@ -0,0 +1,217 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)rmt.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt RMT 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rmt
+.Nd remote magtape protocol module
+.Sh SYNOPSIS
+.Nm rmt
+.Sh DESCRIPTION
+.Nm Rmt
+is a program used by the remote dump and restore programs
+in manipulating a magnetic tape drive through an interprocess
+communication connection.
+.Nm Rmt
+is normally started up with an
+.Xr rexec 3
+or
+.Xr rcmd 3
+call.
+.Pp
+The
+.Nm rmt
+program accepts requests specific to the manipulation of
+magnetic tapes, performs the commands, then responds with
+a status indication. All responses are in
+.Tn ASCII
+and in
+one of two forms.
+Successful commands have responses of:
+.Bd -filled -offset indent
+.Sm off
+.Sy A Ar number No \en
+.Sm on
+.Ed
+.Pp
+.Ar Number
+is an
+.Tn ASCII
+representation of a decimal number.
+Unsuccessful commands are responded to with:
+.Bd -filled -offset indent
+.Sm off
+.Xo Sy E Ar error-number
+.No \en Ar error-message
+.No \en
+.Xc
+.Sm on
+.Ed
+.Pp
+.Ar Error-number
+is one of the possible error
+numbers described in
+.Xr intro 2
+and
+.Ar error-message
+is the corresponding error string as printed
+from a call to
+.Xr perror 3 .
+The protocol is comprised of the
+following commands, which are sent as indicated - no spaces are supplied
+between the command and its arguments, or between its arguments, and
+.Ql \en
+indicates that a newline should be supplied:
+.Bl -tag -width Ds
+.Sm off
+.It Xo Sy \&O Ar device
+.No \en Ar mode No \en
+.Xc
+Open the specified
+.Ar device
+using the indicated
+.Ar mode .
+.Ar Device
+is a full pathname and
+.Ar mode
+is an
+.Tn ASCII
+representation of a decimal
+number suitable for passing to
+.Xr open 2 .
+If a device had already been opened, it is
+closed before a new open is performed.
+.It Xo Sy C Ar device No \en
+.Xc
+Close the currently open device. The
+.Ar device
+specified is ignored.
+.It Xo Sy L
+.Ar whence No \en
+.Ar offset No \en
+.Xc
+.Sm on
+Perform an
+.Xr lseek 2
+operation using the specified parameters.
+The response value is that returned from the
+.Xr lseek
+call.
+.Sm off
+.It Sy W Ar count No \en
+.Sm on
+Write data onto the open device.
+.Nm Rmt
+reads
+.Ar count
+bytes from the connection, aborting if
+a premature end-of-file is encountered.
+The response value is that returned from
+the
+.Xr write 2
+call.
+.Sm off
+.It Sy R Ar count No \en
+.Sm on
+Read
+.Ar count
+bytes of data from the open device.
+If
+.Ar count
+exceeds the size of the data buffer (10 kilobytes), it is
+truncated to the data buffer size.
+.Nm rmt
+then performs the requested
+.Xr read 2
+and responds with
+.Sm off
+.Sy A Ar count-read No \en
+.Sm on
+if the read was
+successful; otherwise an error in the
+standard format is returned. If the read
+was successful, the data read is then sent.
+.Sm off
+.It Xo Sy I Ar operation
+.No \en Ar count No \en
+.Xc
+.Sm on
+Perform a
+.Dv MTIOCOP
+.Xr ioctl 2
+command using the specified parameters.
+The parameters are interpreted as the
+.Tn ASCII
+representations of the decimal values
+to place in the
+.Ar mt_op
+and
+.Ar mt_count
+fields of the structure used in the
+.Xr ioctl
+call. The return value is the
+.Ar count
+parameter when the operation is successful.
+.It Sy S
+Return the status of the open device, as
+obtained with a
+.Dv MTIOCGET
+.Xr ioctl
+call. If the operation was successful,
+an ``ack'' is sent with the size of the
+status buffer, then the status buffer is
+sent (in binary).
+.El
+.Sm on
+.Pp
+Any other command causes
+.Nm rmt
+to exit.
+.Sh DIAGNOSTICS
+All responses are of the form described above.
+.Sh SEE ALSO
+.Xr rcmd 3 ,
+.Xr rexec 3 ,
+.Xr mtio 4 ,
+.Xr rdump 8 ,
+.Xr rrestore 8
+.Sh BUGS
+People should be discouraged from using this for a remote
+file access protocol.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/rmt/rmt.c b/usr.sbin/rmt/rmt.c
new file mode 100644
index 0000000..098e502
--- /dev/null
+++ b/usr.sbin/rmt/rmt.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rmt.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * rmt
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/mtio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sgtty.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int tape = -1;
+
+char *record;
+int maxrecsize = -1;
+
+#define SSIZE 64
+char device[SSIZE];
+char count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
+
+char resp[BUFSIZ];
+
+FILE *debug;
+#define DEBUG(f) if (debug) fprintf(debug, f)
+#define DEBUG1(f,a) if (debug) fprintf(debug, f, a)
+#define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2)
+
+char *checkbuf __P((char *, int));
+void error __P((int));
+void getstring __P((char *));
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int rval;
+ char c;
+ int n, i, cc;
+
+ argc--, argv++;
+ if (argc > 0) {
+ debug = fopen(*argv, "w");
+ if (debug == 0)
+ exit(1);
+ (void)setbuf(debug, (char *)0);
+ }
+top:
+ errno = 0;
+ rval = 0;
+ if (read(0, &c, 1) != 1)
+ exit(0);
+ switch (c) {
+
+ case 'O':
+ if (tape >= 0)
+ (void) close(tape);
+ getstring(device);
+ getstring(mode);
+ DEBUG2("rmtd: O %s %s\n", device, mode);
+ tape = open(device, atoi(mode));
+ if (tape < 0)
+ goto ioerror;
+ goto respond;
+
+ case 'C':
+ DEBUG("rmtd: C\n");
+ getstring(device); /* discard */
+ if (close(tape) < 0)
+ goto ioerror;
+ tape = -1;
+ goto respond;
+
+ case 'L':
+ getstring(count);
+ getstring(pos);
+ DEBUG2("rmtd: L %s %s\n", count, pos);
+ rval = lseek(tape, (off_t)atol(count), atoi(pos));
+ if (rval < 0)
+ goto ioerror;
+ goto respond;
+
+ case 'W':
+ getstring(count);
+ n = atoi(count);
+ DEBUG1("rmtd: W %s\n", count);
+ record = checkbuf(record, n);
+ for (i = 0; i < n; i += cc) {
+ cc = read(0, &record[i], n - i);
+ if (cc <= 0) {
+ DEBUG("rmtd: premature eof\n");
+ exit(2);
+ }
+ }
+ rval = write(tape, record, n);
+ if (rval < 0)
+ goto ioerror;
+ goto respond;
+
+ case 'R':
+ getstring(count);
+ DEBUG1("rmtd: R %s\n", count);
+ n = atoi(count);
+ record = checkbuf(record, n);
+ rval = read(tape, record, n);
+ if (rval < 0)
+ goto ioerror;
+ (void)sprintf(resp, "A%d\n", rval);
+ (void)write(1, resp, strlen(resp));
+ (void)write(1, record, rval);
+ goto top;
+
+ case 'I':
+ getstring(op);
+ getstring(count);
+ DEBUG2("rmtd: I %s %s\n", op, count);
+ { struct mtop mtop;
+ mtop.mt_op = atoi(op);
+ mtop.mt_count = atoi(count);
+ if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
+ goto ioerror;
+ rval = mtop.mt_count;
+ }
+ goto respond;
+
+ case 'S': /* status */
+ DEBUG("rmtd: S\n");
+ { struct mtget mtget;
+ if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0)
+ goto ioerror;
+ rval = sizeof (mtget);
+ (void)sprintf(resp, "A%d\n", rval);
+ (void)write(1, resp, strlen(resp));
+ (void)write(1, (char *)&mtget, sizeof (mtget));
+ goto top;
+ }
+
+ default:
+ DEBUG1("rmtd: garbage command %c\n", c);
+ exit(3);
+ }
+respond:
+ DEBUG1("rmtd: A %d\n", rval);
+ (void)sprintf(resp, "A%d\n", rval);
+ (void)write(1, resp, strlen(resp));
+ goto top;
+ioerror:
+ error(errno);
+ goto top;
+}
+
+void
+getstring(bp)
+ char *bp;
+{
+ int i;
+ char *cp = bp;
+
+ for (i = 0; i < SSIZE; i++) {
+ if (read(0, cp+i, 1) != 1)
+ exit(0);
+ if (cp[i] == '\n')
+ break;
+ }
+ cp[i] = '\0';
+}
+
+char *
+checkbuf(record, size)
+ char *record;
+ int size;
+{
+
+ if (size <= maxrecsize)
+ return (record);
+ if (record != 0)
+ free(record);
+ record = malloc(size);
+ if (record == 0) {
+ DEBUG("rmtd: cannot allocate buffer space\n");
+ exit(4);
+ }
+ maxrecsize = size;
+ while (size > 1024 &&
+ setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0)
+ size -= 1024;
+ return (record);
+}
+
+void
+error(num)
+ int num;
+{
+
+ DEBUG2("rmtd: E %d (%s)\n", num, strerror(num));
+ (void)sprintf(resp, "E%d\n%s\n", num, strerror(num));
+ (void)write(1, resp, strlen(resp));
+}
diff --git a/usr.sbin/rwhod/Makefile b/usr.sbin/rwhod/Makefile
new file mode 100644
index 0000000..5846743
--- /dev/null
+++ b/usr.sbin/rwhod/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= rwhod
+MAN8= rwhod.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/rwhod/rwhod.8 b/usr.sbin/rwhod/rwhod.8
new file mode 100644
index 0000000..4b8492e
--- /dev/null
+++ b/usr.sbin/rwhod/rwhod.8
@@ -0,0 +1,146 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)rwhod.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt RWHOD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rwhod
+.Nd system status server
+.Sh SYNOPSIS
+.Nm rwhod
+.Sh DESCRIPTION
+.Nm Rwhod
+is the server which maintains the database used by the
+.Xr rwho 1
+and
+.Xr ruptime 1
+programs. Its operation is predicated on the ability to
+.Em broadcast
+messages on a network.
+.Pp
+.Nm Rwhod
+operates as both a producer and consumer of status information.
+As a producer of information it periodically
+queries the state of the system and constructs
+status messages which are broadcast on a network.
+As a consumer of information, it listens for other
+.Nm rwhod
+servers' status messages, validating them, then recording
+them in a collection of files located in the directory
+.Pa /var/rwho .
+.Pp
+The server transmits and receives messages at the port indicated
+in the ``rwho'' service specification; see
+.Xr services 5 .
+The messages sent and received, are of the form:
+.Bd -literal -offset indent
+struct outmp {
+ char out_line[8]; /* tty name */
+ char out_name[8]; /* user id */
+ long out_time; /* time on */
+};
+
+struct whod {
+ char wd_vers;
+ char wd_type;
+ char wd_fill[2];
+ int wd_sendtime;
+ int wd_recvtime;
+ char wd_hostname[32];
+ int wd_loadav[3];
+ int wd_boottime;
+ struct whoent {
+ struct outmp we_utmp;
+ int we_idle;
+ } wd_we[1024 / sizeof (struct whoent)];
+};
+.Ed
+.Pp
+All fields are converted to network byte order prior to
+transmission. The load averages are as calculated by the
+.Xr w 1
+program, and represent load averages over the 5, 10, and 15 minute
+intervals prior to a server's transmission; they are multiplied by 100
+for representation in an integer. The host name
+included is that returned by the
+.Xr gethostname 2
+system call, with any trailing domain name omitted.
+The array at the end of the message contains information about
+the users logged in to the sending machine. This information
+includes the contents of the
+.Xr utmp 5
+entry for each non-idle terminal line and a value indicating the
+time in seconds since a character was last received on the terminal line.
+.Pp
+Messages received by the
+.Xr rwho
+server are discarded unless they originated at an
+.Xr rwho
+server's port. In addition, if the host's name, as specified
+in the message, contains any unprintable
+.Tn ASCII
+characters, the
+message is discarded. Valid messages received by
+.Nm rwhod
+are placed in files named
+.Pa whod.hostname
+in the directory
+.Pa /var/rwho .
+These files contain only the most recent message, in the
+format described above.
+.Pp
+Status messages are generated approximately once every
+3 minutes.
+.Nm Rwhod
+performs an
+.Xr nlist 3
+on
+.Pa /vmunix
+every 30 minutes to guard against
+the possibility that this file is not the system
+image currently operating.
+.Sh SEE ALSO
+.Xr rwho 1 ,
+.Xr ruptime 1
+.Sh BUGS
+There should be a way to relay status information between networks.
+Status information should be sent only upon request rather than continuously.
+People often interpret the server dying
+or network communication failures
+as a machine going down.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c
new file mode 100644
index 0000000..75c02ff
--- /dev/null
+++ b/usr.sbin/rwhod/rwhod.c
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <protocols/rwhod.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <utmp.h>
+
+/*
+ * Alarm interval. Don't forget to change the down time check in ruptime
+ * if this is changed.
+ */
+#define AL_INTERVAL (3 * 60)
+
+char myname[MAXHOSTNAMELEN];
+
+/*
+ * We communicate with each neighbor in a list constructed at the time we're
+ * started up. Neighbors are currently directly connected via a hardware
+ * interface.
+ */
+struct neighbor {
+ struct neighbor *n_next;
+ char *n_name; /* interface name */
+ struct sockaddr *n_addr; /* who to send to */
+ int n_addrlen; /* size of address */
+ int n_flags; /* should forward?, interface flags */
+};
+
+struct neighbor *neighbors;
+struct whod mywd;
+struct servent *sp;
+int s, utmpf;
+
+#define WHDRSIZE (sizeof(mywd) - sizeof(mywd.wd_we))
+
+int configure __P((int));
+void getboottime __P((int));
+void onalrm __P((int));
+void quit __P((char *));
+void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+int verify __P((char *));
+#ifdef DEBUG
+char *interval __P((int, char *));
+void Sendto __P((int, char *, int, int, char *, int));
+#define sendto Sendto
+#endif
+
+int
+main(argc, argv)
+ int argc;
+ char argv[];
+{
+ struct sockaddr_in from;
+ struct stat st;
+ char path[64];
+ int on = 1;
+ char *cp;
+ struct sockaddr_in sin;
+
+ if (getuid()) {
+ fprintf(stderr, "rwhod: not super user\n");
+ exit(1);
+ }
+ sp = getservbyname("who", "udp");
+ if (sp == NULL) {
+ fprintf(stderr, "rwhod: udp/who: unknown service\n");
+ exit(1);
+ }
+#ifndef DEBUG
+ daemon(1, 0);
+#endif
+ if (chdir(_PATH_RWHODIR) < 0) {
+ (void)fprintf(stderr, "rwhod: %s: %s\n",
+ _PATH_RWHODIR, strerror(errno));
+ exit(1);
+ }
+ (void) signal(SIGHUP, getboottime);
+ openlog("rwhod", LOG_PID, LOG_DAEMON);
+ /*
+ * Establish host name as returned by system.
+ */
+ if (gethostname(myname, sizeof(myname) - 1) < 0) {
+ syslog(LOG_ERR, "gethostname: %m");
+ exit(1);
+ }
+ if ((cp = index(myname, '.')) != NULL)
+ *cp = '\0';
+ strncpy(mywd.wd_hostname, myname, sizeof(myname) - 1);
+ utmpf = open(_PATH_UTMP, O_RDONLY|O_CREAT, 0644);
+ if (utmpf < 0) {
+ syslog(LOG_ERR, "%s: %m", _PATH_UTMP);
+ exit(1);
+ }
+ getboottime(0);
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ syslog(LOG_ERR, "socket: %m");
+ exit(1);
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+ exit(1);
+ }
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = sp->s_port;
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ exit(1);
+ }
+ if (!configure(s))
+ exit(1);
+ signal(SIGALRM, onalrm);
+ onalrm(0);
+ for (;;) {
+ struct whod wd;
+ int cc, whod, len = sizeof(from);
+
+ cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0,
+ (struct sockaddr *)&from, &len);
+ if (cc <= 0) {
+ if (cc < 0 && errno != EINTR)
+ syslog(LOG_WARNING, "recv: %m");
+ continue;
+ }
+ if (from.sin_port != sp->s_port) {
+ syslog(LOG_WARNING, "%d: bad from port",
+ ntohs(from.sin_port));
+ continue;
+ }
+ if (wd.wd_vers != WHODVERSION)
+ continue;
+ if (wd.wd_type != WHODTYPE_STATUS)
+ continue;
+ if (!verify(wd.wd_hostname)) {
+ syslog(LOG_WARNING, "malformed host name from %x",
+ from.sin_addr);
+ continue;
+ }
+ (void) sprintf(path, "whod.%s", wd.wd_hostname);
+ /*
+ * Rather than truncating and growing the file each time,
+ * use ftruncate if size is less than previous size.
+ */
+ whod = open(path, O_WRONLY | O_CREAT, 0644);
+ if (whod < 0) {
+ syslog(LOG_WARNING, "%s: %m", path);
+ continue;
+ }
+#if ENDIAN != BIG_ENDIAN
+ {
+ int i, n = (cc - WHDRSIZE)/sizeof(struct whoent);
+ struct whoent *we;
+
+ /* undo header byte swapping before writing to file */
+ wd.wd_sendtime = ntohl(wd.wd_sendtime);
+ for (i = 0; i < 3; i++)
+ wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]);
+ wd.wd_boottime = ntohl(wd.wd_boottime);
+ we = wd.wd_we;
+ for (i = 0; i < n; i++) {
+ we->we_idle = ntohl(we->we_idle);
+ we->we_utmp.out_time =
+ ntohl(we->we_utmp.out_time);
+ we++;
+ }
+ }
+#endif
+ (void) time((time_t *)&wd.wd_recvtime);
+ (void) write(whod, (char *)&wd, cc);
+ if (fstat(whod, &st) < 0 || st.st_size > cc)
+ ftruncate(whod, cc);
+ (void) close(whod);
+ }
+}
+
+/*
+ * Check out host name for unprintables
+ * and other funnies before allowing a file
+ * to be created. Sorry, but blanks aren't allowed.
+ */
+int
+verify(name)
+ register char *name;
+{
+ register int size = 0;
+
+ while (*name) {
+ if (!isascii(*name) || !(isalnum(*name) || ispunct(*name)))
+ return (0);
+ name++, size++;
+ }
+ return (size > 0);
+}
+
+int utmptime;
+int utmpent;
+int utmpsize = 0;
+struct utmp *utmp;
+int alarmcount;
+
+void
+onalrm(signo)
+ int signo;
+{
+ register struct neighbor *np;
+ register struct whoent *we = mywd.wd_we, *wlast;
+ register int i;
+ struct stat stb;
+ double avenrun[3];
+ time_t now;
+ int cc;
+
+ now = time(NULL);
+ if (alarmcount % 10 == 0)
+ getboottime(0);
+ alarmcount++;
+ (void) fstat(utmpf, &stb);
+ if ((stb.st_mtime != utmptime) || (stb.st_size > utmpsize)) {
+ utmptime = stb.st_mtime;
+ if (stb.st_size > utmpsize) {
+ utmpsize = stb.st_size + 10 * sizeof(struct utmp);
+ if (utmp)
+ utmp = (struct utmp *)realloc(utmp, utmpsize);
+ else
+ utmp = (struct utmp *)malloc(utmpsize);
+ if (! utmp) {
+ fprintf(stderr, "rwhod: malloc failed\n");
+ utmpsize = 0;
+ goto done;
+ }
+ }
+ (void) lseek(utmpf, (off_t)0, L_SET);
+ cc = read(utmpf, (char *)utmp, stb.st_size);
+ if (cc < 0) {
+ fprintf(stderr, "rwhod: %s: %s\n",
+ _PATH_UTMP, strerror(errno));
+ goto done;
+ }
+ wlast = &mywd.wd_we[1024 / sizeof(struct whoent) - 1];
+ utmpent = cc / sizeof(struct utmp);
+ for (i = 0; i < utmpent; i++)
+ if (utmp[i].ut_name[0]) {
+ memcpy(we->we_utmp.out_line, utmp[i].ut_line,
+ sizeof(utmp[i].ut_line));
+ memcpy(we->we_utmp.out_name, utmp[i].ut_name,
+ sizeof(utmp[i].ut_name));
+ we->we_utmp.out_time = htonl(utmp[i].ut_time);
+ if (we >= wlast)
+ break;
+ we++;
+ }
+ utmpent = we - mywd.wd_we;
+ }
+
+ /*
+ * The test on utmpent looks silly---after all, if no one is
+ * logged on, why worry about efficiency?---but is useful on
+ * (e.g.) compute servers.
+ */
+ if (utmpent && chdir(_PATH_DEV)) {
+ syslog(LOG_ERR, "chdir(%s): %m", _PATH_DEV);
+ exit(1);
+ }
+ we = mywd.wd_we;
+ for (i = 0; i < utmpent; i++) {
+ if (stat(we->we_utmp.out_line, &stb) >= 0)
+ we->we_idle = htonl(now - stb.st_atime);
+ we++;
+ }
+ (void)getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
+ for (i = 0; i < 3; i++)
+ mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100));
+ cc = (char *)we - (char *)&mywd;
+ mywd.wd_sendtime = htonl(time(0));
+ mywd.wd_vers = WHODVERSION;
+ mywd.wd_type = WHODTYPE_STATUS;
+ for (np = neighbors; np != NULL; np = np->n_next)
+ (void)sendto(s, (char *)&mywd, cc, 0,
+ np->n_addr, np->n_addrlen);
+ if (utmpent && chdir(_PATH_RWHODIR)) {
+ syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR);
+ exit(1);
+ }
+done:
+ (void) alarm(AL_INTERVAL);
+}
+
+void
+getboottime(signo)
+ int signo;
+{
+ int mib[2];
+ size_t size;
+ struct timeval tm;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ size = sizeof(tm);
+ if (sysctl(mib, 2, &tm, &size, NULL, 0) == -1) {
+ syslog(LOG_ERR, "cannot get boottime: %m");
+ exit(1);
+ }
+ mywd.wd_boottime = htonl(tm.tv_sec);
+}
+
+void
+quit(msg)
+ char *msg;
+{
+ syslog(LOG_ERR, msg);
+ exit(1);
+}
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+ register caddr_t cp, cplim;
+ register struct rt_addrinfo *rtinfo;
+{
+ register struct sockaddr *sa;
+ register int i;
+
+ memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
+ for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+ if ((rtinfo->rti_addrs & (1 << i)) == 0)
+ continue;
+ rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+ ADVANCE(cp, sa);
+ }
+}
+
+/*
+ * Figure out device configuration and select
+ * networks which deserve status information.
+ */
+int
+configure(s)
+ int s;
+{
+ register struct neighbor *np;
+ register struct if_msghdr *ifm;
+ register struct ifa_msghdr *ifam;
+ struct sockaddr_dl *sdl;
+ size_t needed;
+ int mib[6], flags = 0, len;
+ char *buf, *lim, *next;
+ struct rt_addrinfo info;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ quit("route-sysctl-estimate");
+ if ((buf = malloc(needed)) == NULL)
+ quit("malloc");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ quit("actual retrieval of interface table");
+ lim = buf + needed;
+
+ sdl = NULL; /* XXX just to keep gcc -Wall happy */
+ for (next = buf; next < lim; next += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *)next;
+ if (ifm->ifm_type == RTM_IFINFO) {
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+ flags = ifm->ifm_flags;
+ continue;
+ }
+ if ((flags & IFF_UP) == 0 ||
+ (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0)
+ continue;
+ if (ifm->ifm_type != RTM_NEWADDR)
+ quit("out of sync parsing NET_RT_IFLIST");
+ ifam = (struct ifa_msghdr *)ifm;
+ info.rti_addrs = ifam->ifam_addrs;
+ rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
+ &info);
+ /* gag, wish we could get rid of Internet dependencies */
+#define dstaddr info.rti_info[RTAX_BRD]
+#define IPADDR_SA(x) ((struct sockaddr_in *)(x))->sin_addr.s_addr
+#define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port
+ if (dstaddr == 0 || dstaddr->sa_family != AF_INET)
+ continue;
+ PORT_SA(dstaddr) = sp->s_port;
+ for (np = neighbors; np != NULL; np = np->n_next)
+ if (memcmp(sdl->sdl_data, np->n_name,
+ sdl->sdl_nlen) == 0 &&
+ IPADDR_SA(np->n_addr) == IPADDR_SA(dstaddr))
+ break;
+ if (np != NULL)
+ continue;
+ len = sizeof(*np) + dstaddr->sa_len + sdl->sdl_nlen + 1;
+ np = (struct neighbor *)malloc(len);
+ if (np == NULL)
+ quit("malloc of neighbor structure");
+ memset(np, 0, len);
+ np->n_flags = flags;
+ np->n_addr = (struct sockaddr *)(np + 1);
+ np->n_addrlen = dstaddr->sa_len;
+ np->n_name = np->n_addrlen + (char *)np->n_addr;
+ np->n_next = neighbors;
+ neighbors = np;
+ memcpy((char *)np->n_addr, (char *)dstaddr, np->n_addrlen);
+ memcpy(np->n_name, sdl->sdl_data, sdl->sdl_nlen);
+ }
+ free(buf);
+ return (1);
+}
+
+#ifdef DEBUG
+void
+Sendto(s, buf, cc, flags, to, tolen)
+ int s;
+ char *buf;
+ int cc, flags;
+ char *to;
+ int tolen;
+{
+ register struct whod *w = (struct whod *)buf;
+ register struct whoent *we;
+ struct sockaddr_in *sin = (struct sockaddr_in *)to;
+
+ printf("sendto %x.%d\n", ntohl(sin->sin_addr), ntohs(sin->sin_port));
+ printf("hostname %s %s\n", w->wd_hostname,
+ interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up"));
+ printf("load %4.2f, %4.2f, %4.2f\n",
+ ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0,
+ ntohl(w->wd_loadav[2]) / 100.0);
+ cc -= WHDRSIZE;
+ for (we = w->wd_we, cc /= sizeof(struct whoent); cc > 0; cc--, we++) {
+ time_t t = ntohl(we->we_utmp.out_time);
+ printf("%-8.8s %s:%s %.12s",
+ we->we_utmp.out_name,
+ w->wd_hostname, we->we_utmp.out_line,
+ ctime(&t)+4);
+ we->we_idle = ntohl(we->we_idle) / 60;
+ if (we->we_idle) {
+ if (we->we_idle >= 100*60)
+ we->we_idle = 100*60 - 1;
+ if (we->we_idle >= 60)
+ printf(" %2d", we->we_idle / 60);
+ else
+ printf(" ");
+ printf(":%02d", we->we_idle % 60);
+ }
+ printf("\n");
+ }
+}
+
+char *
+interval(time, updown)
+ int time;
+ char *updown;
+{
+ static char resbuf[32];
+ int days, hours, minutes;
+
+ if (time < 0 || time > 3*30*24*60*60) {
+ (void) sprintf(resbuf, " %s ??:??", updown);
+ return (resbuf);
+ }
+ minutes = (time + 59) / 60; /* round to minutes */
+ hours = minutes / 60; minutes %= 60;
+ days = hours / 24; hours %= 24;
+ if (days)
+ (void) sprintf(resbuf, "%s %2d+%02d:%02d",
+ updown, days, hours, minutes);
+ else
+ (void) sprintf(resbuf, "%s %2d:%02d",
+ updown, hours, minutes);
+ return (resbuf);
+}
+#endif
diff --git a/usr.sbin/sendmail/cf/cf/alpha.mc b/usr.sbin/sendmail/cf/cf/alpha.mc
new file mode 100644
index 0000000..026fed1
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/alpha.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)alpha.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(osf1)dnl
+DOMAIN(s2k)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/auspex.mc b/usr.sbin/sendmail/cf/cf/auspex.mc
new file mode 100644
index 0000000..961c139
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/auspex.mc
@@ -0,0 +1,42 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)auspex.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+FEATURE(use_cw_file)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/chez.mc b/usr.sbin/sendmail/cf/cf/chez.mc
new file mode 100644
index 0000000..13f9519
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/chez.mc
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)chez.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.4)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+define(`MASQUERADE_NAME', vangogh.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+Fw/etc/sendmail.cw
diff --git a/usr.sbin/sendmail/cf/cf/cogsci.mc b/usr.sbin/sendmail/cf/cf/cogsci.mc
new file mode 100644
index 0000000..4faa46d
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cogsci.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cogsci.mc 8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MAILER(smtp)dnl
+MAILER(uucp)dnl
+SITECONFIG(uucp.cogsci, Ucogsci, U)
diff --git a/usr.sbin/sendmail/cf/cf/cs-exposed.mc b/usr.sbin/sendmail/cf/cf/cs-exposed.mc
new file mode 100644
index 0000000..62072b7
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-exposed.mc
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-hidden.mc b/usr.sbin/sendmail/cf/cf/cs-hidden.mc
new file mode 100644
index 0000000..216062c
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-hidden.mc
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cs-hidden.mc 8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc
new file mode 100644
index 0000000..4f61ffd
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)hpux-cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(hpux)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc
new file mode 100644
index 0000000..33cf580
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)hpux-cs-hidden.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(hpux)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/osf1-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/osf1-cs-exposed.mc
new file mode 100644
index 0000000..eaed6cc
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/osf1-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)osf1-cs-exposed.mc 8.1 (Berkeley) 10/15/93')
+OSTYPE(osf1)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/osf1-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/osf1-cs-hidden.mc
new file mode 100644
index 0000000..2b85ba4
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/osf1-cs-hidden.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)osf1-cs-hidden.mc 8.1 (Berkeley) 10/15/93')
+OSTYPE(osf1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/python.mc b/usr.sbin/sendmail/cf/cf/python.mc
new file mode 100644
index 0000000..ac23e61
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/python.mc
@@ -0,0 +1,52 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)python.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.4)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+define(`MASQUERADE_NAME', vangogh.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+
+# accept mail sent to the domain head
+DDBostic.COM
+
+LOCAL_RULE_0
+# accept mail sent to the domain head
+R< @ $D . > : $* $@ $>7 $1 @here:... -> ...
+R$* $=O $* < @ $D . > $@ $>7 $1 $2 $3 ...@here -> ...
+R$* < @ $D . > $#local $: $1 user@here -> user
diff --git a/usr.sbin/sendmail/cf/cf/riscos-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/riscos-cs-exposed.mc
new file mode 100644
index 0000000..a92b770
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/riscos-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)riscos-cs-exposed.mc 8.1 (Berkeley) 12/1/93')
+OSTYPE(riscos4.5)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/s2k.mc b/usr.sbin/sendmail/cf/cf/s2k.mc
new file mode 100644
index 0000000..e65fc9f
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/s2k.mc
@@ -0,0 +1,42 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)s2k.mc 8.1 (Berkeley) 6/7/93')
+OLDSENDMAIL
+OSTYPE(ultrix4.1)dnl
+DOMAIN(s2k)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sample.mc b/usr.sbin/sendmail/cf/cf/sample.mc
new file mode 100644
index 0000000..760409d
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sample.mc
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sample.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.4)
+DOMAIN(cs.hidden)
+MAILER(smtp)
diff --git a/usr.sbin/sendmail/cf/cf/sleepy.mc b/usr.sbin/sendmail/cf/cf/sleepy.mc
new file mode 100644
index 0000000..ff6a7cd
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sleepy.mc
@@ -0,0 +1,43 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(@(#)sleepy.mc 8.1 (Berkeley) 6/7/93)
+OSTYPE(hpux)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', diva.Berkeley.EDU)dnl
+define(`MASQUERADE_NAME', diva.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc
new file mode 100644
index 0000000..46d04d9
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos3.5-cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos3.5)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc
new file mode 100644
index 0000000..a3d6f20
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos3.5-cs-hidden.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos3.5)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc
new file mode 100644
index 0000000..7c94ba5
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos4.1-cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc
new file mode 100644
index 0000000..8e1dbb9
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos4.1-cs-hidden.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/udb.mc b/usr.sbin/sendmail/cf/cf/udb.mc
new file mode 100644
index 0000000..624d2d4
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/udb.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)udb.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(smtp)dnl
+define(`USERDB_FILE', `/home/auspex/a/staff/gnn/UDB/UI')dnl
diff --git a/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc
new file mode 100644
index 0000000..093590f
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ultrix4.1-cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc
new file mode 100644
index 0000000..ea25375
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ultrix4.1-cs-hidden.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/vangogh.mc b/usr.sbin/sendmail/cf/cf/vangogh.mc
new file mode 100644
index 0000000..2406364
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/vangogh.mc
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)vangogh.mc 8.2 (Berkeley) 1/26/94')
+DOMAIN(cs.exposed)dnl
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`MCI_CACHE_SIZE', 5)
+Cw okeeffe.CS.Berkeley.EDU
+Cw python.CS.Berkeley.EDU
diff --git a/usr.sbin/sendmail/cf/domain/Berkeley.m4 b/usr.sbin/sendmail/cf/domain/Berkeley.m4
new file mode 100644
index 0000000..4f572d6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/Berkeley.m4
@@ -0,0 +1,42 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)Berkeley.m4 8.5 (Berkeley) 2/18/94')
+define(`UUCP_RELAY', `ucbvax.Berkeley.EDU')dnl
+define(`BITNET_RELAY', `CMSA.Berkeley.EDU')dnl
+define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward')dnl
+define(`confCW_FILE', `-o /etc/sendmail.cw')dnl
+FEATURE(redirect)dnl
+FEATURE(use_cw_file)dnl
diff --git a/usr.sbin/sendmail/cf/domain/cs.exposed.m4 b/usr.sbin/sendmail/cf/domain/cs.exposed.m4
new file mode 100644
index 0000000..43c07be
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/cs.exposed.m4
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)cs.exposed.m4 8.1 (Berkeley) 6/7/93')
+DOMAIN(Berkeley)dnl
+HACK(cssubdomain)dnl
+define(`confUSERDB_SPEC',
+ `/usr/sww/share/lib/users.cs.db,/usr/sww/share/lib/users.eecs.db')dnl
diff --git a/usr.sbin/sendmail/cf/domain/cs.hidden.m4 b/usr.sbin/sendmail/cf/domain/cs.hidden.m4
new file mode 100644
index 0000000..3d9721a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/cs.hidden.m4
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)cs.hidden.m4 8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MASQUERADE_AS(CS.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/eecs.hidden.m4 b/usr.sbin/sendmail/cf/domain/eecs.hidden.m4
new file mode 100644
index 0000000..bbdc01a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/eecs.hidden.m4
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)eecs.hidden.m4 8.1 (Berkeley) 6/7/93')
+DOMAIN(Berkeley)dnl
+MASQUERADE_AS(EECS.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/s2k.m4 b/usr.sbin/sendmail/cf/domain/s2k.m4
new file mode 100644
index 0000000..25b931f
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/s2k.m4
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)s2k.m4 8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MASQUERADE_AS(postgres.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/hpux.m4 b/usr.sbin/sendmail/cf/ostype/hpux.m4
new file mode 100644
index 0000000..1be21f3
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/hpux.m4
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)hpux.m4 8.5 (Berkeley) 1/9/94')
+
+define(`QUEUE_DIR', /usr/spool/mqueue)dnl
+define(`ALIAS_FILE', /usr/lib/aliases)dnl
+define(`STATUS_FILE', /usr/lib/sendmail.st)dnl
+define(`LOCAL_MAILER_FLAGS', `m')dnl
+define(`UUCP_MAILER_ARGS', `uux - -r -a$f -gC $h!rmail ($u)')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/irix.m4 b/usr.sbin/sendmail/cf/ostype/irix.m4
new file mode 100644
index 0000000..6cd7fc9
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/irix.m4
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)irix.m4 8.4 (Berkeley) 2/1/94')
+define(`LOCAL_MAILER_FLAGS', Ehm)dnl
+define(`QUEUE_DIR', /usr/spool/mqueue)dnl
+define(`ALIAS_FILE', /usr/lib/aliases)dnl
+define(`STATUS_FILE', /usr/lib/sendmail.st)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/ultrix4.1.m4 b/usr.sbin/sendmail/cf/ostype/ultrix4.1.m4
new file mode 100644
index 0000000..87c4425
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/ultrix4.1.m4
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)ultrix4.1.m4 8.1 (Berkeley) 6/7/93')
+ifdef(`_OLD_SENDMAIL_', `define(`NEED_DOMAIN', `')')dnl
diff --git a/usr.sbin/sendmail/contrib/rcpt-streaming b/usr.sbin/sendmail/contrib/rcpt-streaming
new file mode 100644
index 0000000..a43af6d
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/rcpt-streaming
@@ -0,0 +1,305 @@
+Message-ID: <wgKo1lW00WBw46OU8k@andrew.cmu.edu>
+Date: Sun, 1 Aug 1993 00:02:57 -0400 (EDT)
+From: John Gardiner Myers <jgm+@CMU.EDU>
+To: sendmail@cs.berkeley.edu
+Subject: contrib/rcpt-streaming
+Beak: Is
+
+This patch implements "RCPT streaming" in sendmail version 8. This
+patch is not an official part of sendmail. Please report all problems
+with this patch to jgm+@cmu.edu.
+
+RCPT streming avoids network round trips by sending all RCPT commands
+for a single SMTP transaction together. Sendmail then waits for all
+the replies, matching them up with the apropriate addresses.
+
+Apply to the sendmail src directory (your line numbers may vary) and
+compile with -DRCPTSTREAM
+
+diff -cr ./src/deliver.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/deliver.c
+*** ./src/deliver.c Thu Jul 22 14:28:19 1993
+--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/deliver.c Fri Jul 30 21:11:16 1993
+***************
+*** 1334,1339 ****
+--- 1334,1354 ----
+ register int i;
+
+ /* send the recipient list */
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++ *
++ * RCPT streaming code by John G Myers, jgm+@cmu.edu
++ * This is not supported by the maintainer of sendmail.
++ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++ *
++ ***********************************************************************
++ */
++ for (to = tochain; to != NULL; to = to->q_tchain)
++ {
++ smtpstreammessage("RCPT To:<%s>", m, mci,
++ to->q_user);
++ }
++ #endif
+ tobuf[0] = '\0';
+ for (to = tochain; to != NULL; to = to->q_tchain)
+ {
+diff -cr ./src/usersmtp.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/usersmtp.c
+*** ./src/usersmtp.c Mon Jul 19 23:50:43 1993
+--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/usersmtp.c Fri Jul 30 21:12:00 1993
+***************
+*** 44,49 ****
+--- 44,61 ----
+
+ # include <sysexits.h>
+ # include <errno.h>
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++ *
++ * RCPT streaming code by John G Myers, jgm+@cmu.edu
++ * This is not supported by the maintainer of sendmail.
++ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++ *
++ ***********************************************************************
++ */
++ # include <sys/types.h>
++ # include <sys/time.h>
++ #endif
+
+ # ifdef SMTP
+
+***************
+*** 62,67 ****
+--- 74,87 ----
+ char SmtpError[MAXLINE] = ""; /* save failure error messages */
+ int SmtpPid; /* pid of mailer */
+
++ #ifdef RCPTSTREAM
++ char *SmtpStreamBuf; /* buffer for streaming output */
++ int SmtpStreamBufSize = 0; /* allocated size of buffer */
++ char *SmtpStreamStart; /* pointer to text not yet written */
++ int SmtpStreamLen = 0; /* # chars not yet written */
++ #endif
++
++
+ #ifdef __STDC__
+ extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);
+ #endif
+***************
+*** 404,410 ****
+--- 424,434 ----
+ {
+ register int r;
+
++ #ifdef RCPTSTREAM
++ sprintf(SmtpMsgBuffer, "RCPT To:<%s>", to->q_user);
++ #else
+ smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
++ #endif
+
+ SmtpPhase = mci->mci_phase = "client RCPT";
+ setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+***************
+*** 667,672 ****
+--- 694,703 ----
+ bool firstline = TRUE;
+ char junkbuf[MAXLINE];
+
++ #ifdef RCPTSTREAM
++ extern char MsgBuf[]; /* err.c */
++ #endif
++
+ if (mci->mci_out != NULL)
+ (void) fflush(mci->mci_out);
+
+***************
+*** 682,687 ****
+--- 713,755 ----
+ register char *p;
+ extern time_t curtime();
+
++ #ifdef RCPTSTREAM
++ if (SmtpStreamLen > 0) {
++ int outfd;
++
++ outfd = fileno(mci->mci_out);
++
++ nonblock(outfd, TRUE);
++ r = write(outfd, SmtpStreamStart, SmtpStreamLen);
++ nonblock(outfd, FALSE);
++ if (r == -1 && errno != EAGAIN
++ #ifdef EWOULDBLOCK
++ && errno != EWOULDBLOCK
++ #endif
++ ) {
++
++ mci->mci_errno = errno;
++ message("451 streamreply: write error to %s",
++ mci->mci_host);
++
++ /* if debugging, pause so we can see state */
++ if (tTd(18, 100))
++ pause();
++ # ifdef LOG
++ if (LogLevel > 0)
++ syslog(LOG_INFO, "%s", &MsgBuf[4]);
++ # endif /* LOG */
++ /* stop trying to write output */
++ SmtpStreamLen = 0;
++ continue;
++ }
++ if (r > 0) {
++ SmtpStreamStart += r;
++ SmtpStreamLen -= r;
++ }
++ }
++ #endif /* RCPTSTREAM */
++
+ /* actually do the read */
+ if (e->e_xfp != NULL)
+ (void) fflush(e->e_xfp); /* for debugging */
+***************
+*** 792,797 ****
+--- 860,937 ----
+
+ return (r);
+ }
++
++ #ifdef RCPTSTREAM
++ /*
++ ** SMTPSTREAMMESSAGE -- buffer message to be streamed to server
++ **
++ ** Parameters:
++ ** f -- format
++ ** m -- the mailer to control formatting.
++ ** a, b, c -- parameters
++ **
++ ** Returns:
++ ** none.
++ **
++ ** Side Effects:
++ ** stores message in SmtpStreamBuf
++ */
++
++ /*VARARGS1*/
++ #ifdef __STDC__
++ smtpstreammessage(char *f, MAILER *m, MCI *mci, ...)
++ #else
++ smtpstreammessage(f, m, mci, va_alist)
++ char *f;
++ MAILER *m;
++ MCI *mci;
++ va_dcl
++ #endif
++ {
++ VA_LOCAL_DECL
++ int len;
++
++ VA_START(mci);
++ (void) vsprintf(SmtpMsgBuffer, f, ap);
++ VA_END;
++
++ if (tTd(18, 1) || Verbose)
++ nmessage(">>> %s", SmtpMsgBuffer);
++ if (TrafficLogFile != NULL)
++ fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), SmtpMsgBuffer);
++
++ if (mci->mci_out == NULL) {
++ if (tTd(18, 1)) printf("smtpstreammessage: NULL mci_out\n");
++ return;
++ }
++
++ strcat(SmtpMsgBuffer, m == NULL ? "\r\n" : m->m_eol);
++ len = strlen(SmtpMsgBuffer);
++
++ if (SmtpStreamLen == 0) {
++ if (SmtpStreamBufSize == 0) {
++ SmtpStreamBufSize = MAXLINE;
++ SmtpStreamBuf = xalloc(SmtpStreamBufSize);
++ }
++ SmtpStreamStart = SmtpStreamBuf;
++ }
++
++ if (SmtpStreamBufSize - SmtpStreamLen < len + 1) {
++ int start = SmtpStreamStart - SmtpStreamBuf;
++ SmtpStreamBufSize += MAXLINE;
++ SmtpStreamBuf = realloc(SmtpStreamBuf, SmtpStreamBufSize);
++ if (!SmtpStreamBuf) {
++ syserr("Out of memory!!");
++ abort();
++ /* exit(EX_UNAVAILABLE); */
++ }
++ SmtpStreamStart = SmtpStreamBuf + start;
++ }
++
++ strcpy(SmtpStreamBuf + SmtpStreamLen, SmtpMsgBuffer);
++ SmtpStreamLen += len;
++ }
++ #endif /* RCPTSTREAM */
+ /*
+ ** SMTPMESSAGE -- send message to server
+ **
+Only in /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src: usersmtp.c~
+diff -cr ./src/util.c /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/util.c
+*** ./src/util.c Mon Jul 19 23:50:45 1993
+--- /afs/andrew.cmu.edu/system/src/local/../host/oldsmail/016/src/util.c Mon Jul 26 17:17:10 1993
+***************
+*** 1034,1039 ****
+--- 1034,1091 ----
+ return (FALSE);
+ return (TRUE);
+ }
++
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++ *
++ * RCPT streaming code by John G Myers, jgm+@cmu.edu
++ * This is not supported by the maintainer of sendmail.
++ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++ *
++ ***********************************************************************
++ */
++
++ #include <fcntl.h>
++
++ /*
++ ** NONBLOCK -- set or clear non-blocking mode on file descriptor
++ **
++ ** Parameters:
++ ** fd -- the file descriptor
++ ** mode -- TRUE to set non-blocking mode
++ ** FALSE to clear non-blocking mode
++ **
++ ** Returns:
++ ** none
++ **
++ ** Side Effects:
++ ** modifies nonblocking status of fd
++ */
++
++ nonblock(fd, mode)
++ int fd;
++ bool mode;
++ {
++ int flags;
++
++ flags = fcntl(fd, F_GETFL, 0);
++ if (mode) {
++ #ifdef FNONBIO
++ flags |= FNONBIO;
++ #else
++ flags |= O_NDELAY;
++ #endif
++ }
++ else {
++ #ifdef FNONBIO
++ flags &= ~FNONBIO;
++ #else
++ flags &= ~O_NDELAY;
++ #endif
++ }
++ fcntl(fd, F_SETFL, flags);
++ }
++ #endif
+ /*
+ ** STRCONTAINEDIN -- tell if one string is contained in another
+ **
diff --git a/usr.sbin/sendmail/doc/Makefile b/usr.sbin/sendmail/doc/Makefile
new file mode 100644
index 0000000..fc9dc19
--- /dev/null
+++ b/usr.sbin/sendmail/doc/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 8.1 (Berkeley) 6/7/93
+
+SUBDIR= op intro usenix
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/sendmail/doc/op/spell.ok b/usr.sbin/sendmail/doc/op/spell.ok
new file mode 100644
index 0000000..d1cb19e
--- /dev/null
+++ b/usr.sbin/sendmail/doc/op/spell.ok
@@ -0,0 +1,324 @@
+AA06698
+AA06703
+AA22757
+AA22777
+AA99999
+ACHECK
+ARPANET
+AVENRUN
+Allman
+Arpa
+Arpanet
+BSD
+BSD4.4
+BTree
+Bcc
+BitNET
+CHmonet
+CHucbmonet
+CNAME
+CS.Berkeley.EDU
+Cdaemon
+Ceric
+Cnt
+Ctest.cf
+DB
+DLA
+DdfAA13557
+Dj
+DlFrom
+DnMAILER
+Dq
+EDU
+EOH
+EXPN
+Eol
+Eowner
+Eric.Allman
+FAX
+FSCALE
+Fri
+GECOS
+Guide''SMM:07
+H?F?from
+H?P?return
+H?x?full
+HELO
+HTo
+HdrInfo
+HiTech.COM
+Hmessage
+Hreceived
+Hsubject
+INT
+IP
+IPC
+Jul
+Kmapname
+LAN
+LHS
+LOCKF
+Linelimit
+LocalMailer
+MATCHGECOS
+MAXATOM
+MAXHOP
+MAXLINE
+MAXMAILERS
+MAXMXHOSTS
+MAXNAME
+MAXPRIORITIES
+MAXPV
+MAXRWSETS
+MAXTRUST
+MAXUSERENVIRON
+MX
+Makefile
+Makefile.dist
+Maxsize
+Meta
+Mether
+Mlocal
+MsgSize
+NEWDB
+NIS
+NOOP
+NOTUNIX
+NoReturn
+OJ
+OSTYPE
+OT3d
+PSyserr
+Pfirst
+Pjunk
+Pspecial
+QUEUESIZE
+RCPT
+README
+RFC
+RFC's
+RFC1123
+RFC819
+RFC821
+RFC822
+RHS
+Rbostic
+Reric
+Ruleset
+Rulesets
+S,D
+SETPROCTITLE
+SITECONFIG
+SMM:07
+SMTP
+SUBR
+SYS5TZ
+SYSTEM5
+Seric
+TCP
+TSyserr
+UCBARPA
+UCBARPA:eric
+UGLYUUCP
+USERDB
+Ucbvax
+Ultrix3.0
+Usrerr
+VRFY
+Wildcard
+YP
+a.CC.Berkeley.EDU
+aliases.db
+aliases.dir
+aliases.pag
+args
+automounter
+av
+avenrun
+bd
+behaviour
+bi
+bollard
+bool
+bostic
+bp
+bt
+btree
+buf
+bufsize
+bz
+c70:user
+calder
+canonification
+checkcompat
+cnt
+conf.c
+conf.h
+contessa
+cs
+cs.exposed.m4
+cs.hidden.m4
+csam
+csam.arpa
+cw
+daemon.c
+db
+decvax
+default:mailname
+delivermail
+dev
+dir
+doc
+ef
+email
+eric
+eric:mailname
+ernie
+errno
+fallback
+fax
+fi
+filename
+filenames
+fo
+foo.bar.baz.de
+fullname
+gateway.HiTech.COM
+getla
+getloadavg
+groupid
+hdrinfo
+hname
+hoptoad
+host.domain
+hosta
+hostb
+htemplate
+ie
+iff
+int
+ip
+lbl
+lf
+lhs
+lib
+lnx
+localhost
+lockf
+lp
+mail.CS.Berkeley.EDU
+mail.cf
+maildrop
+mailname
+mailq
+mailstats
+mailstats.c
+makemap
+mammoth.Berkeley.EDU
+mammoth.Berkeley.EDU.HiTech.COM
+mapclass
+maphostname
+mapname
+matisse
+mc
+mckusick
+meC
+mflags
+monet
+monet:bollard
+mqueue
+msg
+name1
+name2
+nameserver
+newalias
+nkainc
+nosuchuser
+num
+oM
+oQ
+oT1d
+oT2m
+okeeffe.CS.Berkeley.EDU
+omqueue
+ostype
+pUUCP:uunet
+pag
+pag,dir
+pathname
+pathnames
+pathnames.h
+pid
+pp
+prep.ai.MIT.EDU
+prog
+q30m
+qf
+querytype
+queueups
+rc.local
+resolv.conf
+rfc819.lpr
+rfc822.lpr
+rhs
+rlsm
+ruleset
+rulesets
+rwset
+rwsets
+sam
+sbin
+sendmail.cf
+sendmail.cw
+sendmail.fc
+sendmail.hf
+sendmail.st
+setupmaps
+si
+site.config.file
+siteconfig
+smtp
+sp
+src
+suid
+syserr
+sysname
+tcpproto.mc
+test.cf
+text1
+text2
+tf
+timestamp
+timestamps
+ucb
+ucbarpa
+ucblib
+ucbmonet
+ucbvax
+ucbvax.mc
+udbspec
+user1
+user2
+usera
+userb
+userc
+userid
+username
+usrerr
+uucpproto.mc
+uunet
+val
+vangogh.CS.Berkeley.EDU
+vangogh.berkeley.edu
+var
+vikki
+voyeurism
+wildcard
+wildcards
+wnj
+word1
+word2
+xf
+xxx
+xyzvax
+yp
diff --git a/usr.sbin/sendmail/doc/rfc/rfc819.txt b/usr.sbin/sendmail/doc/rfc/rfc819.txt
new file mode 100644
index 0000000..d66f8d9
--- /dev/null
+++ b/usr.sbin/sendmail/doc/rfc/rfc819.txt
@@ -0,0 +1,1044 @@
+
+
+Network Working Group Zaw-Sing Su (SRI)
+Request for Comments: 819 Jon Postel (ISI)
+ August 1982
+
+
+
+ The Domain Naming Convention for Internet User Applications
+
+
+
+
+1. Introduction
+
+ For many years, the naming convention "<user>@<host>" has served the
+ ARPANET user community for its mail system, and the substring
+ "<host>" has been used for other applications such as file transfer
+ (FTP) and terminal access (Telnet). With the advent of network
+ interconnection, this naming convention needs to be generalized to
+ accommodate internetworking. A decision has recently been reached to
+ replace the simple name field, "<host>", by a composite name field,
+ "<domain>" [2]. This note is an attempt to clarify this generalized
+ naming convention, the Internet Naming Convention, and to explore the
+ implications of its adoption for Internet name service and user
+ applications.
+
+ The following example illustrates the changes in naming convention:
+
+ ARPANET Convention: Fred@ISIF
+ Internet Convention: Fred@F.ISI.ARPA
+
+ The intent is that the Internet names be used to form a
+ tree-structured administrative dependent, rather than a strictly
+ topology dependent, hierarchy. The left-to-right string of name
+ components proceeds from the most specific to the most general, that
+ is, the root of the tree, the administrative universe, is on the
+ right.
+
+ The name service for realizing the Internet naming convention is
+ assumed to be application independent. It is not a part of any
+ particular application, but rather an independent name service serves
+ different user applications.
+
+2. The Structural Model
+
+ The Internet naming convention is based on the domain concept. The
+ name of a domain consists of a concatenation of one or more <simple
+ names>. A domain can be considered as a region of jurisdiction for
+ name assignment and of responsibility for name-to-address
+ translation. The set of domains forms a hierarchy.
+
+ Using a graph theory representation, this hierarchy may be modeled as
+ a directed graph. A directed graph consists of a set of nodes and a
+
+
+Su & Postel [Page 1]
+
+
+
+RFC 819 August 1982;
+
+
+ collection of arcs, where arcs are identified by ordered pairs of
+ distinct nodes [1]. Each node of the graph represents a domain. An
+ ordered pair (B, A), an arc from B to A, indicates that B is a
+ subdomain of domain A, and B is a simple name unique within A. We
+ will refer to B as a child of A, and A a parent of B. The directed
+ graph that best describes the naming hierarchy is called an
+ "in-tree", which is a rooted tree with all arcs directed towards the
+ root (Figure 1). The root of the tree represents the naming universe,
+ ancestor of all domains. Endpoints (or leaves) of the tree are the
+ lowest-level domains.
+
+ U
+ / | \
+ / | \ U -- Naming Universe
+ ^ ^ ^ I -- Intermediate Domain
+ | | | E -- Endpoint Domain
+ I E I
+ / \ |
+ ^ ^ ^
+ | | |
+ E E I
+ / | \
+ ^ ^ ^
+ | | |
+ E E E
+
+ Figure 1
+ The In-Tree Model for Domain Hierarchy
+
+ The simple name of a child in this model is necessarily unique within
+ its parent domain. Since the simple name of the child's parent is
+ unique within the child's grandparent domain, the child can be
+ uniquely named in its grandparent domain by the concatenation of its
+ simple name followed by its parent's simple name.
+
+ For example, if the simple name of a child is "C1" then no other
+ child of the same parent may be named "C1". Further, if the
+ parent of this child is named "P1", then "P1" is a unique simple
+ name in the child's grandparent domain. Thus, the concatenation
+ C1.P1 is unique in C1's grandparent domain.
+
+ Similarly, each element of the hierarchy is uniquely named in the
+ universe by its complete name, the concatenation of its simple name
+ and those for the domains along the trail leading to the naming
+ universe.
+
+ The hierarchical structure of the Internet naming convention supports
+ decentralization of naming authority and distribution of name service
+ capability. We assume a naming authority and a name server
+
+
+Su & Postel [Page 2]
+
+
+
+RFC 819 August 1982;
+
+
+ associated with each domain. In Sections 5 and 6 respectively the
+ name service and the naming authority are discussed.
+
+ Within an endpoint domain, unique names are assigned to <user>
+ representing user mailboxes. User mailboxes may be viewed as
+ children of their respective domains.
+
+ In reality, anomalies may exist violating the in-tree model of naming
+ hierarchy. Overlapping domains imply multiple parentage, i.e., an
+ entity of the naming hierarchy being a child of more than one domain.
+ It is conceivable that ISI can be a member of the ARPA domain as well
+ as a member of the USC domain (Figure 2). Such a relation
+ constitutes an anomaly to the rule of one-connectivity between any
+ two points of a tree. The common child and the sub-tree below it
+ become descendants of both parent domains.
+
+ U
+ / | \
+ / . \
+ . . ARPA
+ . . | \
+ USC | \
+ \ | .
+ \ | .
+ ISI
+
+ Figure 2
+ Anomaly in the In-Tree Model
+
+ Some issues resulting from multiple parentage are addressed in
+ Appendix B. The general implications of multiple parentage are a
+ subject for further investigation.
+
+3. Advantage of Absolute Naming
+
+ Absolute naming implies that the (complete) names are assigned with
+ respect to a universal reference point. The advantage of absolute
+ naming is that a name thus assigned can be universally interpreted
+ with respect to the universal reference point. The Internet naming
+ convention provides absolute naming with the naming universe as its
+ universal reference point.
+
+ For relative naming, an entity is named depending upon the position
+ of the naming entity relative to that of the named entity. A set of
+ hosts running the "unix" operating system exchange mail using a
+ method called "uucp". The naming convention employed by uucp is an
+ example of relative naming. The mail recipient is typically named by
+ a source route identifying a chain of locally known hosts linking the
+
+
+
+Su & Postel [Page 3]
+
+
+
+RFC 819 August 1982;
+
+
+ sender's host to the recipient's. A destination name can be, for
+ example,
+
+ "alpha!beta!gamma!john",
+
+ where "alpha" is presumably known to the originating host, "beta" is
+ known to "alpha", and so on.
+
+ The uucp mail system has demonstrated many of the problems inherent
+ to relative naming. When the host names are only locally
+ interpretable, routing optimization becomes impossible. A reply
+ message may have to traverse the reverse route to the original sender
+ in order to be forwarded to other parties.
+
+ Furthermore, if a message is forwarded by one of the original
+ recipients or passed on as the text of another message, the frame of
+ reference of the relative source route can be completely lost. Such
+ relative naming schemes have severe problems for many of the uses
+ that we depend upon in the ARPA Internet community.
+
+4. Interoperability
+
+ To allow interoperation with a different naming convention, the names
+ assigned by a foreign naming convention need to be accommodated.
+ Given the autonomous nature of domains, a foreign naming environment
+ may be incorporated as a domain anywhere in the hierarchy. Within
+ the naming universe, the name service for a domain is provided within
+ that domain. Thus, a foreign naming convention can be independent of
+ the Internet naming convention. What is implied here is that no
+ standard convention for naming needs to be imposed to allow
+ interoperations among heterogeneous naming environments.
+
+ For example:
+
+ There might be a naming convention, say, in the FOO world,
+ something like "<user>%<host>%<area>". Communications with an
+ entity in that environment can be achieved from the Internet
+ community by simply appending ".FOO" on the end of the name in
+ that foreign convention.
+
+ John%ISI-Tops20-7%California.FOO
+
+ Another example:
+
+ One way of accommodating the "uucp world" described in the last
+ section is to declare it as a foreign system. Thus, a uucp
+ name
+
+ "alpha!beta!gamma!john"
+
+
+Su & Postel [Page 4]
+
+
+
+RFC 819 August 1982;
+
+
+ might be known in the Internet community as
+
+ "alpha!beta!gamma!john.UUCP".
+
+ Communicating with a complex subdomain is another case which can
+ be treated as interoperation. A complex subdomain is a domain
+ with complex internal naming structure presumably unknown to the
+ outside world (or the outside world does not care to be concerned
+ with its complexity).
+
+ For the mail system application, the names embedded in the message
+ text are often used by the destination for such purpose as to reply
+ to the original message. Thus, the embedded names may need to be
+ converted for the benefit of the name server in the destination
+ environment.
+
+ Conversion of names on the boundary between heterogeneous naming
+ environments is a complex subject. The following example illustrates
+ some of the involved issues.
+
+ For example:
+
+ A message is sent from the Internet community to the FOO
+ environment. It may bear the "From" and "To" fields as:
+
+ From: Fred@F.ISI.ARPA
+ To: John%ISI-Tops20-7%California.FOO
+
+ where "FOO" is a domain independent of the Internet naming
+ environment. The interface on the boundary of the two
+ environments may be represented by a software module. We may
+ assume this interface to be an entity of the Internet community
+ as well as an entity of the FOO community. For the benefit of
+ the FOO environment, the "From" and "To" fields need to be
+ modified upon the message's arrival at the boundary. One may
+ view naming as a separate layer of protocol, and treat
+ conversion as a protocol translation. The matter is
+ complicated when the message is sent to more than one
+ destination within different naming environments; or the
+ message is destined within an environment not sharing boundary
+ with the originating naming environment.
+
+ While the general subject concerning conversion is beyond the scope
+ of this note, a few questions are raised in Appendix D.
+
+
+
+
+
+
+
+Su & Postel [Page 5]
+
+
+
+RFC 819 August 1982;
+
+
+5. Name Service
+
+ Name service is a network service providing name-to-address
+ translation. Such service may be achieved in a number of ways. For
+ a simple networking environment, it can be accomplished with a single
+ central database containing name-to-address correspondence for all
+ the pertinent network entities, such as hosts.
+
+ In the case of the old ARPANET host names, a central database is
+ duplicated in each individual host. The originating module of an
+ application process would query the local name service (e.g., make a
+ system call) to obtain network address for the destination host. With
+ the proliferation of networks and an accelerating increase in the
+ number of hosts participating in networking, the ever growing size,
+ update frequency, and the dissemination of the central database makes
+ this approach unmanageable.
+
+ The hierarchical structure of the Internet naming convention supports
+ decentralization of naming authority and distribution of name service
+ capability. It readily accommodates growth of the naming universe.
+ It allows an arbitrary number of hierarchical layers. The addition
+ of a new domain adds little complexity to an existing Internet
+ system.
+
+ The name service at each domain is assumed to be provided by one or
+ more name servers. There are two models for how a name server
+ completes its work, these might be called "iterative" and
+ "recursive".
+
+ For an iterative name server there may be two kinds of responses.
+ The first kind of response is a destination address. The second
+ kind of response is the address of another name server. If the
+ response is a destination address, then the query is satisfied. If
+ the response is the address of another name server, then the query
+ must be repeated using that name server, and so on until a
+ destination address is obtained.
+
+ For a recursive name server there is only one kind of response --
+ a destination address. This puts an obligation on the name server
+ to actually make the call on another name server if it can't
+ answer the query itself.
+
+ It is noted that looping can be avoided since the names presented for
+ translation can only be of finite concatenation. However, care
+ should be taken in employing mechanisms such as a pointer to the next
+ simple name for resolution.
+
+ We believe that some name servers will be recursive, but we don't
+ believe that all will be. This means that the caller must be
+
+
+Su & Postel [Page 6]
+
+
+
+RFC 819 August 1982;
+
+
+ prepared for either type of server. Further discussion and examples
+ of name service is given in Appendix C.
+
+ The basic name service at each domain is the translation of simple
+ names to addresses for all of its children. However, if only this
+ basic name service is provided, the use of complete (or fully
+ qualified) names would be required. Such requirement can be
+ unreasonable in practice. Thus, we propose the use of partial names
+ in the context in which their uniqueness is preserved. By
+ construction, naming uniqueness is preserved within the domain of a
+ common ancestry. Thus, a partially qualified name is constructed by
+ omitting from the complete name ancestors common to the communicating
+ parties. When a partially qualified name leaves its context of
+ uniqueness it must be additionally qualified.
+
+ The use of partially qualified names places a requirement on the
+ Internet name service. To satisfy this requirement, the name service
+ at each domain must be capable of, in addition to the basic service,
+ resolving simple names for all of its ancestors (including itself)
+ and their children. In Appendix B, the required distinction among
+ simple names for such resolution is addressed.
+
+6. Naming Authority
+
+ Associated with each domain there must be a naming authority to
+ assign simple names and ensure proper distinction among simple names.
+
+ Note that if the use of partially qualified names is allowed in a
+ sub-domain, the uniqueness of simple names inside that sub-domain is
+ insufficient to avoid ambiguity with names outside the subdomain.
+ Appendix B discusses simple name assignment in a sub-domain that
+ would allow the use of partially qualified names without ambiguity.
+
+ Administratively, associated with each domain there is a single
+ person (or office) called the registrar. The registrar of the naming
+ universe specifies the top-level set of domains and designates a
+ registrar for each of these domains. The registrar for any given
+ domain maintains the naming authority for that domain.
+
+7. Network-Oriented Applications
+
+ For user applications such as file transfer and terminal access, the
+ remote host needs to be named. To be compatible with ARPANET naming
+ convention, a host can be treated as an endpoint domain.
+
+ Many operating systems or programming language run-time environments
+ provide functions or calls (JSYSs, SVCs, UUOs, SYSs, etc.) for
+ standard services (e.g., time-of-day, account-of-logged-in-user,
+ convert-number-to-string). It is likely to be very helpful if such a
+
+
+Su & Postel [Page 7]
+
+
+
+RFC 819 August 1982;
+
+
+ function or call is developed for translating a host name to an
+ address. Indeed, several systems on the ARPANET already have such
+ facilities for translating an ARPANET host name into an ARPANET
+ address based on internal tables.
+
+ We recommend that this provision of a standard function or call for
+ translating names to addresses be extended to accept names of
+ Internet convention. This will promote a consistent interface to the
+ users of programs involving internetwork activities. The standard
+ facility for translating Internet names to Internet addresses should
+ include all the mechanisms available on the host, such as checking a
+ local table or cache of recently checked names, or consulting a name
+ server via the Internet.
+
+8. Mail Relaying
+
+ Relaying is a feature adopted by more and more mail systems.
+ Relaying facilitates, among other things, interoperations between
+ heterogeneous mail systems. The term "relay" is used to describe the
+ situation where a message is routed via one or more intermediate
+ points between the sender and the recipient. The mail relays are
+ normally specified explicitly as relay points in the instructions for
+ message delivery. Usually, each of the intermediate relays assume
+ responsibility for the relayed message [3].
+
+ A point should be made on the basic difference between mail
+ relaying and the uucp naming system. The difference is that
+ although mail relaying with absolute naming can also be considered
+ as a form of source routing, the names of each intermediate points
+ and that of the destination are universally interpretable, while
+ the host names along a source route of the uucp convention is
+ relative and thus only locally interpretable.
+
+ The Internet naming convention explicitly allows interoperations
+ among heterogeneous systems. This implies that the originator of a
+ communication may name a destination which resides in a foreign
+ system. The probability is that the destination network address may
+ not be comprehensible to the transport system of the originator.
+ Thus, an implicit relaying mechanism is called for at the boundary
+ between the domains. The function of this implicit relay is the same
+ as the explicit relay.
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 8]
+
+
+
+RFC 819 August 1982;
+
+
+9. Implementation
+
+ The Actual Domains
+
+ The initial set of top-level names include:
+
+ ARPA
+
+ This represents the set of organizations involved in the
+ Internet system through the authority of the U.S. Defense
+ Advanced Research Projects Agency. This includes all the
+ research and development hosts on the ARPANET and hosts on
+ many other nets as well. But note very carefully that the
+ top-level domain "ARPA" does not map one-to-one with the
+ ARPANET -- domains are administrative, not topological.
+
+ Transition
+
+ In the transition from the ARPANET naming convention to the
+ Internet naming convention, a host name may be used as a simple
+ name for an endpoint domain. Thus, if "USC-ISIF" is an ARPANET
+ host name, then "USC-ISIF.ARPA" is the name of an Internet domain.
+
+10. Summary
+
+ A hierarchical naming convention based on the domain concept has been
+ adopted by the Internet community. It is an absolute naming
+ convention defined along administrative rather than topological
+ boundaries. This naming convention is adaptive for interoperations
+ with other naming conventions. Thus, no standard convention needs to
+ be imposed for interoperations among heterogeneous naming
+ environments.
+
+ This Internet naming convention allows distributed name service and
+ naming authority functions at each domain. We have specified these
+ functions required at each domain. Also discussed are implications
+ on network-oriented applications, mail systems, and administrative
+ aspects of this convention.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 9]
+
+
+
+RFC 819 August 1982;
+
+
+APPENDIX A
+
+ The BNF Specification
+
+ We present here a rather detailed "BNF" definition of the allowed
+ form for a computer mail "mailbox" composed of a "local-part" and a
+ "domain" (separated by an at sign). Clearly, the domain can be used
+ separately in other network-oriented applications.
+
+ <mailbox> ::= <local-part> "@" <domain>
+
+ <local-part> ::= <string> | <quoted-string>
+
+ <string> ::= <char> | <char> <string>
+
+ <quoted-string> ::= """ <qtext> """
+
+ <qtext> ::= "\" <x> | "\" <x> <qtext> | <q> | <q> <qtext>
+
+ <char> ::= <c> | "\" <x>
+
+ <domain> ::= <naming-domain> | <naming-domain> "." <domain>
+
+ <naming-domain> ::= <simple-name> | <address>
+
+ <simple-name> ::= <a> <ldh-str> <let-dig>
+
+ <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+ <let-dig> ::= <a> | <d>
+
+ <let-dig-hyp> ::= <a> | <d> | "-"
+
+ <address> :: = "#" <number> | "[" <dotnum> "]"
+
+ <number> ::= <d> | <d> <number>
+
+ <dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>
+
+ <snum> ::= one, two, or three digits representing a decimal integer
+ value in the range 0 through 255
+
+ <a> ::= any one of the 52 alphabetic characters A through Z in upper
+ case and a through z in lower case
+
+ <c> ::= any one of the 128 ASCII characters except <s> or <SP>
+
+ <d> ::= any one of the ten digits 0 through 9
+
+
+
+Su & Postel [Page 10]
+
+
+
+RFC 819 August 1982;
+
+
+ <q> ::= any one of the 128 ASCII characters except CR, LF, quote ("),
+ or backslash (\)
+
+ <x> ::= any one of the 128 ASCII characters (no exceptions)
+
+ <s> ::= "<", ">", "(", ")", "[", "]", "\", ".", ",", ";", ":", "@",
+ """, and the control characters (ASCII codes 0 through 31 inclusive
+ and 127)
+
+ Note that the backslash, "\", is a quote character, which is used to
+ indicate that the next character is to be used literally (instead of
+ its normal interpretation). For example, "Joe\,Smith" could be used
+ to indicate a single nine character user field with comma being the
+ fourth character of the field.
+
+ The simple names that make up a domain may contain both upper and
+ lower case letters (as well as digits and hyphen), but these names
+ are not case sensitive.
+
+ Hosts are generally known by names. Sometimes a host is not known to
+ the translation function and communication is blocked. To bypass
+ this barrier two forms of addresses are also allowed for host
+ "names". One form is a decimal integer prefixed by a pound sign, "#".
+ Another form, called "dotted decimal", is four small decimal integers
+ separated by dots and enclosed by brackets, e.g., "[123.255.37.2]",
+ which indicates a 32-bit ARPA Internet Address in four 8-bit fields.
+ (Of course, these numeric address forms are specific to the Internet,
+ other forms may have to be provided if this problem arises in other
+ transport systems.)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 11]
+
+
+
+RFC 819 August 1982;
+
+
+APPENDIX B
+
+ An Aside on the Assignment of Simple Names
+
+ In the following example, there are two naming hierarchies joining at
+ the naming universe 'U'. One consists of domains (S, R, N, J, P, Q,
+ B, A); and the other (L, E, F, G, H, D, C, K, B, A). Domain B is
+ assumed to have multiple parentage as shown.
+
+ U
+ / \
+ / \
+ J L
+ / \
+ N E
+ / \ / \
+ R P D F
+ / \ | \ \
+ S Q C (X) G
+ \ / \ \
+ B K H
+ /
+ A
+
+ Figure 3
+ Illustration of Requirements for the Distinction of Simple Names
+
+ Suppose someone at A tries to initiate communication with destination
+ H. The fully qualified destination name would be
+
+ H.G.F.E.L.U
+
+ Omitting common ancestors, the partially qualified name for the
+ destination would be
+
+ H.G.F
+
+ To permit the case of partially qualified names, name server at A
+ needs to resolve the simple name F, i.e., F needs to be distinct from
+ all the other simple names in its database.
+
+ To enable the name server of a domain to resolve simple names, a
+ simple name for a child needs to be assigned distinct from those of
+ all of its ancestors and their immediate children. However, such
+ distinction would not be sufficient to allow simple name resolution
+ at lower-level domains because lower-level domains could have
+ multiple parentage below the level of this domain.
+
+ In the example above, let us assume that a name is to be assigned
+
+
+Su & Postel [Page 12]
+
+
+
+RFC 819 August 1982;
+
+
+ to a new domain X by D. To allow name server at D to resolve
+ simple names, the name for X must be distinct from L, E, D, C, F,
+ and J. However, allowing A to resolve simple names, X needs to be
+ also distinct from A, B, K, as well as from Q, P, N, and R.
+
+ The following observations can be made.
+
+ Simple names along parallel trails (distinct trails leading from
+ one domain to the naming universe) must be distinct, e.g., N must
+ be distinct from E for B or A to properly resolve simple names.
+
+ No universal uniqueness of simple names is called for, e.g., the
+ simple name S does not have to be distinct from that of E, F, G,
+ H, D, C, K, Q, B, or A.
+
+ The lower the level at which a domain occurs, the more immune it
+ is to the requirement of naming uniqueness.
+
+ To satisfy the required distinction of simple names for proper
+ resolution at all levels, a naming authority needs to ensure the
+ simple name to be assigned distinct from those in the name server
+ databases at the endpoint naming domains within its domain. As an
+ example, for D to assign a simple name for X, it would need to
+ consult databases at A and K. It is, however, acceptable to have
+ simple names under domain A identical with those under K. Failure of
+ such distinct assignment of simple names by naming authority of one
+ domain would jeopardize the capability of simple name resolution for
+ entities within the subtree under that domain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 13]
+
+
+
+RFC 819 August 1982;
+
+
+APPENDIX C
+
+ Further Discussion of Name Service and Name Servers
+
+ The name service on a system should appear to the programmer of an
+ application program simply as a system call or library subroutine.
+ Within that call or subroutine there may be several types of methods
+ for resolving the name string into an address.
+
+ First, a local table may be consulted. This table may be a
+ complete table and may be updated frequently, or it may simply be
+ a cache of the few latest name to address mappings recently
+ determined.
+
+ Second, a call may be made to a name server to resolve the string
+ into a destination address.
+
+ Third, a call may be made to a name server to resolve the string
+ into a relay address.
+
+ Whenever a name server is called it may be a recursive server or an
+ interactive server.
+
+ If the server is recursive, the caller won't be able to tell if
+ the server itself had the information to resolve the query or
+ called another server recursively (except perhaps for the time it
+ takes).
+
+ If the server is iterative, the caller must be prepared for either
+ the answer to its query, or a response indicating that it should
+ call on a different server.
+
+ It should be noted that the main name service discussed in this memo
+ is simply a name string to address service. For some applications
+ there may be other services needed.
+
+ For example, even within the Internet there are several procedures
+ or protocols for actually transferring mail. One need is to
+ determine which mail procedures a destination host can use.
+ Another need is to determine the name of a relay host if the
+ source and destination hosts do not have a common mail procedure.
+ These more specialized services must be specific to each
+ application since the answers may be application dependent, but
+ the basic name to address translation is application independent.
+
+
+
+
+
+
+
+Su & Postel [Page 14]
+
+
+
+RFC 819 August 1982;
+
+
+APPENDIX D
+
+ Further Discussion of Interoperability and Protocol Translations
+
+ The translation of protocols from one system to another is often
+ quite difficult. Following are some questions that stem from
+ considering the translations of addresses between mail systems:
+
+ What is the impact of different addressing environments (i.e.,
+ environments of different address formats)?
+
+ It is noted that the boundary of naming environment may or may not
+ coincide with the boundary of different mail systems. Should the
+ conversion of naming be independent of the application system?
+
+ The boundary between different addressing environments may or may
+ not coincide with that of different naming environments or
+ application systems. Some generic approach appears to be
+ necessary.
+
+ If the conversion of naming is to be independent of the
+ application system, some form of interaction appears necessary
+ between the interface module of naming conversion with some
+ application level functions, such as the parsing and modification
+ of message text.
+
+ To accommodate encryption, conversion may not be desirable at all.
+ What then can be an alternative to conversion?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 15]
+
+
+
+RFC 819 August 1982;
+
+
+GLOSSARY
+
+ address
+
+ An address is a numerical identifier for the topological location
+ of the named entity.
+
+ name
+
+ A name is an alphanumeric identifier associated with the named
+ entity. For unique identification, a name needs to be unique in
+ the context in which the name is used. A name can be mapped to an
+ address.
+
+ complete (fully qualified) name
+
+ A complete name is a concatenation of simple names representing
+ the hierarchical relation of the named with respect to the naming
+ universe, that is it is the concatenation of the simple names of
+ the domain structure tree nodes starting with its own name and
+ ending with the top level node name. It is a unique name in the
+ naming universe.
+
+ partially qualified name
+
+ A partially qualified name is an abbreviation of the complete name
+ omitting simple names of the common ancestors of the communicating
+ parties.
+
+ simple name
+
+ A simple name is an alphanumeric identifier unique only within its
+ parent domain.
+
+ domain
+
+ A domain defines a region of jurisdiction for name assignment and
+ of responsibility for name-to-address translation.
+
+ naming universe
+
+ Naming universe is the ancestor of all network entities.
+
+ naming environment
+
+ A networking environment employing a specific naming convention.
+
+
+
+
+
+Su & Postel [Page 16]
+
+
+
+RFC 819 August 1982;
+
+
+ name service
+
+ Name service is a network service for name-to-address mapping.
+
+ name server
+
+ A name server is a network mechanism (e.g., a process) realizing
+ the function of name service.
+
+ naming authority
+
+ Naming authority is an administrative entity having the authority
+ for assigning simple names and responsibility for resolving naming
+ conflict.
+
+ parallel relations
+
+ A network entity may have one or more hierarchical relations with
+ respect to the naming universe. Such multiple relations are
+ parallel relations to each other.
+
+ multiple parentage
+
+ A network entity has multiple parentage when it is assigned a
+ simple name by more than one naming domain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 17]
+
+
+
+RFC 819 August 1982;
+
+
+REFERENCES
+
+ [1] F. Harary, "Graph Theory", Addison-Wesley, Reading,
+ Massachusetts, 1969.
+
+ [2] J. Postel, "Computer Mail Meeting Notes", RFC-805,
+ USC/Information Sciences Institute, 8 February 1982.
+
+ [3] J. Postel, "Simple Mail Transfer Protocol", RFC-821,
+ USC/Information Sciences Institute, August 1982.
+
+ [4] D. Crocker, "Standard for the Format of ARPA Internet Text
+ Messages", RFC-822, Department of Electrical Engineering, University
+ of Delaware, August 1982.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Su & Postel [Page 18]
+
diff --git a/usr.sbin/sendmail/doc/rfc/rfc821.txt b/usr.sbin/sendmail/doc/rfc/rfc821.txt
new file mode 100644
index 0000000..d877b72
--- /dev/null
+++ b/usr.sbin/sendmail/doc/rfc/rfc821.txt
@@ -0,0 +1,4050 @@
+
+
+
+ RFC 821
+
+
+
+
+
+ SIMPLE MAIL TRANSFER PROTOCOL
+
+
+
+ Jonathan B. Postel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 1982
+
+
+
+ Information Sciences Institute
+ University of Southern California
+ 4676 Admiralty Way
+ Marina del Rey, California 90291
+
+ (213) 822-1511
+
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ TABLE OF CONTENTS
+
+ 1. INTRODUCTION .................................................. 1
+
+ 2. THE SMTP MODEL ................................................ 2
+
+ 3. THE SMTP PROCEDURE ............................................ 4
+
+ 3.1. Mail ..................................................... 4
+ 3.2. Forwarding ............................................... 7
+ 3.3. Verifying and Expanding .................................. 8
+ 3.4. Sending and Mailing ..................................... 11
+ 3.5. Opening and Closing ..................................... 13
+ 3.6. Relaying ................................................ 14
+ 3.7. Domains ................................................. 17
+ 3.8. Changing Roles .......................................... 18
+
+ 4. THE SMTP SPECIFICATIONS ...................................... 19
+
+ 4.1. SMTP Commands ........................................... 19
+ 4.1.1. Command Semantics ..................................... 19
+ 4.1.2. Command Syntax ........................................ 27
+ 4.2. SMTP Replies ............................................ 34
+ 4.2.1. Reply Codes by Function Group ......................... 35
+ 4.2.2. Reply Codes in Numeric Order .......................... 36
+ 4.3. Sequencing of Commands and Replies ...................... 37
+ 4.4. State Diagrams .......................................... 39
+ 4.5. Details ................................................. 41
+ 4.5.1. Minimum Implementation ................................ 41
+ 4.5.2. Transparency .......................................... 41
+ 4.5.3. Sizes ................................................. 42
+
+ APPENDIX A: TCP ................................................. 44
+ APPENDIX B: NCP ................................................. 45
+ APPENDIX C: NITS ................................................ 46
+ APPENDIX D: X.25 ................................................ 47
+ APPENDIX E: Theory of Reply Codes ............................... 48
+ APPENDIX F: Scenarios ........................................... 51
+
+ GLOSSARY ......................................................... 64
+
+ REFERENCES ....................................................... 67
+
+
+
+
+Network Working Group J. Postel
+Request for Comments: DRAFT ISI
+Replaces: RFC 788, 780, 772 August 1982
+
+ SIMPLE MAIL TRANSFER PROTOCOL
+
+
+1. INTRODUCTION
+
+ The objective of Simple Mail Transfer Protocol (SMTP) is to transfer
+ mail reliably and efficiently.
+
+ SMTP is independent of the particular transmission subsystem and
+ requires only a reliable ordered data stream channel. Appendices A,
+ B, C, and D describe the use of SMTP with various transport services.
+ A Glossary provides the definitions of terms as used in this
+ document.
+
+ An important feature of SMTP is its capability to relay mail across
+ transport service environments. A transport service provides an
+ interprocess communication environment (IPCE). An IPCE may cover one
+ network, several networks, or a subset of a network. It is important
+ to realize that transport systems (or IPCEs) are not one-to-one with
+ networks. A process can communicate directly with another process
+ through any mutually known IPCE. Mail is an application or use of
+ interprocess communication. Mail can be communicated between
+ processes in different IPCEs by relaying through a process connected
+ to two (or more) IPCEs. More specifically, mail can be relayed
+ between hosts on different transport systems by a host on both
+ transport systems.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 1]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+2. THE SMTP MODEL
+
+ The SMTP design is based on the following model of communication: as
+ the result of a user mail request, the sender-SMTP establishes a
+ two-way transmission channel to a receiver-SMTP. The receiver-SMTP
+ may be either the ultimate destination or an intermediate. SMTP
+ commands are generated by the sender-SMTP and sent to the
+ receiver-SMTP. SMTP replies are sent from the receiver-SMTP to the
+ sender-SMTP in response to the commands.
+
+ Once the transmission channel is established, the SMTP-sender sends a
+ MAIL command indicating the sender of the mail. If the SMTP-receiver
+ can accept mail it responds with an OK reply. The SMTP-sender then
+ sends a RCPT command identifying a recipient of the mail. If the
+ SMTP-receiver can accept mail for that recipient it responds with an
+ OK reply; if not, it responds with a reply rejecting that recipient
+ (but not the whole mail transaction). The SMTP-sender and
+ SMTP-receiver may negotiate several recipients. When the recipients
+ have been negotiated the SMTP-sender sends the mail data, terminating
+ with a special sequence. If the SMTP-receiver successfully processes
+ the mail data it responds with an OK reply. The dialog is purposely
+ lock-step, one-at-a-time.
+
+ -------------------------------------------------------------
+
+
+ +----------+ +----------+
+ +------+ | | | |
+ | User |<-->| | SMTP | |
+ +------+ | Sender- |Commands/Replies| Receiver-|
+ +------+ | SMTP |<-------------->| SMTP | +------+
+ | File |<-->| | and Mail | |<-->| File |
+ |System| | | | | |System|
+ +------+ +----------+ +----------+ +------+
+
+
+ Sender-SMTP Receiver-SMTP
+
+ Model for SMTP Use
+
+ Figure 1
+
+ -------------------------------------------------------------
+
+ The SMTP provides mechanisms for the transmission of mail; directly
+ from the sending user's host to the receiving user's host when the
+
+
+
+[Page 2] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ two host are connected to the same transport service, or via one or
+ more relay SMTP-servers when the source and destination hosts are not
+ connected to the same transport service.
+
+ To be able to provide the relay capability the SMTP-server must be
+ supplied with the name of the ultimate destination host as well as
+ the destination mailbox name.
+
+ The argument to the MAIL command is a reverse-path, which specifies
+ who the mail is from. The argument to the RCPT command is a
+ forward-path, which specifies who the mail is to. The forward-path
+ is a source route, while the reverse-path is a return route (which
+ may be used to return a message to the sender when an error occurs
+ with a relayed message).
+
+ When the same message is sent to multiple recipients the SMTP
+ encourages the transmission of only one copy of the data for all the
+ recipients at the same destination host.
+
+ The mail commands and replies have a rigid syntax. Replies also have
+ a numeric code. In the following, examples appear which use actual
+ commands and replies. The complete lists of commands and replies
+ appears in Section 4 on specifications.
+
+ Commands and replies are not case sensitive. That is, a command or
+ reply word may be upper case, lower case, or any mixture of upper and
+ lower case. Note that this is not true of mailbox user names. For
+ some hosts the user name is case sensitive, and SMTP implementations
+ must take case to preserve the case of user names as they appear in
+ mailbox arguments. Host names are not case sensitive.
+
+ Commands and replies are composed of characters from the ASCII
+ character set [1]. When the transport service provides an 8-bit byte
+ (octet) transmission channel, each 7-bit character is transmitted
+ right justified in an octet with the high order bit cleared to zero.
+
+ When specifying the general form of a command or reply, an argument
+ (or special symbol) will be denoted by a meta-linguistic variable (or
+ constant), for example, "<string>" or "<reverse-path>". Here the
+ angle brackets indicate these are meta-linguistic variables.
+ However, some arguments use the angle brackets literally. For
+ example, an actual reverse-path is enclosed in angle brackets, i.e.,
+ "<John.Smith@USC-ISI.ARPA>" is an instance of <reverse-path> (the
+ angle brackets are actually transmitted in the command or reply).
+
+
+
+
+
+Postel [Page 3]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+3. THE SMTP PROCEDURES
+
+ This section presents the procedures used in SMTP in several parts.
+ First comes the basic mail procedure defined as a mail transaction.
+ Following this are descriptions of forwarding mail, verifying mailbox
+ names and expanding mailing lists, sending to terminals instead of or
+ in combination with mailboxes, and the opening and closing exchanges.
+ At the end of this section are comments on relaying, a note on mail
+ domains, and a discussion of changing roles. Throughout this section
+ are examples of partial command and reply sequences, several complete
+ scenarios are presented in Appendix F.
+
+ 3.1. MAIL
+
+ There are three steps to SMTP mail transactions. The transaction
+ is started with a MAIL command which gives the sender
+ identification. A series of one or more RCPT commands follows
+ giving the receiver information. Then a DATA command gives the
+ mail data. And finally, the end of mail data indicator confirms
+ the transaction.
+
+ The first step in the procedure is the MAIL command. The
+ <reverse-path> contains the source mailbox.
+
+ MAIL <SP> FROM:<reverse-path> <CRLF>
+
+ This command tells the SMTP-receiver that a new mail
+ transaction is starting and to reset all its state tables and
+ buffers, including any recipients or mail data. It gives the
+ reverse-path which can be used to report errors. If accepted,
+ the receiver-SMTP returns a 250 OK reply.
+
+ The <reverse-path> can contain more than just a mailbox. The
+ <reverse-path> is a reverse source routing list of hosts and
+ source mailbox. The first host in the <reverse-path> should be
+ the host sending this command.
+
+ The second step in the procedure is the RCPT command.
+
+ RCPT <SP> TO:<forward-path> <CRLF>
+
+ This command gives a forward-path identifying one recipient.
+ If accepted, the receiver-SMTP returns a 250 OK reply, and
+ stores the forward-path. If the recipient is unknown the
+ receiver-SMTP returns a 550 Failure reply. This second step of
+ the procedure can be repeated any number of times.
+
+
+
+[Page 4] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ The <forward-path> can contain more than just a mailbox. The
+ <forward-path> is a source routing list of hosts and the
+ destination mailbox. The first host in the <forward-path>
+ should be the host receiving this command.
+
+ The third step in the procedure is the DATA command.
+
+ DATA <CRLF>
+
+ If accepted, the receiver-SMTP returns a 354 Intermediate reply
+ and considers all succeeding lines to be the message text.
+ When the end of text is received and stored the SMTP-receiver
+ sends a 250 OK reply.
+
+ Since the mail data is sent on the transmission channel the end
+ of the mail data must be indicated so that the command and
+ reply dialog can be resumed. SMTP indicates the end of the
+ mail data by sending a line containing only a period. A
+ transparency procedure is used to prevent this from interfering
+ with the user's text (see Section 4.5.2).
+
+ Please note that the mail data includes the memo header
+ items such as Date, Subject, To, Cc, From [2].
+
+ The end of mail data indicator also confirms the mail
+ transaction and tells the receiver-SMTP to now process the
+ stored recipients and mail data. If accepted, the
+ receiver-SMTP returns a 250 OK reply. The DATA command should
+ fail only if the mail transaction was incomplete (for example,
+ no recipients), or if resources are not available.
+
+ The above procedure is an example of a mail transaction. These
+ commands must be used only in the order discussed above.
+ Example 1 (below) illustrates the use of these commands in a mail
+ transaction.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 5]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ -------------------------------------------------------------
+
+ Example of the SMTP Procedure
+
+ This SMTP example shows mail sent by Smith at host Alpha.ARPA,
+ to Jones, Green, and Brown at host Beta.ARPA. Here we assume
+ that host Alpha contacts host Beta directly.
+
+ S: MAIL FROM:<Smith@Alpha.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Jones@Beta.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Green@Beta.ARPA>
+ R: 550 No such user here
+
+ S: RCPT TO:<Brown@Beta.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: <CRLF>.<CRLF>
+ R: 250 OK
+
+ The mail has now been accepted for Jones and Brown. Green did
+ not have a mailbox at host Beta.
+
+ Example 1
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 6] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 3.2. FORWARDING
+
+ There are some cases where the destination information in the
+ <forward-path> is incorrect, but the receiver-SMTP knows the
+ correct destination. In such cases, one of the following replies
+ should be used to allow the sender to contact the correct
+ destination.
+
+ 251 User not local; will forward to <forward-path>
+
+ This reply indicates that the receiver-SMTP knows the user's
+ mailbox is on another host and indicates the correct
+ forward-path to use in the future. Note that either the
+ host or user or both may be different. The receiver takes
+ responsibility for delivering the message.
+
+ 551 User not local; please try <forward-path>
+
+ This reply indicates that the receiver-SMTP knows the user's
+ mailbox is on another host and indicates the correct
+ forward-path to use. Note that either the host or user or
+ both may be different. The receiver refuses to accept mail
+ for this user, and the sender must either redirect the mail
+ according to the information provided or return an error
+ response to the originating user.
+
+ Example 2 illustrates the use of these responses.
+
+ -------------------------------------------------------------
+
+ Example of Forwarding
+
+ Either
+
+ S: RCPT TO:<Postel@USC-ISI.ARPA>
+ R: 251 User not local; will forward to <Postel@USC-ISIF.ARPA>
+
+ Or
+
+ S: RCPT TO:<Paul@USC-ISIB.ARPA>
+ R: 551 User not local; please try <Mockapetris@USC-ISIF.ARPA>
+
+ Example 2
+
+ -------------------------------------------------------------
+
+
+
+
+Postel [Page 7]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ 3.3. VERIFYING AND EXPANDING
+
+ SMTP provides as additional features, commands to verify a user
+ name or expand a mailing list. This is done with the VRFY and
+ EXPN commands, which have character string arguments. For the
+ VRFY command, the string is a user name, and the response may
+ include the full name of the user and must include the mailbox of
+ the user. For the EXPN command, the string identifies a mailing
+ list, and the multiline response may include the full name of the
+ users and must give the mailboxes on the mailing list.
+
+ "User name" is a fuzzy term and used purposely. If a host
+ implements the VRFY or EXPN commands then at least local mailboxes
+ must be recognized as "user names". If a host chooses to
+ recognize other strings as "user names" that is allowed.
+
+ In some hosts the distinction between a mailing list and an alias
+ for a single mailbox is a bit fuzzy, since a common data structure
+ may hold both types of entries, and it is possible to have mailing
+ lists of one mailbox. If a request is made to verify a mailing
+ list a positive response can be given if on receipt of a message
+ so addressed it will be delivered to everyone on the list,
+ otherwise an error should be reported (e.g., "550 That is a
+ mailing list, not a user"). If a request is made to expand a user
+ name a positive response can be formed by returning a list
+ containing one name, or an error can be reported (e.g., "550 That
+ is a user name, not a mailing list").
+
+ In the case of a multiline reply (normal for EXPN) exactly one
+ mailbox is to be specified on each line of the reply. In the case
+ of an ambiguous request, for example, "VRFY Smith", where there
+ are two Smith's the response must be "553 User ambiguous".
+
+ The case of verifying a user name is straightforward as shown in
+ example 3.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 8] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ -------------------------------------------------------------
+
+ Example of Verifying a User Name
+
+ Either
+
+ S: VRFY Smith
+ R: 250 Fred Smith <Smith@USC-ISIF.ARPA>
+
+ Or
+
+ S: VRFY Smith
+ R: 251 User not local; will forward to <Smith@USC-ISIQ.ARPA>
+
+ Or
+
+ S: VRFY Jones
+ R: 550 String does not match anything.
+
+ Or
+
+ S: VRFY Jones
+ R: 551 User not local; please try <Jones@USC-ISIQ.ARPA>
+
+ Or
+
+ S: VRFY Gourzenkyinplatz
+ R: 553 User ambiguous.
+
+ Example 3
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 9]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ The case of expanding a mailbox list requires a multiline reply as
+ shown in example 4.
+
+ -------------------------------------------------------------
+
+ Example of Expanding a Mailing List
+
+ Either
+
+ S: EXPN Example-People
+ R: 250-Jon Postel <Postel@USC-ISIF.ARPA>
+ R: 250-Fred Fonebone <Fonebone@USC-ISIQ.ARPA>
+ R: 250-Sam Q. Smith <SQSmith@USC-ISIQ.ARPA>
+ R: 250-Quincy Smith <@USC-ISIF.ARPA:Q-Smith@ISI-VAXA.ARPA>
+ R: 250-<joe@foo-unix.ARPA>
+ R: 250 <xyz@bar-unix.ARPA>
+
+ Or
+
+ S: EXPN Executive-Washroom-List
+ R: 550 Access Denied to You.
+
+ Example 4
+
+ -------------------------------------------------------------
+
+ The character string arguments of the VRFY and EXPN commands
+ cannot be further restricted due to the variety of implementations
+ of the user name and mailbox list concepts. On some systems it
+ may be appropriate for the argument of the EXPN command to be a
+ file name for a file containing a mailing list, but again there is
+ a variety of file naming conventions in the Internet.
+
+ The VRFY and EXPN commands are not included in the minimum
+ implementation (Section 4.5.1), and are not required to work
+ across relays when they are implemented.
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 10] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 3.4. SENDING AND MAILING
+
+ The main purpose of SMTP is to deliver messages to user's
+ mailboxes. A very similar service provided by some hosts is to
+ deliver messages to user's terminals (provided the user is active
+ on the host). The delivery to the user's mailbox is called
+ "mailing", the delivery to the user's terminal is called
+ "sending". Because in many hosts the implementation of sending is
+ nearly identical to the implementation of mailing these two
+ functions are combined in SMTP. However the sending commands are
+ not included in the required minimum implementation
+ (Section 4.5.1). Users should have the ability to control the
+ writing of messages on their terminals. Most hosts permit the
+ users to accept or refuse such messages.
+
+ The following three command are defined to support the sending
+ options. These are used in the mail transaction instead of the
+ MAIL command and inform the receiver-SMTP of the special semantics
+ of this transaction:
+
+ SEND <SP> FROM:<reverse-path> <CRLF>
+
+ The SEND command requires that the mail data be delivered to
+ the user's terminal. If the user is not active (or not
+ accepting terminal messages) on the host a 450 reply may
+ returned to a RCPT command. The mail transaction is
+ successful if the message is delivered the terminal.
+
+ SOML <SP> FROM:<reverse-path> <CRLF>
+
+ The Send Or MaiL command requires that the mail data be
+ delivered to the user's terminal if the user is active (and
+ accepting terminal messages) on the host. If the user is
+ not active (or not accepting terminal messages) then the
+ mail data is entered into the user's mailbox. The mail
+ transaction is successful if the message is delivered either
+ to the terminal or the mailbox.
+
+ SAML <SP> FROM:<reverse-path> <CRLF>
+
+ The Send And MaiL command requires that the mail data be
+ delivered to the user's terminal if the user is active (and
+ accepting terminal messages) on the host. In any case the
+ mail data is entered into the user's mailbox. The mail
+ transaction is successful if the message is delivered the
+ mailbox.
+
+
+
+Postel [Page 11]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ The same reply codes that are used for the MAIL commands are used
+ for these commands.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 12] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 3.5. OPENING AND CLOSING
+
+ At the time the transmission channel is opened there is an
+ exchange to ensure that the hosts are communicating with the hosts
+ they think they are.
+
+ The following two commands are used in transmission channel
+ opening and closing:
+
+ HELO <SP> <domain> <CRLF>
+
+ QUIT <CRLF>
+
+ In the HELO command the host sending the command identifies
+ itself; the command may be interpreted as saying "Hello, I am
+ <domain>".
+
+ -------------------------------------------------------------
+
+ Example of Connection Opening
+
+ R: 220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready
+ S: HELO USC-ISIF.ARPA
+ R: 250 BBN-UNIX.ARPA
+
+ Example 5
+
+ -------------------------------------------------------------
+
+ -------------------------------------------------------------
+
+ Example of Connection Closing
+
+ S: QUIT
+ R: 221 BBN-UNIX.ARPA Service closing transmission channel
+
+ Example 6
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+Postel [Page 13]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ 3.6. RELAYING
+
+ The forward-path may be a source route of the form
+ "@ONE,@TWO:JOE@THREE", where ONE, TWO, and THREE are hosts. This
+ form is used to emphasize the distinction between an address and a
+ route. The mailbox is an absolute address, and the route is
+ information about how to get there. The two concepts should not
+ be confused.
+
+ Conceptually the elements of the forward-path are moved to the
+ reverse-path as the message is relayed from one server-SMTP to
+ another. The reverse-path is a reverse source route, (i.e., a
+ source route from the current location of the message to the
+ originator of the message). When a server-SMTP deletes its
+ identifier from the forward-path and inserts it into the
+ reverse-path, it must use the name it is known by in the
+ environment it is sending into, not the environment the mail came
+ from, in case the server-SMTP is known by different names in
+ different environments.
+
+ If when the message arrives at an SMTP the first element of the
+ forward-path is not the identifier of that SMTP the element is not
+ deleted from the forward-path and is used to determine the next
+ SMTP to send the message to. In any case, the SMTP adds its own
+ identifier to the reverse-path.
+
+ Using source routing the receiver-SMTP receives mail to be relayed
+ to another server-SMTP The receiver-SMTP may accept or reject the
+ task of relaying the mail in the same way it accepts or rejects
+ mail for a local user. The receiver-SMTP transforms the command
+ arguments by moving its own identifier from the forward-path to
+ the beginning of the reverse-path. The receiver-SMTP then becomes
+ a sender-SMTP, establishes a transmission channel to the next SMTP
+ in the forward-path, and sends it the mail.
+
+ The first host in the reverse-path should be the host sending the
+ SMTP commands, and the first host in the forward-path should be
+ the host receiving the SMTP commands.
+
+ Notice that the forward-path and reverse-path appear in the SMTP
+ commands and replies, but not necessarily in the message. That
+ is, there is no need for these paths and especially this syntax to
+ appear in the "To:" , "From:", "CC:", etc. fields of the message
+ header.
+
+ If a server-SMTP has accepted the task of relaying the mail and
+
+
+
+[Page 14] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ later finds that the forward-path is incorrect or that the mail
+ cannot be delivered for whatever reason, then it must construct an
+ "undeliverable mail" notification message and send it to the
+ originator of the undeliverable mail (as indicated by the
+ reverse-path).
+
+ This notification message must be from the server-SMTP at this
+ host. Of course, server-SMTPs should not send notification
+ messages about problems with notification messages. One way to
+ prevent loops in error reporting is to specify a null reverse-path
+ in the MAIL command of a notification message. When such a
+ message is relayed it is permissible to leave the reverse-path
+ null. A MAIL command with a null reverse-path appears as follows:
+
+ MAIL FROM:<>
+
+ An undeliverable mail notification message is shown in example 7.
+ This notification is in response to a message originated by JOE at
+ HOSTW and sent via HOSTX to HOSTY with instructions to relay it on
+ to HOSTZ. What we see in the example is the transaction between
+ HOSTY and HOSTX, which is the first step in the return of the
+ notification message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 15]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ -------------------------------------------------------------
+
+ Example Undeliverable Mail Notification Message
+
+ S: MAIL FROM:<>
+ R: 250 ok
+ S: RCPT TO:<@HOSTX.ARPA:JOE@HOSTW.ARPA>
+ R: 250 ok
+ S: DATA
+ R: 354 send the mail data, end with .
+ S: Date: 23 Oct 81 11:22:33
+ S: From: SMTP@HOSTY.ARPA
+ S: To: JOE@HOSTW.ARPA
+ S: Subject: Mail System Problem
+ S:
+ S: Sorry JOE, your message to SAM@HOSTZ.ARPA lost.
+ S: HOSTZ.ARPA said this:
+ S: "550 No Such User"
+ S: .
+ R: 250 ok
+
+ Example 7
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 16] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 3.7. DOMAINS
+
+ Domains are a recently introduced concept in the ARPA Internet
+ mail system. The use of domains changes the address space from a
+ flat global space of simple character string host names to a
+ hierarchically structured rooted tree of global addresses. The
+ host name is replaced by a domain and host designator which is a
+ sequence of domain element strings separated by periods with the
+ understanding that the domain elements are ordered from the most
+ specific to the most general.
+
+ For example, "USC-ISIF.ARPA", "Fred.Cambridge.UK", and
+ "PC7.LCS.MIT.ARPA" might be host-and-domain identifiers.
+
+ Whenever domain names are used in SMTP only the official names are
+ used, the use of nicknames or aliases is not allowed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 17]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ 3.8. CHANGING ROLES
+
+ The TURN command may be used to reverse the roles of the two
+ programs communicating over the transmission channel.
+
+ If program-A is currently the sender-SMTP and it sends the TURN
+ command and receives an ok reply (250) then program-A becomes the
+ receiver-SMTP.
+
+ If program-B is currently the receiver-SMTP and it receives the
+ TURN command and sends an ok reply (250) then program-B becomes
+ the sender-SMTP.
+
+ To refuse to change roles the receiver sends the 502 reply.
+
+ Please note that this command is optional. It would not normally
+ be used in situations where the transmission channel is TCP.
+ However, when the cost of establishing the transmission channel is
+ high, this command may be quite useful. For example, this command
+ may be useful in supporting be mail exchange using the public
+ switched telephone system as a transmission channel, especially if
+ some hosts poll other hosts for mail exchanges.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 18] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+4. THE SMTP SPECIFICATIONS
+
+ 4.1. SMTP COMMANDS
+
+ 4.1.1. COMMAND SEMANTICS
+
+ The SMTP commands define the mail transfer or the mail system
+ function requested by the user. SMTP commands are character
+ strings terminated by <CRLF>. The command codes themselves are
+ alphabetic characters terminated by <SP> if parameters follow
+ and <CRLF> otherwise. The syntax of mailboxes must conform to
+ receiver site conventions. The SMTP commands are discussed
+ below. The SMTP replies are discussed in the Section 4.2.
+
+ A mail transaction involves several data objects which are
+ communicated as arguments to different commands. The
+ reverse-path is the argument of the MAIL command, the
+ forward-path is the argument of the RCPT command, and the mail
+ data is the argument of the DATA command. These arguments or
+ data objects must be transmitted and held pending the
+ confirmation communicated by the end of mail data indication
+ which finalizes the transaction. The model for this is that
+ distinct buffers are provided to hold the types of data
+ objects, that is, there is a reverse-path buffer, a
+ forward-path buffer, and a mail data buffer. Specific commands
+ cause information to be appended to a specific buffer, or cause
+ one or more buffers to be cleared.
+
+ HELLO (HELO)
+
+ This command is used to identify the sender-SMTP to the
+ receiver-SMTP. The argument field contains the host name of
+ the sender-SMTP.
+
+ The receiver-SMTP identifies itself to the sender-SMTP in
+ the connection greeting reply, and in the response to this
+ command.
+
+ This command and an OK reply to it confirm that both the
+ sender-SMTP and the receiver-SMTP are in the initial state,
+ that is, there is no transaction in progress and all state
+ tables and buffers are cleared.
+
+
+
+
+
+
+
+Postel [Page 19]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ MAIL (MAIL)
+
+ This command is used to initiate a mail transaction in which
+ the mail data is delivered to one or more mailboxes. The
+ argument field contains a reverse-path.
+
+ The reverse-path consists of an optional list of hosts and
+ the sender mailbox. When the list of hosts is present, it
+ is a "reverse" source route and indicates that the mail was
+ relayed through each host on the list (the first host in the
+ list was the most recent relay). This list is used as a
+ source route to return non-delivery notices to the sender.
+ As each relay host adds itself to the beginning of the list,
+ it must use its name as known in the IPCE to which it is
+ relaying the mail rather than the IPCE from which the mail
+ came (if they are different). In some types of error
+ reporting messages (for example, undeliverable mail
+ notifications) the reverse-path may be null (see Example 7).
+
+ This command clears the reverse-path buffer, the
+ forward-path buffer, and the mail data buffer; and inserts
+ the reverse-path information from this command into the
+ reverse-path buffer.
+
+ RECIPIENT (RCPT)
+
+ This command is used to identify an individual recipient of
+ the mail data; multiple recipients are specified by multiple
+ use of this command.
+
+ The forward-path consists of an optional list of hosts and a
+ required destination mailbox. When the list of hosts is
+ present, it is a source route and indicates that the mail
+ must be relayed to the next host on the list. If the
+ receiver-SMTP does not implement the relay function it may
+ user the same reply it would for an unknown local user
+ (550).
+
+ When mail is relayed, the relay host must remove itself from
+ the beginning forward-path and put itself at the beginning
+ of the reverse-path. When mail reaches its ultimate
+ destination (the forward-path contains only a destination
+ mailbox), the receiver-SMTP inserts it into the destination
+ mailbox in accordance with its host mail conventions.
+
+
+
+
+
+[Page 20] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ For example, mail received at relay host A with arguments
+
+ FROM:<USERX@HOSTY.ARPA>
+ TO:<@HOSTA.ARPA,@HOSTB.ARPA:USERC@HOSTD.ARPA>
+
+ will be relayed on to host B with arguments
+
+ FROM:<@HOSTA.ARPA:USERX@HOSTY.ARPA>
+ TO:<@HOSTB.ARPA:USERC@HOSTD.ARPA>.
+
+ This command causes its forward-path argument to be appended
+ to the forward-path buffer.
+
+ DATA (DATA)
+
+ The receiver treats the lines following the command as mail
+ data from the sender. This command causes the mail data
+ from this command to be appended to the mail data buffer.
+ The mail data may contain any of the 128 ASCII character
+ codes.
+
+ The mail data is terminated by a line containing only a
+ period, that is the character sequence "<CRLF>.<CRLF>" (see
+ Section 4.5.2 on Transparency). This is the end of mail
+ data indication.
+
+ The end of mail data indication requires that the receiver
+ must now process the stored mail transaction information.
+ This processing consumes the information in the reverse-path
+ buffer, the forward-path buffer, and the mail data buffer,
+ and on the completion of this command these buffers are
+ cleared. If the processing is successful the receiver must
+ send an OK reply. If the processing fails completely the
+ receiver must send a failure reply.
+
+ When the receiver-SMTP accepts a message either for relaying
+ or for final delivery it inserts at the beginning of the
+ mail data a time stamp line. The time stamp line indicates
+ the identity of the host that sent the message, and the
+ identity of the host that received the message (and is
+ inserting this time stamp), and the date and time the
+ message was received. Relayed messages will have multiple
+ time stamp lines.
+
+ When the receiver-SMTP makes the "final delivery" of a
+ message it inserts at the beginning of the mail data a
+
+
+
+Postel [Page 21]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ return path line. The return path line preserves the
+ information in the <reverse-path> from the MAIL command.
+ Here, final delivery means the message leaves the SMTP
+ world. Normally, this would mean it has been delivered to
+ the destination user, but in some cases it may be further
+ processed and transmitted by another mail system.
+
+ It is possible for the mailbox in the return path be
+ different from the actual sender's mailbox, for example,
+ if error responses are to be delivered a special error
+ handling mailbox rather than the message senders.
+
+ The preceding two paragraphs imply that the final mail data
+ will begin with a return path line, followed by one or more
+ time stamp lines. These lines will be followed by the mail
+ data header and body [2]. See Example 8.
+
+ Special mention is needed of the response and further action
+ required when the processing following the end of mail data
+ indication is partially successful. This could arise if
+ after accepting several recipients and the mail data, the
+ receiver-SMTP finds that the mail data can be successfully
+ delivered to some of the recipients, but it cannot be to
+ others (for example, due to mailbox space allocation
+ problems). In such a situation, the response to the DATA
+ command must be an OK reply. But, the receiver-SMTP must
+ compose and send an "undeliverable mail" notification
+ message to the originator of the message. Either a single
+ notification which lists all of the recipients that failed
+ to get the message, or separate notification messages must
+ be sent for each failed recipient (see Example 7). All
+ undeliverable mail notification messages are sent using the
+ MAIL command (even if they result from processing a SEND,
+ SOML, or SAML command).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 22] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ -------------------------------------------------------------
+
+ Example of Return Path and Received Time Stamps
+
+ Return-Path: <@GHI.ARPA,@DEF.ARPA,@ABC.ARPA:JOE@ABC.ARPA>
+ Received: from GHI.ARPA by JKL.ARPA ; 27 Oct 81 15:27:39 PST
+ Received: from DEF.ARPA by GHI.ARPA ; 27 Oct 81 15:15:13 PST
+ Received: from ABC.ARPA by DEF.ARPA ; 27 Oct 81 15:01:59 PST
+ Date: 27 Oct 81 15:01:01 PST
+ From: JOE@ABC.ARPA
+ Subject: Improved Mailing System Installed
+ To: SAM@JKL.ARPA
+
+ This is to inform you that ...
+
+ Example 8
+
+ -------------------------------------------------------------
+
+ SEND (SEND)
+
+ This command is used to initiate a mail transaction in which
+ the mail data is delivered to one or more terminals. The
+ argument field contains a reverse-path. This command is
+ successful if the message is delivered to a terminal.
+
+ The reverse-path consists of an optional list of hosts and
+ the sender mailbox. When the list of hosts is present, it
+ is a "reverse" source route and indicates that the mail was
+ relayed through each host on the list (the first host in the
+ list was the most recent relay). This list is used as a
+ source route to return non-delivery notices to the sender.
+ As each relay host adds itself to the beginning of the list,
+ it must use its name as known in the IPCE to which it is
+ relaying the mail rather than the IPCE from which the mail
+ came (if they are different).
+
+ This command clears the reverse-path buffer, the
+ forward-path buffer, and the mail data buffer; and inserts
+ the reverse-path information from this command into the
+ reverse-path buffer.
+
+ SEND OR MAIL (SOML)
+
+ This command is used to initiate a mail transaction in which
+ the mail data is delivered to one or more terminals or
+
+
+
+Postel [Page 23]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ mailboxes. For each recipient the mail data is delivered to
+ the recipient's terminal if the recipient is active on the
+ host (and accepting terminal messages), otherwise to the
+ recipient's mailbox. The argument field contains a
+ reverse-path. This command is successful if the message is
+ delivered to a terminal or the mailbox.
+
+ The reverse-path consists of an optional list of hosts and
+ the sender mailbox. When the list of hosts is present, it
+ is a "reverse" source route and indicates that the mail was
+ relayed through each host on the list (the first host in the
+ list was the most recent relay). This list is used as a
+ source route to return non-delivery notices to the sender.
+ As each relay host adds itself to the beginning of the list,
+ it must use its name as known in the IPCE to which it is
+ relaying the mail rather than the IPCE from which the mail
+ came (if they are different).
+
+ This command clears the reverse-path buffer, the
+ forward-path buffer, and the mail data buffer; and inserts
+ the reverse-path information from this command into the
+ reverse-path buffer.
+
+ SEND AND MAIL (SAML)
+
+ This command is used to initiate a mail transaction in which
+ the mail data is delivered to one or more terminals and
+ mailboxes. For each recipient the mail data is delivered to
+ the recipient's terminal if the recipient is active on the
+ host (and accepting terminal messages), and for all
+ recipients to the recipient's mailbox. The argument field
+ contains a reverse-path. This command is successful if the
+ message is delivered to the mailbox.
+
+ The reverse-path consists of an optional list of hosts and
+ the sender mailbox. When the list of hosts is present, it
+ is a "reverse" source route and indicates that the mail was
+ relayed through each host on the list (the first host in the
+ list was the most recent relay). This list is used as a
+ source route to return non-delivery notices to the sender.
+ As each relay host adds itself to the beginning of the list,
+ it must use its name as known in the IPCE to which it is
+ relaying the mail rather than the IPCE from which the mail
+ came (if they are different).
+
+ This command clears the reverse-path buffer, the
+
+
+
+[Page 24] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ forward-path buffer, and the mail data buffer; and inserts
+ the reverse-path information from this command into the
+ reverse-path buffer.
+
+ RESET (RSET)
+
+ This command specifies that the current mail transaction is
+ to be aborted. Any stored sender, recipients, and mail data
+ must be discarded, and all buffers and state tables cleared.
+ The receiver must send an OK reply.
+
+ VERIFY (VRFY)
+
+ This command asks the receiver to confirm that the argument
+ identifies a user. If it is a user name, the full name of
+ the user (if known) and the fully specified mailbox are
+ returned.
+
+ This command has no effect on any of the reverse-path
+ buffer, the forward-path buffer, or the mail data buffer.
+
+ EXPAND (EXPN)
+
+ This command asks the receiver to confirm that the argument
+ identifies a mailing list, and if so, to return the
+ membership of that list. The full name of the users (if
+ known) and the fully specified mailboxes are returned in a
+ multiline reply.
+
+ This command has no effect on any of the reverse-path
+ buffer, the forward-path buffer, or the mail data buffer.
+
+ HELP (HELP)
+
+ This command causes the receiver to send helpful information
+ to the sender of the HELP command. The command may take an
+ argument (e.g., any command name) and return more specific
+ information as a response.
+
+ This command has no effect on any of the reverse-path
+ buffer, the forward-path buffer, or the mail data buffer.
+
+
+
+
+
+
+
+
+Postel [Page 25]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ NOOP (NOOP)
+
+ This command does not affect any parameters or previously
+ entered commands. It specifies no action other than that
+ the receiver send an OK reply.
+
+ This command has no effect on any of the reverse-path
+ buffer, the forward-path buffer, or the mail data buffer.
+
+ QUIT (QUIT)
+
+ This command specifies that the receiver must send an OK
+ reply, and then close the transmission channel.
+
+ The receiver should not close the transmission channel until
+ it receives and replies to a QUIT command (even if there was
+ an error). The sender should not close the transmission
+ channel until it send a QUIT command and receives the reply
+ (even if there was an error response to a previous command).
+ If the connection is closed prematurely the receiver should
+ act as if a RSET command had been received (canceling any
+ pending transaction, but not undoing any previously
+ completed transaction), the sender should act as if the
+ command or transaction in progress had received a temporary
+ error (4xx).
+
+ TURN (TURN)
+
+ This command specifies that the receiver must either (1)
+ send an OK reply and then take on the role of the
+ sender-SMTP, or (2) send a refusal reply and retain the role
+ of the receiver-SMTP.
+
+ If program-A is currently the sender-SMTP and it sends the
+ TURN command and receives an OK reply (250) then program-A
+ becomes the receiver-SMTP. Program-A is then in the initial
+ state as if the transmission channel just opened, and it
+ then sends the 220 service ready greeting.
+
+ If program-B is currently the receiver-SMTP and it receives
+ the TURN command and sends an OK reply (250) then program-B
+ becomes the sender-SMTP. Program-B is then in the initial
+ state as if the transmission channel just opened, and it
+ then expects to receive the 220 service ready greeting.
+
+ To refuse to change roles the receiver sends the 502 reply.
+
+
+
+[Page 26] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ There are restrictions on the order in which these command may
+ be used.
+
+ The first command in a session must be the HELO command.
+ The HELO command may be used later in a session as well. If
+ the HELO command argument is not acceptable a 501 failure
+ reply must be returned and the receiver-SMTP must stay in
+ the same state.
+
+ The NOOP, HELP, EXPN, and VRFY commands can be used at any
+ time during a session.
+
+ The MAIL, SEND, SOML, or SAML commands begin a mail
+ transaction. Once started a mail transaction consists of
+ one of the transaction beginning commands, one or more RCPT
+ commands, and a DATA command, in that order. A mail
+ transaction may be aborted by the RSET command. There may
+ be zero or more transactions in a session.
+
+ If the transaction beginning command argument is not
+ acceptable a 501 failure reply must be returned and the
+ receiver-SMTP must stay in the same state. If the commands
+ in a transaction are out of order a 503 failure reply must
+ be returned and the receiver-SMTP must stay in the same
+ state.
+
+ The last command in a session must be the QUIT command. The
+ QUIT command can not be used at any other time in a session.
+
+ 4.1.2. COMMAND SYNTAX
+
+ The commands consist of a command code followed by an argument
+ field. Command codes are four alphabetic characters. Upper
+ and lower case alphabetic characters are to be treated
+ identically. Thus, any of the following may represent the mail
+ command:
+
+ MAIL Mail mail MaIl mAIl
+
+ This also applies to any symbols representing parameter values,
+ such as "TO" or "to" for the forward-path. Command codes and
+ the argument fields are separated by one or more spaces.
+ However, within the reverse-path and forward-path arguments
+ case is important. In particular, in some hosts the user
+ "smith" is different from the user "Smith".
+
+
+
+
+Postel [Page 27]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ The argument field consists of a variable length character
+ string ending with the character sequence <CRLF>. The receiver
+ is to take no action until this sequence is received.
+
+ Square brackets denote an optional argument field. If the
+ option is not taken, the appropriate default is implied.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 28] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ The following are the SMTP commands:
+
+ HELO <SP> <domain> <CRLF>
+
+ MAIL <SP> FROM:<reverse-path> <CRLF>
+
+ RCPT <SP> TO:<forward-path> <CRLF>
+
+ DATA <CRLF>
+
+ RSET <CRLF>
+
+ SEND <SP> FROM:<reverse-path> <CRLF>
+
+ SOML <SP> FROM:<reverse-path> <CRLF>
+
+ SAML <SP> FROM:<reverse-path> <CRLF>
+
+ VRFY <SP> <string> <CRLF>
+
+ EXPN <SP> <string> <CRLF>
+
+ HELP [<SP> <string>] <CRLF>
+
+ NOOP <CRLF>
+
+ QUIT <CRLF>
+
+ TURN <CRLF>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 29]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ The syntax of the above argument fields (using BNF notation
+ where applicable) is given below. The "..." notation indicates
+ that a field may be repeated one or more times.
+
+ <reverse-path> ::= <path>
+
+ <forward-path> ::= <path>
+
+ <path> ::= "<" [ <a-d-l> ":" ] <mailbox> ">"
+
+ <a-d-l> ::= <at-domain> | <at-domain> "," <a-d-l>
+
+ <at-domain> ::= "@" <domain>
+
+ <domain> ::= <element> | <element> "." <domain>
+
+ <element> ::= <name> | "#" <number> | "[" <dotnum> "]"
+
+ <mailbox> ::= <local-part> "@" <domain>
+
+ <local-part> ::= <dot-string> | <quoted-string>
+
+ <name> ::= <a> <ldh-str> <let-dig>
+
+ <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+ <let-dig> ::= <a> | <d>
+
+ <let-dig-hyp> ::= <a> | <d> | "-"
+
+ <dot-string> ::= <string> | <string> "." <dot-string>
+
+ <string> ::= <char> | <char> <string>
+
+ <quoted-string> ::= """ <qtext> """
+
+ <qtext> ::= "\" <x> | "\" <x> <qtext> | <q> | <q> <qtext>
+
+ <char> ::= <c> | "\" <x>
+
+ <dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>
+
+ <number> ::= <d> | <d> <number>
+
+ <CRLF> ::= <CR> <LF>
+
+
+
+
+[Page 30] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ <CR> ::= the carriage return character (ASCII code 13)
+
+ <LF> ::= the line feed character (ASCII code 10)
+
+ <SP> ::= the space character (ASCII code 32)
+
+ <snum> ::= one, two, or three digits representing a decimal
+ integer value in the range 0 through 255
+
+ <a> ::= any one of the 52 alphabetic characters A through Z
+ in upper case and a through z in lower case
+
+ <c> ::= any one of the 128 ASCII characters, but not any
+ <special> or <SP>
+
+ <d> ::= any one of the ten digits 0 through 9
+
+ <q> ::= any one of the 128 ASCII characters except <CR>,
+ <LF>, quote ("), or backslash (\)
+
+ <x> ::= any one of the 128 ASCII characters (no exceptions)
+
+ <special> ::= "<" | ">" | "(" | ")" | "[" | "]" | "\" | "."
+ | "," | ";" | ":" | "@" """ | the control
+ characters (ASCII codes 0 through 31 inclusive and
+ 127)
+
+ Note that the backslash, "\", is a quote character, which is
+ used to indicate that the next character is to be used
+ literally (instead of its normal interpretation). For example,
+ "Joe\,Smith" could be used to indicate a single nine character
+ user field with comma being the fourth character of the field.
+
+ Hosts are generally known by names which are translated to
+ addresses in each host. Note that the name elements of domains
+ are the official names -- no use of nicknames or aliases is
+ allowed.
+
+ Sometimes a host is not known to the translation function and
+ communication is blocked. To bypass this barrier two numeric
+ forms are also allowed for host "names". One form is a decimal
+ integer prefixed by a pound sign, "#", which indicates the
+ number is the address of the host. Another form is four small
+ decimal integers separated by dots and enclosed by brackets,
+ e.g., "[123.255.37.2]", which indicates a 32-bit ARPA Internet
+ Address in four 8-bit fields.
+
+
+
+Postel [Page 31]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ The time stamp line and the return path line are formally
+ defined as follows:
+
+ <return-path-line> ::= "Return-Path:" <SP><reverse-path><CRLF>
+
+ <time-stamp-line> ::= "Received:" <SP> <stamp> <CRLF>
+
+ <stamp> ::= <from-domain> <by-domain> <opt-info> ";"
+ <daytime>
+
+ <from-domain> ::= "FROM" <SP> <domain> <SP>
+
+ <by-domain> ::= "BY" <SP> <domain> <SP>
+
+ <opt-info> ::= [<via>] [<with>] [<id>] [<for>]
+
+ <via> ::= "VIA" <SP> <link> <SP>
+
+ <with> ::= "WITH" <SP> <protocol> <SP>
+
+ <id> ::= "ID" <SP> <string> <SP>
+
+ <for> ::= "FOR" <SP> <path> <SP>
+
+ <link> ::= The standard names for links are registered with
+ the Network Information Center.
+
+ <protocol> ::= The standard names for protocols are
+ registered with the Network Information Center.
+
+ <daytime> ::= <SP> <date> <SP> <time>
+
+ <date> ::= <dd> <SP> <mon> <SP> <yy>
+
+ <time> ::= <hh> ":" <mm> ":" <ss> <SP> <zone>
+
+ <dd> ::= the one or two decimal integer day of the month in
+ the range 1 to 31.
+
+ <mon> ::= "JAN" | "FEB" | "MAR" | "APR" | "MAY" | "JUN" |
+ "JUL" | "AUG" | "SEP" | "OCT" | "NOV" | "DEC"
+
+ <yy> ::= the two decimal integer year of the century in the
+ range 00 to 99.
+
+
+
+
+
+[Page 32] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ <hh> ::= the two decimal integer hour of the day in the
+ range 00 to 24.
+
+ <mm> ::= the two decimal integer minute of the hour in the
+ range 00 to 59.
+
+ <ss> ::= the two decimal integer second of the minute in the
+ range 00 to 59.
+
+ <zone> ::= "UT" for Universal Time (the default) or other
+ time zone designator (as in [2]).
+
+
+
+ -------------------------------------------------------------
+
+ Return Path Example
+
+ Return-Path: <@CHARLIE.ARPA,@BAKER.ARPA:JOE@ABLE.ARPA>
+
+ Example 9
+
+ -------------------------------------------------------------
+
+ -------------------------------------------------------------
+
+ Time Stamp Line Example
+
+ Received: FROM ABC.ARPA BY XYZ.ARPA ; 22 OCT 81 09:23:59 PDT
+
+ Received: from ABC.ARPA by XYZ.ARPA via TELENET with X25
+ id M12345 for Smith@PDQ.ARPA ; 22 OCT 81 09:23:59 PDT
+
+ Example 10
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 33]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ 4.2. SMTP REPLIES
+
+ Replies to SMTP commands are devised to ensure the synchronization
+ of requests and actions in the process of mail transfer, and to
+ guarantee that the sender-SMTP always knows the state of the
+ receiver-SMTP. Every command must generate exactly one reply.
+
+ The details of the command-reply sequence are made explicit in
+ Section 5.3 on Sequencing and Section 5.4 State Diagrams.
+
+ An SMTP reply consists of a three digit number (transmitted as
+ three alphanumeric characters) followed by some text. The number
+ is intended for use by automata to determine what state to enter
+ next; the text is meant for the human user. It is intended that
+ the three digits contain enough encoded information that the
+ sender-SMTP need not examine the text and may either discard it or
+ pass it on to the user, as appropriate. In particular, the text
+ may be receiver-dependent and context dependent, so there are
+ likely to be varying texts for each reply code. A discussion of
+ the theory of reply codes is given in Appendix E. Formally, a
+ reply is defined to be the sequence: a three-digit code, <SP>,
+ one line of text, and <CRLF>, or a multiline reply (as defined in
+ Appendix E). Only the EXPN and HELP commands are expected to
+ result in multiline replies in normal circumstances, however
+ multiline replies are allowed for any command.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 34] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 4.2.1. REPLY CODES BY FUNCTION GROUPS
+
+ 500 Syntax error, command unrecognized
+ [This may include errors such as command line too long]
+ 501 Syntax error in parameters or arguments
+ 502 Command not implemented
+ 503 Bad sequence of commands
+ 504 Command parameter not implemented
+
+ 211 System status, or system help reply
+ 214 Help message
+ [Information on how to use the receiver or the meaning of a
+ particular non-standard command; this reply is useful only
+ to the human user]
+
+ 220 <domain> Service ready
+ 221 <domain> Service closing transmission channel
+ 421 <domain> Service not available,
+ closing transmission channel
+ [This may be a reply to any command if the service knows it
+ must shut down]
+
+ 250 Requested mail action okay, completed
+ 251 User not local; will forward to <forward-path>
+ 450 Requested mail action not taken: mailbox unavailable
+ [E.g., mailbox busy]
+ 550 Requested action not taken: mailbox unavailable
+ [E.g., mailbox not found, no access]
+ 451 Requested action aborted: error in processing
+ 551 User not local; please try <forward-path>
+ 452 Requested action not taken: insufficient system storage
+ 552 Requested mail action aborted: exceeded storage allocation
+ 553 Requested action not taken: mailbox name not allowed
+ [E.g., mailbox syntax incorrect]
+ 354 Start mail input; end with <CRLF>.<CRLF>
+ 554 Transaction failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 35]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ 4.2.2. NUMERIC ORDER LIST OF REPLY CODES
+
+ 211 System status, or system help reply
+ 214 Help message
+ [Information on how to use the receiver or the meaning of a
+ particular non-standard command; this reply is useful only
+ to the human user]
+ 220 <domain> Service ready
+ 221 <domain> Service closing transmission channel
+ 250 Requested mail action okay, completed
+ 251 User not local; will forward to <forward-path>
+
+ 354 Start mail input; end with <CRLF>.<CRLF>
+
+ 421 <domain> Service not available,
+ closing transmission channel
+ [This may be a reply to any command if the service knows it
+ must shut down]
+ 450 Requested mail action not taken: mailbox unavailable
+ [E.g., mailbox busy]
+ 451 Requested action aborted: local error in processing
+ 452 Requested action not taken: insufficient system storage
+
+ 500 Syntax error, command unrecognized
+ [This may include errors such as command line too long]
+ 501 Syntax error in parameters or arguments
+ 502 Command not implemented
+ 503 Bad sequence of commands
+ 504 Command parameter not implemented
+ 550 Requested action not taken: mailbox unavailable
+ [E.g., mailbox not found, no access]
+ 551 User not local; please try <forward-path>
+ 552 Requested mail action aborted: exceeded storage allocation
+ 553 Requested action not taken: mailbox name not allowed
+ [E.g., mailbox syntax incorrect]
+ 554 Transaction failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 36] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 4.3. SEQUENCING OF COMMANDS AND REPLIES
+
+ The communication between the sender and receiver is intended to
+ be an alternating dialogue, controlled by the sender. As such,
+ the sender issues a command and the receiver responds with a
+ reply. The sender must wait for this response before sending
+ further commands.
+
+ One important reply is the connection greeting. Normally, a
+ receiver will send a 220 "Service ready" reply when the connection
+ is completed. The sender should wait for this greeting message
+ before sending any commands.
+
+ Note: all the greeting type replies have the official name of
+ the server host as the first word following the reply code.
+
+ For example,
+
+ 220 <SP> USC-ISIF.ARPA <SP> Service ready <CRLF>
+
+ The table below lists alternative success and failure replies for
+ each command. These must be strictly adhered to; a receiver may
+ substitute text in the replies, but the meaning and action implied
+ by the code numbers and by the specific command reply sequence
+ cannot be altered.
+
+ COMMAND-REPLY SEQUENCES
+
+ Each command is listed with its possible replies. The prefixes
+ used before the possible replies are "P" for preliminary (not
+ used in SMTP), "I" for intermediate, "S" for success, "F" for
+ failure, and "E" for error. The 421 reply (service not
+ available, closing transmission channel) may be given to any
+ command if the SMTP-receiver knows it must shut down. This
+ listing forms the basis for the State Diagrams in Section 4.4.
+
+ CONNECTION ESTABLISHMENT
+ S: 220
+ F: 421
+ HELO
+ S: 250
+ E: 500, 501, 504, 421
+ MAIL
+ S: 250
+ F: 552, 451, 452
+ E: 500, 501, 421
+
+
+
+Postel [Page 37]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ RCPT
+ S: 250, 251
+ F: 550, 551, 552, 553, 450, 451, 452
+ E: 500, 501, 503, 421
+ DATA
+ I: 354 -> data -> S: 250
+ F: 552, 554, 451, 452
+ F: 451, 554
+ E: 500, 501, 503, 421
+ RSET
+ S: 250
+ E: 500, 501, 504, 421
+ SEND
+ S: 250
+ F: 552, 451, 452
+ E: 500, 501, 502, 421
+ SOML
+ S: 250
+ F: 552, 451, 452
+ E: 500, 501, 502, 421
+ SAML
+ S: 250
+ F: 552, 451, 452
+ E: 500, 501, 502, 421
+ VRFY
+ S: 250, 251
+ F: 550, 551, 553
+ E: 500, 501, 502, 504, 421
+ EXPN
+ S: 250
+ F: 550
+ E: 500, 501, 502, 504, 421
+ HELP
+ S: 211, 214
+ E: 500, 501, 502, 504, 421
+ NOOP
+ S: 250
+ E: 500, 421
+ QUIT
+ S: 221
+ E: 500
+ TURN
+ S: 250
+ F: 502
+ E: 500, 503
+
+
+
+
+[Page 38] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 4.4. STATE DIAGRAMS
+
+ Following are state diagrams for a simple-minded SMTP
+ implementation. Only the first digit of the reply codes is used.
+ There is one state diagram for each group of SMTP commands. The
+ command groupings were determined by constructing a model for each
+ command and then collecting together the commands with
+ structurally identical models.
+
+ For each command there are three possible outcomes: "success"
+ (S), "failure" (F), and "error" (E). In the state diagrams below
+ we use the symbol B for "begin", and the symbol W for "wait for
+ reply".
+
+ First, the diagram that represents most of the SMTP commands:
+
+
+ 1,3 +---+
+ ----------->| E |
+ | +---+
+ |
+ +---+ cmd +---+ 2 +---+
+ | B |---------->| W |---------->| S |
+ +---+ +---+ +---+
+ |
+ | 4,5 +---+
+ ----------->| F |
+ +---+
+
+
+ This diagram models the commands:
+
+ HELO, MAIL, RCPT, RSET, SEND, SOML, SAML, VRFY, EXPN, HELP,
+ NOOP, QUIT, TURN.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 39]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ A more complex diagram models the DATA command:
+
+
+ +---+ DATA +---+ 1,2 +---+
+ | B |---------->| W |-------------------->| E |
+ +---+ +---+ ------------>+---+
+ 3| |4,5 |
+ | | |
+ -------------- ----- |
+ | | | +---+
+ | ---------- -------->| S |
+ | | | | +---+
+ | | ------------
+ | | | |
+ V 1,3| |2 |
+ +---+ data +---+ --------------->+---+
+ | |---------->| W | | F |
+ +---+ +---+-------------------->+---+
+ 4,5
+
+
+ Note that the "data" here is a series of lines sent from the
+ sender to the receiver with no response expected until the last
+ line is sent.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 40] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ 4.5. DETAILS
+
+ 4.5.1. MINIMUM IMPLEMENTATION
+
+ In order to make SMTP workable, the following minimum
+ implementation is required for all receivers:
+
+ COMMANDS -- HELO
+ MAIL
+ RCPT
+ DATA
+ RSET
+ NOOP
+ QUIT
+
+ 4.5.2. TRANSPARENCY
+
+ Without some provision for data transparency the character
+ sequence "<CRLF>.<CRLF>" ends the mail text and cannot be sent
+ by the user. In general, users are not aware of such
+ "forbidden" sequences. To allow all user composed text to be
+ transmitted transparently the following procedures are used.
+
+ 1. Before sending a line of mail text the sender-SMTP checks
+ the first character of the line. If it is a period, one
+ additional period is inserted at the beginning of the line.
+
+ 2. When a line of mail text is received by the receiver-SMTP
+ it checks the line. If the line is composed of a single
+ period it is the end of mail. If the first character is a
+ period and there are other characters on the line, the first
+ character is deleted.
+
+ The mail data may contain any of the 128 ASCII characters. All
+ characters are to be delivered to the recipient's mailbox
+ including format effectors and other control characters. If
+ the transmission channel provides an 8-bit byte (octets) data
+ stream, the 7-bit ASCII codes are transmitted right justified
+ in the octets with the high order bits cleared to zero.
+
+ In some systems it may be necessary to transform the data as
+ it is received and stored. This may be necessary for hosts
+ that use a different character set than ASCII as their local
+ character set, or that store data in records rather than
+
+
+
+
+
+Postel [Page 41]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ strings. If such transforms are necessary, they must be
+ reversible -- especially if such transforms are applied to
+ mail being relayed.
+
+ 4.5.3. SIZES
+
+ There are several objects that have required minimum maximum
+ sizes. That is, every implementation must be able to receive
+ objects of at least these sizes, but must not send objects
+ larger than these sizes.
+
+
+ ****************************************************
+ * *
+ * TO THE MAXIMUM EXTENT POSSIBLE, IMPLEMENTATION *
+ * TECHNIQUES WHICH IMPOSE NO LIMITS ON THE LENGTH *
+ * OF THESE OBJECTS SHOULD BE USED. *
+ * *
+ ****************************************************
+
+ user
+
+ The maximum total length of a user name is 64 characters.
+
+ domain
+
+ The maximum total length of a domain name or number is 64
+ characters.
+
+ path
+
+ The maximum total length of a reverse-path or
+ forward-path is 256 characters (including the punctuation
+ and element separators).
+
+ command line
+
+ The maximum total length of a command line including the
+ command word and the <CRLF> is 512 characters.
+
+ reply line
+
+ The maximum total length of a reply line including the
+ reply code and the <CRLF> is 512 characters.
+
+
+
+
+
+[Page 42] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ text line
+
+ The maximum total length of a text line including the
+ <CRLF> is 1000 characters (but not counting the leading
+ dot duplicated for transparency).
+
+ recipients buffer
+
+ The maximum total number of recipients that must be
+ buffered is 100 recipients.
+
+
+ ****************************************************
+ * *
+ * TO THE MAXIMUM EXTENT POSSIBLE, IMPLEMENTATION *
+ * TECHNIQUES WHICH IMPOSE NO LIMITS ON THE LENGTH *
+ * OF THESE OBJECTS SHOULD BE USED. *
+ * *
+ ****************************************************
+
+ Errors due to exceeding these limits may be reported by using
+ the reply codes, for example:
+
+ 500 Line too long.
+
+ 501 Path too long
+
+ 552 Too many recipients.
+
+ 552 Too much mail data.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 43]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+APPENDIX A
+
+ TCP Transport service
+
+ The Transmission Control Protocol [3] is used in the ARPA
+ Internet, and in any network following the US DoD standards for
+ internetwork protocols.
+
+ Connection Establishment
+
+ The SMTP transmission channel is a TCP connection established
+ between the sender process port U and the receiver process port
+ L. This single full duplex connection is used as the
+ transmission channel. This protocol is assigned the service
+ port 25 (31 octal), that is L=25.
+
+ Data Transfer
+
+ The TCP connection supports the transmission of 8-bit bytes.
+ The SMTP data is 7-bit ASCII characters. Each character is
+ transmitted as an 8-bit byte with the high-order bit cleared to
+ zero.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 44] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+APPENDIX B
+
+ NCP Transport service
+
+ The ARPANET Host-to-Host Protocol [4] (implemented by the Network
+ Control Program) may be used in the ARPANET.
+
+ Connection Establishment
+
+ The SMTP transmission channel is established via NCP between
+ the sender process socket U and receiver process socket L. The
+ Initial Connection Protocol [5] is followed resulting in a pair
+ of simplex connections. This pair of connections is used as
+ the transmission channel. This protocol is assigned the
+ contact socket 25 (31 octal), that is L=25.
+
+ Data Transfer
+
+ The NCP data connections are established in 8-bit byte mode.
+ The SMTP data is 7-bit ASCII characters. Each character is
+ transmitted as an 8-bit byte with the high-order bit cleared to
+ zero.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 45]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+APPENDIX C
+
+ NITS
+
+ The Network Independent Transport Service [6] may be used.
+
+ Connection Establishment
+
+ The SMTP transmission channel is established via NITS between
+ the sender process and receiver process. The sender process
+ executes the CONNECT primitive, and the waiting receiver
+ process executes the ACCEPT primitive.
+
+ Data Transfer
+
+ The NITS connection supports the transmission of 8-bit bytes.
+ The SMTP data is 7-bit ASCII characters. Each character is
+ transmitted as an 8-bit byte with the high-order bit cleared to
+ zero.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 46] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+APPENDIX D
+
+ X.25 Transport service
+
+ It may be possible to use the X.25 service [7] as provided by the
+ Public Data Networks directly, however, it is suggested that a
+ reliable end-to-end protocol such as TCP be used on top of X.25
+ connections.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 47]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+APPENDIX E
+
+ Theory of Reply Codes
+
+ The three digits of the reply each have a special significance.
+ The first digit denotes whether the response is good, bad or
+ incomplete. An unsophisticated sender-SMTP will be able to
+ determine its next action (proceed as planned, redo, retrench,
+ etc.) by simply examining this first digit. A sender-SMTP that
+ wants to know approximately what kind of error occurred (e.g.,
+ mail system error, command syntax error) may examine the second
+ digit, reserving the third digit for the finest gradation of
+ information.
+
+ There are five values for the first digit of the reply code:
+
+ 1yz Positive Preliminary reply
+
+ The command has been accepted, but the requested action
+ is being held in abeyance, pending confirmation of the
+ information in this reply. The sender-SMTP should send
+ another command specifying whether to continue or abort
+ the action.
+
+ [Note: SMTP does not have any commands that allow this
+ type of reply, and so does not have the continue or
+ abort commands.]
+
+ 2yz Positive Completion reply
+
+ The requested action has been successfully completed. A
+ new request may be initiated.
+
+ 3yz Positive Intermediate reply
+
+ The command has been accepted, but the requested action
+ is being held in abeyance, pending receipt of further
+ information. The sender-SMTP should send another command
+ specifying this information. This reply is used in
+ command sequence groups.
+
+ 4yz Transient Negative Completion reply
+
+ The command was not accepted and the requested action did
+ not occur. However, the error condition is temporary and
+ the action may be requested again. The sender should
+
+
+
+[Page 48] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ return to the beginning of the command sequence (if any).
+ It is difficult to assign a meaning to "transient" when
+ two different sites (receiver- and sender- SMTPs) must
+ agree on the interpretation. Each reply in this category
+ might have a different time value, but the sender-SMTP is
+ encouraged to try again. A rule of thumb to determine if
+ a reply fits into the 4yz or the 5yz category (see below)
+ is that replies are 4yz if they can be repeated without
+ any change in command form or in properties of the sender
+ or receiver. (E.g., the command is repeated identically
+ and the receiver does not put up a new implementation.)
+
+ 5yz Permanent Negative Completion reply
+
+ The command was not accepted and the requested action did
+ not occur. The sender-SMTP is discouraged from repeating
+ the exact request (in the same sequence). Even some
+ "permanent" error conditions can be corrected, so the
+ human user may want to direct the sender-SMTP to
+ reinitiate the command sequence by direct action at some
+ point in the future (e.g., after the spelling has been
+ changed, or the user has altered the account status).
+
+ The second digit encodes responses in specific categories:
+
+ x0z Syntax -- These replies refer to syntax errors,
+ syntactically correct commands that don't fit any
+ functional category, and unimplemented or superfluous
+ commands.
+
+ x1z Information -- These are replies to requests for
+ information, such as status or help.
+
+ x2z Connections -- These are replies referring to the
+ transmission channel.
+
+ x3z Unspecified as yet.
+
+ x4z Unspecified as yet.
+
+ x5z Mail system -- These replies indicate the status of
+ the receiver mail system vis-a-vis the requested
+ transfer or other mail system action.
+
+ The third digit gives a finer gradation of meaning in each
+ category specified by the second digit. The list of replies
+
+
+
+Postel [Page 49]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ illustrates this. Each reply text is recommended rather than
+ mandatory, and may even change according to the command with
+ which it is associated. On the other hand, the reply codes
+ must strictly follow the specifications in this section.
+ Receiver implementations should not invent new codes for
+ slightly different situations from the ones described here, but
+ rather adapt codes already defined.
+
+ For example, a command such as NOOP whose successful execution
+ does not offer the sender-SMTP any new information will return
+ a 250 reply. The response is 502 when the command requests an
+ unimplemented non-site-specific action. A refinement of that
+ is the 504 reply for a command that is implemented, but that
+ requests an unimplemented parameter.
+
+ The reply text may be longer than a single line; in these cases
+ the complete text must be marked so the sender-SMTP knows when it
+ can stop reading the reply. This requires a special format to
+ indicate a multiple line reply.
+
+ The format for multiline replies requires that every line,
+ except the last, begin with the reply code, followed
+ immediately by a hyphen, "-" (also known as minus), followed by
+ text. The last line will begin with the reply code, followed
+ immediately by <SP>, optionally some text, and <CRLF>.
+
+ For example:
+ 123-First line
+ 123-Second line
+ 123-234 text beginning with numbers
+ 123 The last line
+
+ In many cases the sender-SMTP then simply needs to search for
+ the reply code followed by <SP> at the beginning of a line, and
+ ignore all preceding lines. In a few cases, there is important
+ data for the sender in the reply "text". The sender will know
+ these cases from the current context.
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 50] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+APPENDIX F
+
+ Scenarios
+
+ This section presents complete scenarios of several types of SMTP
+ sessions.
+
+ A Typical SMTP Transaction Scenario
+
+ This SMTP example shows mail sent by Smith at host USC-ISIF, to
+ Jones, Green, and Brown at host BBN-UNIX. Here we assume that
+ host USC-ISIF contacts host BBN-UNIX directly. The mail is
+ accepted for Jones and Brown. Green does not have a mailbox at
+ host BBN-UNIX.
+
+ -------------------------------------------------------------
+
+ R: 220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready
+ S: HELO USC-ISIF.ARPA
+ R: 250 BBN-UNIX.ARPA
+
+ S: MAIL FROM:<Smith@USC-ISIF.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Jones@BBN-UNIX.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Green@BBN-UNIX.ARPA>
+ R: 550 No such user here
+
+ S: RCPT TO:<Brown@BBN-UNIX.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 BBN-UNIX.ARPA Service closing transmission channel
+
+ Scenario 1
+
+ -------------------------------------------------------------
+
+
+
+Postel [Page 51]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ Aborted SMTP Transaction Scenario
+
+ -------------------------------------------------------------
+
+ R: 220 MIT-Multics.ARPA Simple Mail Transfer Service Ready
+ S: HELO ISI-VAXA.ARPA
+ R: 250 MIT-Multics.ARPA
+
+ S: MAIL FROM:<Smith@ISI-VAXA.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Jones@MIT-Multics.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Green@MIT-Multics.ARPA>
+ R: 550 No such user here
+
+ S: RSET
+ R: 250 OK
+
+ S: QUIT
+ R: 221 MIT-Multics.ARPA Service closing transmission channel
+
+ Scenario 2
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 52] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Relayed Mail Scenario
+
+ -------------------------------------------------------------
+
+ Step 1 -- Source Host to Relay Host
+
+ R: 220 USC-ISIE.ARPA Simple Mail Transfer Service Ready
+ S: HELO MIT-AI.ARPA
+ R: 250 USC-ISIE.ARPA
+
+ S: MAIL FROM:<JQP@MIT-AI.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<@USC-ISIE.ARPA:Jones@BBN-VAX.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Date: 2 Nov 81 22:33:44
+ S: From: John Q. Public <JQP@MIT-AI.ARPA>
+ S: Subject: The Next Meeting of the Board
+ S: To: Jones@BBN-Vax.ARPA
+ S:
+ S: Bill:
+ S: The next meeting of the board of directors will be
+ S: on Tuesday.
+ S: John.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISIE.ARPA Service closing transmission channel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 53]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ Step 2 -- Relay Host to Destination Host
+
+ R: 220 BBN-VAX.ARPA Simple Mail Transfer Service Ready
+ S: HELO USC-ISIE.ARPA
+ R: 250 BBN-VAX.ARPA
+
+ S: MAIL FROM:<@USC-ISIE.ARPA:JQP@MIT-AI.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Jones@BBN-VAX.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Received: from MIT-AI.ARPA by USC-ISIE.ARPA ;
+ 2 Nov 81 22:40:10 UT
+ S: Date: 2 Nov 81 22:33:44
+ S: From: John Q. Public <JQP@MIT-AI.ARPA>
+ S: Subject: The Next Meeting of the Board
+ S: To: Jones@BBN-Vax.ARPA
+ S:
+ S: Bill:
+ S: The next meeting of the board of directors will be
+ S: on Tuesday.
+ S: John.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISIE.ARPA Service closing transmission channel
+
+ Scenario 3
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 54] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Verifying and Sending Scenario
+
+ -------------------------------------------------------------
+
+ R: 220 SU-SCORE.ARPA Simple Mail Transfer Service Ready
+ S: HELO MIT-MC.ARPA
+ R: 250 SU-SCORE.ARPA
+
+ S: VRFY Crispin
+ R: 250 Mark Crispin <Admin.MRC@SU-SCORE.ARPA>
+
+ S: SEND FROM:<EAK@MIT-MC.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Admin.MRC@SU-SCORE.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 SU-SCORE.ARPA Service closing transmission channel
+
+ Scenario 4
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 55]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ Sending and Mailing Scenarios
+
+ First the user's name is verified, then an attempt is made to
+ send to the user's terminal. When that fails, the messages is
+ mailed to the user's mailbox.
+
+ -------------------------------------------------------------
+
+ R: 220 SU-SCORE.ARPA Simple Mail Transfer Service Ready
+ S: HELO MIT-MC.ARPA
+ R: 250 SU-SCORE.ARPA
+
+ S: VRFY Crispin
+ R: 250 Mark Crispin <Admin.MRC@SU-SCORE.ARPA>
+
+ S: SEND FROM:<EAK@MIT-MC.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Admin.MRC@SU-SCORE.ARPA>
+ R: 450 User not active now
+
+ S: RSET
+ R: 250 OK
+
+ S: MAIL FROM:<EAK@MIT-MC.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Admin.MRC@SU-SCORE.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 SU-SCORE.ARPA Service closing transmission channel
+
+ Scenario 5
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+[Page 56] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Doing the preceding scenario more efficiently.
+
+ -------------------------------------------------------------
+
+ R: 220 SU-SCORE.ARPA Simple Mail Transfer Service Ready
+ S: HELO MIT-MC.ARPA
+ R: 250 SU-SCORE.ARPA
+
+ S: VRFY Crispin
+ R: 250 Mark Crispin <Admin.MRC@SU-SCORE.ARPA>
+
+ S: SOML FROM:<EAK@MIT-MC.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Admin.MRC@SU-SCORE.ARPA>
+ R: 250 User not active now, so will do mail.
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 SU-SCORE.ARPA Service closing transmission channel
+
+ Scenario 6
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 57]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ Mailing List Scenario
+
+ First each of two mailing lists are expanded in separate sessions
+ with different hosts. Then the message is sent to everyone that
+ appeared on either list (but no duplicates) via a relay host.
+
+ -------------------------------------------------------------
+
+ Step 1 -- Expanding the First List
+
+ R: 220 MIT-AI.ARPA Simple Mail Transfer Service Ready
+ S: HELO SU-SCORE.ARPA
+ R: 250 MIT-AI.ARPA
+
+ S: EXPN Example-People
+ R: 250-<ABC@MIT-MC.ARPA>
+ R: 250-Fred Fonebone <Fonebone@USC-ISIQ.ARPA>
+ R: 250-Xenon Y. Zither <XYZ@MIT-AI.ARPA>
+ R: 250-Quincy Smith <@USC-ISIF.ARPA:Q-Smith@ISI-VAXA.ARPA>
+ R: 250-<joe@foo-unix.ARPA>
+ R: 250 <xyz@bar-unix.ARPA>
+
+ S: QUIT
+ R: 221 MIT-AI.ARPA Service closing transmission channel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 58] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Step 2 -- Expanding the Second List
+
+ R: 220 MIT-MC.ARPA Simple Mail Transfer Service Ready
+ S: HELO SU-SCORE.ARPA
+ R: 250 MIT-MC.ARPA
+
+ S: EXPN Interested-Parties
+ R: 250-Al Calico <ABC@MIT-MC.ARPA>
+ R: 250-<XYZ@MIT-AI.ARPA>
+ R: 250-Quincy Smith <@USC-ISIF.ARPA:Q-Smith@ISI-VAXA.ARPA>
+ R: 250-<fred@BBN-UNIX.ARPA>
+ R: 250 <xyz@bar-unix.ARPA>
+
+ S: QUIT
+ R: 221 MIT-MC.ARPA Service closing transmission channel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 59]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ Step 3 -- Mailing to All via a Relay Host
+
+ R: 220 USC-ISIE.ARPA Simple Mail Transfer Service Ready
+ S: HELO SU-SCORE.ARPA
+ R: 250 USC-ISIE.ARPA
+
+ S: MAIL FROM:<Account.Person@SU-SCORE.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:ABC@MIT-MC.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:Fonebone@USC-ISIQA.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:XYZ@MIT-AI.ARPA>
+ R: 250 OK
+ S: RCPT
+ TO:<@USC-ISIE.ARPA,@USC-ISIF.ARPA:Q-Smith@ISI-VAXA.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:joe@FOO-UNIX.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:xyz@BAR-UNIX.ARPA>
+ R: 250 OK
+ S: RCPT TO:<@USC-ISIE.ARPA:fred@BBN-UNIX.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISIE.ARPA Service closing transmission channel
+
+ Scenario 7
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 60] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Forwarding Scenarios
+
+ -------------------------------------------------------------
+
+ R: 220 USC-ISIF.ARPA Simple Mail Transfer Service Ready
+ S: HELO LBL-UNIX.ARPA
+ R: 250 USC-ISIF.ARPA
+
+ S: MAIL FROM:<mo@LBL-UNIX.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<fred@USC-ISIF.ARPA>
+ R: 251 User not local; will forward to <Jones@USC-ISI.ARPA>
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISIF.ARPA Service closing transmission channel
+
+ Scenario 8
+
+ -------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Postel [Page 61]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ -------------------------------------------------------------
+
+ Step 1 -- Trying the Mailbox at the First Host
+
+ R: 220 USC-ISIF.ARPA Simple Mail Transfer Service Ready
+ S: HELO LBL-UNIX.ARPA
+ R: 250 USC-ISIF.ARPA
+
+ S: MAIL FROM:<mo@LBL-UNIX.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<fred@USC-ISIF.ARPA>
+ R: 251 User not local; will forward to <Jones@USC-ISI.ARPA>
+
+ S: RSET
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISIF.ARPA Service closing transmission channel
+
+ Step 2 -- Delivering the Mail at the Second Host
+
+ R: 220 USC-ISI.ARPA Simple Mail Transfer Service Ready
+ S: HELO LBL-UNIX.ARPA
+ R: 250 USC-ISI.ARPA
+
+ S: MAIL FROM:<mo@LBL-UNIX.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<Jones@USC-ISI.ARPA>
+ R: OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 USC-ISI.ARPA Service closing transmission channel
+
+ Scenario 9
+
+ -------------------------------------------------------------
+
+
+
+
+[Page 62] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ Too Many Recipients Scenario
+
+ -------------------------------------------------------------
+
+ R: 220 BERKELEY.ARPA Simple Mail Transfer Service Ready
+ S: HELO USC-ISIF.ARPA
+ R: 250 BERKELEY.ARPA
+
+ S: MAIL FROM:<Postel@USC-ISIF.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<fabry@BERKELEY.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<eric@BERKELEY.ARPA>
+ R: 552 Recipient storage full, try again in another transaction
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: MAIL FROM:<Postel@USC-ISIF.ARPA>
+ R: 250 OK
+
+ S: RCPT TO:<eric@BERKELEY.ARPA>
+ R: 250 OK
+
+ S: DATA
+ R: 354 Start mail input; end with <CRLF>.<CRLF>
+ S: Blah blah blah...
+ S: ...etc. etc. etc.
+ S: .
+ R: 250 OK
+
+ S: QUIT
+ R: 221 BERKELEY.ARPA Service closing transmission channel
+
+ Scenario 10
+
+ -------------------------------------------------------------
+
+ Note that a real implementation must handle many recipients as
+ specified in Section 4.5.3.
+
+
+
+Postel [Page 63]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+GLOSSARY
+
+ ASCII
+
+ American Standard Code for Information Interchange [1].
+
+ command
+
+ A request for a mail service action sent by the sender-SMTP to the
+ receiver-SMTP.
+
+ domain
+
+ The hierarchially structured global character string address of a
+ host computer in the mail system.
+
+ end of mail data indication
+
+ A special sequence of characters that indicates the end of the
+ mail data. In particular, the five characters carriage return,
+ line feed, period, carriage return, line feed, in that order.
+
+ host
+
+ A computer in the internetwork environment on which mailboxes or
+ SMTP processes reside.
+
+ line
+
+ A a sequence of ASCII characters ending with a <CRLF>.
+
+ mail data
+
+ A sequence of ASCII characters of arbitrary length, which conforms
+ to the standard set in the Standard for the Format of ARPA
+ Internet Text Messages (RFC 822 [2]).
+
+ mailbox
+
+ A character string (address) which identifies a user to whom mail
+ is to be sent. Mailbox normally consists of the host and user
+ specifications. The standard mailbox naming convention is defined
+ to be "user@domain". Additionally, the "container" in which mail
+ is stored.
+
+
+
+
+
+[Page 64] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+ receiver-SMTP process
+
+ A process which transfers mail in cooperation with a sender-SMTP
+ process. It waits for a connection to be established via the
+ transport service. It receives SMTP commands from the
+ sender-SMTP, sends replies, and performs the specified operations.
+
+ reply
+
+ A reply is an acknowledgment (positive or negative) sent from
+ receiver to sender via the transmission channel in response to a
+ command. The general form of a reply is a completion code
+ (including error codes) followed by a text string. The codes are
+ for use by programs and the text is usually intended for human
+ users.
+
+ sender-SMTP process
+
+ A process which transfers mail in cooperation with a receiver-SMTP
+ process. A local language may be used in the user interface
+ command/reply dialogue. The sender-SMTP initiates the transport
+ service connection. It initiates SMTP commands, receives replies,
+ and governs the transfer of mail.
+
+ session
+
+ The set of exchanges that occur while the transmission channel is
+ open.
+
+ transaction
+
+ The set of exchanges required for one message to be transmitted
+ for one or more recipients.
+
+ transmission channel
+
+ A full-duplex communication path between a sender-SMTP and a
+ receiver-SMTP for the exchange of commands, replies, and mail
+ text.
+
+ transport service
+
+ Any reliable stream-oriented data communication services. For
+ example, NCP, TCP, NITS.
+
+
+
+
+
+Postel [Page 65]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ user
+
+ A human being (or a process on behalf of a human being) wishing to
+ obtain mail transfer service. In addition, a recipient of
+ computer mail.
+
+ word
+
+ A sequence of printing characters.
+
+ <CRLF>
+
+ The characters carriage return and line feed (in that order).
+
+ <SP>
+
+ The space character.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 66] Postel
+
+
+
+RFC 821 August 1982
+ Simple Mail Transfer Protocol
+
+
+
+REFERENCES
+
+ [1] ASCII
+
+ ASCII, "USA Code for Information Interchange", United States of
+ America Standards Institute, X3.4, 1968. Also in: Feinler, E.
+ and J. Postel, eds., "ARPANET Protocol Handbook", NIC 7104, for
+ the Defense Communications Agency by SRI International, Menlo
+ Park, California, Revised January 1978.
+
+ [2] RFC 822
+
+ Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages," RFC 822, Department of Electrical Engineering,
+ University of Delaware, August 1982.
+
+ [3] TCP
+
+ Postel, J., ed., "Transmission Control Protocol - DARPA Internet
+ Program Protocol Specification", RFC 793, USC/Information Sciences
+ Institute, NTIS AD Number A111091, September 1981. Also in:
+ Feinler, E. and J. Postel, eds., "Internet Protocol Transition
+ Workbook", SRI International, Menlo Park, California, March 1982.
+
+ [4] NCP
+
+ McKenzie,A., "Host/Host Protocol for the ARPA Network", NIC 8246,
+ January 1972. Also in: Feinler, E. and J. Postel, eds., "ARPANET
+ Protocol Handbook", NIC 7104, for the Defense Communications
+ Agency by SRI International, Menlo Park, California, Revised
+ January 1978.
+
+ [5] Initial Connection Protocol
+
+ Postel, J., "Official Initial Connection Protocol", NIC 7101,
+ 11 June 1971. Also in: Feinler, E. and J. Postel, eds., "ARPANET
+ Protocol Handbook", NIC 7104, for the Defense Communications
+ Agency by SRI International, Menlo Park, California, Revised
+ January 1978.
+
+ [6] NITS
+
+ PSS/SG3, "A Network Independent Transport Service", Study Group 3,
+ The Post Office PSS Users Group, February 1980. Available from
+ the DCPU, National Physical Laboratory, Teddington, UK.
+
+
+
+
+Postel [Page 67]
+
+
+
+August 1982 RFC 821
+Simple Mail Transfer Protocol
+
+
+
+ [7] X.25
+
+ CCITT, "Recommendation X.25 - Interface Between Data Terminal
+ Equipment (DTE) and Data Circuit-terminating Equipment (DCE) for
+ Terminals Operating in the Packet Mode on Public Data Networks,"
+ CCITT Orange Book, Vol. VIII.2, International Telephone and
+ Telegraph Consultative Committee, Geneva, 1976.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[Page 68] Postel
+
diff --git a/usr.sbin/sendmail/doc/rfc/rfc822.txt b/usr.sbin/sendmail/doc/rfc/rfc822.txt
new file mode 100644
index 0000000..35b09a3
--- /dev/null
+++ b/usr.sbin/sendmail/doc/rfc/rfc822.txt
@@ -0,0 +1,2901 @@
+
+
+
+
+
+
+ RFC # 822
+
+ Obsoletes: RFC #733 (NIC #41952)
+
+
+
+
+
+
+
+
+
+
+
+
+ STANDARD FOR THE FORMAT OF
+
+ ARPA INTERNET TEXT MESSAGES
+
+
+
+
+
+
+ August 13, 1982
+
+
+
+
+
+
+ Revised by
+
+ David H. Crocker
+
+
+ Dept. of Electrical Engineering
+ University of Delaware, Newark, DE 19711
+ Network: DCrocker @ UDel-Relay
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ TABLE OF CONTENTS
+
+
+ PREFACE .................................................... ii
+
+ 1. INTRODUCTION ........................................... 1
+
+ 1.1. Scope ............................................ 1
+ 1.2. Communication Framework .......................... 2
+
+ 2. NOTATIONAL CONVENTIONS ................................. 3
+
+ 3. LEXICAL ANALYSIS OF MESSAGES ........................... 5
+
+ 3.1. General Description .............................. 5
+ 3.2. Header Field Definitions ......................... 9
+ 3.3. Lexical Tokens ................................... 10
+ 3.4. Clarifications ................................... 11
+
+ 4. MESSAGE SPECIFICATION .................................. 17
+
+ 4.1. Syntax ........................................... 17
+ 4.2. Forwarding ....................................... 19
+ 4.3. Trace Fields ..................................... 20
+ 4.4. Originator Fields ................................ 21
+ 4.5. Receiver Fields .................................. 23
+ 4.6. Reference Fields ................................. 23
+ 4.7. Other Fields ..................................... 24
+
+ 5. DATE AND TIME SPECIFICATION ............................ 26
+
+ 5.1. Syntax ........................................... 26
+ 5.2. Semantics ........................................ 26
+
+ 6. ADDRESS SPECIFICATION .................................. 27
+
+ 6.1. Syntax ........................................... 27
+ 6.2. Semantics ........................................ 27
+ 6.3. Reserved Address ................................. 33
+
+ 7. BIBLIOGRAPHY ........................................... 34
+
+
+ APPENDIX
+
+ A. EXAMPLES ............................................... 36
+ B. SIMPLE FIELD PARSING ................................... 40
+ C. DIFFERENCES FROM RFC #733 .............................. 41
+ D. ALPHABETICAL LISTING OF SYNTAX RULES ................... 44
+
+
+ August 13, 1982 - i - RFC #822
+
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ PREFACE
+
+
+ By 1977, the Arpanet employed several informal standards for
+ the text messages (mail) sent among its host computers. It was
+ felt necessary to codify these practices and provide for those
+ features that seemed imminent. The result of that effort was
+ Request for Comments (RFC) #733, "Standard for the Format of ARPA
+ Network Text Message", by Crocker, Vittal, Pogran, and Henderson.
+ The specification attempted to avoid major changes in existing
+ software, while permitting several new features.
+
+ This document revises the specifications in RFC #733, in
+ order to serve the needs of the larger and more complex ARPA
+ Internet. Some of RFC #733's features failed to gain adequate
+ acceptance. In order to simplify the standard and the software
+ that follows it, these features have been removed. A different
+ addressing scheme is used, to handle the case of inter-network
+ mail; and the concept of re-transmission has been introduced.
+
+ This specification is intended for use in the ARPA Internet.
+ However, an attempt has been made to free it of any dependence on
+ that environment, so that it can be applied to other network text
+ message systems.
+
+ The specification of RFC #733 took place over the course of
+ one year, using the ARPANET mail environment, itself, to provide
+ an on-going forum for discussing the capabilities to be included.
+ More than twenty individuals, from across the country, partici-
+ pated in the original discussion. The development of this
+ revised specification has, similarly, utilized network mail-based
+ group discussion. Both specification efforts greatly benefited
+ from the comments and ideas of the participants.
+
+ The syntax of the standard, in RFC #733, was originally
+ specified in the Backus-Naur Form (BNF) meta-language. Ken L.
+ Harrenstien, of SRI International, was responsible for re-coding
+ the BNF into an augmented BNF that makes the representation
+ smaller and easier to understand.
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - ii - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 1. INTRODUCTION
+
+ 1.1. SCOPE
+
+ This standard specifies a syntax for text messages that are
+ sent among computer users, within the framework of "electronic
+ mail". The standard supersedes the one specified in ARPANET
+ Request for Comments #733, "Standard for the Format of ARPA Net-
+ work Text Messages".
+
+ In this context, messages are viewed as having an envelope
+ and contents. The envelope contains whatever information is
+ needed to accomplish transmission and delivery. The contents
+ compose the object to be delivered to the recipient. This stan-
+ dard applies only to the format and some of the semantics of mes-
+ sage contents. It contains no specification of the information
+ in the envelope.
+
+ However, some message systems may use information from the
+ contents to create the envelope. It is intended that this stan-
+ dard facilitate the acquisition of such information by programs.
+
+ Some message systems may store messages in formats that
+ differ from the one specified in this standard. This specifica-
+ tion is intended strictly as a definition of what message content
+ format is to be passed BETWEEN hosts.
+
+ Note: This standard is NOT intended to dictate the internal for-
+ mats used by sites, the specific message system features
+ that they are expected to support, or any of the charac-
+ teristics of user interface programs that create or read
+ messages.
+
+ A distinction should be made between what the specification
+ REQUIRES and what it ALLOWS. Messages can be made complex and
+ rich with formally-structured components of information or can be
+ kept small and simple, with a minimum of such information. Also,
+ the standard simplifies the interpretation of differing visual
+ formats in messages; only the visual aspect of a message is
+ affected and not the interpretation of information within it.
+ Implementors may choose to retain such visual distinctions.
+
+ The formal definition is divided into four levels. The bot-
+ tom level describes the meta-notation used in this document. The
+ second level describes basic lexical analyzers that feed tokens
+ to higher-level parsers. Next is an overall specification for
+ messages; it permits distinguishing individual fields. Finally,
+ there is definition of the contents of several structured fields.
+
+
+
+ August 13, 1982 - 1 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 1.2. COMMUNICATION FRAMEWORK
+
+ Messages consist of lines of text. No special provisions
+ are made for encoding drawings, facsimile, speech, or structured
+ text. No significant consideration has been given to questions
+ of data compression or to transmission and storage efficiency,
+ and the standard tends to be free with the number of bits con-
+ sumed. For example, field names are specified as free text,
+ rather than special terse codes.
+
+ A general "memo" framework is used. That is, a message con-
+ sists of some information in a rigid format, followed by the main
+ part of the message, with a format that is not specified in this
+ document. The syntax of several fields of the rigidly-formated
+ ("headers") section is defined in this specification; some of
+ these fields must be included in all messages.
+
+ The syntax that distinguishes between header fields is
+ specified separately from the internal syntax for particular
+ fields. This separation is intended to allow simple parsers to
+ operate on the general structure of messages, without concern for
+ the detailed structure of individual header fields. Appendix B
+ is provided to facilitate construction of these parsers.
+
+ In addition to the fields specified in this document, it is
+ expected that other fields will gain common use. As necessary,
+ the specifications for these "extension-fields" will be published
+ through the same mechanism used to publish this document. Users
+ may also wish to extend the set of fields that they use
+ privately. Such "user-defined fields" are permitted.
+
+ The framework severely constrains document tone and appear-
+ ance and is primarily useful for most intra-organization communi-
+ cations and well-structured inter-organization communication.
+ It also can be used for some types of inter-process communica-
+ tion, such as simple file transfer and remote job entry. A more
+ robust framework might allow for multi-font, multi-color, multi-
+ dimension encoding of information. A less robust one, as is
+ present in most single-machine message systems, would more
+ severely constrain the ability to add fields and the decision to
+ include specific fields. In contrast with paper-based communica-
+ tion, it is interesting to note that the RECEIVER of a message
+ can exercise an extraordinary amount of control over the
+ message's appearance. The amount of actual control available to
+ message receivers is contingent upon the capabilities of their
+ individual message systems.
+
+
+
+
+
+ August 13, 1982 - 2 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 2. NOTATIONAL CONVENTIONS
+
+ This specification uses an augmented Backus-Naur Form (BNF)
+ notation. The differences from standard BNF involve naming rules
+ and indicating repetition and "local" alternatives.
+
+ 2.1. RULE NAMING
+
+ Angle brackets ("<", ">") are not used, in general. The
+ name of a rule is simply the name itself, rather than "<name>".
+ Quotation-marks enclose literal text (which may be upper and/or
+ lower case). Certain basic rules are in uppercase, such as
+ SPACE, TAB, CRLF, DIGIT, ALPHA, etc. Angle brackets are used in
+ rule definitions, and in the rest of this document, whenever
+ their presence will facilitate discerning the use of rule names.
+
+ 2.2. RULE1 / RULE2: ALTERNATIVES
+
+ Elements separated by slash ("/") are alternatives. There-
+ fore "foo / bar" will accept foo or bar.
+
+ 2.3. (RULE1 RULE2): LOCAL ALTERNATIVES
+
+ Elements enclosed in parentheses are treated as a single
+ element. Thus, "(elem (foo / bar) elem)" allows the token
+ sequences "elem foo elem" and "elem bar elem".
+
+ 2.4. *RULE: REPETITION
+
+ The character "*" preceding an element indicates repetition.
+ The full form is:
+
+ <l>*<m>element
+
+ indicating at least <l> and at most <m> occurrences of element.
+ Default values are 0 and infinity so that "*(element)" allows any
+ number, including zero; "1*element" requires at least one; and
+ "1*2element" allows one or two.
+
+ 2.5. [RULE]: OPTIONAL
+
+ Square brackets enclose optional elements; "[foo bar]" is
+ equivalent to "*1(foo bar)".
+
+ 2.6. NRULE: SPECIFIC REPETITION
+
+ "<n>(element)" is equivalent to "<n>*<n>(element)"; that is,
+ exactly <n> occurrences of (element). Thus 2DIGIT is a 2-digit
+ number, and 3ALPHA is a string of three alphabetic characters.
+
+
+ August 13, 1982 - 3 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 2.7. #RULE: LISTS
+
+ A construct "#" is defined, similar to "*", as follows:
+
+ <l>#<m>element
+
+ indicating at least <l> and at most <m> elements, each separated
+ by one or more commas (","). This makes the usual form of lists
+ very easy; a rule such as '(element *("," element))' can be shown
+ as "1#element". Wherever this construct is used, null elements
+ are allowed, but do not contribute to the count of elements
+ present. That is, "(element),,(element)" is permitted, but
+ counts as only two elements. Therefore, where at least one ele-
+ ment is required, at least one non-null element must be present.
+ Default values are 0 and infinity so that "#(element)" allows any
+ number, including zero; "1#element" requires at least one; and
+ "1#2element" allows one or two.
+
+ 2.8. ; COMMENTS
+
+ A semi-colon, set off some distance to the right of rule
+ text, starts a comment that continues to the end of line. This
+ is a simple way of including useful notes in parallel with the
+ specifications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 4 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 3. LEXICAL ANALYSIS OF MESSAGES
+
+ 3.1. GENERAL DESCRIPTION
+
+ A message consists of header fields and, optionally, a body.
+ The body is simply a sequence of lines containing ASCII charac-
+ ters. It is separated from the headers by a null line (i.e., a
+ line with nothing preceding the CRLF).
+
+ 3.1.1. LONG HEADER FIELDS
+
+ Each header field can be viewed as a single, logical line of
+ ASCII characters, comprising a field-name and a field-body.
+ For convenience, the field-body portion of this conceptual
+ entity can be split into a multiple-line representation; this
+ is called "folding". The general rule is that wherever there
+ may be linear-white-space (NOT simply LWSP-chars), a CRLF
+ immediately followed by AT LEAST one LWSP-char may instead be
+ inserted. Thus, the single line
+
+ To: "Joe & J. Harvey" <ddd @Org>, JJV @ BBN
+
+ can be represented as:
+
+ To: "Joe & J. Harvey" <ddd @ Org>,
+ JJV@BBN
+
+ and
+
+ To: "Joe & J. Harvey"
+ <ddd@ Org>, JJV
+ @BBN
+
+ and
+
+ To: "Joe &
+ J. Harvey" <ddd @ Org>, JJV @ BBN
+
+ The process of moving from this folded multiple-line
+ representation of a header field to its single line represen-
+ tation is called "unfolding". Unfolding is accomplished by
+ regarding CRLF immediately followed by a LWSP-char as
+ equivalent to the LWSP-char.
+
+ Note: While the standard permits folding wherever linear-
+ white-space is permitted, it is recommended that struc-
+ tured fields, such as those containing addresses, limit
+ folding to higher-level syntactic breaks. For address
+ fields, it is recommended that such folding occur
+
+
+ August 13, 1982 - 5 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ between addresses, after the separating comma.
+
+ 3.1.2. STRUCTURE OF HEADER FIELDS
+
+ Once a field has been unfolded, it may be viewed as being com-
+ posed of a field-name followed by a colon (":"), followed by a
+ field-body, and terminated by a carriage-return/line-feed.
+ The field-name must be composed of printable ASCII characters
+ (i.e., characters that have values between 33. and 126.,
+ decimal, except colon). The field-body may be composed of any
+ ASCII characters, except CR or LF. (While CR and/or LF may be
+ present in the actual text, they are removed by the action of
+ unfolding the field.)
+
+ Certain field-bodies of headers may be interpreted according
+ to an internal syntax that some systems may wish to parse.
+ These fields are called "structured fields". Examples
+ include fields containing dates and addresses. Other fields,
+ such as "Subject" and "Comments", are regarded simply as
+ strings of text.
+
+ Note: Any field which has a field-body that is defined as
+ other than simply <text> is to be treated as a struc-
+ tured field.
+
+ Field-names, unstructured field bodies and structured
+ field bodies each are scanned by their own, independent
+ "lexical" analyzers.
+
+ 3.1.3. UNSTRUCTURED FIELD BODIES
+
+ For some fields, such as "Subject" and "Comments", no struc-
+ turing is assumed, and they are treated simply as <text>s, as
+ in the message body. Rules of folding apply to these fields,
+ so that such field bodies which occupy several lines must
+ therefore have the second and successive lines indented by at
+ least one LWSP-char.
+
+ 3.1.4. STRUCTURED FIELD BODIES
+
+ To aid in the creation and reading of structured fields, the
+ free insertion of linear-white-space (which permits folding
+ by inclusion of CRLFs) is allowed between lexical tokens.
+ Rather than obscuring the syntax specifications for these
+ structured fields with explicit syntax for this linear-white-
+ space, the existence of another "lexical" analyzer is assumed.
+ This analyzer does not apply for unstructured field bodies
+ that are simply strings of text, as described above. The
+ analyzer provides an interpretation of the unfolded text
+
+
+ August 13, 1982 - 6 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ composing the body of the field as a sequence of lexical sym-
+ bols.
+
+ These symbols are:
+
+ - individual special characters
+ - quoted-strings
+ - domain-literals
+ - comments
+ - atoms
+
+ The first four of these symbols are self-delimiting. Atoms
+ are not; they are delimited by the self-delimiting symbols and
+ by linear-white-space. For the purposes of regenerating
+ sequences of atoms and quoted-strings, exactly one SPACE is
+ assumed to exist, and should be used, between them. (Also, in
+ the "Clarifications" section on "White Space", below, note the
+ rules about treatment of multiple contiguous LWSP-chars.)
+
+ So, for example, the folded body of an address field
+
+ ":sysmail"@ Some-Group. Some-Org,
+ Muhammed.(I am the greatest) Ali @(the)Vegas.WBA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 7 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ is analyzed into the following lexical symbols and types:
+
+ :sysmail quoted string
+ @ special
+ Some-Group atom
+ . special
+ Some-Org atom
+ , special
+ Muhammed atom
+ . special
+ (I am the greatest) comment
+ Ali atom
+ @ atom
+ (the) comment
+ Vegas atom
+ . special
+ WBA atom
+
+ The canonical representations for the data in these addresses
+ are the following strings:
+
+ ":sysmail"@Some-Group.Some-Org
+
+ and
+
+ Muhammed.Ali@Vegas.WBA
+
+ Note: For purposes of display, and when passing such struc-
+ tured information to other systems, such as mail proto-
+ col services, there must be NO linear-white-space
+ between <word>s that are separated by period (".") or
+ at-sign ("@") and exactly one SPACE between all other
+ <word>s. Also, headers should be in a folded form.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 8 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 3.2. HEADER FIELD DEFINITIONS
+
+ These rules show a field meta-syntax, without regard for the
+ particular type or internal syntax. Their purpose is to permit
+ detection of fields; also, they present to higher-level parsers
+ an image of each field as fitting on one line.
+
+ field = field-name ":" [ field-body ] CRLF
+
+ field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":">
+
+ field-body = field-body-contents
+ [CRLF LWSP-char field-body]
+
+ field-body-contents =
+ <the ASCII characters making up the field-body, as
+ defined in the following sections, and consisting
+ of combinations of atom, quoted-string, and
+ specials tokens, or else consisting of texts>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 9 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 3.3. LEXICAL TOKENS
+
+ The following rules are used to define an underlying lexical
+ analyzer, which feeds tokens to higher level parsers. See the
+ ANSI references, in the Bibliography.
+
+ ; ( Octal, Decimal.)
+ CHAR = <any ASCII character> ; ( 0-177, 0.-127.)
+ ALPHA = <any ASCII alphabetic character>
+ ; (101-132, 65.- 90.)
+ ; (141-172, 97.-122.)
+ DIGIT = <any ASCII decimal digit> ; ( 60- 71, 48.- 57.)
+ CTL = <any ASCII control ; ( 0- 37, 0.- 31.)
+ character and DEL> ; ( 177, 127.)
+ CR = <ASCII CR, carriage return> ; ( 15, 13.)
+ LF = <ASCII LF, linefeed> ; ( 12, 10.)
+ SPACE = <ASCII SP, space> ; ( 40, 32.)
+ HTAB = <ASCII HT, horizontal-tab> ; ( 11, 9.)
+ <"> = <ASCII quote mark> ; ( 42, 34.)
+ CRLF = CR LF
+
+ LWSP-char = SPACE / HTAB ; semantics = SPACE
+
+ linear-white-space = 1*([CRLF] LWSP-char) ; semantics = SPACE
+ ; CRLF => folding
+
+ specials = "(" / ")" / "<" / ">" / "@" ; Must be in quoted-
+ / "," / ";" / ":" / "\" / <"> ; string, to use
+ / "." / "[" / "]" ; within a word.
+
+ delimiters = specials / linear-white-space / comment
+
+ text = <any CHAR, including bare ; => atoms, specials,
+ CR & bare LF, but NOT ; comments and
+ including CRLF> ; quoted-strings are
+ ; NOT recognized.
+
+ atom = 1*<any CHAR except specials, SPACE and CTLs>
+
+ quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
+ ; quoted chars.
+
+ qtext = <any CHAR excepting <">, ; => may be folded
+ "\" & CR, and including
+ linear-white-space>
+
+ domain-literal = "[" *(dtext / quoted-pair) "]"
+
+
+
+
+ August 13, 1982 - 10 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ dtext = <any CHAR excluding "[", ; => may be folded
+ "]", "\" & CR, & including
+ linear-white-space>
+
+ comment = "(" *(ctext / quoted-pair / comment) ")"
+
+ ctext = <any CHAR excluding "(", ; => may be folded
+ ")", "\" & CR, & including
+ linear-white-space>
+
+ quoted-pair = "\" CHAR ; may quote any char
+
+ phrase = 1*word ; Sequence of words
+
+ word = atom / quoted-string
+
+
+ 3.4. CLARIFICATIONS
+
+ 3.4.1. QUOTING
+
+ Some characters are reserved for special interpretation, such
+ as delimiting lexical tokens. To permit use of these charac-
+ ters as uninterpreted data, a quoting mechanism is provided.
+ To quote a character, precede it with a backslash ("\").
+
+ This mechanism is not fully general. Characters may be quoted
+ only within a subset of the lexical constructs. In particu-
+ lar, quoting is limited to use within:
+
+ - quoted-string
+ - domain-literal
+ - comment
+
+ Within these constructs, quoting is REQUIRED for CR and "\"
+ and for the character(s) that delimit the token (e.g., "(" and
+ ")" for a comment). However, quoting is PERMITTED for any
+ character.
+
+ Note: In particular, quoting is NOT permitted within atoms.
+ For example when the local-part of an addr-spec must
+ contain a special character, a quoted string must be
+ used. Therefore, a specification such as:
+
+ Full\ Name@Domain
+
+ is not legal and must be specified as:
+
+ "Full Name"@Domain
+
+
+ August 13, 1982 - 11 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 3.4.2. WHITE SPACE
+
+ Note: In structured field bodies, multiple linear space ASCII
+ characters (namely HTABs and SPACEs) are treated as
+ single spaces and may freely surround any symbol. In
+ all header fields, the only place in which at least one
+ LWSP-char is REQUIRED is at the beginning of continua-
+ tion lines in a folded field.
+
+ When passing text to processes that do not interpret text
+ according to this standard (e.g., mail protocol servers), then
+ NO linear-white-space characters should occur between a period
+ (".") or at-sign ("@") and a <word>. Exactly ONE SPACE should
+ be used in place of arbitrary linear-white-space and comment
+ sequences.
+
+ Note: Within systems conforming to this standard, wherever a
+ member of the list of delimiters is allowed, LWSP-chars
+ may also occur before and/or after it.
+
+ Writers of mail-sending (i.e., header-generating) programs
+ should realize that there is no network-wide definition of the
+ effect of ASCII HT (horizontal-tab) characters on the appear-
+ ance of text at another network host; therefore, the use of
+ tabs in message headers, though permitted, is discouraged.
+
+ 3.4.3. COMMENTS
+
+ A comment is a set of ASCII characters, which is enclosed in
+ matching parentheses and which is not within a quoted-string
+ The comment construct permits message originators to add text
+ which will be useful for human readers, but which will be
+ ignored by the formal semantics. Comments should be retained
+ while the message is subject to interpretation according to
+ this standard. However, comments must NOT be included in
+ other cases, such as during protocol exchanges with mail
+ servers.
+
+ Comments nest, so that if an unquoted left parenthesis occurs
+ in a comment string, there must also be a matching right
+ parenthesis. When a comment acts as the delimiter between a
+ sequence of two lexical symbols, such as two atoms, it is lex-
+ ically equivalent with a single SPACE, for the purposes of
+ regenerating the sequence, such as when passing the sequence
+ onto a mail protocol server. Comments are detected as such
+ only within field-bodies of structured fields.
+
+ If a comment is to be "folded" onto multiple lines, then the
+ syntax for folding must be adhered to. (See the "Lexical
+
+
+ August 13, 1982 - 12 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ Analysis of Messages" section on "Folding Long Header Fields"
+ above, and the section on "Case Independence" below.) Note
+ that the official semantics therefore do not "see" any
+ unquoted CRLFs that are in comments, although particular pars-
+ ing programs may wish to note their presence. For these pro-
+ grams, it would be reasonable to interpret a "CRLF LWSP-char"
+ as being a CRLF that is part of the comment; i.e., the CRLF is
+ kept and the LWSP-char is discarded. Quoted CRLFs (i.e., a
+ backslash followed by a CR followed by a LF) still must be
+ followed by at least one LWSP-char.
+
+ 3.4.4. DELIMITING AND QUOTING CHARACTERS
+
+ The quote character (backslash) and characters that delimit
+ syntactic units are not, generally, to be taken as data that
+ are part of the delimited or quoted unit(s). In particular,
+ the quotation-marks that define a quoted-string, the
+ parentheses that define a comment and the backslash that
+ quotes a following character are NOT part of the quoted-
+ string, comment or quoted character. A quotation-mark that is
+ to be part of a quoted-string, a parenthesis that is to be
+ part of a comment and a backslash that is to be part of either
+ must each be preceded by the quote-character backslash ("\").
+ Note that the syntax allows any character to be quoted within
+ a quoted-string or comment; however only certain characters
+ MUST be quoted to be included as data. These characters are
+ the ones that are not part of the alternate text group (i.e.,
+ ctext or qtext).
+
+ The one exception to this rule is that a single SPACE is
+ assumed to exist between contiguous words in a phrase, and
+ this interpretation is independent of the actual number of
+ LWSP-chars that the creator places between the words. To
+ include more than one SPACE, the creator must make the LWSP-
+ chars be part of a quoted-string.
+
+ Quotation marks that delimit a quoted string and backslashes
+ that quote the following character should NOT accompany the
+ quoted-string when the string is passed to processes that do
+ not interpret data according to this specification (e.g., mail
+ protocol servers).
+
+ 3.4.5. QUOTED-STRINGS
+
+ Where permitted (i.e., in words in structured fields) quoted-
+ strings are treated as a single symbol. That is, a quoted-
+ string is equivalent to an atom, syntactically. If a quoted-
+ string is to be "folded" onto multiple lines, then the syntax
+ for folding must be adhered to. (See the "Lexical Analysis of
+
+
+ August 13, 1982 - 13 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ Messages" section on "Folding Long Header Fields" above, and
+ the section on "Case Independence" below.) Therefore, the
+ official semantics do not "see" any bare CRLFs that are in
+ quoted-strings; however particular parsing programs may wish
+ to note their presence. For such programs, it would be rea-
+ sonable to interpret a "CRLF LWSP-char" as being a CRLF which
+ is part of the quoted-string; i.e., the CRLF is kept and the
+ LWSP-char is discarded. Quoted CRLFs (i.e., a backslash fol-
+ lowed by a CR followed by a LF) are also subject to rules of
+ folding, but the presence of the quoting character (backslash)
+ explicitly indicates that the CRLF is data to the quoted
+ string. Stripping off the first following LWSP-char is also
+ appropriate when parsing quoted CRLFs.
+
+ 3.4.6. BRACKETING CHARACTERS
+
+ There is one type of bracket which must occur in matched pairs
+ and may have pairs nested within each other:
+
+ o Parentheses ("(" and ")") are used to indicate com-
+ ments.
+
+ There are three types of brackets which must occur in matched
+ pairs, and which may NOT be nested:
+
+ o Colon/semi-colon (":" and ";") are used in address
+ specifications to indicate that the included list of
+ addresses are to be treated as a group.
+
+ o Angle brackets ("<" and ">") are generally used to
+ indicate the presence of a one machine-usable refer-
+ ence (e.g., delimiting mailboxes), possibly including
+ source-routing to the machine.
+
+ o Square brackets ("[" and "]") are used to indicate the
+ presence of a domain-literal, which the appropriate
+ name-domain is to use directly, bypassing normal
+ name-resolution mechanisms.
+
+ 3.4.7. CASE INDEPENDENCE
+
+ Except as noted, alphabetic strings may be represented in any
+ combination of upper and lower case. The only syntactic units
+
+
+
+
+
+
+
+
+ August 13, 1982 - 14 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ which requires preservation of case information are:
+
+ - text
+ - qtext
+ - dtext
+ - ctext
+ - quoted-pair
+ - local-part, except "Postmaster"
+
+ When matching any other syntactic unit, case is to be ignored.
+ For example, the field-names "From", "FROM", "from", and even
+ "FroM" are semantically equal and should all be treated ident-
+ ically.
+
+ When generating these units, any mix of upper and lower case
+ alphabetic characters may be used. The case shown in this
+ specification is suggested for message-creating processes.
+
+ Note: The reserved local-part address unit, "Postmaster", is
+ an exception. When the value "Postmaster" is being
+ interpreted, it must be accepted in any mixture of
+ case, including "POSTMASTER", and "postmaster".
+
+ 3.4.8. FOLDING LONG HEADER FIELDS
+
+ Each header field may be represented on exactly one line con-
+ sisting of the name of the field and its body, and terminated
+ by a CRLF; this is what the parser sees. For readability, the
+ field-body portion of long header fields may be "folded" onto
+ multiple lines of the actual field. "Long" is commonly inter-
+ preted to mean greater than 65 or 72 characters. The former
+ length serves as a limit, when the message is to be viewed on
+ most simple terminals which use simple display software; how-
+ ever, the limit is not imposed by this standard.
+
+ Note: Some display software often can selectively fold lines,
+ to suit the display terminal. In such cases, sender-
+ provided folding can interfere with the display
+ software.
+
+ 3.4.9. BACKSPACE CHARACTERS
+
+ ASCII BS characters (Backspace, decimal 8) may be included in
+ texts and quoted-strings to effect overstriking. However, any
+ use of backspaces which effects an overstrike to the left of
+ the beginning of the text or quoted-string is prohibited.
+
+
+
+
+
+ August 13, 1982 - 15 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 3.4.10. NETWORK-SPECIFIC TRANSFORMATIONS
+
+ During transmission through heterogeneous networks, it may be
+ necessary to force data to conform to a network's local con-
+ ventions. For example, it may be required that a CR be fol-
+ lowed either by LF, making a CRLF, or by <null>, if the CR is
+ to stand alone). Such transformations are reversed, when the
+ message exits that network.
+
+ When crossing network boundaries, the message should be
+ treated as passing through two modules. It will enter the
+ first module containing whatever network-specific transforma-
+ tions that were necessary to permit migration through the
+ "current" network. It then passes through the modules:
+
+ o Transformation Reversal
+
+ The "current" network's idiosyncracies are removed and
+ the message is returned to the canonical form speci-
+ fied in this standard.
+
+ o Transformation
+
+ The "next" network's local idiosyncracies are imposed
+ on the message.
+
+ ------------------
+ From ==> | Remove Net-A |
+ Net-A | idiosyncracies |
+ ------------------
+ ||
+ \/
+ Conformance
+ with standard
+ ||
+ \/
+ ------------------
+ | Impose Net-B | ==> To
+ | idiosyncracies | Net-B
+ ------------------
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 16 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 4. MESSAGE SPECIFICATION
+
+ 4.1. SYNTAX
+
+ Note: Due to an artifact of the notational conventions, the syn-
+ tax indicates that, when present, some fields, must be in
+ a particular order. Header fields are NOT required to
+ occur in any particular order, except that the message
+ body must occur AFTER the headers. It is recommended
+ that, if present, headers be sent in the order "Return-
+ Path", "Received", "Date", "From", "Subject", "Sender",
+ "To", "cc", etc.
+
+ This specification permits multiple occurrences of most
+ fields. Except as noted, their interpretation is not
+ specified here, and their use is discouraged.
+
+ The following syntax for the bodies of various fields should
+ be thought of as describing each field body as a single long
+ string (or line). The "Lexical Analysis of Message" section on
+ "Long Header Fields", above, indicates how such long strings can
+ be represented on more than one line in the actual transmitted
+ message.
+
+ message = fields *( CRLF *text ) ; Everything after
+ ; first null line
+ ; is message body
+
+ fields = dates ; Creation time,
+ source ; author id & one
+ 1*destination ; address required
+ *optional-field ; others optional
+
+ source = [ trace ] ; net traversals
+ originator ; original mail
+ [ resent ] ; forwarded
+
+ trace = return ; path to sender
+ 1*received ; receipt tags
+
+ return = "Return-path" ":" route-addr ; return address
+
+ received = "Received" ":" ; one per relay
+ ["from" domain] ; sending host
+ ["by" domain] ; receiving host
+ ["via" atom] ; physical path
+ *("with" atom) ; link/mail protocol
+ ["id" msg-id] ; receiver msg id
+ ["for" addr-spec] ; initial form
+
+
+ August 13, 1982 - 17 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ ";" date-time ; time received
+
+ originator = authentic ; authenticated addr
+ [ "Reply-To" ":" 1#address] )
+
+ authentic = "From" ":" mailbox ; Single author
+ / ( "Sender" ":" mailbox ; Actual submittor
+ "From" ":" 1#mailbox) ; Multiple authors
+ ; or not sender
+
+ resent = resent-authentic
+ [ "Resent-Reply-To" ":" 1#address] )
+
+ resent-authentic =
+ = "Resent-From" ":" mailbox
+ / ( "Resent-Sender" ":" mailbox
+ "Resent-From" ":" 1#mailbox )
+
+ dates = orig-date ; Original
+ [ resent-date ] ; Forwarded
+
+ orig-date = "Date" ":" date-time
+
+ resent-date = "Resent-Date" ":" date-time
+
+ destination = "To" ":" 1#address ; Primary
+ / "Resent-To" ":" 1#address
+ / "cc" ":" 1#address ; Secondary
+ / "Resent-cc" ":" 1#address
+ / "bcc" ":" #address ; Blind carbon
+ / "Resent-bcc" ":" #address
+
+ optional-field =
+ / "Message-ID" ":" msg-id
+ / "Resent-Message-ID" ":" msg-id
+ / "In-Reply-To" ":" *(phrase / msg-id)
+ / "References" ":" *(phrase / msg-id)
+ / "Keywords" ":" #phrase
+ / "Subject" ":" *text
+ / "Comments" ":" *text
+ / "Encrypted" ":" 1#2word
+ / extension-field ; To be defined
+ / user-defined-field ; May be pre-empted
+
+ msg-id = "<" addr-spec ">" ; Unique message id
+
+
+
+
+
+
+ August 13, 1982 - 18 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ extension-field =
+ <Any field which is defined in a document
+ published as a formal extension to this
+ specification; none will have names beginning
+ with the string "X-">
+
+ user-defined-field =
+ <Any field which has not been defined
+ in this specification or published as an
+ extension to this specification; names for
+ such fields must be unique and may be
+ pre-empted by published extensions>
+
+ 4.2. FORWARDING
+
+ Some systems permit mail recipients to forward a message,
+ retaining the original headers, by adding some new fields. This
+ standard supports such a service, through the "Resent-" prefix to
+ field names.
+
+ Whenever the string "Resent-" begins a field name, the field
+ has the same semantics as a field whose name does not have the
+ prefix. However, the message is assumed to have been forwarded
+ by an original recipient who attached the "Resent-" field. This
+ new field is treated as being more recent than the equivalent,
+ original field. For example, the "Resent-From", indicates the
+ person that forwarded the message, whereas the "From" field indi-
+ cates the original author.
+
+ Use of such precedence information depends upon partici-
+ pants' communication needs. For example, this standard does not
+ dictate when a "Resent-From:" address should receive replies, in
+ lieu of sending them to the "From:" address.
+
+ Note: In general, the "Resent-" fields should be treated as con-
+ taining a set of information that is independent of the
+ set of original fields. Information for one set should
+ not automatically be taken from the other. The interpre-
+ tation of multiple "Resent-" fields, of the same type, is
+ undefined.
+
+ In the remainder of this specification, occurrence of legal
+ "Resent-" fields are treated identically with the occurrence of
+
+
+
+
+
+
+
+
+ August 13, 1982 - 19 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ fields whose names do not contain this prefix.
+
+ 4.3. TRACE FIELDS
+
+ Trace information is used to provide an audit trail of mes-
+ sage handling. In addition, it indicates a route back to the
+ sender of the message.
+
+ The list of known "via" and "with" values are registered
+ with the Network Information Center, SRI International, Menlo
+ Park, California.
+
+ 4.3.1. RETURN-PATH
+
+ This field is added by the final transport system that
+ delivers the message to its recipient. The field is intended
+ to contain definitive information about the address and route
+ back to the message's originator.
+
+ Note: The "Reply-To" field is added by the originator and
+ serves to direct replies, whereas the "Return-Path"
+ field is used to identify a path back to the origina-
+ tor.
+
+ While the syntax indicates that a route specification is
+ optional, every attempt should be made to provide that infor-
+ mation in this field.
+
+ 4.3.2. RECEIVED
+
+ A copy of this field is added by each transport service that
+ relays the message. The information in the field can be quite
+ useful for tracing transport problems.
+
+ The names of the sending and receiving hosts and time-of-
+ receipt may be specified. The "via" parameter may be used, to
+ indicate what physical mechanism the message was sent over,
+ such as Arpanet or Phonenet, and the "with" parameter may be
+ used to indicate the mail-, or connection-, level protocol
+ that was used, such as the SMTP mail protocol, or X.25 tran-
+ sport protocol.
+
+ Note: Several "with" parameters may be included, to fully
+ specify the set of protocols that were used.
+
+ Some transport services queue mail; the internal message iden-
+ tifier that is assigned to the message may be noted, using the
+ "id" parameter. When the sending host uses a destination
+ address specification that the receiving host reinterprets, by
+
+
+ August 13, 1982 - 20 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ expansion or transformation, the receiving host may wish to
+ record the original specification, using the "for" parameter.
+ For example, when a copy of mail is sent to the member of a
+ distribution list, this parameter may be used to record the
+ original address that was used to specify the list.
+
+ 4.4. ORIGINATOR FIELDS
+
+ The standard allows only a subset of the combinations possi-
+ ble with the From, Sender, Reply-To, Resent-From, Resent-Sender,
+ and Resent-Reply-To fields. The limitation is intentional.
+
+ 4.4.1. FROM / RESENT-FROM
+
+ This field contains the identity of the person(s) who wished
+ this message to be sent. The message-creation process should
+ default this field to be a single, authenticated machine
+ address, indicating the AGENT (person, system or process)
+ entering the message. If this is not done, the "Sender" field
+ MUST be present. If the "From" field IS defaulted this way,
+ the "Sender" field is optional and is redundant with the
+ "From" field. In all cases, addresses in the "From" field
+ must be machine-usable (addr-specs) and may not contain named
+ lists (groups).
+
+ 4.4.2. SENDER / RESENT-SENDER
+
+ This field contains the authenticated identity of the AGENT
+ (person, system or process) that sends the message. It is
+ intended for use when the sender is not the author of the mes-
+ sage, or to indicate who among a group of authors actually
+ sent the message. If the contents of the "Sender" field would
+ be completely redundant with the "From" field, then the
+ "Sender" field need not be present and its use is discouraged
+ (though still legal). In particular, the "Sender" field MUST
+ be present if it is NOT the same as the "From" Field.
+
+ The Sender mailbox specification includes a word sequence
+ which must correspond to a specific agent (i.e., a human user
+ or a computer program) rather than a standard address. This
+ indicates the expectation that the field will identify the
+ single AGENT (person, system, or process) responsible for
+ sending the mail and not simply include the name of a mailbox
+ from which the mail was sent. For example in the case of a
+ shared login name, the name, by itself, would not be adequate.
+ The local-part address unit, which refers to this agent, is
+ expected to be a computer system term, and not (for example) a
+ generalized person reference which can be used outside the
+ network text message context.
+
+
+ August 13, 1982 - 21 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ Since the critical function served by the "Sender" field is
+ identification of the agent responsible for sending mail and
+ since computer programs cannot be held accountable for their
+ behavior, it is strongly recommended that when a computer pro-
+ gram generates a message, the HUMAN who is responsible for
+ that program be referenced as part of the "Sender" field mail-
+ box specification.
+
+ 4.4.3. REPLY-TO / RESENT-REPLY-TO
+
+ This field provides a general mechanism for indicating any
+ mailbox(es) to which responses are to be sent. Three typical
+ uses for this feature can be distinguished. In the first
+ case, the author(s) may not have regular machine-based mail-
+ boxes and therefore wish(es) to indicate an alternate machine
+ address. In the second case, an author may wish additional
+ persons to be made aware of, or responsible for, replies. A
+ somewhat different use may be of some help to "text message
+ teleconferencing" groups equipped with automatic distribution
+ services: include the address of that service in the "Reply-
+ To" field of all messages submitted to the teleconference;
+ then participants can "reply" to conference submissions to
+ guarantee the correct distribution of any submission of their
+ own.
+
+ Note: The "Return-Path" field is added by the mail transport
+ service, at the time of final deliver. It is intended
+ to identify a path back to the orginator of the mes-
+ sage. The "Reply-To" field is added by the message
+ originator and is intended to direct replies.
+
+ 4.4.4. AUTOMATIC USE OF FROM / SENDER / REPLY-TO
+
+ For systems which automatically generate address lists for
+ replies to messages, the following recommendations are made:
+
+ o The "Sender" field mailbox should be sent notices of
+ any problems in transport or delivery of the original
+ messages. If there is no "Sender" field, then the
+ "From" field mailbox should be used.
+
+ o The "Sender" field mailbox should NEVER be used
+ automatically, in a recipient's reply message.
+
+ o If the "Reply-To" field exists, then the reply should
+ go to the addresses indicated in that field and not to
+ the address(es) indicated in the "From" field.
+
+
+
+
+ August 13, 1982 - 22 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ o If there is a "From" field, but no "Reply-To" field,
+ the reply should be sent to the address(es) indicated
+ in the "From" field.
+
+ Sometimes, a recipient may actually wish to communicate with
+ the person that initiated the message transfer. In such
+ cases, it is reasonable to use the "Sender" address.
+
+ This recommendation is intended only for automated use of
+ originator-fields and is not intended to suggest that replies
+ may not also be sent to other recipients of messages. It is
+ up to the respective mail-handling programs to decide what
+ additional facilities will be provided.
+
+ Examples are provided in Appendix A.
+
+ 4.5. RECEIVER FIELDS
+
+ 4.5.1. TO / RESENT-TO
+
+ This field contains the identity of the primary recipients of
+ the message.
+
+ 4.5.2. CC / RESENT-CC
+
+ This field contains the identity of the secondary (informa-
+ tional) recipients of the message.
+
+ 4.5.3. BCC / RESENT-BCC
+
+ This field contains the identity of additional recipients of
+ the message. The contents of this field are not included in
+ copies of the message sent to the primary and secondary reci-
+ pients. Some systems may choose to include the text of the
+ "Bcc" field only in the author(s)'s copy, while others may
+ also include it in the text sent to all those indicated in the
+ "Bcc" list.
+
+ 4.6. REFERENCE FIELDS
+
+ 4.6.1. MESSAGE-ID / RESENT-MESSAGE-ID
+
+ This field contains a unique identifier (the local-part
+ address unit) which refers to THIS version of THIS message.
+ The uniqueness of the message identifier is guaranteed by the
+ host which generates it. This identifier is intended to be
+ machine readable and not necessarily meaningful to humans. A
+ message identifier pertains to exactly one instantiation of a
+ particular message; subsequent revisions to the message should
+
+
+ August 13, 1982 - 23 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ each receive new message identifiers.
+
+ 4.6.2. IN-REPLY-TO
+
+ The contents of this field identify previous correspon-
+ dence which this message answers. Note that if message iden-
+ tifiers are used in this field, they must use the msg-id
+ specification format.
+
+ 4.6.3. REFERENCES
+
+ The contents of this field identify other correspondence
+ which this message references. Note that if message identif-
+ iers are used, they must use the msg-id specification format.
+
+ 4.6.4. KEYWORDS
+
+ This field contains keywords or phrases, separated by
+ commas.
+
+ 4.7. OTHER FIELDS
+
+ 4.7.1. SUBJECT
+
+ This is intended to provide a summary, or indicate the
+ nature, of the message.
+
+ 4.7.2. COMMENTS
+
+ Permits adding text comments onto the message without
+ disturbing the contents of the message's body.
+
+ 4.7.3. ENCRYPTED
+
+ Sometimes, data encryption is used to increase the
+ privacy of message contents. If the body of a message has
+ been encrypted, to keep its contents private, the "Encrypted"
+ field can be used to note the fact and to indicate the nature
+ of the encryption. The first <word> parameter indicates the
+ software used to encrypt the body, and the second, optional
+ <word> is intended to aid the recipient in selecting the
+ proper decryption key. This code word may be viewed as an
+ index to a table of keys held by the recipient.
+
+ Note: Unfortunately, headers must contain envelope, as well
+ as contents, information. Consequently, it is neces-
+ sary that they remain unencrypted, so that mail tran-
+ sport services may access them. Since names,
+ addresses, and "Subject" field contents may contain
+
+
+ August 13, 1982 - 24 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ sensitive information, this requirement limits total
+ message privacy.
+
+ Names of encryption software are registered with the Net-
+ work Information Center, SRI International, Menlo Park, Cali-
+ fornia.
+
+ 4.7.4. EXTENSION-FIELD
+
+ A limited number of common fields have been defined in
+ this document. As network mail requirements dictate, addi-
+ tional fields may be standardized. To provide user-defined
+ fields with a measure of safety, in name selection, such
+ extension-fields will never have names that begin with the
+ string "X-".
+
+ Names of Extension-fields are registered with the Network
+ Information Center, SRI International, Menlo Park, California.
+
+ 4.7.5. USER-DEFINED-FIELD
+
+ Individual users of network mail are free to define and
+ use additional header fields. Such fields must have names
+ which are not already used in the current specification or in
+ any definitions of extension-fields, and the overall syntax of
+ these user-defined-fields must conform to this specification's
+ rules for delimiting and folding fields. Due to the
+ extension-field publishing process, the name of a user-
+ defined-field may be pre-empted
+
+ Note: The prefatory string "X-" will never be used in the
+ names of Extension-fields. This provides user-defined
+ fields with a protected set of names.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 25 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 5. DATE AND TIME SPECIFICATION
+
+ 5.1. SYNTAX
+
+ date-time = [ day "," ] date time ; dd mm yy
+ ; hh:mm:ss zzz
+
+ day = "Mon" / "Tue" / "Wed" / "Thu"
+ / "Fri" / "Sat" / "Sun"
+
+ date = 1*2DIGIT month 2DIGIT ; day month year
+ ; e.g. 20 Jun 82
+
+ month = "Jan" / "Feb" / "Mar" / "Apr"
+ / "May" / "Jun" / "Jul" / "Aug"
+ / "Sep" / "Oct" / "Nov" / "Dec"
+
+ time = hour zone ; ANSI and Military
+
+ hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
+ ; 00:00:00 - 23:59:59
+
+ zone = "UT" / "GMT" ; Universal Time
+ ; North American : UT
+ / "EST" / "EDT" ; Eastern: - 5/ - 4
+ / "CST" / "CDT" ; Central: - 6/ - 5
+ / "MST" / "MDT" ; Mountain: - 7/ - 6
+ / "PST" / "PDT" ; Pacific: - 8/ - 7
+ / 1ALPHA ; Military: Z = UT;
+ ; A:-1; (J not used)
+ ; M:-12; N:+1; Y:+12
+ / ( ("+" / "-") 4DIGIT ) ; Local differential
+ ; hours+min. (HHMM)
+
+ 5.2. SEMANTICS
+
+ If included, day-of-week must be the day implied by the date
+ specification.
+
+ Time zone may be indicated in several ways. "UT" is Univer-
+ sal Time (formerly called "Greenwich Mean Time"); "GMT" is per-
+ mitted as a reference to Universal Time. The military standard
+ uses a single character for each zone. "Z" is Universal Time.
+ "A" indicates one hour earlier, and "M" indicates 12 hours ear-
+ lier; "N" is one hour later, and "Y" is 12 hours later. The
+ letter "J" is not used. The other remaining two forms are taken
+ from ANSI standard X3.51-1975. One allows explicit indication of
+ the amount of offset from UT; the other uses common 3-character
+ strings for indicating time zones in North America.
+
+
+ August 13, 1982 - 26 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 6. ADDRESS SPECIFICATION
+
+ 6.1. SYNTAX
+
+ address = mailbox ; one addressee
+ / group ; named list
+
+ group = phrase ":" [#mailbox] ";"
+
+ mailbox = addr-spec ; simple address
+ / phrase route-addr ; name & addr-spec
+
+ route-addr = "<" [route] addr-spec ">"
+
+ route = 1#("@" domain) ":" ; path-relative
+
+ addr-spec = local-part "@" domain ; global address
+
+ local-part = word *("." word) ; uninterpreted
+ ; case-preserved
+
+ domain = sub-domain *("." sub-domain)
+
+ sub-domain = domain-ref / domain-literal
+
+ domain-ref = atom ; symbolic reference
+
+ 6.2. SEMANTICS
+
+ A mailbox receives mail. It is a conceptual entity which
+ does not necessarily pertain to file storage. For example, some
+ sites may choose to print mail on their line printer and deliver
+ the output to the addressee's desk.
+
+ A mailbox specification comprises a person, system or pro-
+ cess name reference, a domain-dependent string, and a name-domain
+ reference. The name reference is optional and is usually used to
+ indicate the human name of a recipient. The name-domain refer-
+ ence specifies a sequence of sub-domains. The domain-dependent
+ string is uninterpreted, except by the final sub-domain; the rest
+ of the mail service merely transmits it as a literal string.
+
+ 6.2.1. DOMAINS
+
+ A name-domain is a set of registered (mail) names. A name-
+ domain specification resolves to a subordinate name-domain
+ specification or to a terminal domain-dependent string.
+ Hence, domain specification is extensible, permitting any
+ number of registration levels.
+
+
+ August 13, 1982 - 27 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ Name-domains model a global, logical, hierarchical addressing
+ scheme. The model is logical, in that an address specifica-
+ tion is related to name registration and is not necessarily
+ tied to transmission path. The model's hierarchy is a
+ directed graph, called an in-tree, such that there is a single
+ path from the root of the tree to any node in the hierarchy.
+ If more than one path actually exists, they are considered to
+ be different addresses.
+
+ The root node is common to all addresses; consequently, it is
+ not referenced. Its children constitute "top-level" name-
+ domains. Usually, a service has access to its own full domain
+ specification and to the names of all top-level name-domains.
+
+ The "top" of the domain addressing hierarchy -- a child of the
+ root -- is indicated by the right-most field, in a domain
+ specification. Its child is specified to the left, its child
+ to the left, and so on.
+
+ Some groups provide formal registration services; these con-
+ stitute name-domains that are independent logically of
+ specific machines. In addition, networks and machines impli-
+ citly compose name-domains, since their membership usually is
+ registered in name tables.
+
+ In the case of formal registration, an organization implements
+ a (distributed) data base which provides an address-to-route
+ mapping service for addresses of the form:
+
+ person@registry.organization
+
+ Note that "organization" is a logical entity, separate from
+ any particular communication network.
+
+ A mechanism for accessing "organization" is universally avail-
+ able. That mechanism, in turn, seeks an instantiation of the
+ registry; its location is not indicated in the address specif-
+ ication. It is assumed that the system which operates under
+ the name "organization" knows how to find a subordinate regis-
+ try. The registry will then use the "person" string to deter-
+ mine where to send the mail specification.
+
+ The latter, network-oriented case permits simple, direct,
+ attachment-related address specification, such as:
+
+ user@host.network
+
+ Once the network is accessed, it is expected that a message
+ will go directly to the host and that the host will resolve
+
+
+ August 13, 1982 - 28 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ the user name, placing the message in the user's mailbox.
+
+ 6.2.2. ABBREVIATED DOMAIN SPECIFICATION
+
+ Since any number of levels is possible within the domain
+ hierarchy, specification of a fully qualified address can
+ become inconvenient. This standard permits abbreviated domain
+ specification, in a special case:
+
+ For the address of the sender, call the left-most
+ sub-domain Level N. In a header address, if all of
+ the sub-domains above (i.e., to the right of) Level N
+ are the same as those of the sender, then they do not
+ have to appear in the specification. Otherwise, the
+ address must be fully qualified.
+
+ This feature is subject to approval by local sub-
+ domains. Individual sub-domains may require their
+ member systems, which originate mail, to provide full
+ domain specification only. When permitted, abbrevia-
+ tions may be present only while the message stays
+ within the sub-domain of the sender.
+
+ Use of this mechanism requires the sender's sub-domain
+ to reserve the names of all top-level domains, so that
+ full specifications can be distinguished from abbrevi-
+ ated specifications.
+
+ For example, if a sender's address is:
+
+ sender@registry-A.registry-1.organization-X
+
+ and one recipient's address is:
+
+ recipient@registry-B.registry-1.organization-X
+
+ and another's is:
+
+ recipient@registry-C.registry-2.organization-X
+
+ then ".registry-1.organization-X" need not be specified in the
+ the message, but "registry-C.registry-2" DOES have to be
+ specified. That is, the first two addresses may be abbrevi-
+ ated, but the third address must be fully specified.
+
+ When a message crosses a domain boundary, all addresses must
+ be specified in the full format, ending with the top-level
+ name-domain in the right-most field. It is the responsibility
+ of mail forwarding services to ensure that addresses conform
+
+
+ August 13, 1982 - 29 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ with this requirement. In the case of abbreviated addresses,
+ the relaying service must make the necessary expansions. It
+ should be noted that it often is difficult for such a service
+ to locate all occurrences of address abbreviations. For exam-
+ ple, it will not be possible to find such abbreviations within
+ the body of the message. The "Return-Path" field can aid
+ recipients in recovering from these errors.
+
+ Note: When passing any portion of an addr-spec onto a process
+ which does not interpret data according to this stan-
+ dard (e.g., mail protocol servers). There must be NO
+ LWSP-chars preceding or following the at-sign or any
+ delimiting period ("."), such as shown in the above
+ examples, and only ONE SPACE between contiguous
+ <word>s.
+
+ 6.2.3. DOMAIN TERMS
+
+ A domain-ref must be THE official name of a registry, network,
+ or host. It is a symbolic reference, within a name sub-
+ domain. At times, it is necessary to bypass standard mechan-
+ isms for resolving such references, using more primitive
+ information, such as a network host address rather than its
+ associated host name.
+
+ To permit such references, this standard provides the domain-
+ literal construct. Its contents must conform with the needs
+ of the sub-domain in which it is interpreted.
+
+ Domain-literals which refer to domains within the ARPA Inter-
+ net specify 32-bit Internet addresses, in four 8-bit fields
+ noted in decimal, as described in Request for Comments #820,
+ "Assigned Numbers." For example:
+
+ [10.0.3.19]
+
+ Note: THE USE OF DOMAIN-LITERALS IS STRONGLY DISCOURAGED. It
+ is permitted only as a means of bypassing temporary
+ system limitations, such as name tables which are not
+ complete.
+
+ The names of "top-level" domains, and the names of domains
+ under in the ARPA Internet, are registered with the Network
+ Information Center, SRI International, Menlo Park, California.
+
+ 6.2.4. DOMAIN-DEPENDENT LOCAL STRING
+
+ The local-part of an addr-spec in a mailbox specification
+ (i.e., the host's name for the mailbox) is understood to be
+
+
+ August 13, 1982 - 30 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ whatever the receiving mail protocol server allows. For exam-
+ ple, some systems do not understand mailbox references of the
+ form "P. D. Q. Bach", but others do.
+
+ This specification treats periods (".") as lexical separators.
+ Hence, their presence in local-parts which are not quoted-
+ strings, is detected. However, such occurrences carry NO
+ semantics. That is, if a local-part has periods within it, an
+ address parser will divide the local-part into several tokens,
+ but the sequence of tokens will be treated as one uninter-
+ preted unit. The sequence will be re-assembled, when the
+ address is passed outside of the system such as to a mail pro-
+ tocol service.
+
+ For example, the address:
+
+ First.Last@Registry.Org
+
+ is legal and does not require the local-part to be surrounded
+ with quotation-marks. (However, "First Last" DOES require
+ quoting.) The local-part of the address, when passed outside
+ of the mail system, within the Registry.Org domain, is
+ "First.Last", again without quotation marks.
+
+ 6.2.5. BALANCING LOCAL-PART AND DOMAIN
+
+ In some cases, the boundary between local-part and domain can
+ be flexible. The local-part may be a simple string, which is
+ used for the final determination of the recipient's mailbox.
+ All other levels of reference are, therefore, part of the
+ domain.
+
+ For some systems, in the case of abbreviated reference to the
+ local and subordinate sub-domains, it may be possible to
+ specify only one reference within the domain part and place
+ the other, subordinate name-domain references within the
+ local-part. This would appear as:
+
+ mailbox.sub1.sub2@this-domain
+
+ Such a specification would be acceptable to address parsers
+ which conform to RFC #733, but do not support this newer
+ Internet standard. While contrary to the intent of this stan-
+ dard, the form is legal.
+
+ Also, some sub-domains have a specification syntax which does
+ not conform to this standard. For example:
+
+ sub-net.mailbox@sub-domain.domain
+
+
+ August 13, 1982 - 31 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ uses a different parsing sequence for local-part than for
+ domain.
+
+ Note: As a rule, the domain specification should contain
+ fields which are encoded according to the syntax of
+ this standard and which contain generally-standardized
+ information. The local-part specification should con-
+ tain only that portion of the address which deviates
+ from the form or intention of the domain field.
+
+ 6.2.6. MULTIPLE MAILBOXES
+
+ An individual may have several mailboxes and wish to receive
+ mail at whatever mailbox is convenient for the sender to
+ access. This standard does not provide a means of specifying
+ "any member of" a list of mailboxes.
+
+ A set of individuals may wish to receive mail as a single unit
+ (i.e., a distribution list). The <group> construct permits
+ specification of such a list. Recipient mailboxes are speci-
+ fied within the bracketed part (":" - ";"). A copy of the
+ transmitted message is to be sent to each mailbox listed.
+ This standard does not permit recursive specification of
+ groups within groups.
+
+ While a list must be named, it is not required that the con-
+ tents of the list be included. In this case, the <address>
+ serves only as an indication of group distribution and would
+ appear in the form:
+
+ name:;
+
+ Some mail services may provide a group-list distribution
+ facility, accepting a single mailbox reference, expanding it
+ to the full distribution list, and relaying the mail to the
+ list's members. This standard provides no additional syntax
+ for indicating such a service. Using the <group> address
+ alternative, while listing one mailbox in it, can mean either
+ that the mailbox reference will be expanded to a list or that
+ there is a group with one member.
+
+ 6.2.7. EXPLICIT PATH SPECIFICATION
+
+ At times, a message originator may wish to indicate the
+ transmission path that a message should follow. This is
+ called source routing. The normal addressing scheme, used in
+ an addr-spec, is carefully separated from such information;
+ the <route> portion of a route-addr is provided for such occa-
+ sions. It specifies the sequence of hosts and/or transmission
+
+
+ August 13, 1982 - 32 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ services that are to be traversed. Both domain-refs and
+ domain-literals may be used.
+
+ Note: The use of source routing is discouraged. Unless the
+ sender has special need of path restriction, the choice
+ of transmission route should be left to the mail tran-
+ sport service.
+
+ 6.3. RESERVED ADDRESS
+
+ It often is necessary to send mail to a site, without know-
+ ing any of its valid addresses. For example, there may be mail
+ system dysfunctions, or a user may wish to find out a person's
+ correct address, at that site.
+
+ This standard specifies a single, reserved mailbox address
+ (local-part) which is to be valid at each site. Mail sent to
+ that address is to be routed to a person responsible for the
+ site's mail system or to a person with responsibility for general
+ site operation. The name of the reserved local-part address is:
+
+ Postmaster
+
+ so that "Postmaster@domain" is required to be valid.
+
+ Note: This reserved local-part must be matched without sensi-
+ tivity to alphabetic case, so that "POSTMASTER", "postmas-
+ ter", and even "poStmASteR" is to be accepted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 33 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ 7. BIBLIOGRAPHY
+
+
+ ANSI. "USA Standard Code for Information Interchange," X3.4.
+ American National Standards Institute: New York (1968). Also
+ in: Feinler, E. and J. Postel, eds., "ARPANET Protocol Hand-
+ book", NIC 7104.
+
+ ANSI. "Representations of Universal Time, Local Time Differen-
+ tials, and United States Time Zone References for Information
+ Interchange," X3.51-1975. American National Standards Insti-
+ tute: New York (1975).
+
+ Bemer, R.W., "Time and the Computer." In: Interface Age (Feb.
+ 1979).
+
+ Bennett, C.J. "JNT Mail Protocol". Joint Network Team, Ruther-
+ ford and Appleton Laboratory: Didcot, England.
+
+ Bhushan, A.K., Pogran, K.T., Tomlinson, R.S., and White, J.E.
+ "Standardizing Network Mail Headers," ARPANET Request for
+ Comments No. 561, Network Information Center No. 18516; SRI
+ International: Menlo Park (September 1973).
+
+ Birrell, A.D., Levin, R., Needham, R.M., and Schroeder, M.D.
+ "Grapevine: An Exercise in Distributed Computing," Communica-
+ tions of the ACM 25, 4 (April 1982), 260-274.
+
+ Crocker, D.H., Vittal, J.J., Pogran, K.T., Henderson, D.A.
+ "Standard for the Format of ARPA Network Text Message,"
+ ARPANET Request for Comments No. 733, Network Information
+ Center No. 41952. SRI International: Menlo Park (November
+ 1977).
+
+ Feinler, E.J. and Postel, J.B. ARPANET Protocol Handbook, Net-
+ work Information Center No. 7104 (NTIS AD A003890). SRI
+ International: Menlo Park (April 1976).
+
+ Harary, F. "Graph Theory". Addison-Wesley: Reading, Mass.
+ (1969).
+
+ Levin, R. and Schroeder, M. "Transport of Electronic Messages
+ through a Network," TeleInformatics 79, pp. 29-33. North
+ Holland (1979). Also as Xerox Palo Alto Research Center
+ Technical Report CSL-79-4.
+
+ Myer, T.H. and Henderson, D.A. "Message Transmission Protocol,"
+ ARPANET Request for Comments, No. 680, Network Information
+ Center No. 32116. SRI International: Menlo Park (1975).
+
+
+ August 13, 1982 - 34 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ NBS. "Specification of Message Format for Computer Based Message
+ Systems, Recommended Federal Information Processing Standard."
+ National Bureau of Standards: Gaithersburg, Maryland
+ (October 1981).
+
+ NIC. Internet Protocol Transition Workbook. Network Information
+ Center, SRI-International, Menlo Park, California (March
+ 1982).
+
+ Oppen, D.C. and Dalal, Y.K. "The Clearinghouse: A Decentralized
+ Agent for Locating Named Objects in a Distributed Environ-
+ ment," OPD-T8103. Xerox Office Products Division: Palo Alto,
+ CA. (October 1981).
+
+ Postel, J.B. "Assigned Numbers," ARPANET Request for Comments,
+ No. 820. SRI International: Menlo Park (August 1982).
+
+ Postel, J.B. "Simple Mail Transfer Protocol," ARPANET Request
+ for Comments, No. 821. SRI International: Menlo Park (August
+ 1982).
+
+ Shoch, J.F. "Internetwork naming, addressing and routing," in
+ Proc. 17th IEEE Computer Society International Conference, pp.
+ 72-79, Sept. 1978, IEEE Cat. No. 78 CH 1388-8C.
+
+ Su, Z. and Postel, J. "The Domain Naming Convention for Internet
+ User Applications," ARPANET Request for Comments, No. 819.
+ SRI International: Menlo Park (August 1982).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 35 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ APPENDIX
+
+
+ A. EXAMPLES
+
+ A.1. ADDRESSES
+
+ A.1.1. Alfred Neuman <Neuman@BBN-TENEXA>
+
+ A.1.2. Neuman@BBN-TENEXA
+
+ These two "Alfred Neuman" examples have identical seman-
+ tics, as far as the operation of the local host's mail sending
+ (distribution) program (also sometimes called its "mailer")
+ and the remote host's mail protocol server are concerned. In
+ the first example, the "Alfred Neuman" is ignored by the
+ mailer, as "Neuman@BBN-TENEXA" completely specifies the reci-
+ pient. The second example contains no superfluous informa-
+ tion, and, again, "Neuman@BBN-TENEXA" is the intended reci-
+ pient.
+
+ Note: When the message crosses name-domain boundaries, then
+ these specifications must be changed, so as to indicate
+ the remainder of the hierarchy, starting with the top
+ level.
+
+ A.1.3. "George, Ted" <Shared@Group.Arpanet>
+
+ This form might be used to indicate that a single mailbox
+ is shared by several users. The quoted string is ignored by
+ the originating host's mailer, because "Shared@Group.Arpanet"
+ completely specifies the destination mailbox.
+
+ A.1.4. Wilt . (the Stilt) Chamberlain@NBA.US
+
+ The "(the Stilt)" is a comment, which is NOT included in
+ the destination mailbox address handed to the originating
+ system's mailer. The local-part of the address is the string
+ "Wilt.Chamberlain", with NO space between the first and second
+ words.
+
+ A.1.5. Address Lists
+
+ Gourmets: Pompous Person <WhoZiWhatZit@Cordon-Bleu>,
+ Childs@WGBH.Boston, Galloping Gourmet@
+ ANT.Down-Under (Australian National Television),
+ Cheapie@Discount-Liquors;,
+ Cruisers: Port@Portugal, Jones@SEA;,
+ Another@Somewhere.SomeOrg
+
+
+ August 13, 1982 - 36 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ This group list example points out the use of comments and the
+ mixing of addresses and groups.
+
+ A.2. ORIGINATOR ITEMS
+
+ A.2.1. Author-sent
+
+ George Jones logs into his host as "Jones". He sends
+ mail himself.
+
+ From: Jones@Group.Org
+
+ or
+
+ From: George Jones <Jones@Group.Org>
+
+ A.2.2. Secretary-sent
+
+ George Jones logs in as Jones on his host. His secre-
+ tary, who logs in as Secy sends mail for him. Replies to the
+ mail should go to George.
+
+ From: George Jones <Jones@Group>
+ Sender: Secy@Other-Group
+
+ A.2.3. Secretary-sent, for user of shared directory
+
+ George Jones' secretary sends mail for George. Replies
+ should go to George.
+
+ From: George Jones<Shared@Group.Org>
+ Sender: Secy@Other-Group
+
+ Note that there need not be a space between "Jones" and the
+ "<", but adding a space enhances readability (as is the case
+ in other examples.
+
+ A.2.4. Committee activity, with one author
+
+ George is a member of a committee. He wishes to have any
+ replies to his message go to all committee members.
+
+ From: George Jones <Jones@Host.Net>
+ Sender: Jones@Host
+ Reply-To: The Committee: Jones@Host.Net,
+ Smith@Other.Org,
+ Doe@Somewhere-Else;
+
+ Note that if George had not included himself in the
+
+
+ August 13, 1982 - 37 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ enumeration of The Committee, he would not have gotten an
+ implicit reply; the presence of the "Reply-to" field SUPER-
+ SEDES the sending of a reply to the person named in the "From"
+ field.
+
+ A.2.5. Secretary acting as full agent of author
+
+ George Jones asks his secretary (Secy@Host) to send a
+ message for him in his capacity as Group. He wants his secre-
+ tary to handle all replies.
+
+ From: George Jones <Group@Host>
+ Sender: Secy@Host
+ Reply-To: Secy@Host
+
+ A.2.6. Agent for user without online mailbox
+
+ A friend of George's, Sarah, is visiting. George's
+ secretary sends some mail to a friend of Sarah in computer-
+ land. Replies should go to George, whose mailbox is Jones at
+ Registry.
+
+ From: Sarah Friendly <Secy@Registry>
+ Sender: Secy-Name <Secy@Registry>
+ Reply-To: Jones@Registry.
+
+ A.2.7. Agent for member of a committee
+
+ George's secretary sends out a message which was authored
+ jointly by all the members of a committee. Note that the name
+ of the committee cannot be specified, since <group> names are
+ not permitted in the From field.
+
+ From: Jones@Host,
+ Smith@Other-Host,
+ Doe@Somewhere-Else
+ Sender: Secy@SHost
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 38 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ A.3. COMPLETE HEADERS
+
+ A.3.1. Minimum required
+
+ Date: 26 Aug 76 1429 EDT Date: 26 Aug 76 1429 EDT
+ From: Jones@Registry.Org or From: Jones@Registry.Org
+ Bcc: To: Smith@Registry.Org
+
+ Note that the "Bcc" field may be empty, while the "To" field
+ is required to have at least one address.
+
+ A.3.2. Using some of the additional fields
+
+ Date: 26 Aug 76 1430 EDT
+ From: George Jones<Group@Host>
+ Sender: Secy@SHOST
+ To: "Al Neuman"@Mad-Host,
+ Sam.Irving@Other-Host
+ Message-ID: <some.string@SHOST>
+
+ A.3.3. About as complex as you're going to get
+
+ Date : 27 Aug 76 0932 PDT
+ From : Ken Davis <KDavis@This-Host.This-net>
+ Subject : Re: The Syntax in the RFC
+ Sender : KSecy@Other-Host
+ Reply-To : Sam.Irving@Reg.Organization
+ To : George Jones <Group@Some-Reg.An-Org>,
+ Al.Neuman@MAD.Publisher
+ cc : Important folk:
+ Tom Softwood <Balsa@Tree.Root>,
+ "Sam Irving"@Other-Host;,
+ Standard Distribution:
+ /main/davis/people/standard@Other-Host,
+ "<Jones>standard.dist.3"@Tops-20-Host>;
+ Comment : Sam is away on business. He asked me to handle
+ his mail for him. He'll be able to provide a
+ more accurate explanation when he returns
+ next week.
+ In-Reply-To: <some.string@DBM.Group>, George's message
+ X-Special-action: This is a sample of user-defined field-
+ names. There could also be a field-name
+ "Special-action", but its name might later be
+ preempted
+ Message-ID: <4231.629.XYzi-What@Other-Host>
+
+
+
+
+
+
+ August 13, 1982 - 39 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ B. SIMPLE FIELD PARSING
+
+ Some mail-reading software systems may wish to perform only
+ minimal processing, ignoring the internal syntax of structured
+ field-bodies and treating them the same as unstructured-field-
+ bodies. Such software will need only to distinguish:
+
+ o Header fields from the message body,
+
+ o Beginnings of fields from lines which continue fields,
+
+ o Field-names from field-contents.
+
+ The abbreviated set of syntactic rules which follows will
+ suffice for this purpose. It describes a limited view of mes-
+ sages and is a subset of the syntactic rules provided in the main
+ part of this specification. One small exception is that the con-
+ tents of field-bodies consist only of text:
+
+ B.1. SYNTAX
+
+
+ message = *field *(CRLF *text)
+
+ field = field-name ":" [field-body] CRLF
+
+ field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":">
+
+ field-body = *text [CRLF LWSP-char field-body]
+
+
+ B.2. SEMANTICS
+
+ Headers occur before the message body and are terminated by
+ a null line (i.e., two contiguous CRLFs).
+
+ A line which continues a header field begins with a SPACE or
+ HTAB character, while a line beginning a field starts with a
+ printable character which is not a colon.
+
+ A field-name consists of one or more printable characters
+ (excluding colon, space, and control-characters). A field-name
+ MUST be contained on one line. Upper and lower case are not dis-
+ tinguished when comparing field-names.
+
+
+
+
+
+
+
+ August 13, 1982 - 40 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ C. DIFFERENCES FROM RFC #733
+
+ The following summarizes the differences between this stan-
+ dard and the one specified in Arpanet Request for Comments #733,
+ "Standard for the Format of ARPA Network Text Messages". The
+ differences are listed in the order of their occurrence in the
+ current specification.
+
+ C.1. FIELD DEFINITIONS
+
+ C.1.1. FIELD NAMES
+
+ These now must be a sequence of printable characters. They
+ may not contain any LWSP-chars.
+
+ C.2. LEXICAL TOKENS
+
+ C.2.1. SPECIALS
+
+ The characters period ("."), left-square bracket ("["), and
+ right-square bracket ("]") have been added. For presentation
+ purposes, and when passing a specification to a system that
+ does not conform to this standard, periods are to be contigu-
+ ous with their surrounding lexical tokens. No linear-white-
+ space is permitted between them. The presence of one LWSP-
+ char between other tokens is still directed.
+
+ C.2.2. ATOM
+
+ Atoms may not contain SPACE.
+
+ C.2.3. SPECIAL TEXT
+
+ ctext and qtext have had backslash ("\") added to the list of
+ prohibited characters.
+
+ C.2.4. DOMAINS
+
+ The lexical tokens <domain-literal> and <dtext> have been
+ added.
+
+ C.3. MESSAGE SPECIFICATION
+
+ C.3.1. TRACE
+
+ The "Return-path:" and "Received:" fields have been specified.
+
+
+
+
+
+ August 13, 1982 - 41 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ C.3.2. FROM
+
+ The "From" field must contain machine-usable addresses (addr-
+ spec). Multiple addresses may be specified, but named-lists
+ (groups) may not.
+
+ C.3.3. RESENT
+
+ The meta-construct of prefacing field names with the string
+ "Resent-" has been added, to indicate that a message has been
+ forwarded by an intermediate recipient.
+
+ C.3.4. DESTINATION
+
+ A message must contain at least one destination address field.
+ "To" and "CC" are required to contain at least one address.
+
+ C.3.5. IN-REPLY-TO
+
+ The field-body is no longer a comma-separated list, although a
+ sequence is still permitted.
+
+ C.3.6. REFERENCE
+
+ The field-body is no longer a comma-separated list, although a
+ sequence is still permitted.
+
+ C.3.7. ENCRYPTED
+
+ A field has been specified that permits senders to indicate
+ that the body of a message has been encrypted.
+
+ C.3.8. EXTENSION-FIELD
+
+ Extension fields are prohibited from beginning with the char-
+ acters "X-".
+
+ C.4. DATE AND TIME SPECIFICATION
+
+ C.4.1. SIMPLIFICATION
+
+ Fewer optional forms are permitted and the list of three-
+ letter time zones has been shortened.
+
+ C.5. ADDRESS SPECIFICATION
+
+
+
+
+
+
+ August 13, 1982 - 42 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ C.5.1. ADDRESS
+
+ The use of quoted-string, and the ":"-atom-":" construct, have
+ been removed. An address now is either a single mailbox
+ reference or is a named list of addresses. The latter indi-
+ cates a group distribution.
+
+ C.5.2. GROUPS
+
+ Group lists are now required to to have a name. Group lists
+ may not be nested.
+
+ C.5.3. MAILBOX
+
+ A mailbox specification may indicate a person's name, as
+ before. Such a named list no longer may specify multiple
+ mailboxes and may not be nested.
+
+ C.5.4. ROUTE ADDRESSING
+
+ Addresses now are taken to be absolute, global specifications,
+ independent of transmission paths. The <route> construct has
+ been provided, to permit explicit specification of transmis-
+ sion path. RFC #733's use of multiple at-signs ("@") was
+ intended as a general syntax for indicating routing and/or
+ hierarchical addressing. The current standard separates these
+ specifications and only one at-sign is permitted.
+
+ C.5.5. AT-SIGN
+
+ The string " at " no longer is used as an address delimiter.
+ Only at-sign ("@") serves the function.
+
+ C.5.6. DOMAINS
+
+ Hierarchical, logical name-domains have been added.
+
+ C.6. RESERVED ADDRESS
+
+ The local-part "Postmaster" has been reserved, so that users can
+ be guaranteed at least one valid address at a site.
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 43 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ D. ALPHABETICAL LISTING OF SYNTAX RULES
+
+ address = mailbox ; one addressee
+ / group ; named list
+ addr-spec = local-part "@" domain ; global address
+ ALPHA = <any ASCII alphabetic character>
+ ; (101-132, 65.- 90.)
+ ; (141-172, 97.-122.)
+ atom = 1*<any CHAR except specials, SPACE and CTLs>
+ authentic = "From" ":" mailbox ; Single author
+ / ( "Sender" ":" mailbox ; Actual submittor
+ "From" ":" 1#mailbox) ; Multiple authors
+ ; or not sender
+ CHAR = <any ASCII character> ; ( 0-177, 0.-127.)
+ comment = "(" *(ctext / quoted-pair / comment) ")"
+ CR = <ASCII CR, carriage return> ; ( 15, 13.)
+ CRLF = CR LF
+ ctext = <any CHAR excluding "(", ; => may be folded
+ ")", "\" & CR, & including
+ linear-white-space>
+ CTL = <any ASCII control ; ( 0- 37, 0.- 31.)
+ character and DEL> ; ( 177, 127.)
+ date = 1*2DIGIT month 2DIGIT ; day month year
+ ; e.g. 20 Jun 82
+ dates = orig-date ; Original
+ [ resent-date ] ; Forwarded
+ date-time = [ day "," ] date time ; dd mm yy
+ ; hh:mm:ss zzz
+ day = "Mon" / "Tue" / "Wed" / "Thu"
+ / "Fri" / "Sat" / "Sun"
+ delimiters = specials / linear-white-space / comment
+ destination = "To" ":" 1#address ; Primary
+ / "Resent-To" ":" 1#address
+ / "cc" ":" 1#address ; Secondary
+ / "Resent-cc" ":" 1#address
+ / "bcc" ":" #address ; Blind carbon
+ / "Resent-bcc" ":" #address
+ DIGIT = <any ASCII decimal digit> ; ( 60- 71, 48.- 57.)
+ domain = sub-domain *("." sub-domain)
+ domain-literal = "[" *(dtext / quoted-pair) "]"
+ domain-ref = atom ; symbolic reference
+ dtext = <any CHAR excluding "[", ; => may be folded
+ "]", "\" & CR, & including
+ linear-white-space>
+ extension-field =
+ <Any field which is defined in a document
+ published as a formal extension to this
+ specification; none will have names beginning
+ with the string "X-">
+
+
+ August 13, 1982 - 44 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ field = field-name ":" [ field-body ] CRLF
+ fields = dates ; Creation time,
+ source ; author id & one
+ 1*destination ; address required
+ *optional-field ; others optional
+ field-body = field-body-contents
+ [CRLF LWSP-char field-body]
+ field-body-contents =
+ <the ASCII characters making up the field-body, as
+ defined in the following sections, and consisting
+ of combinations of atom, quoted-string, and
+ specials tokens, or else consisting of texts>
+ field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":">
+ group = phrase ":" [#mailbox] ";"
+ hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
+ ; 00:00:00 - 23:59:59
+ HTAB = <ASCII HT, horizontal-tab> ; ( 11, 9.)
+ LF = <ASCII LF, linefeed> ; ( 12, 10.)
+ linear-white-space = 1*([CRLF] LWSP-char) ; semantics = SPACE
+ ; CRLF => folding
+ local-part = word *("." word) ; uninterpreted
+ ; case-preserved
+ LWSP-char = SPACE / HTAB ; semantics = SPACE
+ mailbox = addr-spec ; simple address
+ / phrase route-addr ; name & addr-spec
+ message = fields *( CRLF *text ) ; Everything after
+ ; first null line
+ ; is message body
+ month = "Jan" / "Feb" / "Mar" / "Apr"
+ / "May" / "Jun" / "Jul" / "Aug"
+ / "Sep" / "Oct" / "Nov" / "Dec"
+ msg-id = "<" addr-spec ">" ; Unique message id
+ optional-field =
+ / "Message-ID" ":" msg-id
+ / "Resent-Message-ID" ":" msg-id
+ / "In-Reply-To" ":" *(phrase / msg-id)
+ / "References" ":" *(phrase / msg-id)
+ / "Keywords" ":" #phrase
+ / "Subject" ":" *text
+ / "Comments" ":" *text
+ / "Encrypted" ":" 1#2word
+ / extension-field ; To be defined
+ / user-defined-field ; May be pre-empted
+ orig-date = "Date" ":" date-time
+ originator = authentic ; authenticated addr
+ [ "Reply-To" ":" 1#address] )
+ phrase = 1*word ; Sequence of words
+
+
+
+
+ August 13, 1982 - 45 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ qtext = <any CHAR excepting <">, ; => may be folded
+ "\" & CR, and including
+ linear-white-space>
+ quoted-pair = "\" CHAR ; may quote any char
+ quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
+ ; quoted chars.
+ received = "Received" ":" ; one per relay
+ ["from" domain] ; sending host
+ ["by" domain] ; receiving host
+ ["via" atom] ; physical path
+ *("with" atom) ; link/mail protocol
+ ["id" msg-id] ; receiver msg id
+ ["for" addr-spec] ; initial form
+ ";" date-time ; time received
+
+ resent = resent-authentic
+ [ "Resent-Reply-To" ":" 1#address] )
+ resent-authentic =
+ = "Resent-From" ":" mailbox
+ / ( "Resent-Sender" ":" mailbox
+ "Resent-From" ":" 1#mailbox )
+ resent-date = "Resent-Date" ":" date-time
+ return = "Return-path" ":" route-addr ; return address
+ route = 1#("@" domain) ":" ; path-relative
+ route-addr = "<" [route] addr-spec ">"
+ source = [ trace ] ; net traversals
+ originator ; original mail
+ [ resent ] ; forwarded
+ SPACE = <ASCII SP, space> ; ( 40, 32.)
+ specials = "(" / ")" / "<" / ">" / "@" ; Must be in quoted-
+ / "," / ";" / ":" / "\" / <"> ; string, to use
+ / "." / "[" / "]" ; within a word.
+ sub-domain = domain-ref / domain-literal
+ text = <any CHAR, including bare ; => atoms, specials,
+ CR & bare LF, but NOT ; comments and
+ including CRLF> ; quoted-strings are
+ ; NOT recognized.
+ time = hour zone ; ANSI and Military
+ trace = return ; path to sender
+ 1*received ; receipt tags
+ user-defined-field =
+ <Any field which has not been defined
+ in this specification or published as an
+ extension to this specification; names for
+ such fields must be unique and may be
+ pre-empted by published extensions>
+ word = atom / quoted-string
+
+
+
+
+ August 13, 1982 - 46 - RFC #822
+
+
+
+ Standard for ARPA Internet Text Messages
+
+
+ zone = "UT" / "GMT" ; Universal Time
+ ; North American : UT
+ / "EST" / "EDT" ; Eastern: - 5/ - 4
+ / "CST" / "CDT" ; Central: - 6/ - 5
+ / "MST" / "MDT" ; Mountain: - 7/ - 6
+ / "PST" / "PDT" ; Pacific: - 8/ - 7
+ / 1ALPHA ; Military: Z = UT;
+ <"> = <ASCII quote mark> ; ( 42, 34.)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ August 13, 1982 - 47 - RFC #822
+
diff --git a/usr.sbin/sendmail/makemap/Makefile.dist b/usr.sbin/sendmail/makemap/Makefile.dist
new file mode 100644
index 0000000..3e7817a
--- /dev/null
+++ b/usr.sbin/sendmail/makemap/Makefile.dist
@@ -0,0 +1,81 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.dist 8.2 (Berkeley) 11/27/93
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# location of sendmail source directory
+SRCDIR= ../src
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# The really old (V7) DBM library is no longer supported.
+#
+DBMDEF= -DNDBM -DNEWDB
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I${SRCDIR} -I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm
+
+# location of makemap binary (usually /usr/sbin or /usr/etc)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= makemap.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= bin
+BINGRP= bin
+BINMODE=555
+
+ALL= makemap makemap.0
+
+all: ${ALL}
+
+makemap: ${BEFORE} ${OBJS}
+ ${CC} -o makemap ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+makemap.0: makemap.8
+ nroff -h -mandoc makemap.8 > makemap.0
+
+install: install-makemap install-docs
+
+install-makemap: makemap
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} makemap ${BINDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: makemap.0
+
+clean:
+ rm -f ${OBJS} makemap makemap.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: ${SRCDIR}/conf.h
diff --git a/usr.sbin/sendmail/praliases/Makefile.dist b/usr.sbin/sendmail/praliases/Makefile.dist
new file mode 100644
index 0000000..a7b07f4
--- /dev/null
+++ b/usr.sbin/sendmail/praliases/Makefile.dist
@@ -0,0 +1,81 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.dist 8.1 (Berkeley) 11/27/93
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# location of sendmail source directory
+SRCDIR= ../src
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# The really old (V7) DBM library is no longer supported.
+#
+DBMDEF= -DNDBM -DNEWDB
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I${SRCDIR} -I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm
+
+# location of praliases binary (usually /usr/sbin or /usr/etc)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= praliases.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= bin
+BINGRP= bin
+BINMODE=555
+
+ALL= praliases praliases.0
+
+all: ${ALL}
+
+praliases: ${BEFORE} ${OBJS}
+ ${CC} -o praliases ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+praliases.0: praliases.8
+ nroff -h -mandoc praliases.8 > praliases.0
+
+install: install-praliases install-docs
+
+install-praliases: praliases
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} praliases ${BINDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: praliases.0
+
+clean:
+ rm -f ${OBJS} praliases praliases.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: ${SRCDIR}/conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.386BSD b/usr.sbin/sendmail/src/Makefile.386BSD
new file mode 100644
index 0000000..63d94aa
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.386BSD
@@ -0,0 +1,42 @@
+# @(#)Makefile.386BSD 8.1 (Berkeley) 2/26/94
+
+PROG= sendmail
+
+# define the database format to use for aliases et al. Can be -DNEWDB (for
+# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
+# database package. The old putrescent V7 DBM package is no longer
+# supported.
+# You can define both NEWDB and NDBM during a transition period; old
+# databases are read, but the new format will be used on any rebuilds. On
+# really gnarly systems, you can set this to null; it will crawl like a high
+# spiral snail, but it will work.
+DBMDEF= -DNEWDB
+
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DMIME
+
+SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+ mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+ stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+ util.c version.c
+DPADD=
+LDADD= $(LIBUTIL)
+MAN1= newaliases.0 mailq.0
+MAN5= aliases.0
+MAN8= sendmail.0
+LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
+ /usr/sbin/sendmail /usr/bin/mailq
+BINDIR= /usr/sbin
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+beforeinstall:
+# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+# ${DESTDIR}/etc/sendmail.fc
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${DESTDIR}/var/log/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+ ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.AIX b/usr.sbin/sendmail/src/Makefile.AIX
new file mode 100644
index 0000000..5d3041d
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.AIX
@@ -0,0 +1,113 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on AIX 3.1.5 and 3.2.3e.
+#
+# @(#)Makefile.AIX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+# you can use -O3 on AIX 3.2.4 or greater ONLY!
+O= -g
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB -DNIS
+#
+# If you did not install the NEWDB on your AIX platform, use:
+#DBMDEF=-DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -D_AIX3
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldbm -ldb
+#
+# If you did not install the NEWDB on your AIX platform, use:
+#LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+INSTALL=/usr/ucb/install
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/sbin/newaliases ${DESTDIR}/usr/sbin/mailq
+BINOWN= root
+BINGRP= system
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.AUX b/usr.sbin/sendmail/src/Makefile.AUX
new file mode 100644
index 0000000..dc84b21
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.AUX
@@ -0,0 +1,105 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.AUX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldbm -lposix
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.BSD43 b/usr.sbin/sendmail/src/Makefile.BSD43
new file mode 100644
index 0000000..4177c3b
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.BSD43
@@ -0,0 +1,123 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This is based on work from Jim Oldroyd -- I believe he was
+# using a fairly old Mt Xinu port.
+#
+# It should also work on UMIPS-BSD from MIPS, if you still have
+# any lying around.
+#
+# @(#)Makefile.BSD43 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DoldBSD43
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldbm -lresolv -ll
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE= unistd.h stddef.h stdlib.h dirent.h sys/time.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+unistd.h stddef.h stdlib.h sys/time.h:
+ cp /dev/null $@
+
+sys/time.h: sys
+
+sys:
+ mkdir sys
+
+dirent.h:
+ echo "#include <sys/dir.h>" > dirent.h
+ echo "#define dirent direct" >> dirent.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.BSDI b/usr.sbin/sendmail/src/Makefile.BSDI
new file mode 100644
index 0000000..898de3e
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.BSDI
@@ -0,0 +1,32 @@
+# @(#)Makefile.BSDI 8.1 (Berkeley) 2/26/94
+
+PROG= sendmail
+DBMDEF= -DNEWDB
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO
+
+SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+ mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+ stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+ util.c version.c
+DPADD= ${LIBUTIL} ${LIBKVM}
+LDADD= -lutil -lkvm
+MAN1= mailq.0 newaliases.0
+MAN5= aliases.0
+MAN8= sendmail.0
+LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
+ /usr/sbin/sendmail /usr/bin/mailq
+BINDIR= /usr/sbin
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+beforeinstall:
+# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+# ${DESTDIR}/etc/sendmail.fc
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${DESTDIR}/var/log/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+ ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.CLIX b/usr.sbin/sendmail/src/Makefile.CLIX
new file mode 100644
index 0000000..7e54e36
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.CLIX
@@ -0,0 +1,115 @@
+#
+# This makefile is for clipper-based Intergraph systems running CLIX.
+# It and the defines supporting it in the source tree should be considered
+# alpha-quality and used at own risk.
+#
+# Porting done for CICNet, Inc., on behalf the Michigan State Department
+# of Natural Resources.
+#
+# --Paul Southworth <pauls@cic.net>
+#
+# @(#)Makefile.CLIX 8.1 (Berkeley) 4/12/94
+#
+
+# make sure the shell constructs below use the right shell
+SHELL= /bin/sh
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+CC= gcc
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DCLIX
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS= -I/usr/include
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -lnsl -lbsd
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD= getusershell.o
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq
+BINOWN= root
+BINGRP= mail
+BINMODE=6555
+INSTALL=cp
+
+ALL= sendmail # aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail #install-docs
+
+install-sendmail: sendmail
+ #${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ ${INSTALL} sendmail ${BINDIR}
+ chmod ${BINMODE} ${BINDIR}/sendmail
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ #${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ # ${STDIR}/sendmail.st
+ ${INSTALL} /dev/null ${STDIR}/sendmail.st
+ #${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+ ${INSTALL} sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail #aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.ConvexOS b/usr.sbin/sendmail/src/Makefile.ConvexOS
new file mode 100644
index 0000000..7bf7450
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.ConvexOS
@@ -0,0 +1,105 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on CxOS 11.0 beta 1 and 10.x.
+#
+# @(#)Makefile.ConvexOS 8.3 (Berkeley) 4/11/94
+#
+
+
+# use O=-O (usual) or O=-g (debugging)
+O= -g -tm c1 -D__STDC__ -d non_int_bit_field
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DYPCOMPAT -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS=
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.DGUX b/usr.sbin/sendmail/src/Makefile.DGUX
new file mode 100644
index 0000000..d7f63af
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.DGUX
@@ -0,0 +1,101 @@
+#
+# Tested on DG/UX 5.4.2 by A. Bryan Curnutt <bryan@Stoner.COM>.
+#
+# @(#)Makefile.DGUX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=-DDGUX
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/bin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/etc
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= bin
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Dell b/usr.sbin/sendmail/src/Makefile.Dell
new file mode 100644
index 0000000..39bc1e8
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Dell
@@ -0,0 +1,113 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# Based on a Makefile for Dell SVR4 Issue 2.2 from Kimmo Suominen
+# <kim@grendel.lut.fi> -- I haven't tested this myself. It may
+# work on other SVR4 ports.
+#
+# @(#)Makefile.Dell 8.3 (Berkeley) 4/11/94
+#
+
+# make sure the shell constructs below use the right shell
+SHELL= /bin/sh
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O2
+
+CC= gcc
+#DESTDIR=/usr/local/sendmail
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNEWDB -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -D__svr4__
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -ldb -ldbm -lresolv -lsocket -lnsl -lelf
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/ucblib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/ucblib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/ucblib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= mail
+BINMODE=6555
+INSTALL=/usr/ucb/install
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.DomainOS b/usr.sbin/sendmail/src/Makefile.DomainOS
new file mode 100644
index 0000000..5564ecb
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.DomainOS
@@ -0,0 +1,123 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on DomainOS 10.3.5
+#
+# @(#)Makefile.DomainOS 8.5 (Berkeley) 4/12/94
+#
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
+# -DNIS -- include client NIS support
+# The really old (V7) DBM library is no longer supported.
+# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
+# both the NEWDB and DBM libraries (the DBM just for YP).
+#
+
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+# You might want to use the BIND 4.9 resolver library here
+#LIBS= -ldb -ldbm
+LIBS= -ldbm -lresolv
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE= unistd.h dirent.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. -A nansi $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+unistd.h:
+ cp /dev/null unistd.h
+
+dirent.h:
+ echo "#include <sys/dir.h>" > dirent.h
+ echo "#define dirent direct" >> dirent.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Dynix b/usr.sbin/sendmail/src/Makefile.Dynix
new file mode 100644
index 0000000..344a9b7
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Dynix
@@ -0,0 +1,113 @@
+#
+# Tested on Dynix 3.2.0.
+#
+# From Jim Davis <jdavis@cs.arizona.edu>.
+#
+# ``There is no strtol in libc (well there is in the 'att universe'
+# libc, but I couldn't figure out how to link that in), so I
+# got the Chris Torek strtol.c from bsd-sources on uunet and
+# compiled that. There is no native ndbm either; I couldn't
+# get db 1.72 to pass it's regression test, so I used gdbm-1.7
+# instead. I compiled it with gcc 1.40a. The -lseq is to pick
+# up getopt.''
+#
+# @(#)Makefile.Dynix 8.3 (Berkeley) 4/11/94
+#
+
+CC= gcc
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O -g
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -lseq -lgdbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=strtol.o
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= staff # no kmem group,
+BINMODE=4555 # so not setgid
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.FreeBSD b/usr.sbin/sendmail/src/Makefile.FreeBSD
new file mode 100644
index 0000000..e86ff59
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.FreeBSD
@@ -0,0 +1,50 @@
+#
+# Makefile for FreeBSD
+#
+# @(#)Makefile.FreeBSD 8.1 (Berkeley) 2/26/94
+
+PROG= sendmail
+
+# define the database format to use for aliases et al. Can be -DNEWDB (for
+# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
+# database package. The old putrescent V7 DBM package is no longer
+# supported.
+# You can define both NEWDB and NDBM during a transition period; old
+# databases are read, but the new format will be used on any rebuilds. On
+# really gnarly systems, you can set this to null; it will crawl like a high
+# spiral snail, but it will work.
+DBMDEF= -DNEWDB
+
+# FreeBSD 1.0 RELEASE has uname(2) now. Use -DUSEUNAME in order to use it.
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DMIME -DUSEUNAME
+
+SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+ mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+ stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+ util.c version.c
+DPADD=
+LDADD= $(LIBUTIL)
+#
+# FreeBSD 1.0 RELEASE has GNU man and doesn't need preformatted man pages anymore
+# (assuming you consider a slower "man" command a feature)
+#
+MAN1= mailq.1 newaliases.1
+MAN5= aliases.5
+MAN8= sendmail.8
+LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
+ /usr/sbin/sendmail /usr/bin/mailq
+BINDIR= /usr/sbin
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+beforeinstall:
+# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+# ${DESTDIR}/etc/sendmail.fc
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${DESTDIR}/var/log/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+ ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.HP-UX b/usr.sbin/sendmail/src/Makefile.HP-UX
new file mode 100644
index 0000000..cebc499
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.HP-UX
@@ -0,0 +1,105 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on HP-UX 8.07 on 7xx series.
+#
+# @(#)Makefile.HP-UX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+# +O is OK on 7xx, and 300xx at 9.0
+O= +O1
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq
+BINOWN= root
+BINGRP= mail
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ cpset sendmail ${BINDIR} ${BINMODE} ${BINOWN} ${BINGRP}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ cpset /dev/null ${STDIR}/sendmail.st 644 ${BINOWN} ${BINGRP}
+ cpset sendmail.hf ${HFDIR} 444 ${BINOWN} ${BINGRP}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.IRIX b/usr.sbin/sendmail/src/Makefile.IRIX
new file mode 100644
index 0000000..30e8f1c
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.IRIX
@@ -0,0 +1,109 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on IRIX 4.0.4.
+#
+# @(#)Makefile.IRIX 8.4 (Berkeley) 4/11/94
+#
+SHELL= /bin/sh
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+CC=gcc
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB (requires -ldb)
+# -DNIS -- include NIS support (requires -lsun)
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DIRIX
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -lmld
+#LIBS= -lsun -ldb -lmld
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/bsd/newaliases ${DESTDIR}/usr/bsd/mailq
+BINOWN= root
+BINGRP= sys
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -u ${BINOWN} -g ${BINGRP} -m ${BINMODE} -f ${BINDIR} sendmail
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ cp /dev/null ${STDIR}/sendmail.st
+ chmod 644 ${STDIR}/sendmail.st
+ chown ${BINOWN} ${STDIR}/sendmail.st
+ chgrp ${BINGRP} ${STDIR}/sendmail.st
+ install -u ${BINOWN} -g ${BINGRP} -m 444 -f ${HFDIR} sendmail.hf
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Linux b/usr.sbin/sendmail/src/Makefile.Linux
new file mode 100644
index 0000000..3c8f3e5
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Linux
@@ -0,0 +1,120 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on Linux 0.99p10.
+#
+# Linux doesn't really have standard places to install things, so this
+# Makefile is likely to require a lot of customization. Read it over
+# carefully before proceeding.
+#
+# @(#)Makefile.Linux 8.7 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/local/include
+
+# library directories
+LIBDIRS=-L/usr/local/lib
+
+# libraries required on your system
+LIBS= -lndbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+unistd.h:
+ cp /dev/null unistd.h
+
+dirent.h:
+ echo "#include <sys/dir.h>" > dirent.h
+ echo "#define dirent direct" >> dirent.h
+
+NROFF= nroff
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ cp /dev/null ${STDIR}/sendmail.st
+ chmod 644 ${STDIR}/sendmail.st
+ chown ${BINOWN} ${STDIR}/sendmail.st
+ chgrp ${BINGRP} ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Mach386 b/usr.sbin/sendmail/src/Makefile.Mach386
new file mode 100644
index 0000000..eaed6ca
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Mach386
@@ -0,0 +1,107 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.Mach386 8.3 (Berkeley) 4/11/94
+#
+
+CC= gcc
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.NCR3000 b/usr.sbin/sendmail/src/Makefile.NCR3000
new file mode 100644
index 0000000..a556951
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.NCR3000
@@ -0,0 +1,109 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# NCR 3000 support from Kevin Darcy <kevin@tech.mis.cfc.com>.
+#
+# @(#)Makefile.NCR3000 8.2 (Berkeley) 4/16/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DNCR3000
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/ucbinclude
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/ucblib
+
+# libraries required on your system
+LIBS= -lsocket -lc -lelf -lucb -ldbm -lnet -lnsl
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/ucblib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/ucblib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/ucblib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+INSTALL=install
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.NeXT b/usr.sbin/sendmail/src/Makefile.NeXT
new file mode 100644
index 0000000..de0dc7f
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.NeXT
@@ -0,0 +1,114 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on NeXT 2.1.
+#
+# @(#)Makefile.NeXT 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DNeXT -DNETINFO
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# library directories
+LIBDIRS=-L/usr/local/lib
+
+# libraries required on your system
+LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc/sendmail
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE= unistd.h dirent.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+unistd.h:
+ cp /dev/null unistd.h
+
+dirent.h:
+ echo "#include <sys/dir.h>" > dirent.h
+ echo "#define dirent direct" >> dirent.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.NetBSD b/usr.sbin/sendmail/src/Makefile.NetBSD
new file mode 100644
index 0000000..ebeacd0
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.NetBSD
@@ -0,0 +1,46 @@
+#
+# NetBSD Makefile
+#
+# @(#)Makefile.NetBSD 8.1 (Berkeley) 2/26/94
+# @Id: Makefile.NetBSD,v 1.3 1994/02/01 05:33:44 glass Exp $
+#
+
+PROG= sendmail
+
+# define the database format to use for aliases et al. Can be -DNEWDB (for
+# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
+# database package. The old putrescent V7 DBM package is no longer
+# supported.
+# You can define both NEWDB and NDBM during a transition period; old
+# databases are read, but the new format will be used on any rebuilds. On
+# really gnarly systems, you can set this to null; it will crawl like a high
+# spiral snail, but it will work.
+DBMDEF= -DNEWDB -DNIS
+
+#nasty warning about gcc 2.4.x caused bugs
+CFLAGS=-I${.CURDIR} ${DBMDEF} -DNETISO
+#CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO
+
+SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+ mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+ stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+ util.c version.c
+MAN1= mailq.0 newaliases.0
+MAN5= aliases.0
+MAN8= sendmail.0
+LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
+ /usr/sbin/sendmail /usr/bin/mailq
+BINDIR= /usr/sbin
+BINOWN= root
+BINMODE=4555
+
+beforeinstall:
+# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+# ${DESTDIR}/etc/sendmail.fc
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${DESTDIR}/var/log/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+ ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.OSF1 b/usr.sbin/sendmail/src/Makefile.OSF1
new file mode 100644
index 0000000..c79b2bb
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.OSF1
@@ -0,0 +1,109 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on OSF/1 1.3
+#
+# @(#)Makefile.OSF1 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -Olimit 1000
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib -L/usr/shlib -L/usr/lib
+
+# libraries required on your system
+LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/adm/sendmail
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional link flags
+#LDADD= -non_shared
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${BINDIR}/newaliases ${BINDIR}/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDADD} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ installbsd -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ cp /dev/null ${STDIR}/sendmail.st
+ chmod 644 ${STDIR}/sendmail.st
+ chown ${BINOWN}.${BINGRP} ${STDIR}/sendmail.st
+ installbsd -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+ rm -f /usr/sbin/smtpd
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.PTX b/usr.sbin/sendmail/src/Makefile.PTX
new file mode 100644
index 0000000..f27238b
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.PTX
@@ -0,0 +1,114 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# For Sequent DYNIX/ptx.
+#
+# From Tim "Pinball Wizard" Wright <timw@sequent.com>.
+#
+# @(#)Makefile.PTX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -g
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+LIBDIRS=
+
+# libraries required on your system
+#LIBS= -ldb -ldbm
+LIBS= -lsocket -linet -lnsl -lseq
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq
+BINOWN= root
+BINGRP= sys
+BINMODE=6555
+
+ALL= sendmail aliases.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: $& ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+INSTALL=install
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.RISCos b/usr.sbin/sendmail/src/Makefile.RISCos
new file mode 100644
index 0000000..b4c4b36
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.RISCos
@@ -0,0 +1,117 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# For Mips RISC/os 4.52.
+#
+# @(#)Makefile.RISCos 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# be sure we are compiling in BSD mode
+CC= cc -systype bsd43
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DRISCOS -Olimit 800
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -lmld
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE= stdlib.h dirent.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+stdlib.h:
+ cp /dev/null $@
+
+dirent.h:
+ echo "#include <sys/dir.h>" > dirent.h
+ echo "#define dirent direct" >> dirent.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SCO b/usr.sbin/sendmail/src/Makefile.SCO
new file mode 100644
index 0000000..f1e7316
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.SCO
@@ -0,0 +1,104 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on SCO.
+#
+# @(#)Makefile.SCO 8.4 (Berkeley) 4/12/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF=
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -D_SCO_unix_
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -lsocket
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SVR4 b/usr.sbin/sendmail/src/Makefile.SVR4
new file mode 100644
index 0000000..92de6dd
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.SVR4
@@ -0,0 +1,113 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# Based on a Makefile for Dell SVR4 Issue 2.2 from Kimmo Suominen
+# <kim@grendel.lut.fi> -- I haven't tested this myself. It may
+# work on other SVR4 ports.
+#
+# @(#)Makefile.SVR4 8.3 (Berkeley) 4/11/94
+#
+
+# make sure the shell constructs below use the right shell
+SHELL= /bin/sh
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+CC= gcc
+#DESTDIR=/usr/local/sendmail
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNEWDB -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -D__svr4__
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -ldb -ldbm -lresolv -lsocket -lnsl -lelf
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/ucblib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/usr/ucblib
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/ucblib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= mail
+BINMODE=6555
+INSTALL=/usr/ucb/install
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Solaris b/usr.sbin/sendmail/src/Makefile.Solaris
new file mode 100644
index 0000000..cf359e6
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Solaris
@@ -0,0 +1,115 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on Solaris 2.1 and 2.2.
+#
+# @(#)Makefile.Solaris 8.5 (Berkeley) 4/12/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+# warning: do not use -O with gcc
+O=
+
+CC= gcc
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+# include -DSOLARIS_2_3 for version 2.3 and higher
+ENVDEF= -DSOLARIS
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -lresolv -lsocket -lnsl -lelf
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/etc/mail
+
+# additional .o files needed
+OBJADD=
+
+# things to be made before compilation begins
+BEFORE= sysexits.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= sys
+BINMODE=6555
+INSTALL=/usr/ucb/install
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+sysexits.h: /usr/ucbinclude/sysexits.h
+ ln -s /usr/ucbinclude/sysexits.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SunOS b/usr.sbin/sendmail/src/Makefile.SunOS
new file mode 100644
index 0000000..ee3025f
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.SunOS
@@ -0,0 +1,111 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on SunOS 4.1.[12].
+# For SunOS 4.0.3, add -DSUNOS403 to the ENVDEF macro, and
+# create empty files stdlib.h and stddef.h in your
+# compile directory.
+#
+# @(#)Makefile.SunOS 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+# need to add -DSUNOS403 if you are on a SunOS 4.0.3 system
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS= -Bstatic
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm -lresolv
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3 b/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3
new file mode 100644
index 0000000..126ac64
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3
@@ -0,0 +1,113 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# You may find you need to find versions of some routines
+# such as strcasecmp in order to link this on SunOS 4.0.3.
+#
+# @(#)Makefile.SunOS.4.0.3 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DSUNOS403
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS= -Bstatic
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm -lresolv
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/etc
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+BEFORE= stdlib.h stddef.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+stddef.h stdlib.h:
+ cp /dev/null $@
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.5.x b/usr.sbin/sendmail/src/Makefile.SunOS.5.x
new file mode 100644
index 0000000..d40f9dd
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.SunOS.5.x
@@ -0,0 +1,115 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on Solaris 2.3.
+#
+# @(#)Makefile.SunOS.5.x 8.5 (Berkeley) 4/12/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+# warning: do not use -O with gcc
+O=
+
+CC= gcc
+
+# define the database mechanism used for alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+# include -DSOLARIS_2_3 for version 2.3 and higher
+ENVDEF= -DSOLARIS_2_3
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -lresolv -lsocket -lnsl -lelf
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/etc/mail
+
+# additional .o files needed
+OBJADD=
+
+# things to be made before compilation begins
+BEFORE= sysexits.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= sys
+BINMODE=6555
+INSTALL=/usr/ucb/install
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+sysexits.h: /usr/ucbinclude/sysexits.h
+ ln -s /usr/ucbinclude/sysexits.h
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Titan b/usr.sbin/sendmail/src/Makefile.Titan
new file mode 100644
index 0000000..89b156a
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Titan
@@ -0,0 +1,114 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.Titan 8.3 (Berkeley) 4/11/94
+#
+
+# put the compiler in BSD mode
+CC= cc -43
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+# additional .o files needed
+OBJADD=
+
+# additional pseudo-sources needed
+BEFORE= stddef.h stdlib.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+stddef.h stdlib.h:
+ cp /dev/null $@
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.ULTRIX b/usr.sbin/sendmail/src/Makefile.ULTRIX
new file mode 100644
index 0000000..a3f222e
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.ULTRIX
@@ -0,0 +1,107 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on Ultrix 4.2A and 4.3A.
+#
+# @(#)Makefile.ULTRIX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -Olimit 800
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.UMAX b/usr.sbin/sendmail/src/Makefile.UMAX
new file mode 100644
index 0000000..c69e2b6
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.UMAX
@@ -0,0 +1,114 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# This has been tested on Encore UMAX V
+#
+# @(#)Makefile.UMAX 8.3 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNIS
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF= -DUMAXV
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=
+
+# libraries required on your system
+LIBS= -lyp -lrpc
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/lib
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+# additional .o files needed
+OBJADD=
+
+# things to do before compilation
+BEFORE= stddef.h
+
+stddef.h:
+ echo "#define _STDDEF_H" > stddef.h
+ chmod 444 stddef.h
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Utah b/usr.sbin/sendmail/src/Makefile.Utah
new file mode 100644
index 0000000..84ee571
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.Utah
@@ -0,0 +1,40 @@
+# @(#)Makefile.Utah 8.1 (Berkeley) 2/26/94
+
+PROG= sendmail
+
+# define the database format to use for aliases et al. Can be -DNEWDB (for
+# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
+# database package. The old putrescent V7 DBM package is no longer
+# supported.
+# You can define both NEWDB and NDBM during a transition period; old
+# databases are read, but the new format will be used on any rebuilds. On
+# really gnarly systems, you can set this to null; it will crawl like a high
+# spiral snail, but it will work.
+DBMDEF= -DNEWDB -DNDBM -DOLD_NEWDB
+
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -Dsetpgid=setpgrp
+
+SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+ mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+ stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+ util.c version.c
+DPADD= ${LIBDBM} ${LIBCOMPAT}
+LDADD=
+MAN1= mailq.0 newaliases.0
+MAN5= aliases.0
+MAN8= sendmail.0
+LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
+ ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
+BINDIR= /usr/sbin
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+beforeinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${DESTDIR}/var/log/sendmail.st
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+ ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.dist b/usr.sbin/sendmail/src/Makefile.dist
new file mode 100644
index 0000000..5fab596
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile.dist
@@ -0,0 +1,107 @@
+#
+# This Makefile is designed to work on the old "make" program. It does
+# not use the obj subdirectory. It also does not install documentation
+# automatically -- think of it as a quick start for sites that have the
+# old make program (I recommend that you get and port the new make if you
+# are going to be doing any signficant work on sendmail).
+#
+# @(#)Makefile.dist 8.12 (Berkeley) 4/11/94
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O= -O
+
+# define the database mechanisms available for map & alias lookups:
+# -DNDBM -- use new DBM
+# -DNEWDB -- use new Berkeley DB
+# -DNIS -- include NIS support
+# The really old (V7) DBM library is no longer supported.
+# See READ_ME for a description of how these flags interact.
+#
+DBMDEF= -DNDBM -DNEWDB
+
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# loader options
+LDOPTS=
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS= -ldb -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR= ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+# additional .o files needed
+OBJADD=
+
+################### end of user configuration flags ######################
+
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
+
+OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+ deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+ map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+ savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN= root
+BINGRP= kmem
+BINMODE=6555
+
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
+
+NROFF= nroff -h
+
+aliases.0: aliases.5
+ ${NROFF} -mandoc aliases.5 > aliases.0
+
+mailq.0: mailq.1
+ ${NROFF} -mandoc mailq.1 > mailq.0
+
+newaliases.0: newaliases.1
+ ${NROFF} -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+ ${NROFF} -mandoc sendmail.8 > sendmail.0
+
+INSTALL=install
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+ ${STDIR}/sendmail.st
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
+
+clean:
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+# dependencies
+# gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/TODO b/usr.sbin/sendmail/src/TODO
new file mode 100644
index 0000000..80d35d0
--- /dev/null
+++ b/usr.sbin/sendmail/src/TODO
@@ -0,0 +1,287 @@
+(Version 8.22 of 3/12/94)
+
+Key:
+ X -- extension (user visible change)
+ B -- bug fix
+ S -- security fix
+ E -- enhancement to existing algorithm
+
+
+X **** 8 -> 7 bit MIME conversion.
+
+E **** Change NoReturn to be an envelope flag. [8.7]
+
+X **** Add M_NOLOOPBACKCHK (k) mailer flag to turn off check of name in
+ HELO command. [8.8]
+
+X **** Merge Sun changes. [8.7]
+
+X **** Macro giving size of the message in bytes.
+
+X **** Create a "service switch" abstraction that will interface with
+ Sun NSS, Ultrix /etc/svc.conf, etc. This will allow you to
+ turn off DNS entirely, a la ``OIoff''. [8.7]
+
+X **** Should have new mailer flags to override LocalMailer stuff:
+ - M_ALIASABLE (A) -- can use as the LHS of an alias.
+ - M_HASPWENT (w) -- should have a /etc/passwd entry. If not found
+ there, implies user unknown. Also implies .forward and UDB
+ searching, search for |, /, and :include:, etc.).
+ - Actually, UDB searching and |, /, and :include: mapping should
+ probably be on another flag. (Cannot be 'l' for back compat
+ reasons.)
+ - Need for $@host part of triple and Return-Receipt-To: processing
+ should also be split apart.
+ [8.8]
+
+X **** Mailer flag to enable/disable surrounding route-addrs with
+ angle brackets in setsender(). UUCP cleanup scripts treat
+ these as file redirection.
+
+X **** Mailer flag to override MX lookups.
+
+E **** Fix parseaddr to return a dummy mailer with QBADADDR set for
+ all cases except null input; change calls to be more sceptical
+ about the return value, checking this bit instead of just
+ checking for == NULL. (Eric Wassenaar) [8.7]
+
+X **** Run time configurable locking -- e.g., compile in HASFLOCK and
+ HASLOCKF, and then choose at runtime between these.
+
+B **** Aliases with .REDIRECT fail during newaliases if the "n" flag
+ is given. Problem is, sometimes you want them to, sometimes
+ you don't. Perhaps two flavors of "error" mailer?
+
+B **** Calls to gethostbyname with a trailing dot fail if you are
+ not running DNS.
+
+E **** Move delivery forking from sendenvelope to sendall so that
+ the connection cache works between split envelopes, and to
+ avoid a flurry of processes should you be sending to lots of
+ sub-lists.
+
+X **** Add uucp-bang mailer that strips off any domain name from
+ the envelope recipient address first; this is for use in
+ mailer table entries.
+
+X **** "quote" map (inverse of dequote). Lets you turn node::user
+ into "node::user"@DECNET.gateway
+
+X **** Named rulesets.
+
+? **** Should $( [1.2.3.4] $) convert the address to a name?
+
+E **** Change collect() handling to use high level timeouts instead
+ of per-line timeouts -- the current mechanism is swamping
+ the machine with system calls. (Look at KJS code.)
+
+E *** Long term host status -- store host status on disk for sharing
+ between runs.
+
+X *** Extend I option to allow setting of retry and timeout values.
+ drl@vuse.vanderbilt.edu (David R. Linn).
+
+X *** Total connection cache lifespan timeout -- a way to give a
+ timeout on connections regardless of whether they are active
+ or not. For single threaded servers such as Microsoft SMTP
+ gateway. Douglas Anderson <dlander@afterlife.ncsc.mil>.
+
+X *** Mailer flag that does a "ping" equivalent -- if it fails, wait
+ 30 seconds and try again (for dialup PPP connections). Could
+ just try the connection and then immediately retry on some
+ kinds of failures.
+
+X *** Create a macro that has message size.
+ Peter Wemm <peter@DIALix.oz.au>
+
+E *** Dynamically allocate MAXNAME buffers for headers.
+
+E *** Dynamically allocate "line" buffer in readaliases().
+
+X *** Add ability to disable Return-Receipt-To: on a privacy flag. [8.8]
+
+X *** Add -P to set precedence (e.g., -Pbulk). [8.8] (BCX)
+
+X *** Runtime option to enable/disable IDENT protocol.
+
+E *** Don't send ErrMsgFile to postmaster bounces. (Josh Smith,
+ josh@osiris.ac.hmc.edu).
+
+X *** Add "user" map to look up a user name via getpwnam -- so that
+ non-local names can be forwarded to another site. [8.8]
+
+E *** Have daemons that start up check the alias database for
+ correctness and auto-rebuild if necessary. This is to handle
+ the case of a system crash during an alias database rebuild.
+
+E *** Eliminate E qf line and e_errorqueue; use e_errorsto a la
+ e_receiptto. This simplifies and gives symmetry. (Eric
+ Wassenaar)
+
+X *** DECNET_RELAY support in configs.
+
+X *** -wN command line flag to set the width of mailq output.
+ (Allan Johannesen)
+
+E *** Move mailertable lookup after UUCP-specific class checks?
+ (Kimmo Suominen <kim@tac.nyc.ny.us>)
+
+E *** Users in more than one list with different owners get duplicate
+ deliveries -- maybe just assign them arbitrarily to one
+ envelope or the other?
+
+X ** Make MAXBADCOMMANDS run time configurable.
+
+E ** Allow mailertable entries of the form ``error:message''.
+
+X ** Have .forward files re-queue if the home directory isn't
+ accessible? On some option...
+ (Q.G.Campbell@newcastle.ac.uk)
+
+X ** Have local delivery queue if NIS is down? On some option...
+ (Q.G.Campbell@newcastle.ac.uk)
+
+E ** Have nullclient configuration resolve local names to the local
+ mailer and then redirect them in ruleset 5; this allows you to
+ redirect root differently depending on the client. It's not
+ clear this is really a good idea though.
+
+E ** Move CurHostAddr into mci struct, and make CurMCI variable
+ point to this, so that logging will give the correct address
+ instead of (0) for cached connections. Motonori Nakamura.
+
+X ** Allow use of a generalized network service for aliasing?
+ How would the protocol be defined?
+ James Gritton <gritton@byu.edu>.
+
+E ** Make "local configuration error" a temporary failure?
+ (add EX_CONFIG to the markfailure list)
+
+X ** (sigh) BSMTP.
+
+X ** "E" configuration line that sets environment variables.
+
+E ** Change listen() high-load backoff to accept and issue a 4xx
+ message so that it responds more quickly.
+
+E ** Change "/usr/tmp/dead.letter" to be based on _PATH_VARTMP.
+
+B ** Commas in NAME envariable cause problems (Peter Wan
+ <peter@cc.gatech.edu>). Merge with suggestions to use
+ MIME-format for 8-bit characters?
+
+E ** Save address information that comes back as the "additional
+ records" part of an MX lookup, to avoid additional name server
+ attempts. If there is an MX record without an additional A
+ record, delete it (this avoids a problem with misconfigured
+ DNS situations).
+
+X ** Allow a way to extend the $Z macro with local configuration
+ information.
+
+X ** Allow $x in -bt mode to expand macro "x". (BCX) [8.8]
+
+X ** Allow /address in -bt mode to expand address through ruleset 0,
+ aliases, etc. and display results. [8.8]
+
+X ** "R mailer address" in -bt mode does remotename on address.
+
+E ** Adjust "infinite loop in rule" code to handle entire ruleset
+ (Code from Michael Corrigan).
+
+E ** Allow :include: from command line (not SMTP) to assist in
+ "personal list" management -- i.e., creating lists that
+ cannot be EXPNed.
+
+X ** Database (keyed lookup) auto-rebuild.
+
+X ** Find a good test suite and include in the distribution.
+
+S ** You can use symbolic links to point into protected directories.
+ (AEJ)
+
+X ** Extend OI to allow separate settings for canonification, MX, and A
+ lookups. [8.8?]
+
+X ** Add $!x class to match any number of words not in class x. (KRE)
+
+X ** LOCAL_RULE_5 (Spencer Sun, spencer@phoenix.Princeton.EDU)
+
+X ** Add "bestmx" map -- returns "best MX host" for this address.
+ Allows you to do automatic detection of when you are the best
+ MX for a given address. [8.7?]
+
+X ** Some way to diddle resolver flags on a per-lookup basis, such
+ as a flag to the map declaration. (Rick McCarty)
+ - Is this really a good idea? DNSRCH can be turned off by
+ putting a dot at the end. AAONLY?
+
+X ** Extend makemap to "gather" values -- i.e., merge entries that
+ have the same keys. [8.8] (BCX)
+
+E ** Allow error messages on individual addresses in the qf file.
+ (BCX)
+
+X ** Multi-character option names. [9.1]
+
+X ** User database extensions for mailing lists:
+ list:precedence -- Precedence: value for new message
+ list:envelopefrom -- envelope "from" value for new message
+ others? [8.8]
+
+X ** Command line switch to set precedence (for mailing list
+ generation). (BCX)
+
+B ** Restore `T' line to eliminate X-Authentication-Warning: at
+ inappropriate times. (Christophe Wolfhugel)
+ - T could become a shorthand for Ct -- i.e., create a new
+ predefined class.
+ - Eliminate "<user> set sender to <address>" message entirely?
+ (this is the workaround)
+
+B ** Return-Path: header should have <> added if not already there.
+
+X ** Add heuristic to determine if other end is a sendmail; use
+ that to decide whether or not to honor F=I mailer flag.
+ [der Mouse <mouse@collatz.mcrcim.mcgill.edu>]
+
+X ** Automatically drop into MIME mode if you have a full name
+ with 8-bit characters. See envelope.c 8.19.1.1 and util.c
+ 8.17.1.1. From Anders Ellefsrud <anders@ifi.uio.no>.
+
+X ** -b? flag to read a header and show you what it will look like
+ after all rewriting for an indicated address.
+
+E ** Log $u in logsender() (for=<someaddress>).
+
+B ** Include SOCKADDR in MCI struct for logging (currently gives
+ a sockaddr of zero when printing from the cache).
+
+X ** Allow option to set the characters that are autoquoted in
+ addresses?
+
+X * Map that does MB/MR lookups. Rick McCarty <mccarty@io.com>.
+
+X * Allow $> anywhere in RHS. John Boeske <jboeske@ualberta.ca>.
+
+X * -V flag to print state of all (?) compilation flags.
+
+X * Handle Expires: header field (if still in queue).
+
+X * WIN/3B support (non-atomic rename, no h_addr_list, others?)
+ (Bruce Lilly <blilly!bruce@uu.psi.com>)
+
+X * Sun YBTS daemon uses -ba. [Martin Kiff <MGK@newton.npl.co.uk>]
+
+B * EXPN adds @domain to all mailers, including prog. Is this right?
+ [Bob Henry]
+
+B * EXPN adds @localhost instead of @$M. [Pel Emanuelsson]
+
+E * Change body put code to time out around individual puts. This will
+ make the timeout algorithm more responsive and more resilient.
+ Unfortunately, it's also a pain in the butt.
+
+X * Some way to relay unfound local users to another site.
+
+X * Disable all default RW sets except mailer-specific?
diff --git a/usr.sbin/sliplogin/Makefile b/usr.sbin/sliplogin/Makefile
new file mode 100644
index 0000000..b0fe83f
--- /dev/null
+++ b/usr.sbin/sliplogin/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 8.1 (Berkeley) 7/19/93
+
+PROG= sliplogin
+MAN8= sliplogin.0
+BINOWN= root
+BINMODE=4555
+INSTALLFLAGS=-fschg
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sliplogin/pathnames.h b/usr.sbin/sliplogin/pathnames.h
new file mode 100644
index 0000000..9e792a3
--- /dev/null
+++ b/usr.sbin/sliplogin/pathnames.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#ifndef COMPAT
+#include <paths.h>
+#else
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#define _PATH_ACCESS "/etc/sliphome/slip.hosts"
+#define _PATH_LOGIN "/etc/sliphome/slip.login"
+#define _PATH_LOGOUT "/etc/sliphome/slip.logout"
+#define _PATH_DEBUG "/tmp/sliplogin.XXXXXX"
+
diff --git a/usr.sbin/sliplogin/slip.hosts b/usr.sbin/sliplogin/slip.hosts
new file mode 100644
index 0000000..f6ebf40
--- /dev/null
+++ b/usr.sbin/sliplogin/slip.hosts
@@ -0,0 +1,11 @@
+# @(#)slip.hosts 8.1 (Berkeley) 6/6/93
+#
+# login local-addr remote-addr mask opt1 opt2
+# (normal,compress,noicmp)
+#
+Schez vangogh chez 0xffffff00 compress
+Sjun vangogh 128.32.130.36 0xffffff00 normal
+Sleconte vangogh leconte 0xffffff00 compress
+Sleeb vangogh leeb 0xffffff00 compress
+Smjk vangogh pissaro-sl 0xffffff00 compress
+Soxford vangogh oxford 0xffffff00 compress
diff --git a/usr.sbin/sliplogin/slip.login b/usr.sbin/sliplogin/slip.login
new file mode 100644
index 0000000..3c70095
--- /dev/null
+++ b/usr.sbin/sliplogin/slip.login
@@ -0,0 +1,12 @@
+#!/bin/sh -
+#
+# @(#)slip.login 8.1 (Berkeley) 6/6/93
+
+#
+# generic login file for a slip line. sliplogin invokes this with
+# the parameters:
+# 1 2 3 4 5 6 7-n
+# slipunit ttyspeed loginname local-addr remote-addr mask opt-args
+#
+/sbin/ifconfig sl$1 inet $4 $5 netmask $6
+exit
diff --git a/usr.sbin/sliplogin/sliplogin.8 b/usr.sbin/sliplogin/sliplogin.8
new file mode 100644
index 0000000..1c71988
--- /dev/null
+++ b/usr.sbin/sliplogin/sliplogin.8
@@ -0,0 +1,220 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sliplogin.8 8.2 (Berkeley) 1/5/94
+.\"
+.Dd January 5, 1994
+.Dt SLIPLOGIN 8
+.Os
+.Sh NAME
+.Nm sliplogin
+.Nd attach a serial line network interface
+.Sh SYNOPSIS
+.Nm sliplogin
+.Op Ar loginname
+.Sh DESCRIPTION
+.Nm Sliplogin
+is used to turn the terminal line on standard input into
+a Serial Line IP
+.Pq Tn SLIP
+link to a remote host. To do this, the program
+searches the file
+.Pa /etc/sliphome/slip.hosts
+for an entry matching
+.Ar loginname
+(which defaults to the current login name if omitted).
+If a matching entry is found, the line is configured appropriately
+for slip (8-bit transparent i/o) and converted to
+.Tn SLIP
+line
+discipline. Then a shell script is invoked to initialize the slip
+interface with the appropriate local and remote
+.Tn IP
+address,
+netmask, etc.
+.Pp
+The usual initialization script is
+.Pa /etc/sliphome/slip.login
+but, if particular hosts need special initialization, the file
+.Pa /etc/sliphome/slip.login. Ns Ar loginname
+will be executed instead if it exists.
+The script is invoked with the parameters
+.Bl -tag -width slipunit
+.It Em slipunit
+The unit number of the slip interface assigned to this line. E.g.,
+.Sy 0
+for
+.Sy sl0 .
+.It Em speed
+The speed of the line.
+.It Em args
+The arguments from the
+.Pa /etc/sliphome/slip.hosts
+entry, in order starting with
+.Ar loginname .
+.El
+.Pp
+Only the super-user may attach a network interface. The interface is
+automatically detached when the other end hangs up or the
+.Nm sliplogin
+process dies. If the kernel slip
+module has been configured for it, all routes through that interface will
+also disappear at the same time. If there is other processing a site
+would like done on hangup, the file
+.Pa /etc/sliphome/slip.logout
+or
+.Pa /etc/sliphome/slip.logout. Ns Ar loginname
+is executed if it exists. It is given the same arguments as the login script.
+.Ss Format of /etc/sliphome/slip.hosts
+Comments (lines starting with a `#') and blank lines are ignored.
+Other lines must start with a
+.Ar loginname
+but the remaining arguments can be whatever is appropriate for the
+.Pa slip.login
+file that will be executed for that name.
+Arguments are separated by white space and follow normal
+.Xr sh 1
+quoting conventions (however,
+.Ar loginname
+cannot be quoted).
+Usually, lines have the form
+.Bd -literal -offset indent
+loginname local-address remote-address netmask opt-args
+.Ed
+.Pp
+where
+.Em local-address
+and
+.Em remote-address
+are the IP host names or addresses of the local and remote ends of the
+slip line and
+.Em netmask
+is the appropriate IP netmask. These arguments are passed
+directly to
+.Xr ifconfig 8 .
+.Em Opt-args
+are optional arguments used to configure the line.
+.Sh EXAMPLE
+The normal use of
+.Nm sliplogin
+is to create a
+.Pa /etc/passwd
+entry for each legal, remote slip site with
+.Nm sliplogin
+as the shell for that entry. E.g.,
+.Bd -literal
+Sfoo:ikhuy6:2010:1:slip line to foo:/tmp:/usr/sbin/sliplogin
+.Ed
+.Pp
+(Our convention is to name the account used by remote host
+.Ar hostname
+as
+.Em Shostname . )
+Then an entry is added to
+.Pa slip.hosts
+that looks like:
+.Pp
+.Bd -literal -offset indent -compact
+Sfoo `hostname` foo netmask
+.Ed
+.Pp
+where
+.Em `hostname`
+will be evaluated by
+.Xr sh
+to the local host name and
+.Em netmask
+is the local host IP netmask.
+.Pp
+Note that
+.Nm sliplogin
+must be setuid to root and, while not a security hole, moral defectives
+can use it to place terminal lines in an unusable state and/or deny
+access to legitimate users of a remote slip line. To prevent this,
+a site can create a group, say
+.Em slip ,
+that only the slip login accounts are put in then make sure that
+.Pa /usr/sbin/sliplogin
+is in group
+.Em slip
+and mode 4550 (setuid root, only group
+.Em slip
+can execute binary).
+.Sh DIAGNOSTICS
+.Nm Sliplogin
+logs various information to the system log daemon,
+.Xr syslogd 8 ,
+with a facility code of
+.Em daemon .
+The messages are listed here, grouped by severity level.
+.Pp
+.Sy Error Severity
+.Bl -tag -width Ds -compact
+.It Sy ioctl (TCGETS): Em reason
+A
+.Dv TCGETS
+.Fn ioctl
+to get the line parameters failed.
+.Pp
+.It Sy ioctl (TCSETS): Em reason
+A
+.Dv TCSETS
+.Fn ioctl
+to set the line parameters failed.
+.Pp
+.It Sy /etc/sliphome/slip.hosts: Em reason
+The
+.Pa /etc/sliphome/slip.hosts
+file could not be opened.
+.Pp
+.It Sy access denied for Em user
+No entry for
+.Em user
+was found in
+.Pa /etc/sliphome/slip.hosts .
+.El
+.Pp
+.Sy Notice Severity
+.Bl -tag -width Ds -compact
+.It Sy "attaching slip unit" Em unit Sy for Ar loginname
+.Tn SLIP
+unit
+.Em unit
+was successfully attached.
+.El
+.Sh SEE ALSO
+.Xr slattach 8 ,
+.Xr syslogd 8
+.Sh HISTORY
+The
+.Nm
+command
+.Bt
diff --git a/usr.sbin/sliplogin/sliplogin.c b/usr.sbin/sliplogin/sliplogin.c
new file mode 100644
index 0000000..7e52ff7
--- /dev/null
+++ b/usr.sbin/sliplogin/sliplogin.c
@@ -0,0 +1,381 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)sliplogin.c 8.2 (Berkeley) 2/1/94";
+#endif /* not lint */
+
+/*
+ * sliplogin.c
+ * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!]
+ *
+ * This program initializes its own tty port to be an async TCP/IP interface.
+ * It sets the line discipline to slip, invokes a shell script to initialize
+ * the network interface, then pauses forever waiting for hangup.
+ *
+ * It is a remote descendant of several similar programs with incestuous ties:
+ * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL.
+ * - slattach, probably by Rick Adams but touched by countless hordes.
+ * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it.
+ *
+ * There are two forms of usage:
+ *
+ * "sliplogin"
+ * Invoked simply as "sliplogin", the program looks up the username
+ * in the file /etc/slip.hosts.
+ * If an entry is found, the line on fd0 is configured for SLIP operation
+ * as specified in the file.
+ *
+ * "sliplogin IPhostlogin </dev/ttyb"
+ * Invoked by root with a username, the name is looked up in the
+ * /etc/slip.hosts file and if found fd0 is configured as in case 1.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <sys/file.h>
+#include <sys/syslog.h>
+#include <netdb.h>
+
+#if BSD >= 199006
+#define POSIX
+#endif
+#ifdef POSIX
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#include <ttyent.h>
+#else
+#include <sgtty.h>
+#endif
+#include <net/slip.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include "pathnames.h"
+
+int unit;
+int speed;
+int uid;
+char loginargs[BUFSIZ];
+char loginfile[MAXPATHLEN];
+char loginname[BUFSIZ];
+
+void
+findid(name)
+ char *name;
+{
+ FILE *fp;
+ static char slopt[5][16];
+ static char laddr[16];
+ static char raddr[16];
+ static char mask[16];
+ char user[16];
+ int i, j, n;
+
+ (void)strcpy(loginname, name);
+ if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) {
+ (void)fprintf(stderr, "sliplogin: %s: %s\n",
+ _PATH_ACCESS, strerror(errno));
+ syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
+ exit(1);
+ }
+ while (fgets(loginargs, sizeof(loginargs) - 1, fp)) {
+ if (ferror(fp))
+ break;
+ n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n",
+ user, laddr, raddr, mask, slopt[0], slopt[1],
+ slopt[2], slopt[3], slopt[4]);
+ if (user[0] == '#' || isspace(user[0]))
+ continue;
+ if (strcmp(user, name) != 0)
+ continue;
+
+ /*
+ * we've found the guy we're looking for -- see if
+ * there's a login file we can use. First check for
+ * one specific to this host. If none found, try for
+ * a generic one.
+ */
+ (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name);
+ if (access(loginfile, R_OK|X_OK) != 0) {
+ (void)strcpy(loginfile, _PATH_LOGIN);
+ if (access(loginfile, R_OK|X_OK)) {
+ fputs("access denied - no login file\n",
+ stderr);
+ syslog(LOG_ERR,
+ "access denied for %s - no %s\n",
+ name, _PATH_LOGIN);
+ exit(5);
+ }
+ }
+
+ (void) fclose(fp);
+ return;
+ }
+ (void)fprintf(stderr, "SLIP access denied for %s\n", name);
+ syslog(LOG_ERR, "SLIP access denied for %s\n", name);
+ exit(4);
+ /* NOTREACHED */
+}
+
+char *
+sigstr(s)
+ int s;
+{
+ static char buf[32];
+
+ switch (s) {
+ case SIGHUP: return("HUP");
+ case SIGINT: return("INT");
+ case SIGQUIT: return("QUIT");
+ case SIGILL: return("ILL");
+ case SIGTRAP: return("TRAP");
+ case SIGIOT: return("IOT");
+ case SIGEMT: return("EMT");
+ case SIGFPE: return("FPE");
+ case SIGKILL: return("KILL");
+ case SIGBUS: return("BUS");
+ case SIGSEGV: return("SEGV");
+ case SIGSYS: return("SYS");
+ case SIGPIPE: return("PIPE");
+ case SIGALRM: return("ALRM");
+ case SIGTERM: return("TERM");
+ case SIGURG: return("URG");
+ case SIGSTOP: return("STOP");
+ case SIGTSTP: return("TSTP");
+ case SIGCONT: return("CONT");
+ case SIGCHLD: return("CHLD");
+ case SIGTTIN: return("TTIN");
+ case SIGTTOU: return("TTOU");
+ case SIGIO: return("IO");
+ case SIGXCPU: return("XCPU");
+ case SIGXFSZ: return("XFSZ");
+ case SIGVTALRM: return("VTALRM");
+ case SIGPROF: return("PROF");
+ case SIGWINCH: return("WINCH");
+#ifdef SIGLOST
+ case SIGLOST: return("LOST");
+#endif
+ case SIGUSR1: return("USR1");
+ case SIGUSR2: return("USR2");
+ }
+ (void)sprintf(buf, "sig %d", s);
+ return(buf);
+}
+
+void
+hup_handler(s)
+ int s;
+{
+ char logoutfile[MAXPATHLEN];
+
+ (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname);
+ if (access(logoutfile, R_OK|X_OK) != 0)
+ (void)strcpy(logoutfile, _PATH_LOGOUT);
+ if (access(logoutfile, R_OK|X_OK) == 0) {
+ char logincmd[2*MAXPATHLEN+32];
+
+ (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed,
+ loginargs);
+ (void) system(logincmd);
+ }
+ (void) close(0);
+ syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit,
+ sigstr(s));
+ exit(1);
+ /* NOTREACHED */
+}
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int fd, s, ldisc, odisc;
+ char *name;
+#ifdef POSIX
+ struct termios tios, otios;
+#else
+ struct sgttyb tty, otty;
+#endif
+ char logincmd[2*BUFSIZ+32];
+ extern uid_t getuid();
+
+ if ((name = strrchr(argv[0], '/')) == NULL)
+ name = argv[0];
+ s = getdtablesize();
+ for (fd = 3 ; fd < s ; fd++)
+ (void) close(fd);
+ openlog(name, LOG_PID, LOG_DAEMON);
+ uid = getuid();
+ if (argc > 1) {
+ findid(argv[1]);
+
+ /*
+ * Disassociate from current controlling terminal, if any,
+ * and ensure that the slip line is our controlling terminal.
+ */
+#ifdef POSIX
+ if (fork() > 0)
+ exit(0);
+ if (setsid() != 0)
+ perror("setsid");
+#else
+ if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) {
+ extern char *ttyname();
+
+ (void) ioctl(fd, TIOCNOTTY, (caddr_t)0);
+ (void) close(fd);
+ /* open slip tty again to acquire as controlling tty? */
+ fd = open(ttyname(0), O_RDWR, 0);
+ if (fd >= 0)
+ (void) close(fd);
+ }
+ (void) setpgrp(0, getpid());
+#endif
+ if (argc > 2) {
+ if ((fd = open(argv[2], O_RDWR)) == -1) {
+ perror(argv[2]);
+ exit(2);
+ }
+ (void) dup2(fd, 0);
+ if (fd > 2)
+ close(fd);
+ }
+#ifdef TIOCSCTTY
+ if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0)
+ perror("ioctl (TIOCSCTTY)");
+#endif
+ } else {
+ extern char *getlogin();
+
+ if ((name = getlogin()) == NULL) {
+ (void) fprintf(stderr, "access denied - no username\n");
+ syslog(LOG_ERR, "access denied - getlogin returned 0\n");
+ exit(1);
+ }
+ findid(name);
+ }
+ (void) fchmod(0, 0600);
+ (void) fprintf(stderr, "starting slip login for %s\n", loginname);
+#ifdef POSIX
+ /* set up the line parameters */
+ if (tcgetattr(0, &tios) < 0) {
+ syslog(LOG_ERR, "tcgetattr: %m");
+ exit(1);
+ }
+ otios = tios;
+ cfmakeraw(&tios);
+ tios.c_iflag &= ~IMAXBEL;
+ if (tcsetattr(0, TCSAFLUSH, &tios) < 0) {
+ syslog(LOG_ERR, "tcsetattr: %m");
+ exit(1);
+ }
+ speed = cfgetispeed(&tios);
+#else
+ /* set up the line parameters */
+ if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) {
+ syslog(LOG_ERR, "ioctl (TIOCGETP): %m");
+ exit(1);
+ }
+ otty = tty;
+ speed = tty.sg_ispeed;
+ tty.sg_flags = RAW | ANYP;
+ if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) {
+ syslog(LOG_ERR, "ioctl (TIOCSETP): %m");
+ exit(1);
+ }
+#endif
+ /* find out what ldisc we started with */
+ if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) {
+ syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m");
+ exit(1);
+ }
+ ldisc = SLIPDISC;
+ if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) {
+ syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
+ exit(1);
+ }
+ /* find out what unit number we were assigned */
+ if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) {
+ syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m");
+ exit(1);
+ }
+ (void) signal(SIGHUP, hup_handler);
+ (void) signal(SIGTERM, hup_handler);
+
+ syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname);
+ (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed,
+ loginargs);
+ /*
+ * aim stdout and errout at /dev/null so logincmd output won't
+ * babble into the slip tty line.
+ */
+ (void) close(1);
+ if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) {
+ if (fd < 0) {
+ syslog(LOG_ERR, "open /dev/null: %m");
+ exit(1);
+ }
+ (void) dup2(fd, 1);
+ (void) close(fd);
+ }
+ (void) dup2(1, 2);
+
+ /*
+ * Run login and logout scripts as root (real and effective);
+ * current route(8) is setuid root, and checks the real uid
+ * to see whether changes are allowed (or just "route get").
+ */
+ (void) setuid(0);
+ if (s = system(logincmd)) {
+ syslog(LOG_ERR, "%s login failed: exit status %d from %s",
+ loginname, s, loginfile);
+ (void) ioctl(0, TIOCSETD, (caddr_t)&odisc);
+ exit(6);
+ }
+
+ /* twiddle thumbs until we get a signal */
+ while (1)
+ sigpause(0);
+
+ /* NOTREACHED */
+}
diff --git a/usr.sbin/sysctl/Makefile b/usr.sbin/sysctl/Makefile
new file mode 100644
index 0000000..40d12d2
--- /dev/null
+++ b/usr.sbin/sysctl/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= sysctl
+MAN8= sysctl.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sysctl/pathconf.c b/usr.sbin/sysctl/pathconf.c
new file mode 100644
index 0000000..4b60ccf
--- /dev/null
+++ b/usr.sbin/sysctl/pathconf.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pathconf.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PC_NAMES { \
+ { 0, 0 }, \
+ { "link_max", CTLTYPE_INT }, \
+ { "max_canon", CTLTYPE_INT }, \
+ { "max_input", CTLTYPE_INT }, \
+ { "name_max", CTLTYPE_INT }, \
+ { "path_max", CTLTYPE_INT }, \
+ { "pipe_buf", CTLTYPE_INT }, \
+ { "chown_restricted", CTLTYPE_INT }, \
+ { "no_trunc", CTLTYPE_INT }, \
+ { "vdisable", CTLTYPE_INT }, \
+}
+#define PC_MAXID 10
+
+struct ctlname pcnames[] = PC_NAMES;
+char names[BUFSIZ];
+
+struct list {
+ struct ctlname *list;
+ int size;
+};
+struct list pclist = { pcnames, PC_MAXID };
+
+int Aflag, aflag, nflag, wflag, stdinflag;
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ char *path;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Aan")) != EOF) {
+ switch (ch) {
+
+ case 'A':
+ Aflag = 1;
+ break;
+
+ case 'a':
+ aflag = 1;
+ break;
+
+ case 'n':
+ nflag = 1;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+ path = *argv++;
+ if (strcmp(path, "-") == 0)
+ stdinflag = 1;
+ argc--;
+ if (Aflag || aflag) {
+ listall(path, &pclist);
+ exit(0);
+ }
+ if (argc == 0)
+ usage();
+ while (argc-- > 0)
+ parse(path, *argv, 1);
+ exit(0);
+}
+
+/*
+ * List all variables known to the system.
+ */
+listall(path, lp)
+ char *path;
+ struct list *lp;
+{
+ int lvl2;
+
+ if (lp->list == 0)
+ return;
+ for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
+ if (lp->list[lvl2].ctl_name == 0)
+ continue;
+ parse(path, lp->list[lvl2].ctl_name, Aflag);
+ }
+}
+
+/*
+ * Parse a name into an index.
+ * Lookup and print out the attribute if it exists.
+ */
+parse(pathname, string, flags)
+ char *pathname;
+ char *string;
+ int flags;
+{
+ int indx, value;
+ char *bufp, buf[BUFSIZ];
+
+ bufp = buf;
+ snprintf(buf, BUFSIZ, "%s", string);
+ if ((indx = findname(string, "top", &bufp, &pclist)) == -1)
+ return;
+ if (bufp) {
+ fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
+ return;
+ }
+ if (stdinflag)
+ value = fpathconf(0, indx);
+ else
+ value = pathconf(pathname, indx);
+ if (value == -1) {
+ if (flags == 0)
+ return;
+ switch (errno) {
+ case EOPNOTSUPP:
+ fprintf(stderr, "%s: value is not available\n", string);
+ return;
+ case ENOTDIR:
+ fprintf(stderr, "%s: specification is incomplete\n",
+ string);
+ return;
+ case ENOMEM:
+ fprintf(stderr, "%s: type is unknown to this program\n",
+ string);
+ return;
+ default:
+ perror(string);
+ return;
+ }
+ }
+ if (!nflag)
+ fprintf(stdout, "%s = ", string);
+ fprintf(stdout, "%d\n", value);
+}
+
+/*
+ * Scan a list of names searching for a particular name.
+ */
+findname(string, level, bufp, namelist)
+ char *string;
+ char *level;
+ char **bufp;
+ struct list *namelist;
+{
+ char *name;
+ int i;
+
+ if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
+ fprintf(stderr, "%s: incomplete specification\n", string);
+ return (-1);
+ }
+ for (i = 0; i < namelist->size; i++)
+ if (namelist->list[i].ctl_name != NULL &&
+ strcmp(name, namelist->list[i].ctl_name) == 0)
+ break;
+ if (i == namelist->size) {
+ fprintf(stderr, "%s level name %s in %s is invalid\n",
+ level, name, string);
+ return (-1);
+ }
+ return (i);
+}
+
+usage()
+{
+
+ (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n",
+ "pathname [-n] variable ...",
+ "pathname [-n] -a", "pathname [-n] -A");
+ exit(1);
+}
diff --git a/usr.sbin/sysctl/sysctl.8 b/usr.sbin/sysctl/sysctl.8
new file mode 100644
index 0000000..9def509
--- /dev/null
+++ b/usr.sbin/sysctl/sysctl.8
@@ -0,0 +1,208 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sysctl.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd "June 6, 1993"
+.Dt SYSCTL 8
+.Os
+.Sh NAME
+.Nm sysctl
+.Nd get or set kernel state
+.Sh SYNOPSIS
+.Nm sysctl
+.Op Fl n
+.Ar name ...
+.Nm sysctl
+.Op Fl n
+.Fl w
+.Ar name=value ...
+.Nm sysctl
+.Op Fl n
+.Fl aA
+.Sh DESCRIPTION
+The
+.Nm sysctl
+utility retrieves kernel state and allows processes with
+appropriate privilege to set kernel state.
+The state to be retrieved or set is described using a
+``Management Information Base'' (``MIB'') style name,
+described as a dotted set of components.
+The
+.Fl a
+flag can be used to list all the currently available string or integer values.
+The
+.Fl A
+flag will list all the known MIB names including tables.
+Those with string or integer values will be printed as with the
+.Fl a
+flag; for the table values,
+the name of the utility to retrieve them is given.
+.Pp
+The
+.Fl n
+flag specifies that the printing of the field name should be
+suppressed and that only its value should be output.
+This flag is useful for setting shell variables.
+For example, to save the pagesize in variable psize, use:
+.Bd -literal -offset indent -compact
+set psize=`sysctl -n hw.pagesize`
+.Ed
+.Pp
+If just a MIB style name is given,
+the corresponding value is retrieved.
+If a value is to be set, the
+.Fl w
+flag must be specified and the MIB name followed
+by an equal sign and the new value to be used.
+.Pp
+The information available from
+.Nm sysctl
+consists of integers, strings, and tables.
+The tabular information can only be retrieved by special
+purpose programs such as
+.Nm ps ,
+.Nm systat ,
+and
+.Nm netstat .
+The string and integer information is summaried below.
+For a detailed description of these variable see
+.Xr sysctl 3 .
+The changeable column indicates whether a process with appropriate
+privilege can change the value.
+.Bl -column net.inet.ip.forwardingxxxxxx integerxxx
+.It Sy Name Type Changeable
+.It kern.ostype string no
+.It kern.osrelease string no
+.It kern.osrevision integer no
+.It kern.version string no
+.It kern.maxvnodes integer yes
+.It kern.maxproc integer yes
+.It kern.maxfiles integer yes
+.It kern.argmax integer no
+.It kern.securelevel integer raise only
+.It kern.hostname string yes
+.It kern.hostid integer yes
+.It kern.clockrate struct no
+.It kern.posix1version integer no
+.It kern.ngroups integer no
+.It kern.job_control integer no
+.It kern.saved_ids integer no
+.It kern.link_max integer no
+.It kern.max_canon integer no
+.It kern.max_input integer no
+.It kern.name_max integer no
+.It kern.path_max integer no
+.It kern.pipe_buf integer no
+.It kern.chown_restricted integer no
+.It kern.no_trunc integer no
+.It kern.vdisable integer no
+.It kern.boottime struct no
+.It vm.loadavg struct no
+.It machdep.console_device dev_t no
+.It net.inet.ip.forwarding integer yes
+.It net.inet.ip.redirect integer yes
+.It net.inet.ip.ttl integer yes
+.It net.inet.icmp.maskrepl integer yes
+.It net.inet.udp.checksum integer yes
+.It hw.machine string no
+.It hw.model string no
+.It hw.ncpu integer no
+.It hw.byteorder integer no
+.It hw.physmem integer no
+.It hw.usermem integer no
+.It hw.pagesize integer no
+.It user.cs_path string no
+.It user.bc_base_max integer no
+.It user.bc_dim_max integer no
+.It user.bc_scale_max integer no
+.It user.bc_string_max integer no
+.It user.coll_weights_max integer no
+.It user.expr_nest_max integer no
+.It user.line_max integer no
+.It user.re_dup_max integer no
+.It user.posix2_version integer no
+.It user.posix2_c_bind integer no
+.It user.posix2_c_dev integer no
+.It user.posix2_char_term integer no
+.It user.posix2_fort_dev integer no
+.It user.posix2_fort_run integer no
+.It user.posix2_localedef integer no
+.It user.posix2_sw_dev integer no
+.It user.posix2_upe integer no
+.El
+.Sh EXAMPLES
+.Pp
+For example, to retrieve the maximum number of processes allowed
+in the system, one would use the follow request:
+.Bd -literal -offset indent -compact
+sysctl kern.maxproc
+.Ed
+.Pp
+To set the maximum number of processes allowed
+in the system to 1000, one would use the follow request:
+.Bd -literal -offset indent -compact
+sysctl -w kern.maxproc=1000
+.Ed
+.Pp
+Information about the system clock rate may be obtained with:
+.Bd -literal -offset indent -compact
+sysctl kern.clockrate
+.Ed
+.Pp
+Information about the load average history may be obtained with
+.Bd -literal -offset indent -compact
+sysctl vm.loadavg
+.Ed
+.Sh FILES
+.Bl -tag -width <netinet/icmpXvar.h> -compact
+.It Pa <sys/sysctl.h>
+definitions for top level identifiers, second level kernel and hardware
+identifiers, and user level identifiers
+.It Pa <sys/socket.h>
+definitions for second level network identifiers
+.It Pa <sys/gmon.h>
+definitions for third level profiling identifiers
+.It Pa <vm/vm_param.h>
+definitions for second level virtual memory identifiers
+.It Pa <netinet/in.h>
+definitions for third level Internet identifiers and
+fourth level IP identifiers
+.It Pa <netinet/icmp_var.h>
+definitions for fourth level ICMP identifiers
+.It Pa <netinet/udp_var.h>
+definitions for fourth level UDP identifiers
+.El
+.Sh SEE ALSO
+.Xr sysctl 3
+.Sh HISTORY
+.Nm sysctl
+first appeared in 4.4BSD.
diff --git a/usr.sbin/sysctl/sysctl.c b/usr.sbin/sysctl/sysctl.c
new file mode 100644
index 0000000..a342686
--- /dev/null
+++ b/usr.sbin/sysctl/sysctl.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/gmon.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <vm/vm_param.h>
+#include <machine/cpu.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct ctlname topname[] = CTL_NAMES;
+struct ctlname kernname[] = CTL_KERN_NAMES;
+struct ctlname vmname[] = CTL_VM_NAMES;
+struct ctlname netname[] = CTL_NET_NAMES;
+struct ctlname hwname[] = CTL_HW_NAMES;
+struct ctlname username[] = CTL_USER_NAMES;
+struct ctlname debugname[CTL_DEBUG_MAXID];
+#ifdef CTL_MACHDEP_NAMES
+struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
+#endif
+char names[BUFSIZ];
+
+struct list {
+ struct ctlname *list;
+ int size;
+};
+struct list toplist = { topname, CTL_MAXID };
+struct list secondlevel[] = {
+ { 0, 0 }, /* CTL_UNSPEC */
+ { kernname, KERN_MAXID }, /* CTL_KERN */
+ { vmname, VM_MAXID }, /* CTL_VM */
+ { 0, 0 }, /* CTL_FS */
+ { netname, NET_MAXID }, /* CTL_NET */
+ { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
+ { hwname, HW_MAXID }, /* CTL_HW */
+#ifdef CTL_MACHDEP_NAMES
+ { machdepname, CPU_MAXID }, /* CTL_MACHDEP */
+#else
+ { 0, 0 }, /* CTL_MACHDEP */
+#endif
+ { username, USER_MAXID }, /* CTL_USER_NAMES */
+};
+
+int Aflag, aflag, nflag, wflag;
+
+/*
+ * Variables requiring special processing.
+ */
+#define CLOCK 0x00000001
+#define BOOTTIME 0x00000002
+#define CONSDEV 0x00000004
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ int ch, lvl1;
+
+ while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
+ switch (ch) {
+
+ case 'A':
+ Aflag = 1;
+ break;
+
+ case 'a':
+ aflag = 1;
+ break;
+
+ case 'n':
+ nflag = 1;
+ break;
+
+ case 'w':
+ wflag = 1;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (Aflag || aflag) {
+ debuginit();
+ for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
+ listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
+ exit(0);
+ }
+ if (argc == 0)
+ usage();
+ while (argc-- > 0)
+ parse(*argv, 1);
+ exit(0);
+}
+
+/*
+ * List all variables known to the system.
+ */
+listall(prefix, lp)
+ char *prefix;
+ struct list *lp;
+{
+ int lvl2;
+ char *cp, name[BUFSIZ];
+
+ if (lp->list == 0)
+ return;
+ strcpy(name, prefix);
+ cp = &name[strlen(name)];
+ *cp++ = '.';
+ for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
+ if (lp->list[lvl2].ctl_name == 0)
+ continue;
+ strcpy(cp, lp->list[lvl2].ctl_name);
+ parse(name, Aflag);
+ }
+}
+
+/*
+ * Parse a name into a MIB entry.
+ * Lookup and print out the MIB entry if it exists.
+ * Set a new value if requested.
+ */
+parse(string, flags)
+ char *string;
+ int flags;
+{
+ int indx, type, state, size, len;
+ int special = 0;
+ void *newval = 0;
+ int intval, newsize = 0;
+ quad_t quadval;
+ struct list *lp;
+ int mib[CTL_MAXNAME];
+ char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
+
+ bufp = buf;
+ snprintf(buf, BUFSIZ, "%s", string);
+ if ((cp = strchr(string, '=')) != NULL) {
+ if (!wflag) {
+ fprintf(stderr, "Must specify -w to set variables\n");
+ exit(2);
+ }
+ *strchr(buf, '=') = '\0';
+ *cp++ = '\0';
+ while (isspace(*cp))
+ cp++;
+ newval = cp;
+ newsize = strlen(cp);
+ }
+ if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
+ return;
+ mib[0] = indx;
+ if (indx == CTL_DEBUG)
+ debuginit();
+ lp = &secondlevel[indx];
+ if (lp->list == 0) {
+ fprintf(stderr, "%s: class is not implemented\n",
+ topname[indx]);
+ return;
+ }
+ if (bufp == NULL) {
+ listall(topname[indx].ctl_name, lp);
+ return;
+ }
+ if ((indx = findname(string, "second", &bufp, lp)) == -1)
+ return;
+ mib[1] = indx;
+ type = lp->list[indx].ctl_type;
+ len = 2;
+ switch (mib[0]) {
+
+ case CTL_KERN:
+ switch (mib[1]) {
+ case KERN_PROF:
+ mib[2] = GPROF_STATE;
+ size = sizeof state;
+ if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
+ if (flags == 0)
+ return;
+ if (!nflag)
+ fprintf(stdout, "%s: ", string);
+ fprintf(stderr,
+ "kernel is not compiled for profiling\n");
+ return;
+ }
+ if (!nflag)
+ fprintf(stdout, "%s: %s\n", string,
+ state == GMON_PROF_OFF ? "off" : "running");
+ return;
+ case KERN_VNODE:
+ case KERN_FILE:
+ if (flags == 0)
+ return;
+ fprintf(stderr,
+ "Use pstat to view %s information\n", string);
+ return;
+ case KERN_PROC:
+ if (flags == 0)
+ return;
+ fprintf(stderr,
+ "Use ps to view %s information\n", string);
+ return;
+ case KERN_CLOCKRATE:
+ special |= CLOCK;
+ break;
+ case KERN_BOOTTIME:
+ special |= BOOTTIME;
+ break;
+ }
+ break;
+
+ case CTL_HW:
+ break;
+
+ case CTL_VM:
+ if (mib[1] == VM_LOADAVG) {
+ double loads[3];
+
+ getloadavg(loads, 3);
+ if (!nflag)
+ fprintf(stdout, "%s: ", string);
+ fprintf(stdout, "%.2f %.2f %.2f\n",
+ loads[0], loads[1], loads[2]);
+ return;
+ }
+ if (flags == 0)
+ return;
+ fprintf(stderr,
+ "Use vmstat or systat to view %s information\n", string);
+ return;
+
+ case CTL_NET:
+ if (mib[1] == PF_INET) {
+ len = sysctl_inet(string, &bufp, mib, flags, &type);
+ if (len >= 0)
+ break;
+ return;
+ }
+ if (flags == 0)
+ return;
+ fprintf(stderr, "Use netstat to view %s information\n", string);
+ return;
+
+ case CTL_DEBUG:
+ mib[2] = CTL_DEBUG_VALUE;
+ len = 3;
+ break;
+
+ case CTL_MACHDEP:
+#ifdef CPU_CONSDEV
+ if (mib[1] == CPU_CONSDEV)
+ special |= CONSDEV;
+#endif
+ break;
+
+ case CTL_FS:
+ case CTL_USER:
+ break;
+
+ default:
+ fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
+ return;
+
+ }
+ if (bufp) {
+ fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
+ return;
+ }
+ if (newsize > 0) {
+ switch (type) {
+ case CTLTYPE_INT:
+ intval = atoi(newval);
+ newval = &intval;
+ newsize = sizeof intval;
+ break;
+
+ case CTLTYPE_QUAD:
+ sscanf(newval, "%qd", &quadval);
+ newval = &quadval;
+ newsize = sizeof quadval;
+ break;
+ }
+ }
+ size = BUFSIZ;
+ if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
+ if (flags == 0)
+ return;
+ switch (errno) {
+ case EOPNOTSUPP:
+ fprintf(stderr, "%s: value is not available\n", string);
+ return;
+ case ENOTDIR:
+ fprintf(stderr, "%s: specification is incomplete\n",
+ string);
+ return;
+ case ENOMEM:
+ fprintf(stderr, "%s: type is unknown to this program\n",
+ string);
+ return;
+ default:
+ perror(string);
+ return;
+ }
+ }
+ if (special & CLOCK) {
+ struct clockinfo *clkp = (struct clockinfo *)buf;
+
+ if (!nflag)
+ fprintf(stdout, "%s: ", string);
+ fprintf(stdout,
+ "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
+ clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
+ return;
+ }
+ if (special & BOOTTIME) {
+ struct timeval *btp = (struct timeval *)buf;
+
+ if (!nflag)
+ fprintf(stdout, "%s = %s\n", string,
+ ctime(&btp->tv_sec));
+ else
+ fprintf(stdout, "%d\n", btp->tv_sec);
+ return;
+ }
+ if (special & CONSDEV) {
+ dev_t dev = *(dev_t *)buf;
+
+ if (!nflag)
+ fprintf(stdout, "%s = %s\n", string,
+ devname(dev, S_IFCHR));
+ else
+ fprintf(stdout, "0x%x\n", dev);
+ return;
+ }
+ switch (type) {
+ case CTLTYPE_INT:
+ if (newsize == 0) {
+ if (!nflag)
+ fprintf(stdout, "%s = ", string);
+ fprintf(stdout, "%d\n", *(int *)buf);
+ } else {
+ if (!nflag)
+ fprintf(stdout, "%s: %d -> ", string,
+ *(int *)buf);
+ fprintf(stdout, "%d\n", *(int *)newval);
+ }
+ return;
+
+ case CTLTYPE_STRING:
+ if (newsize == 0) {
+ if (!nflag)
+ fprintf(stdout, "%s = ", string);
+ fprintf(stdout, "%s\n", buf);
+ } else {
+ if (!nflag)
+ fprintf(stdout, "%s: %s -> ", string, buf);
+ fprintf(stdout, "%s\n", newval);
+ }
+ return;
+
+ case CTLTYPE_QUAD:
+ if (newsize == 0) {
+ if (!nflag)
+ fprintf(stdout, "%s = ", string);
+ fprintf(stdout, "%qd\n", *(quad_t *)buf);
+ } else {
+ if (!nflag)
+ fprintf(stdout, "%s: %qd -> ", string,
+ *(quad_t *)buf);
+ fprintf(stdout, "%qd\n", *(quad_t *)newval);
+ }
+ return;
+
+ case CTLTYPE_STRUCT:
+ fprintf(stderr, "%s: unknown structure returned\n",
+ string);
+ return;
+
+ default:
+ case CTLTYPE_NODE:
+ fprintf(stderr, "%s: unknown type returned\n",
+ string);
+ return;
+ }
+}
+
+/*
+ * Initialize the set of debugging names
+ */
+debuginit()
+{
+ int mib[3], size, loc, i;
+
+ if (secondlevel[CTL_DEBUG].list != 0)
+ return;
+ secondlevel[CTL_DEBUG].list = debugname;
+ mib[0] = CTL_DEBUG;
+ mib[2] = CTL_DEBUG_NAME;
+ for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
+ mib[1] = i;
+ size = BUFSIZ - loc;
+ if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
+ continue;
+ debugname[i].ctl_name = &names[loc];
+ debugname[i].ctl_type = CTLTYPE_INT;
+ loc += size;
+ }
+}
+
+struct ctlname inetname[] = CTL_IPPROTO_NAMES;
+struct ctlname ipname[] = IPCTL_NAMES;
+struct ctlname icmpname[] = ICMPCTL_NAMES;
+struct ctlname udpname[] = UDPCTL_NAMES;
+struct list inetlist = { inetname, IPPROTO_MAXID };
+struct list inetvars[] = {
+ { ipname, IPCTL_MAXID }, /* ip */
+ { icmpname, ICMPCTL_MAXID }, /* icmp */
+ { 0, 0 }, /* igmp */
+ { 0, 0 }, /* ggmp */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }, /* tcp */
+ { 0, 0 },
+ { 0, 0 }, /* egp */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }, /* pup */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { udpname, UDPCTL_MAXID }, /* udp */
+};
+
+/*
+ * handle internet requests
+ */
+sysctl_inet(string, bufpp, mib, flags, typep)
+ char *string;
+ char **bufpp;
+ int mib[];
+ int flags;
+ int *typep;
+{
+ struct list *lp;
+ int indx;
+
+ if (*bufpp == NULL) {
+ listall(string, &inetlist);
+ return (-1);
+ }
+ if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
+ return (-1);
+ mib[2] = indx;
+ if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
+ lp = &inetvars[indx];
+ else if (!flags)
+ return (-1);
+ else {
+ fprintf(stderr, "%s: no variables defined for this protocol\n",
+ string);
+ return (-1);
+ }
+ if (*bufpp == NULL) {
+ listall(string, lp);
+ return (-1);
+ }
+ if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
+ return (-1);
+ mib[3] = indx;
+ *typep = lp->list[indx].ctl_type;
+ return (4);
+}
+
+/*
+ * Scan a list of names searching for a particular name.
+ */
+findname(string, level, bufp, namelist)
+ char *string;
+ char *level;
+ char **bufp;
+ struct list *namelist;
+{
+ char *name;
+ int i;
+
+ if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
+ fprintf(stderr, "%s: incomplete specification\n", string);
+ return (-1);
+ }
+ for (i = 0; i < namelist->size; i++)
+ if (namelist->list[i].ctl_name != NULL &&
+ strcmp(name, namelist->list[i].ctl_name) == 0)
+ break;
+ if (i == namelist->size) {
+ fprintf(stderr, "%s level name %s in %s is invalid\n",
+ level, name, string);
+ return (-1);
+ }
+ return (i);
+}
+
+usage()
+{
+
+ (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
+ "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
+ "sysctl [-n] -a", "sysctl [-n] -A");
+ exit(1);
+}
diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile
new file mode 100644
index 0000000..b06fefb
--- /dev/null
+++ b/usr.sbin/syslogd/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= syslogd
+SRCS= syslogd.c ttymsg.c
+.PATH: ${.CURDIR}/../../usr.bin/wall
+MAN5= syslog.conf.0
+MAN8= syslogd.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/syslogd/pathnames.h b/usr.sbin/syslogd/pathnames.h
new file mode 100644
index 0000000..2dc61a8
--- /dev/null
+++ b/usr.sbin/syslogd/pathnames.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#define _PATH_KLOG "/dev/klog"
+#define _PATH_LOGCONF "/etc/syslog.conf"
+#define _PATH_LOGPID "/var/run/syslog.pid"
diff --git a/usr.sbin/syslogd/syslog.conf.5 b/usr.sbin/syslogd/syslog.conf.5
new file mode 100644
index 0000000..b19e75d
--- /dev/null
+++ b/usr.sbin/syslogd/syslog.conf.5
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt SYSLOG.CONF 5
+.Os
+.Sh NAME
+.Nm syslog.conf
+.Nd
+.Xr syslogd 8
+configuration file
+.Sh DESCRIPTION
+The
+.Nm syslog.conf
+file is the configuration file for the
+.Xr syslogd 8
+program.
+It consists of lines with two fields: the
+.Em selector
+field which specifies the types of messages and priorities to which the
+line applies, and an
+.Em action
+field which specifies the action to be taken if a message
+.Xr syslogd
+receives matches the selection criteria.
+The
+.Em selector
+field is separated from the
+.Em action
+field by one or more tab characters.
+.Pp
+The
+.Em Selectors
+function
+are encoded as a
+.Em facility ,
+a period (``.''), and a
+.Em level ,
+with no intervening white-space.
+Both the
+.Em facility
+and the
+.Em level
+are case insensitive.
+.Pp
+The
+.Em facility
+describes the part of the system generating the message, and is one of
+the following keywords: auth, authpriv, cron, daemon, kern, lpr, mail,
+mark, news, syslog, user, uucp and local0 through local7.
+These keywords (with the exception of mark) correspond to the
+similar
+.Dq Dv LOG_
+values specified to the
+.Xr openlog 3
+and
+.Xr syslog 3
+library routines.
+.Pp
+The
+.Em level
+describes the severity of the message, and is a keyword from the
+following ordered list (higher to lower): emerg, alert, crit, err,
+warning, notice and debug.
+These keywords correspond to the
+similar
+.Pq Dv LOG_
+values specified to the
+.Xr syslog
+library routine.
+.Pp
+See
+.Xr syslog 3
+for a further descriptions of both the
+.Em facility
+and
+.Em level
+keywords and their significance.
+.Pp
+If a received message matches the specified
+.Em facility
+and is of the specified
+.Em level
+.Em (or a higher level) ,
+the action specified in the
+.Em action
+field will be taken.
+.Pp
+Multiple
+.Em selectors
+may be specified for a single
+.Em action
+by separating them with semicolon (``;'') characters.
+It is important to note, however, that each
+.Em selector
+can modify the ones preceding it.
+.Pp
+Multiple
+.Em facilities
+may be specified for a single
+.Em level
+by separating them with comma (``,'') characters.
+.Pp
+An asterisk (``*'') can be used to specify all
+.Em facilities
+or all
+.Em levels .
+.Pp
+The special
+.Em facility
+``mark'' receives a message at priority ``info'' every 20 minutes
+(see
+.Xr syslogd 8 ) .
+This is not enabled by a
+.Em facility
+field containing an asterisk.
+.Pp
+The special
+.Em level
+``none'' disables a particular
+.Em facility .
+.Pp
+The
+.Em action
+field of each line specifies the action to be taken when the
+.Em selector
+field selects a message.
+There are four forms:
+.Bl -bullet
+.It
+A pathname (beginning with a leading slash).
+Selected messages are appended to the file.
+.It
+A hostname (preceded by an at (``@'') sign).
+Selected messages are forwarded to the
+.Xr syslogd
+program on the named host.
+.It
+A comma separated list of users.
+Selected messages are written to those users
+if they are logged in.
+.It
+An asterisk.
+Selected messages are written to all logged-in users.
+.El
+.Pp
+Blank lines and lines whose first non-blank character is a hash (``#'')
+character are ignored.
+.Sh EXAMPLES
+.Pp
+A configuration file might appear as follows:
+.Bd -literal
+# Log all kernel messages, authentication messages of
+# level notice or higher and anything of level err or
+# higher to the console.
+# Don't log private authentication messages!
+*.err;kern.*;auth.notice;authpriv.none /dev/console
+
+# Log anything (except mail) of level info or higher.
+# Don't log private authentication messages!
+*.info;mail.none;authpriv.none /var/log/messages
+
+# The authpriv file has restricted access.
+authpriv.* /var/log/secure
+
+# Log all the mail messages in one place.
+mail.* /var/log/maillog
+
+# Everybody gets emergency messages, plus log them on another
+# machine.
+*.emerg *
+*.emerg @arpa.berkeley.edu
+
+# Root and Eric get alert and higher messages.
+*.alert root,eric
+
+# Save mail and news errors of level err and higher in a
+# special file.
+uucp,news.crit /var/log/spoolerr
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/syslog.conf -compact
+.It Pa /etc/syslog.conf
+The
+.Xr syslogd 8
+configuration file.
+.El
+.Sh BUGS
+The effects of multiple selectors are sometimes not intuitive.
+For example ``mail.crit,*.err'' will select ``mail'' facility messages at
+the level of ``err'' or higher, not at the level of ``crit'' or higher.
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr syslogd 8
diff --git a/usr.sbin/syslogd/syslogd.8 b/usr.sbin/syslogd/syslogd.8
new file mode 100644
index 0000000..09f3ddb
--- /dev/null
+++ b/usr.sbin/syslogd/syslogd.8
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1983, 1986, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)syslogd.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt SYSLOGD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm syslogd
+.Nd log systems messages
+.Sh SYNOPSIS
+.Nm syslogd
+.Op Fl f Ar config_file
+.Op Fl m Ar mark_interval
+.Op Fl p Ar log_socket
+.Sh DESCRIPTION
+.Nm Syslogd
+reads and logs messages to the system console, log files, other
+machines and/or users as specified by its configuration file.
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+Specify the pathname of an alternate configuration file;
+the default is
+.Pa /etc/syslog.conf .
+.It Fl m
+Select the number of minutes between ``mark'' messages;
+the default is 20 minutes.
+.It Fl p
+Specify the pathname of an alternate log socket;
+the default is
+.Pa /dev/log .
+.El
+.Pp
+.Nm Syslogd
+reads its configuration file when it starts up and whenever it
+receives a hangup signal.
+For information on the format of the configuration file,
+see
+.Xr syslog.conf 5 .
+.Pp
+.Nm Syslogd
+reads messages from the
+.Tn UNIX
+domain socket
+.Pa /dev/log ,
+from an Internet domain socket specified in
+.Pa /etc/services ,
+and from the special device
+.Pa /dev/klog
+(to read kernel messages).
+.Pp
+.Nm Syslogd
+creates the file
+.Pa /var/run/syslog.pid ,
+and stores its process
+id there.
+This can be used to kill or reconfigure
+.Nm syslogd .
+.Pp
+The message sent to
+.Nm syslogd
+should consist of a single line.
+The message can contain a priority code, which should be a preceding
+decimal number in angle braces, for example,
+.Sq Aq 5.
+This priority code should map into the priorities defined in the
+include file
+.Aq Pa sys/syslog.h .
+.Sh FILES
+.Bl -tag -width /var/run/syslog.pid -compact
+.It Pa /etc/syslog.conf
+The configuration file.
+.It Pa /var/run/syslog.pid
+The process id of current
+.Nm syslogd .
+.It Pa /dev/log
+Name of the
+.Tn UNIX
+domain datagram log socket.
+.It Pa /dev/klog
+The kernel log device.
+.El
+.Sh SEE ALSO
+.Xr logger 1 ,
+.Xr syslog 3 ,
+.Xr services 5 ,
+.Xr syslog.conf 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
new file mode 100644
index 0000000..01c5d51
--- /dev/null
+++ b/usr.sbin/syslogd/syslogd.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 1983, 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
+#endif /* not lint */
+
+/*
+ * syslogd -- log system messages
+ *
+ * This program implements a system log. It takes a series of lines.
+ * Each line may have a priority, signified as "<n>" as
+ * the first characters of the line. If this is
+ * not present, a default priority is used.
+ *
+ * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
+ * cause it to reread its configuration file.
+ *
+ * Defined Constants:
+ *
+ * MAXLINE -- the maximimum line length that can be handled.
+ * DEFUPRI -- the default priority for user messages
+ * DEFSPRI -- the default priority for kernel messages
+ *
+ * Author: Eric Allman
+ * extensive changes by Ralph Campbell
+ * more extensive changes by Eric Allman (again)
+ */
+
+#define MAXLINE 1024 /* maximum line length */
+#define MAXSVLINE 120 /* maximum saved line length */
+#define DEFUPRI (LOG_USER|LOG_NOTICE)
+#define DEFSPRI (LOG_KERN|LOG_CRIT)
+#define TIMERINTVL 30 /* interval for checking flush, mark */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/msgbuf.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include "pathnames.h"
+
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+
+char *LogName = _PATH_LOG;
+char *ConfFile = _PATH_LOGCONF;
+char *PidFile = _PATH_LOGPID;
+char ctty[] = _PATH_CONSOLE;
+
+#define FDMASK(fd) (1 << (fd))
+
+#define dprintf if (Debug) printf
+
+#define MAXUNAMES 20 /* maximum number of user names */
+
+/*
+ * Flags to logmsg().
+ */
+
+#define IGN_CONS 0x001 /* don't print on console */
+#define SYNC_FILE 0x002 /* do fsync on file after printing */
+#define ADDDATE 0x004 /* add a date to the message */
+#define MARK 0x008 /* this message is a mark */
+
+/*
+ * This structure represents the files that will have log
+ * copies printed.
+ */
+
+struct filed {
+ struct filed *f_next; /* next in linked list */
+ short f_type; /* entry type, see below */
+ short f_file; /* file descriptor */
+ time_t f_time; /* time this was last written */
+ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
+ union {
+ char f_uname[MAXUNAMES][UT_NAMESIZE+1];
+ struct {
+ char f_hname[MAXHOSTNAMELEN+1];
+ struct sockaddr_in f_addr;
+ } f_forw; /* forwarding address */
+ char f_fname[MAXPATHLEN];
+ } f_un;
+ char f_prevline[MAXSVLINE]; /* last message logged */
+ char f_lasttime[16]; /* time of last occurrence */
+ char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */
+ int f_prevpri; /* pri of f_prevline */
+ int f_prevlen; /* length of f_prevline */
+ int f_prevcount; /* repetition cnt of prevline */
+ int f_repeatcount; /* number of "repeated" msgs */
+};
+
+/*
+ * Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged. After each flush,
+ * we move to the next interval until we reach the largest.
+ */
+int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
+#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
+#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
+#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
+ (f)->f_repeatcount = MAXREPEAT; \
+ }
+
+/* values for f_type */
+#define F_UNUSED 0 /* unused entry */
+#define F_FILE 1 /* regular file */
+#define F_TTY 2 /* terminal */
+#define F_CONSOLE 3 /* console terminal */
+#define F_FORW 4 /* remote machine */
+#define F_USERS 5 /* list of users */
+#define F_WALL 6 /* everyone logged on */
+
+char *TypeNames[7] = {
+ "UNUSED", "FILE", "TTY", "CONSOLE",
+ "FORW", "USERS", "WALL"
+};
+
+struct filed *Files;
+struct filed consfile;
+
+int Debug; /* debug flag */
+char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
+char *LocalDomain; /* our local domain name */
+int InetInuse = 0; /* non-zero if INET sockets are being used */
+int finet; /* Internet datagram socket */
+int LogPort; /* port number for INET connections */
+int Initialized = 0; /* set when we have initialized ourselves */
+int MarkInterval = 20 * 60; /* interval between marks in seconds */
+int MarkSeq = 0; /* mark sequence number */
+
+void cfline __P((char *, struct filed *));
+char *cvthname __P((struct sockaddr_in *));
+int decode __P((const char *, CODE *));
+void die __P((int));
+void domark __P((int));
+void fprintlog __P((struct filed *, int, char *));
+void init __P((int));
+void logerror __P((char *));
+void logmsg __P((int, char *, char *, int));
+void printline __P((char *, char *));
+void printsys __P((char *));
+void reapchild __P((int));
+char *ttymsg __P((struct iovec *, int, char *, int));
+void usage __P((void));
+void wallmsg __P((struct filed *, struct iovec *));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch, funix, i, inetm, fklog, klogm, len;
+ struct sockaddr_un sunx, fromunix;
+ struct sockaddr_in sin, frominet;
+ FILE *fp;
+ char *p, line[MSG_BSIZE + 1];
+
+ while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)
+ switch(ch) {
+ case 'd': /* debug */
+ Debug++;
+ break;
+ case 'f': /* configuration file */
+ ConfFile = optarg;
+ break;
+ case 'm': /* mark interval */
+ MarkInterval = atoi(optarg) * 60;
+ break;
+ case 'p': /* path */
+ LogName = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ if ((argc -= optind) != 0)
+ usage();
+
+ if (!Debug)
+ (void)daemon(0, 0);
+ else
+ setlinebuf(stdout);
+
+ consfile.f_type = F_CONSOLE;
+ (void)strcpy(consfile.f_un.f_fname, ctty);
+ (void)gethostname(LocalHostName, sizeof(LocalHostName));
+ if ((p = strchr(LocalHostName, '.')) != NULL) {
+ *p++ = '\0';
+ LocalDomain = p;
+ } else
+ LocalDomain = "";
+ (void)signal(SIGTERM, die);
+ (void)signal(SIGINT, Debug ? die : SIG_IGN);
+ (void)signal(SIGQUIT, Debug ? die : SIG_IGN);
+ (void)signal(SIGCHLD, reapchild);
+ (void)signal(SIGALRM, domark);
+ (void)alarm(TIMERINTVL);
+ (void)unlink(LogName);
+
+#ifndef SUN_LEN
+#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
+#endif
+ memset(&sunx, 0, sizeof(sunx));
+ sunx.sun_family = AF_UNIX;
+ (void)strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path));
+ funix = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (funix < 0 ||
+ bind(funix, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 ||
+ chmod(LogName, 0666) < 0) {
+ (void) sprintf(line, "cannot create %s", LogName);
+ logerror(line);
+ dprintf("cannot create %s (%d)\n", LogName, errno);
+ die(0);
+ }
+ finet = socket(AF_INET, SOCK_DGRAM, 0);
+ inetm = 0;
+ if (finet >= 0) {
+ struct servent *sp;
+
+ sp = getservbyname("syslog", "udp");
+ if (sp == NULL) {
+ errno = 0;
+ logerror("syslog/udp: unknown service");
+ die(0);
+ }
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = LogPort = sp->s_port;
+ if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ logerror("bind");
+ if (!Debug)
+ die(0);
+ } else {
+ inetm = FDMASK(finet);
+ InetInuse = 1;
+ }
+ }
+ if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)
+ klogm = FDMASK(fklog);
+ else {
+ dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
+ klogm = 0;
+ }
+
+ /* tuck my process id away */
+ fp = fopen(PidFile, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", getpid());
+ (void) fclose(fp);
+ }
+
+ dprintf("off & running....\n");
+
+ init(0);
+ (void)signal(SIGHUP, init);
+
+ for (;;) {
+ int nfds, readfds = FDMASK(funix) | inetm | klogm;
+
+ dprintf("readfds = %#x\n", readfds);
+ nfds = select(20, (fd_set *)&readfds, (fd_set *)NULL,
+ (fd_set *)NULL, (struct timeval *)NULL);
+ if (nfds == 0)
+ continue;
+ if (nfds < 0) {
+ if (errno != EINTR)
+ logerror("select");
+ continue;
+ }
+ dprintf("got a message (%d, %#x)\n", nfds, readfds);
+ if (readfds & klogm) {
+ i = read(fklog, line, sizeof(line) - 1);
+ if (i > 0) {
+ line[i] = '\0';
+ printsys(line);
+ } else if (i < 0 && errno != EINTR) {
+ logerror("klog");
+ fklog = -1;
+ klogm = 0;
+ }
+ }
+ if (readfds & FDMASK(funix)) {
+ len = sizeof(fromunix);
+ i = recvfrom(funix, line, MAXLINE, 0,
+ (struct sockaddr *)&fromunix, &len);
+ if (i > 0) {
+ line[i] = '\0';
+ printline(LocalHostName, line);
+ } else if (i < 0 && errno != EINTR)
+ logerror("recvfrom unix");
+ }
+ if (readfds & inetm) {
+ len = sizeof(frominet);
+ i = recvfrom(finet, line, MAXLINE, 0,
+ (struct sockaddr *)&frominet, &len);
+ if (i > 0) {
+ line[i] = '\0';
+ printline(cvthname(&frominet), line);
+ } else if (i < 0 && errno != EINTR)
+ logerror("recvfrom inet");
+ }
+ }
+}
+
+void
+usage()
+{
+
+ (void)fprintf(stderr,
+ "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n");
+ exit(1);
+}
+
+/*
+ * Take a raw input line, decode the message, and print the message
+ * on the appropriate log files.
+ */
+void
+printline(hname, msg)
+ char *hname;
+ char *msg;
+{
+ int c, pri;
+ char *p, *q, line[MAXLINE + 1];
+
+ /* test for special codes */
+ pri = DEFUPRI;
+ p = msg;
+ if (*p == '<') {
+ pri = 0;
+ while (isdigit(*++p))
+ pri = 10 * pri + (*p - '0');
+ if (*p == '>')
+ ++p;
+ }
+ if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+ pri = DEFUPRI;
+
+ /* don't allow users to log kernel messages */
+ if (LOG_FAC(pri) == LOG_KERN)
+ pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
+
+ q = line;
+
+ while ((c = *p++ & 0177) != '\0' &&
+ q < &line[sizeof(line) - 1])
+ if (iscntrl(c))
+ if (c == '\n')
+ *q++ = ' ';
+ else if (c == '\t')
+ *q++ = '\t';
+ else {
+ *q++ = '^';
+ *q++ = c ^ 0100;
+ }
+ else
+ *q++ = c;
+ *q = '\0';
+
+ logmsg(pri, line, hname, 0);
+}
+
+/*
+ * Take a raw input line from /dev/klog, split and format similar to syslog().
+ */
+void
+printsys(msg)
+ char *msg;
+{
+ int c, pri, flags;
+ char *lp, *p, *q, line[MAXLINE + 1];
+
+ (void)strcpy(line, "vmunix: ");
+ lp = line + strlen(line);
+ for (p = msg; *p != '\0'; ) {
+ flags = SYNC_FILE | ADDDATE; /* fsync file after write */
+ pri = DEFSPRI;
+ if (*p == '<') {
+ pri = 0;
+ while (isdigit(*++p))
+ pri = 10 * pri + (*p - '0');
+ if (*p == '>')
+ ++p;
+ } else {
+ /* kernel printf's come out on console */
+ flags |= IGN_CONS;
+ }
+ if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+ pri = DEFSPRI;
+ q = lp;
+ while (*p != '\0' && (c = *p++) != '\n' &&
+ q < &line[MAXLINE])
+ *q++ = c;
+ *q = '\0';
+ logmsg(pri, line, LocalHostName, flags);
+ }
+}
+
+time_t now;
+
+/*
+ * Log a message to the appropriate log files, users, etc. based on
+ * the priority.
+ */
+void
+logmsg(pri, msg, from, flags)
+ int pri;
+ char *msg, *from;
+ int flags;
+{
+ struct filed *f;
+ int fac, msglen, omask, prilev;
+ char *timestamp;
+
+ dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
+ pri, flags, from, msg);
+
+ omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
+
+ /*
+ * Check to see if msg looks non-standard.
+ */
+ msglen = strlen(msg);
+ if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+ msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
+ flags |= ADDDATE;
+
+ (void)time(&now);
+ if (flags & ADDDATE)
+ timestamp = ctime(&now) + 4;
+ else {
+ timestamp = msg;
+ msg += 16;
+ msglen -= 16;
+ }
+
+ /* extract facility and priority level */
+ if (flags & MARK)
+ fac = LOG_NFACILITIES;
+ else
+ fac = LOG_FAC(pri);
+ prilev = LOG_PRI(pri);
+
+ /* log the message to the particular outputs */
+ if (!Initialized) {
+ f = &consfile;
+ f->f_file = open(ctty, O_WRONLY, 0);
+
+ if (f->f_file >= 0) {
+ fprintlog(f, flags, msg);
+ (void)close(f->f_file);
+ }
+ (void)sigsetmask(omask);
+ return;
+ }
+ for (f = Files; f; f = f->f_next) {
+ /* skip messages that are incorrect priority */
+ if (f->f_pmask[fac] < prilev ||
+ f->f_pmask[fac] == INTERNAL_NOPRI)
+ continue;
+
+ if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
+ continue;
+
+ /* don't output marks to recently written files */
+ if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
+ continue;
+
+ /*
+ * suppress duplicate lines to this file
+ */
+ if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
+ !strcmp(msg, f->f_prevline) &&
+ !strcmp(from, f->f_prevhost)) {
+ (void)strncpy(f->f_lasttime, timestamp, 15);
+ f->f_prevcount++;
+ dprintf("msg repeated %d times, %ld sec of %d\n",
+ f->f_prevcount, now - f->f_time,
+ repeatinterval[f->f_repeatcount]);
+ /*
+ * If domark would have logged this by now,
+ * flush it now (so we don't hold isolated messages),
+ * but back off so we'll flush less often
+ * in the future.
+ */
+ if (now > REPEATTIME(f)) {
+ fprintlog(f, flags, (char *)NULL);
+ BACKOFF(f);
+ }
+ } else {
+ /* new line, save it */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+ f->f_repeatcount = 0;
+ (void)strncpy(f->f_lasttime, timestamp, 15);
+ (void)strncpy(f->f_prevhost, from,
+ sizeof(f->f_prevhost));
+ if (msglen < MAXSVLINE) {
+ f->f_prevlen = msglen;
+ f->f_prevpri = pri;
+ (void)strcpy(f->f_prevline, msg);
+ fprintlog(f, flags, (char *)NULL);
+ } else {
+ f->f_prevline[0] = 0;
+ f->f_prevlen = 0;
+ fprintlog(f, flags, msg);
+ }
+ }
+ }
+ (void)sigsetmask(omask);
+}
+
+void
+fprintlog(f, flags, msg)
+ struct filed *f;
+ int flags;
+ char *msg;
+{
+ struct iovec iov[6];
+ struct iovec *v;
+ int l;
+ char line[MAXLINE + 1], repbuf[80], greetings[200];
+
+ v = iov;
+ if (f->f_type == F_WALL) {
+ v->iov_base = greetings;
+ v->iov_len = sprintf(greetings,
+ "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
+ f->f_prevhost, ctime(&now));
+ v++;
+ v->iov_base = "";
+ v->iov_len = 0;
+ v++;
+ } else {
+ v->iov_base = f->f_lasttime;
+ v->iov_len = 15;
+ v++;
+ v->iov_base = " ";
+ v->iov_len = 1;
+ v++;
+ }
+ v->iov_base = f->f_prevhost;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ v->iov_base = " ";
+ v->iov_len = 1;
+ v++;
+
+ if (msg) {
+ v->iov_base = msg;
+ v->iov_len = strlen(msg);
+ } else if (f->f_prevcount > 1) {
+ v->iov_base = repbuf;
+ v->iov_len = sprintf(repbuf, "last message repeated %d times",
+ f->f_prevcount);
+ } else {
+ v->iov_base = f->f_prevline;
+ v->iov_len = f->f_prevlen;
+ }
+ v++;
+
+ dprintf("Logging to %s", TypeNames[f->f_type]);
+ f->f_time = now;
+
+ switch (f->f_type) {
+ case F_UNUSED:
+ dprintf("\n");
+ break;
+
+ case F_FORW:
+ dprintf(" %s\n", f->f_un.f_forw.f_hname);
+ l = sprintf(line, "<%d>%.15s %s", f->f_prevpri,
+ iov[0].iov_base, iov[4].iov_base);
+ if (l > MAXLINE)
+ l = MAXLINE;
+ if (sendto(finet, line, l, 0,
+ (struct sockaddr *)&f->f_un.f_forw.f_addr,
+ sizeof(f->f_un.f_forw.f_addr)) != l) {
+ int e = errno;
+ (void)close(f->f_file);
+ f->f_type = F_UNUSED;
+ errno = e;
+ logerror("sendto");
+ }
+ break;
+
+ case F_CONSOLE:
+ if (flags & IGN_CONS) {
+ dprintf(" (ignored)\n");
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case F_TTY:
+ case F_FILE:
+ dprintf(" %s\n", f->f_un.f_fname);
+ if (f->f_type != F_FILE) {
+ v->iov_base = "\r\n";
+ v->iov_len = 2;
+ } else {
+ v->iov_base = "\n";
+ v->iov_len = 1;
+ }
+ again:
+ if (writev(f->f_file, iov, 6) < 0) {
+ int e = errno;
+ (void)close(f->f_file);
+ /*
+ * Check for errors on TTY's due to loss of tty
+ */
+ if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
+ f->f_file = open(f->f_un.f_fname,
+ O_WRONLY|O_APPEND, 0);
+ if (f->f_file < 0) {
+ f->f_type = F_UNUSED;
+ logerror(f->f_un.f_fname);
+ } else
+ goto again;
+ } else {
+ f->f_type = F_UNUSED;
+ errno = e;
+ logerror(f->f_un.f_fname);
+ }
+ } else if (flags & SYNC_FILE)
+ (void)fsync(f->f_file);
+ break;
+
+ case F_USERS:
+ case F_WALL:
+ dprintf("\n");
+ v->iov_base = "\r\n";
+ v->iov_len = 2;
+ wallmsg(f, iov);
+ break;
+ }
+ f->f_prevcount = 0;
+}
+
+/*
+ * WALLMSG -- Write a message to the world at large
+ *
+ * Write the specified message to either the entire
+ * world, or a list of approved users.
+ */
+void
+wallmsg(f, iov)
+ struct filed *f;
+ struct iovec *iov;
+{
+ static int reenter; /* avoid calling ourselves */
+ FILE *uf;
+ struct utmp ut;
+ int i;
+ char *p;
+ char line[sizeof(ut.ut_line) + 1];
+
+ if (reenter++)
+ return;
+ if ((uf = fopen(_PATH_UTMP, "r")) == NULL) {
+ logerror(_PATH_UTMP);
+ reenter = 0;
+ return;
+ }
+ /* NOSTRICT */
+ while (fread((char *)&ut, sizeof(ut), 1, uf) == 1) {
+ if (ut.ut_name[0] == '\0')
+ continue;
+ strncpy(line, ut.ut_line, sizeof(ut.ut_line));
+ line[sizeof(ut.ut_line)] = '\0';
+ if (f->f_type == F_WALL) {
+ if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) {
+ errno = 0; /* already in msg */
+ logerror(p);
+ }
+ continue;
+ }
+ /* should we send the message to this user? */
+ for (i = 0; i < MAXUNAMES; i++) {
+ if (!f->f_un.f_uname[i][0])
+ break;
+ if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
+ UT_NAMESIZE)) {
+ if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) {
+ errno = 0; /* already in msg */
+ logerror(p);
+ }
+ break;
+ }
+ }
+ }
+ (void)fclose(uf);
+ reenter = 0;
+}
+
+void
+reapchild(signo)
+ int signo;
+{
+ union wait status;
+
+ while (wait3((int *)&status, WNOHANG, (struct rusage *)NULL) > 0)
+ ;
+}
+
+/*
+ * Return a printable representation of a host address.
+ */
+char *
+cvthname(f)
+ struct sockaddr_in *f;
+{
+ struct hostent *hp;
+ char *p;
+
+ dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
+
+ if (f->sin_family != AF_INET) {
+ dprintf("Malformed from address\n");
+ return ("???");
+ }
+ hp = gethostbyaddr((char *)&f->sin_addr,
+ sizeof(struct in_addr), f->sin_family);
+ if (hp == 0) {
+ dprintf("Host name for your address (%s) unknown\n",
+ inet_ntoa(f->sin_addr));
+ return (inet_ntoa(f->sin_addr));
+ }
+ if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
+ *p = '\0';
+ return (hp->h_name);
+}
+
+void
+domark(signo)
+ int signo;
+{
+ struct filed *f;
+
+ now = time((time_t *)NULL);
+ MarkSeq += TIMERINTVL;
+ if (MarkSeq >= MarkInterval) {
+ logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
+ MarkSeq = 0;
+ }
+
+ for (f = Files; f; f = f->f_next) {
+ if (f->f_prevcount && now >= REPEATTIME(f)) {
+ dprintf("flush %s: repeated %d times, %d sec.\n",
+ TypeNames[f->f_type], f->f_prevcount,
+ repeatinterval[f->f_repeatcount]);
+ fprintlog(f, 0, (char *)NULL);
+ BACKOFF(f);
+ }
+ }
+ (void)alarm(TIMERINTVL);
+}
+
+/*
+ * Print syslogd errors some place.
+ */
+void
+logerror(type)
+ char *type;
+{
+ char buf[100];
+
+ if (errno)
+ (void)snprintf(buf,
+ sizeof(buf), "syslogd: %s: %s", type, strerror(errno));
+ else
+ (void)snprintf(buf, sizeof(buf), "syslogd: %s", type);
+ errno = 0;
+ dprintf("%s\n", buf);
+ logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
+}
+
+void
+die(signo)
+ int signo;
+{
+ struct filed *f;
+ char buf[100];
+
+ for (f = Files; f != NULL; f = f->f_next) {
+ /* flush any pending output */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+ }
+ if (signo) {
+ dprintf("syslogd: exiting on signal %d\n", signo);
+ (void)sprintf(buf, "exiting on signal %d", signo);
+ errno = 0;
+ logerror(buf);
+ }
+ (void)unlink(LogName);
+ exit(0);
+}
+
+/*
+ * INIT -- Initialize syslogd from configuration table
+ */
+void
+init(signo)
+ int signo;
+{
+ int i;
+ FILE *cf;
+ struct filed *f, *next, **nextp;
+ char *p;
+ char cline[LINE_MAX];
+
+ dprintf("init\n");
+
+ /*
+ * Close all open log files.
+ */
+ Initialized = 0;
+ for (f = Files; f != NULL; f = next) {
+ /* flush any pending output */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+
+ switch (f->f_type) {
+ case F_FILE:
+ case F_TTY:
+ case F_CONSOLE:
+ case F_FORW:
+ (void)close(f->f_file);
+ break;
+ }
+ next = f->f_next;
+ free((char *)f);
+ }
+ Files = NULL;
+ nextp = &Files;
+
+ /* open the configuration file */
+ if ((cf = fopen(ConfFile, "r")) == NULL) {
+ dprintf("cannot open %s\n", ConfFile);
+ *nextp = (struct filed *)calloc(1, sizeof(*f));
+ cfline("*.ERR\t/dev/console", *nextp);
+ (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
+ cfline("*.PANIC\t*", (*nextp)->f_next);
+ Initialized = 1;
+ return;
+ }
+
+ /*
+ * Foreach line in the conf table, open that file.
+ */
+ f = NULL;
+ while (fgets(cline, sizeof(cline), cf) != NULL) {
+ /*
+ * check for end-of-section, comments, strip off trailing
+ * spaces and newline character.
+ */
+ for (p = cline; isspace(*p); ++p)
+ continue;
+ if (*p == NULL || *p == '#')
+ continue;
+ for (p = strchr(cline, '\0'); isspace(*--p);)
+ continue;
+ *++p = '\0';
+ f = (struct filed *)calloc(1, sizeof(*f));
+ *nextp = f;
+ nextp = &f->f_next;
+ cfline(cline, f);
+ }
+
+ /* close the configuration file */
+ (void)fclose(cf);
+
+ Initialized = 1;
+
+ if (Debug) {
+ for (f = Files; f; f = f->f_next) {
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ if (f->f_pmask[i] == INTERNAL_NOPRI)
+ printf("X ");
+ else
+ printf("%d ", f->f_pmask[i]);
+ printf("%s: ", TypeNames[f->f_type]);
+ switch (f->f_type) {
+ case F_FILE:
+ case F_TTY:
+ case F_CONSOLE:
+ printf("%s", f->f_un.f_fname);
+ break;
+
+ case F_FORW:
+ printf("%s", f->f_un.f_forw.f_hname);
+ break;
+
+ case F_USERS:
+ for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
+ printf("%s, ", f->f_un.f_uname[i]);
+ break;
+ }
+ printf("\n");
+ }
+ }
+
+ logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
+ dprintf("syslogd: restarted\n");
+}
+
+/*
+ * Crack a configuration file line
+ */
+void
+cfline(line, f)
+ char *line;
+ struct filed *f;
+{
+ struct hostent *hp;
+ int i, pri;
+ char *bp, *p, *q;
+ char buf[MAXLINE], ebuf[100];
+
+ dprintf("cfline(%s)\n", line);
+
+ errno = 0; /* keep strerror() stuff out of logerror messages */
+
+ /* clear out file entry */
+ memset(f, 0, sizeof(*f));
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ f->f_pmask[i] = INTERNAL_NOPRI;
+
+ /* scan through the list of selectors */
+ for (p = line; *p && *p != '\t';) {
+
+ /* find the end of this facility name list */
+ for (q = p; *q && *q != '\t' && *q++ != '.'; )
+ continue;
+
+ /* collect priority name */
+ for (bp = buf; *q && !strchr("\t,;", *q); )
+ *bp++ = *q++;
+ *bp = '\0';
+
+ /* skip cruft */
+ while (strchr(", ;", *q))
+ q++;
+
+ /* decode priority name */
+ if (*buf == '*')
+ pri = LOG_PRIMASK + 1;
+ else {
+ pri = decode(buf, prioritynames);
+ if (pri < 0) {
+ (void)sprintf(ebuf,
+ "unknown priority name \"%s\"", buf);
+ logerror(ebuf);
+ return;
+ }
+ }
+
+ /* scan facilities */
+ while (*p && !strchr("\t.;", *p)) {
+ for (bp = buf; *p && !strchr("\t,;.", *p); )
+ *bp++ = *p++;
+ *bp = '\0';
+ if (*buf == '*')
+ for (i = 0; i < LOG_NFACILITIES; i++)
+ f->f_pmask[i] = pri;
+ else {
+ i = decode(buf, facilitynames);
+ if (i < 0) {
+ (void)sprintf(ebuf,
+ "unknown facility name \"%s\"",
+ buf);
+ logerror(ebuf);
+ return;
+ }
+ f->f_pmask[i >> 3] = pri;
+ }
+ while (*p == ',' || *p == ' ')
+ p++;
+ }
+
+ p = q;
+ }
+
+ /* skip to action part */
+ while (*p == '\t')
+ p++;
+
+ switch (*p)
+ {
+ case '@':
+ if (!InetInuse)
+ break;
+ (void)strcpy(f->f_un.f_forw.f_hname, ++p);
+ hp = gethostbyname(p);
+ if (hp == NULL) {
+ extern int h_errno;
+
+ logerror(hstrerror(h_errno));
+ break;
+ }
+ memset(&f->f_un.f_forw.f_addr, 0,
+ sizeof(f->f_un.f_forw.f_addr));
+ f->f_un.f_forw.f_addr.sin_family = AF_INET;
+ f->f_un.f_forw.f_addr.sin_port = LogPort;
+ memmove(&f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
+ f->f_type = F_FORW;
+ break;
+
+ case '/':
+ (void)strcpy(f->f_un.f_fname, p);
+ if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) {
+ f->f_file = F_UNUSED;
+ logerror(p);
+ break;
+ }
+ if (isatty(f->f_file))
+ f->f_type = F_TTY;
+ else
+ f->f_type = F_FILE;
+ if (strcmp(p, ctty) == 0)
+ f->f_type = F_CONSOLE;
+ break;
+
+ case '*':
+ f->f_type = F_WALL;
+ break;
+
+ default:
+ for (i = 0; i < MAXUNAMES && *p; i++) {
+ for (q = p; *q && *q != ','; )
+ q++;
+ (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
+ if ((q - p) > UT_NAMESIZE)
+ f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
+ else
+ f->f_un.f_uname[i][q - p] = '\0';
+ while (*q == ',' || *q == ' ')
+ q++;
+ p = q;
+ }
+ f->f_type = F_USERS;
+ break;
+ }
+}
+
+
+/*
+ * Decode a symbolic name to a numeric value
+ */
+int
+decode(name, codetab)
+ const char *name;
+ CODE *codetab;
+{
+ CODE *c;
+ char *p, buf[40];
+
+ if (isdigit(*name))
+ return (atoi(name));
+
+ for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
+ if (isupper(*name))
+ *p = tolower(*name);
+ else
+ *p = *name;
+ }
+ *p = '\0';
+ for (c = codetab; c->c_name; c++)
+ if (!strcmp(buf, c->c_name))
+ return (c->c_val);
+
+ return (-1);
+}
diff --git a/usr.sbin/timed/Makefile b/usr.sbin/timed/Makefile
new file mode 100644
index 0000000..a89ab16
--- /dev/null
+++ b/usr.sbin/timed/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+SUBDIR= timed timedc
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/timed/SMM.doc/timed/Makefile b/usr.sbin/timed/SMM.doc/timed/Makefile
new file mode 100644
index 0000000..22ff6e6
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/8/93
+
+DIR= smm/12.timed
+SRCS= timed.ms
+MACROS= -ms
+PRINTER=Pdp
+
+paper.${PRINTER}: ${SRCS}
+ ${SOELIM} ${SRCS} | ${TBL} | ${ROFF} > ${.TARGET}
+
+.include <bsd.doc.mk>
diff --git a/usr.sbin/timed/SMM.doc/timed/date b/usr.sbin/timed/SMM.doc/timed/date
new file mode 100644
index 0000000..e4e4d58
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/date
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.\" @(#)date 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Seconds of Time to Set
+_
+Microseconds of Time to Set
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/usr.sbin/timed/SMM.doc/timed/loop b/usr.sbin/timed/SMM.doc/timed/loop
new file mode 100644
index 0000000..11ccb4d
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/loop
@@ -0,0 +1,54 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.\" @(#)loop 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c | c s s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Hop Count ( unused )
+_
+( unused )
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/usr.sbin/timed/SMM.doc/timed/spell.ok b/usr.sbin/timed/SMM.doc/timed/spell.ok
new file mode 100644
index 0000000..8ecfe15
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/spell.ok
@@ -0,0 +1,34 @@
+ACK
+ADJTIME
+Adjtime
+CS
+CSELT
+Candidature
+DATEACK
+DoD
+Gusella
+MASTERACK
+MASTERREQ
+MASTERUP
+MSITE
+MSITEREQ
+Protocol''SMM:22
+Riccardo
+SETDATE
+SETDATEREQ
+SETTIME
+SLAVEUP
+SMM:22
+Stefano
+TRACEOFF
+TRACEON
+TSP
+Timedc
+UDP
+USENIX
+Zatti
+candidature
+ce
+daemon
+daemons
+timedc
diff --git a/usr.sbin/timed/SMM.doc/timed/time b/usr.sbin/timed/SMM.doc/timed/time
new file mode 100644
index 0000000..619d171
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/time
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.\" @(#)time 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Seconds of Adjustment
+_
+Microseconds of Adjustment
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/usr.sbin/timed/SMM.doc/timed/timed.ms b/usr.sbin/timed/SMM.doc/timed/timed.ms
new file mode 100644
index 0000000..f5a3b19
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/timed.ms
@@ -0,0 +1,504 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timed.ms 8.1 (Berkeley) 6/8/93
+.\"
+.TL
+The Berkeley
+.UX
+.br
+Time Synchronization Protocol
+.AU
+Riccardo Gusella, Stefano Zatti, and James M. Bloom
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.FS
+This work was sponsored by the Defense Advanced Research Projects Agency
+(DoD), monitored by the Naval Electronics Systems
+Command under contract No. N00039-84-C-0089, and by the Italian CSELT
+Corporation.
+The views and conclusions contained in this document are those of the
+authors and should not be interpreted as representing official policies,
+either expressed or implied, of the Defense Research Projects Agency,
+of the US Government, or of CSELT.
+.FE
+.LP
+.OH 'The Berkeley UNIX Time Synchronization Protocol''SMM:12-%'
+.EH 'SMM:12-%''The Berkeley UNIX Time Synchronization Protocol'
+.SH
+Introduction
+.PP
+The Time Synchronization Protocol (TSP)
+has been designed for specific use by the program \fItimed\fP,
+a local area network clock synchronizer for
+the UNIX 4.3BSD operating
+system.
+Timed is built on the DARPA UDP protocol [4] and
+is based on a master slave scheme.
+.PP
+TSP serves a dual purpose.
+First, it supports messages for the synchronization of the clocks
+of the various hosts in a local area network.
+Second, it supports messages for the election that occurs
+among slave time daemons when, for any reason, the master disappears.
+The synchronization mechanism and the election procedure
+employed by the program timed are described
+in other documents [1,2,3].
+.PP
+Briefly, the synchronization software, which works in a
+local area network, consists of a collection of \fItime daemons\fP
+(one per machine) and is based on a master-slave
+structure.
+The present implementation keeps processor clocks synchronized
+within 20 milliseconds.
+A \fImaster time daemon\fP measures the time
+difference between the clock of the machine on which it
+is running and those of all other machines. The current implementation
+uses ICMP \fITime Stamp Requests\fP [5] to measure the clock difference
+between machines.
+The master computes the \fInetwork time\fP as the average of the
+times provided by nonfaulty clocks.\**
+.FS
+A clock is considered to be faulty when its value
+is more than a small specified
+interval apart from the majority of the clocks
+of the machines on the same network.
+See [1,2] for more details.
+.FE
+It then sends to each \fIslave time daemon\fP the
+correction that should be performed on the clock of its machine.
+This process is repeated periodically.
+Since the correction is expressed as a time difference rather than an
+absolute time, transmission delays do not interfere with synchronization.
+When a machine comes up and joins the network,
+it starts a slave time daemon, which
+will ask the master for the correct time and will reset the machine's clock
+before any user activity can begin.
+The time daemons therefore maintain a single network time in spite of
+the drift of clocks away from each other.
+.PP
+Additionally, a time daemon on gateway machines may run as
+a \fIsubmaster\fP.
+A submaster time daemon functions as a slave on one network that
+already has a master and as master on other networks.
+In addition, a submaster is responsible for propagating broadcast
+packets from one network to the other.
+.PP
+To ensure that service provided is continuous and reliable,
+it is necessary to implement an election algorithm that will elect a
+new master should the machine running the current master crash, the master
+terminate (for example, because of a run-time error), or the network be
+partitioned.
+Under our algorithm, slaves are able to realize when the master has
+stopped functioning and to elect a new master from among themselves.
+It is important to note that since the failure of the master results
+only in a gradual divergence of clock values, the election
+need not occur immediately.
+.PP
+All the communication occurring among time daemons uses the TSP
+protocol.
+While some messages need not be sent in a reliable way,
+most communication in TSP requires reliability not provided by the underlying
+protocol.
+Reliability is achieved by the use of acknowledgements, sequence numbers, and
+retransmission when message losses occur.
+When a message that requires acknowledgment is not acknowledged after
+multiple attempts,
+the time daemon that has sent the message will assume that the
+addressee is down.
+This document will not describe the details of how reliability is
+implemented, but will only point out when
+a message type requires a reliable transport mechanism.
+.PP
+The message format in TSP is the same for all message types;
+however, in some instances, one or more fields are not used.
+The next section describes the message format.
+The following sections describe
+in detail the different message types, their use and the contents
+of each field. NOTE: The message format is likely to change in
+future versions of timed.
+.sp 2
+.SH
+Message Format
+.PP
+All fields are based upon 8-bit bytes. Fields should be sent in
+network byte order if they are more than one byte long.
+The structure of a TSP message is the following:
+.IP 1)
+A one byte message type.
+.IP 2)
+A one byte version number, specifying the protocol version which the
+message uses.
+.IP 3)
+A two byte sequence number to be used for recognizing duplicate messages
+that occur when messages are retransmitted.
+.IP 4)
+Eight bytes of packet specific data. This field contains two 4 byte time
+values, a one byte hop count, or may be unused depending on the type
+of the packet.
+.IP 5)
+A zero-terminated string of up to 256 \s-2ASCII\s+2 characters with the name of
+the machine sending the message.
+.PP
+The following charts describe the message types,
+show their fields, and explain their usages.
+For the purpose of the following discussion, a time daemon can
+be considered to be in
+one of three states: slave, master, or candidate for election to master.
+Also, the term \fIbroadcast\fP refers to
+the sending of a message to all active time daemons.
+.sp 1
+.DS L
+.SH
+Adjtime Message
+.so time
+.LP
+Type: TSP_ADJTIME (1)
+.sp 1
+.PP
+The master sends this message to a slave to communicate
+the difference between
+the clock of the slave and
+the network time the master has just computed.
+The slave will accordingly
+adjust the time of its machine.
+This message requires an acknowledgment.
+.sp 1
+.DE
+.DS L
+.SH
+Acknowledgment Message
+.so unused
+.LP
+Type: TSP_ACK (2)
+.sp 1
+.PP
+Both the master and the slaves use this message for
+acknowledgment only.
+It is used in several different contexts, for example
+in reply to an Adjtime message.
+.sp 1
+.DE
+.DS L
+.SH
+Master Request Message
+.so unused
+.LP
+Type: TSP_MASTERREQ (3)
+.sp 1
+.PP
+A newly-started time daemon broadcasts this message to
+locate a master. No other action is implied by this packet.
+It requires a Master Acknowledgment.
+.sp 1
+.DE
+.DS L
+.SH
+Master Acknowledgement
+.so unused
+.LP
+Type: TSP_MASTERACK (4)
+.sp 1
+.PP
+The master sends this message to acknowledge the Master Request message
+and the Conflict Resolution Message.
+.sp 1
+.DE
+.DS L
+.SH
+Set Network Time Message
+.so date
+.LP
+Type: TSP_SETTIME (5)
+.sp 1
+.PP
+The master sends this message to slave time daemons to set their time.
+This packet is sent to newly started time daemons and when the network
+date is changed.
+It contains the master's time as an approximation of the network time.
+It requires an acknowledgment.
+The next
+synchronization round will eliminate the small time difference
+caused by the random delay in the communication channel.
+.sp 1
+.DE
+.DS L
+.SH
+Master Active Message
+.so unused
+.LP
+Type: TSP_MASTERUP (6)
+.sp 1
+.PP
+The master broadcasts this message to
+solicit the names of the active slaves.
+Slaves will reply with a Slave Active message.
+.sp 1
+.DE
+.DS L
+.SH
+Slave Active Message
+.so unused
+.LP
+Type: TSP_SLAVEUP (7)
+.sp 1
+.PP
+A slave sends this message to the master in answer to a Master Active message.
+This message is also sent when a new slave starts up to inform the master that
+it wants to be synchronized.
+.sp 1
+.DE
+.DS L
+.SH
+Master Candidature Message
+.so unused
+.LP
+Type: TSP_ELECTION (8)
+.sp 1
+.PP
+A slave eligible to become a master broadcasts this message when its election
+timer expires.
+The message declares that the slave wishes to become the new master.
+.sp 1
+.DE
+.DS L
+.SH
+Candidature Acceptance Message
+.so unused
+.LP
+Type: TSP_ACCEPT (9)
+.sp 1
+.PP
+A slave sends this message to accept the candidature of the time daemon
+that has broadcast an Election message.
+The candidate will add the slave's name to the list of machines that it
+will control should it become the master.
+.sp 1
+.DE
+.DS L
+.SH
+Candidature Rejection Message
+.so unused
+.LP
+Type: TSP_REFUSE (10)
+.sp 1
+.PP
+After a slave accepts the candidature of a time daemon, it will reply
+to any election messages from other slaves
+with this message.
+This rejects any candidature other than the first received.
+.sp 1
+.DE
+.DS L
+.SH
+Multiple Master Notification Message
+.so unused
+.LP
+Type: TSP_CONFLICT (11)
+.sp 1
+.PP
+When two or more masters reply to a Master Request message, the slave
+uses this message to inform one of them that more than one master exists.
+.sp 1
+.DE
+.DS L
+.SH
+Conflict Resolution Message
+.so unused
+.LP
+Type: TSP_RESOLVE (12)
+.sp 1
+.PP
+A master which has been informed of the existence of other masters
+broadcasts this message to determine who the other masters are.
+.sp 1
+.DE
+.DS L
+.SH
+Quit Message
+.so unused
+.LP
+Type: TSP_QUIT (13)
+.sp 1
+.PP
+This message is sent by the master in three different contexts:
+1) to a candidate that broadcasts an Master Candidature message,
+2) to another master when notified of its existence,
+3) to another master if a loop is detected.
+In all cases, the recipient time daemon will become a slave.
+This message requires an acknowledgement.
+.sp 1
+.DE
+.DS L
+.SH
+Set Date Message
+.so date
+.LP
+Type: TSP_SETDATE (22)
+.sp 1
+.PP
+The program \fIdate\fP\|(1) sends this message to the local time daemon
+when a super-user wants to set the network date.
+If the local time daemon is the master, it will set the date;
+if it is a slave, it will communicate the desired date to the master.
+.sp 1
+.DE
+.DS L
+.SH
+Set Date Request Message
+.so date
+.LP
+Type: TSP_SETDATEREQ (23)
+.sp 1
+.PP
+A slave that has received a Set Date message will communicate the
+desired date to the master using this message.
+.sp 1
+.DE
+.DS L
+.SH
+Set Date Acknowledgment Message
+.so unused
+.LP
+Type: TSP_DATEACK (16)
+.sp 1
+.PP
+The master sends this message to a slave in acknowledgment of a
+Set Date Request Message.
+The same message is sent by the local time daemon to the program
+\fIdate(1)\fP to confirm that the network date has been set by the
+master.
+.sp 1
+.DE
+.DS L
+.SH
+Start Tracing Message
+.so unused
+.LP
+Type: TSP_TRACEON (17)
+.sp 1
+.PP
+The controlling program \fItimedc\fP sends this message to the local
+time daemon to start the recording in a system file of
+all messages received.
+.sp 1
+.DE
+.DS L
+.SH
+Stop Tracing Message
+.so unused
+.LP
+Type: TSP_TRACEOFF (18)
+.sp 1
+.PP
+\fITimedc\fP sends this message to the local
+time daemon to stop the recording of
+messages received.
+.sp 1
+.DE
+.DS L
+.SH
+Master Site Message
+.so unused
+.LP
+Type: TSP_MSITE (19)
+.sp 1
+.PP
+\fITimedc\fP sends this message to the local time daemon to find out
+where the master is running.
+.sp 1
+.DE
+.DS L
+.SH
+Remote Master Site Message
+.so unused
+.LP
+Type: TSP_MSITEREQ (20)
+.sp 1
+.PP
+A local time daemon broadcasts this message to find the location
+of the master.
+It then uses the Acknowledgement message to
+communicate this location to \fItimedc\fP.
+.sp 1
+.DE
+.DS L
+.SH
+Test Message
+.so unused
+.LP
+Type: TSP_TEST (21)
+.sp 1
+.PP
+For testing purposes, \fItimedc\fP sends this message to a slave
+to cause its election timer to expire. NOTE: \fItimed\fP
+is not normally compiled to support this.
+.sp 1
+.DE
+.SH
+.DS L
+.SH
+Loop Detection Message
+.so loop
+.LP
+Type: TSP_LOOP (24)
+.sp 1
+.PP
+This packet is initiated by all masters occasionally to attempt to detect loops.
+All submasters forward this packet onto the networks over which they are master.
+If a master receives a packet it sent out initially,
+it knows that a loop exists and tries to correct the problem.
+.DE
+.SH
+References
+.IP 1.
+R. Gusella and S. Zatti,
+\fITEMPO: A Network Time Controller for Distributed Berkeley UNIX System\fP,
+USENIX Summer Conference Proceedings, Salt Lake City, June 1984.
+.IP 2.
+R. Gusella and S. Zatti, \fIClock Synchronization in a Local Area Network\fP,
+University of California, Berkeley, Technical Report, \fIto appear\fP.
+.IP 3.
+R. Gusella and S. Zatti,
+\fIAn Election Algorithm for a Distributed Clock Synchronization Program\fP,
+University of California, Berkeley, CS Technical Report #275, Dec. 1985.
+.IP 4.
+Postel, J., \fIUser Datagram Protocol\fP, RFC 768.
+Network Information Center, SRI International, Menlo Park, California,
+August 1980.
+.IP 5.
+Postel, J., \fIInternet Control Message Protocol\fP, RFC 792.
+Network Information Center, SRI International, Menlo Park, California,
+September 1981.
diff --git a/usr.sbin/timed/SMM.doc/timed/unused b/usr.sbin/timed/SMM.doc/timed/unused
new file mode 100644
index 0000000..adadfc3
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timed/unused
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.\" @(#)unused 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+( unused )
+_
+( unused )
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/usr.sbin/timed/SMM.doc/timedop/Makefile b/usr.sbin/timed/SMM.doc/timedop/Makefile
new file mode 100644
index 0000000..ae43850
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timedop/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/8/93
+
+DIR= smm/11.timedop
+SRCS= timed.ms
+MACROS= -ms
+
+.include <bsd.doc.mk>
diff --git a/usr.sbin/timed/SMM.doc/timedop/timed.ms b/usr.sbin/timed/SMM.doc/timedop/timed.ms
new file mode 100644
index 0000000..feea0b5
--- /dev/null
+++ b/usr.sbin/timed/SMM.doc/timedop/timed.ms
@@ -0,0 +1,279 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timed.ms 8.1 (Berkeley) 6/8/93
+.\"
+.TL
+Timed Installation and Operation Guide
+.AU
+Riccardo Gusella, Stefano Zatti, James M. Bloom
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.AU
+Kirk Smith
+.AI
+Engineering Computer Network
+Department of Electrical Engineering
+Purdue University
+West Lafayette, IN 47906
+.FS
+This work was sponsored by the Defense Advanced Research Projects Agency
+(DoD), monitored by the Naval Electronics Systems
+Command under contract No. N00039-84-C-0089, and by the CSELT
+Corporation of Italy.
+The views and conclusions contained in this document are those of the
+authors and should not be interpreted as representing official policies,
+either expressed or implied, of the Defense Research Projects Agency,
+of the US Government, or of CSELT.
+.FE
+.LP
+.EH 'SMM:11-%''Timed Installation and Operation'
+.OH 'Timed Installation and Operation''SMM:11-%'
+.SH
+Introduction
+.PP
+The clock synchronization service for
+the UNIX 4.3BSD operating system is composed of a collection of
+time daemons (\fItimed\fP) running on the machines in a local
+area network.
+The algorithms implemented by the service is based on a master-slave scheme.
+The time daemons communicate with each other using the
+\fITime Synchronization Protocol\fP (TSP) which
+is built on the DARPA UDP protocol and described in detail in [4].
+.PP
+A time daemon has a twofold function.
+First, it supports the synchronization of the clocks
+of the various hosts in a local area network.
+Second, it starts (or takes part in) the election that occurs
+among slave time daemons when, for any reason, the master disappears.
+The synchronization mechanism and the election procedure
+employed by the program \fItimed\fP are described
+in other documents [1,2,3].
+The next paragraphs are a brief overview of how the time daemon works.
+This document is mainly concerned with the administrative and technical
+issues of running \fItimed\fP at a particular site.
+.PP
+A \fImaster time daemon\fP measures the time
+differences between the clock of the machine on which it
+is running and those of all other machines.
+The master computes the \fInetwork time\fP as the average of the
+times provided by nonfaulty clocks.\**
+.FS
+A clock is considered to be faulty when its value
+is more than a small specified
+interval apart from the majority of the clocks
+of the other machines [1,2].
+.FE
+It then sends to each \fIslave time daemon\fP the
+correction that should be performed on the clock of its machine.
+This process is repeated periodically.
+Since the correction is expressed as a time difference rather than an
+absolute time, transmission delays do not interfere with
+the accuracy of the synchronization.
+When a machine comes up and joins the network,
+it starts a slave time daemon which
+will ask the master for the correct time and will reset the machine's clock
+before any user activity can begin.
+The time daemons are able to maintain a single network time in spite of
+the drift of clocks away from each other.
+The present implementation keeps processor clocks synchronized
+within 20 milliseconds.
+.PP
+To ensure that the service provided is continuous and reliable,
+it is necessary to implement an election algorithm to elect a
+new master should the machine running the current master crash, the master
+terminate (for example, because of a run-time error), or
+the network be partitioned.
+Under our algorithm, slaves are able to realize when the master has
+stopped functioning and to elect a new master from among themselves.
+It is important to note that, since the failure of the master results
+only in a gradual divergence of clock values, the election
+need not occur immediately.
+.PP
+The machines that are gateways between distinct local area
+networks require particular care.
+A time daemon on such machines may act as a \fIsubmaster\fP.
+This artifact depends on the current inability of
+transmission protocols to broadcast a message on a network
+other than the one to which the broadcasting machine is connected.
+The submaster appears as a slave on one network, and as a master
+on one or more of the other networks to which it is connected.
+.PP
+A submaster classifies each network as one of three types.
+A \fIslave network\fP is a network on which the submaster acts as a slave.
+There can only be one slave network.
+A \fImaster network\fP is a network on which the submaster acts as a master.
+An \fIignored network\fP is any other network which already has a valid master.
+The submaster tries periodically to become master on an ignored
+network, but gives up immediately if a master already exists.
+.SH
+Guidelines
+.PP
+While the synchronization algorithm is quite general, the election
+one, requiring a broadcast mechanism, puts constraints on
+the kind of network on which time daemons can run.
+The time daemon will only work on networks with broadcast capability
+augmented with point-to-point links.
+Machines that are only connected to point-to-point,
+non-broadcast networks may not use the time daemon.
+.PP
+If we exclude submasters, there will normally be, at most, one master time
+daemon in a local area internetwork.
+During an election, only one of the slave time daemons
+will become the new master.
+However, because of the characteristics of its machine,
+a slave can be prevented from becoming the master.
+Therefore, a subset of machines must be designated as potential
+master time daemons.
+A master time daemon will require CPU resources
+proportional to the number of slaves, in general, more than
+a slave time daemon, so it may be advisable to limit master time
+daemons to machines with more powerful processors or lighter loads.
+Also, machines with inaccurate clocks should not be used as masters.
+This is a purely administrative decision: an organization may
+well allow all of its machines to run master time daemons.
+.PP
+At the administrative level, a time daemon on a machine
+with multiple network interfaces, may be told to ignore all
+but one network or to ignore one network.
+This is done with the \fI\-n network\fP and \fI\-i network\fP
+options respectively at start-up time.
+Typically, the time daemon would be instructed to ignore all but
+the networks belonging to the local administrative control.
+.PP
+There are some limitations to the current
+implementation of the time daemon.
+It is expected that these limitations will be removed in future releases.
+The constant NHOSTS in /usr/src/etc/timed/globals.h limits the
+maximum number of machines that may be directly controlled by one
+master time daemon.
+The current maximum is 29 (NHOSTS \- 1).
+The constant must be changed and the program recompiled if a site wishes to
+run \fItimed\fP on a larger (inter)network.
+.PP
+In addition, there is a \fIpathological situation\fP to
+be avoided at all costs, that might occur when
+time daemons run on multiply-connected local area networks.
+In this case, as we have seen, time daemons running on gateway machines
+will be submasters and they will act on some of those
+networks as master time daemons.
+Consider machines A and B that are both gateways between
+networks X and Y.
+If time daemons were started on both A and B without constraints, it would be
+possible for submaster time daemon A to be a slave on network X
+and the master on network Y, while submaster time daemon B is a slave on
+network Y and the master on network X.
+This \fIloop\fP of master time daemons will not function properly
+or guarantee a unique time on both networks, and will cause
+the submasters to use large amounts of system resources in the form
+of network bandwidth and CPU time.
+In fact, this kind of \fIloop\fP can also be generated with more
+than two master time daemons,
+when several local area networks are interconnected.
+.SH
+Installation
+.PP
+In order to start the time daemon on a given machine,
+the following lines should be
+added to the \fIlocal daemons\fP section in the file \fI/etc/rc.local\fP:
+.sp 2
+.in 1i
+.nf
+if [ -f /etc/timed ]; then
+ /etc/timed \fIflags\fP & echo -n ' timed' >/dev/console
+fi
+.fi
+.in -1i
+.sp
+.LP
+In any case, they must appear after the network
+is configured via ifconfig(8).
+.PP
+Also, the file \fI/etc/services\fP should contain the following
+line:
+.sp 2
+.ti 1i
+timed 525/udp timeserver
+.sp
+.LP
+The \fIflags\fP are:
+.IP "-n network" 13
+to consider the named network.
+.IP "-i network"
+to ignore the named network.
+.IP -t
+to place tracing information in \fI/usr/adm/timed.log\fP.
+.IP -M
+to allow this time daemon to become a master.
+A time daemon run without this option will be forced in the state of
+slave during an election.
+.SH
+Daily Operation
+.PP
+\fITimedc(8)\fP is used to control the operation of the time daemon.
+It may be used to:
+.IP \(bu
+measure the differences between machines' clocks,
+.IP \(bu
+find the location where the master \fItimed\fP is running,
+.IP \(bu
+cause election timers on several machines to expire at the same time,
+.IP \(bu
+enable or disable tracing of messages received by \fItimed\fP.
+.LP
+See the manual page on \fItimed\fP\|(8) and \fItimedc\fP\|(8)
+for more detailed information.
+.PP
+The \fIdate(1)\fP command can be used to set the network date.
+In order to set the time on a single machine, the \fI-n\fP flag
+can be given to date(1).
+.bp
+.SH
+References
+.IP 1.
+R. Gusella and S. Zatti,
+\fITEMPO: A Network Time Controller for Distributed Berkeley UNIX System\fP,
+USENIX Summer Conference Proceedings, Salt Lake City, June 1984.
+.IP 2.
+R. Gusella and S. Zatti, \fIClock Synchronization in a Local Area Network\fP,
+University of California, Berkeley, Technical Report, \fIto appear\fP.
+.IP 3.
+R. Gusella and S. Zatti,
+\fIAn Election Algorithm for a Distributed Clock Synchronization Program\fP,
+University of California, Berkeley, CS Technical Report #275, Dec. 1985.
+.IP 4.
+R. Gusella and S. Zatti,
+\fIThe Berkeley UNIX 4.3BSD Time Synchronization Protocol\fP,
+UNIX Programmer's Manual, 4.3 Berkeley Software Distribution, Volume 2c.
diff --git a/usr.sbin/timed/timed/CHANGES b/usr.sbin/timed/timed/CHANGES
new file mode 100644
index 0000000..773f477
--- /dev/null
+++ b/usr.sbin/timed/timed/CHANGES
@@ -0,0 +1,144 @@
+# @(#)CHANGES 5.1 (Berkeley) 5/11/93
+
+This new version is almost identical to the timed and timedc code
+that has been shipped for years by a workstation vendor.
+
+Among the many changes:
+
+improve `timedc msite` to accept a list of hostnames.
+
+change slave-masters to answer the packets generated by `timedc msite`
+ with the name of the real master, not their own. This makes it
+ possible to "chase the chain" of slave servers to the ultimate
+ master.
+
+much improve the log caused by `timedc trace on`:
+ -made `timed -t` work.
+ -suppression of repeated entries, which both slowed down the daemon
+ (sometimes catastrophically) and tended to make disks fill up
+ even more quickly.
+ -better time stamps on log entries
+ -more messages
+ -dump information about slaves, master, and so on each time
+ a message asking the log be turned on is received, and
+ when the log is turned off.
+ -fewer CPU cycles
+
+use a hash table to keep track of slaves, instead of the stupid linear
+ list. This becomes handy with hundreds of slaves, instead of
+ the original design limit of "a room with a few VAX's."
+
+separate the main protocol timer from that used to look for other networks
+ to master.
+
+time stamp packets received by the daemon, so that time corrections
+ are not made (even more) inaccurate by waiting in the internal,
+ timed queue while the daemon is processing other messages.
+
+made -n and -i work with subnets not named in /etc/networks
+
+compute the median of the measured clocks, instead of the average
+ of "good" times.
+
+vastly improve the accuracy of the clock difference measure by
+ `timedc clockdiff`.
+
+use adjtime() when possible, and directly set the clock only when
+ necessary.
+
+when the requested adjustment is small, perform only part of it, to
+ damp oscillations and improve the long term accuracy of the
+ adjustments.
+
+fix uncounted core-dumps on machines that do not allow dereferencing 0
+ in both the daemon and timedc.
+
+fix "master loop detection".
+
+fix several cases in which multi-homed masters could get into shouting
+ matches, consuming all available network bandwidth and CPU cycles
+ (which ever runs out first), and convincing all bystanders to stop
+ advancing their own clocks.
+
+refuse to behave badly when other machines do. Instead of arguing forever,
+ go off and sulk when other machines refuse to play by the rules.
+
+increase the maximum number of clients.
+
+add "-F host,host2,..." to "freerun" or "trust" only some hosts. This
+ is handy both when only some machines should be trusted to let
+ root use the `date` command to change time in the network.
+
+ It is also handy when one machine has some other way of adjusting
+ its clock, whether NTP or a direct radio or atomic connection.
+ "-F localhost" causes `timed` to "trust" only itself.
+
+ It is also handy to build a hierarchy of timed masters crossing
+ networks. The TSP protocol has no provision of "goodness of clock",
+ no natural way to completely heal network paritions. Judicious
+ use of -F or -G can cause each gateway to trust only itself and
+ machines closer to a central machine with a radio or atomic clock.
+
+add #ifdef code that supports NIS "netgroups" of trusted hosts, which
+ can be easier to administer than -F.
+
+add #ifdef code to compute an aged total adjustment. This can be used
+ in systems that can make long term changes in their system clock
+ frequency, e.g. "timetrim" in the Silicon Graphics kernel.
+
+
+Problems observed by others that are unresolved include:
+
+Practically any users can send to the master TSP messages and this
+ way corrupt the reliability of the system. Authentication
+ of messages should be provided. Unfortunately, that would
+ require changing the protocol with all of the implied
+ compatiblity problems. Fortunately, the new -F and -G args
+ can be used to cause the daemon to ignore time changes from
+ untrusted machines.
+
+MAN. The limit of 1013 on the number of slaves hosts should be doc'ed.
+
+ It should be dynamically allocated with no limit. On a
+ large network, one host could possibly master over many
+ more than 30 hosts. Given the timers in the code and
+ effectively in the protocol, and the time required by each
+ master to talk to each slave, it is not practical to have
+ more than 200-300 slaves. The master cannot keep up because
+ the slave-chatting is single-threaded. when the master
+ gets behind, slaves start demanding elections. To
+ significantly increase the number of slaves would require
+ multi-treading things, and given that a network with more
+ than 300 directly addressable machines has worse problems
+ than keep the time of day right, not worth worrying about.
+
+UGLY,CODE. timedc/cmds.c has a lots of repeated code in it.
+
+**** The first thing is that each command is set up as if it
+ were an individual program taking argc and argv. A more
+ conventional calling style should be used. I don't think
+ any of the routines take more than a couple arguments.
+
+UGLY. fxn definition syntax does't follow convention:
+ has type on same line.
+
+**** It needs to be fixed at least enough that tags
+ will work on it. An entire cleanup might be nice later, but
+ is noncritical.
+
+LOBBY(mildly),CODE: Would be very convenient if date(1) took a
+ +-<number> argument to set the time relatively. With
+ the advent of timed it is now reasonable to synchronize
+ with WWV, which is nearly impossible to do "by hand"
+ with just an absolute date, and scripts are too slow.
+ format could be +-nn...nn.ss, where the '.' is required
+ to remove ambiguity.
+
+**** If you want to do it go ahead. It sounds useful. As far as
+ syntax goes, the normal format for the date should work just
+ fine for this. If the date is preceeded by a plus or minus,
+ the change is relative, otherwise it is absolute.
+
+
+Vernon Schryver.
+vjs@sgi.com
diff --git a/usr.sbin/timed/timed/Makefile b/usr.sbin/timed/timed/Makefile
new file mode 100644
index 0000000..08b41f3
--- /dev/null
+++ b/usr.sbin/timed/timed/Makefile
@@ -0,0 +1,13 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+#
+# optional flags are: MEASURE TESTING DEBUG
+
+PROG= timed
+SRCS= acksend.c candidate.c correct.c master.c networkdelta.c readmsg.c \
+ slave.c timed.c byteorder.c measure.c cksum.c
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+MAN8= timed.0
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/timed/timed/acksend.c b/usr.sbin/timed/timed/acksend.c
new file mode 100644
index 0000000..c84f52d
--- /dev/null
+++ b/usr.sbin/timed/timed/acksend.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)acksend.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.6 $"
+#endif
+
+#include "globals.h"
+
+struct tsp *answer;
+
+extern u_short sequence;
+
+void
+xmit(type, seq, addr)
+ int type;
+ u_int seq;
+ struct sockaddr_in *addr;
+{
+ static struct tsp msg;
+
+ msg.tsp_type = type;
+ msg.tsp_seq = seq;
+ msg.tsp_vers = TSPVERSION;
+ (void)strcpy(msg.tsp_name, hostname);
+ bytenetorder(&msg);
+ if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
+ (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) {
+ trace_sendto_err(addr->sin_addr);
+ }
+}
+
+
+/*
+ * Acksend implements reliable datagram transmission by using sequence
+ * numbers and retransmission when necessary.
+ * If `name' is ANYADDR, this routine implements reliable broadcast.
+ *
+ * Because this function calls readmsg(), none of its args may be in
+ * a message provided by readmsg().
+ */
+struct tsp *
+acksend(message, addr, name, ack, net, bad)
+ struct tsp *message; /* this message */
+ struct sockaddr_in *addr; /* to here */
+ char *name;
+ int ack; /* look for this ack */
+ struct netinfo *net; /* receive from this network */
+ int bad; /* 1=losing patience */
+{
+ struct timeval twait;
+ int count;
+ long msec;
+
+ message->tsp_vers = TSPVERSION;
+ message->tsp_seq = sequence;
+ if (trace) {
+ fprintf(fd, "acksend: to %s: ",
+ (name == ANYADDR ? "broadcast" : name));
+ print(message, addr);
+ }
+ bytenetorder(message);
+
+ msec = 200;
+ count = bad ? 1 : 5; /* 5 packets in 6.4 seconds */
+ answer = 0;
+ do {
+ if (!answer) {
+ /* do not go crazy transmitting just because the
+ * other guy cannot keep our sequence numbers
+ * straight.
+ */
+ if (sendto(sock, (char *)message, sizeof(struct tsp),
+ 0, (struct sockaddr*)addr,
+ sizeof(struct sockaddr)) < 0) {
+ trace_sendto_err(addr->sin_addr);
+ break;
+ }
+ }
+
+ mstotvround(&twait, msec);
+ answer = readmsg(ack, name, &twait, net);
+ if (answer != 0) {
+ if (answer->tsp_seq != sequence) {
+ if (trace)
+ fprintf(fd,"acksend: seq # %u!=%u\n",
+ answer->tsp_seq, sequence);
+ continue;
+ }
+ break;
+ }
+
+ msec *= 2;
+ } while (--count > 0);
+ sequence++;
+
+ return(answer);
+}
diff --git a/usr.sbin/timed/timed/byteorder.c b/usr.sbin/timed/timed/byteorder.c
new file mode 100644
index 0000000..9cbd665
--- /dev/null
+++ b/usr.sbin/timed/timed/byteorder.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)byteorder.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.3 $"
+#endif
+
+#include "globals.h"
+
+/*
+ * Two routines to do the necessary byte swapping for timed protocol
+ * messages. Protocol is defined in /usr/include/protocols/timed.h
+ */
+void
+bytenetorder(ptr)
+ struct tsp *ptr;
+{
+ ptr->tsp_seq = htons((u_short)ptr->tsp_seq);
+ switch (ptr->tsp_type) {
+
+ case TSP_SETTIME:
+ case TSP_ADJTIME:
+ case TSP_SETDATE:
+ case TSP_SETDATEREQ:
+ ptr->tsp_time.tv_sec = htonl((u_long)ptr->tsp_time.tv_sec);
+ ptr->tsp_time.tv_usec = htonl((u_long)ptr->tsp_time.tv_usec);
+ break;
+
+ default:
+ break; /* nothing more needed */
+ }
+}
+
+void
+bytehostorder(ptr)
+ struct tsp *ptr;
+{
+ ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq);
+ switch (ptr->tsp_type) {
+
+ case TSP_SETTIME:
+ case TSP_ADJTIME:
+ case TSP_SETDATE:
+ case TSP_SETDATEREQ:
+ ptr->tsp_time.tv_sec = ntohl((u_long)ptr->tsp_time.tv_sec);
+ ptr->tsp_time.tv_usec = ntohl((u_long)ptr->tsp_time.tv_usec);
+ break;
+
+ default:
+ break; /* nothing more needed */
+ }
+}
diff --git a/usr.sbin/timed/timed/candidate.c b/usr.sbin/timed/timed/candidate.c
new file mode 100644
index 0000000..294eb9b
--- /dev/null
+++ b/usr.sbin/timed/timed/candidate.c
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.9 $"
+#endif
+
+#include "globals.h"
+
+/*
+ * `election' candidates a host as master: it is called by a slave
+ * which runs with the -M option set when its election timeout expires.
+ * Note the conservative approach: if a new timed comes up, or another
+ * candidate sends an election request, the candidature is withdrawn.
+ */
+int
+election(net)
+ struct netinfo *net;
+{
+ struct tsp *resp, msg;
+ struct timeval then, wait;
+ struct tsp *answer;
+ struct hosttbl *htp;
+ char loop_lim = 0;
+
+/* This code can get totally confused if it gets slightly behind. For
+ * example, if readmsg() has some QUIT messages waiting from the last
+ * round, we would send an ELECTION message, get the stale QUIT,
+ * and give up. This results in network storms when several machines
+ * do it at once.
+ */
+ wait.tv_sec = 0;
+ wait.tv_usec = 0;
+ while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) {
+ if (trace)
+ fprintf(fd, "election: discarded stale REFUSE\n");
+ }
+ while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) {
+ if (trace)
+ fprintf(fd, "election: discarded stale QUIT\n");
+ }
+
+again:
+ syslog(LOG_INFO, "This machine is a candidate time master");
+ if (trace)
+ fprintf(fd, "This machine is a candidate time master\n");
+ msg.tsp_type = TSP_ELECTION;
+ msg.tsp_vers = TSPVERSION;
+ (void)strcpy(msg.tsp_name, hostname);
+ bytenetorder(&msg);
+ if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
+ (struct sockaddr*)&net->dest_addr,
+ sizeof(struct sockaddr)) < 0) {
+ trace_sendto_err(net->dest_addr.sin_addr);
+ return(SLAVE);
+ }
+
+ (void)gettimeofday(&then, 0);
+ then.tv_sec += 3;
+ for (;;) {
+ (void)gettimeofday(&wait, 0);
+ timevalsub(&wait,&then,&wait);
+ resp = readmsg(TSP_ANY, ANYADDR, &wait, net);
+ if (!resp)
+ return(MASTER);
+
+ switch (resp->tsp_type) {
+
+ case TSP_ACCEPT:
+ (void)addmach(resp->tsp_name, &from,fromnet);
+ break;
+
+ case TSP_MASTERUP:
+ case TSP_MASTERREQ:
+ /*
+ * If another timedaemon is coming up at the same
+ * time, give up, and let it be the master.
+ */
+ if (++loop_lim < 5
+ && !good_host_name(resp->tsp_name)) {
+ (void)addmach(resp->tsp_name, &from,fromnet);
+ suppress(&from, resp->tsp_name, net);
+ goto again;
+ }
+ rmnetmachs(net);
+ return(SLAVE);
+
+ case TSP_QUIT:
+ case TSP_REFUSE:
+ /*
+ * Collision: change value of election timer
+ * using exponential backoff.
+ *
+ * Fooey.
+ * An exponential backoff on a delay starting at
+ * 6 to 15 minutes for a process that takes
+ * milliseconds is silly. It is particularly
+ * strange that the original code would increase
+ * the backoff without bound.
+ */
+ rmnetmachs(net);
+ return(SLAVE);
+
+ case TSP_ELECTION:
+ /* no master for another round */
+ htp = addmach(resp->tsp_name,&from,fromnet);
+ msg.tsp_type = TSP_REFUSE;
+ (void)strcpy(msg.tsp_name, hostname);
+ answer = acksend(&msg, &htp->addr, htp->name,
+ TSP_ACK, 0, htp->noanswer);
+ if (!answer) {
+ syslog(LOG_ERR, "error in election from %s",
+ htp->name);
+ }
+ break;
+
+ case TSP_SLAVEUP:
+ (void)addmach(resp->tsp_name, &from,fromnet);
+ break;
+
+ case TSP_SETDATE:
+ case TSP_SETDATEREQ:
+ break;
+
+ default:
+ if (trace) {
+ fprintf(fd, "candidate: ");
+ print(resp, &from);
+ }
+ break;
+ }
+ }
+}
diff --git a/usr.sbin/timed/timed/cksum.c b/usr.sbin/timed/timed/cksum.c
new file mode 100644
index 0000000..3d15af3
--- /dev/null
+++ b/usr.sbin/timed/timed/cksum.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cksum.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.3 $"
+#endif
+
+#include <sys/types.h>
+
+/*
+ * I N _ C K S U M
+ *
+ * Checksum routine for Internet Protocol family headers (C Version)
+ *
+ * There is no profit in a specialized version of the checksum
+ * function for any machine where int's are 32 bits and shorts are 16.
+ *
+ * All timed packets are smaller than 32K shorts, so there is no need to
+ * worry about carries except at the end.
+ */
+int
+in_cksum(addr, len)
+ u_short *addr;
+ int len;
+{
+ register int nleft = len;
+ register u_short *w = addr;
+ register u_short answer;
+ register int sum = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum),
+ * we add sequential 16 bit words to it, and at the end, fold
+ * back all the carry bits from the top 16 bits into the lower
+ * 16 bits.
+ */
+ while( nleft > 1 ) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if( nleft == 1 )
+ sum += (*(u_char *)w) << 8;
+
+ /*
+ * add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return (answer);
+}
diff --git a/usr.sbin/timed/timed/correct.c b/usr.sbin/timed/timed/correct.c
new file mode 100644
index 0000000..569d2e1
--- /dev/null
+++ b/usr.sbin/timed/timed/correct.c
@@ -0,0 +1,294 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)correct.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.16 $"
+#endif
+
+#include "globals.h"
+#include <math.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#ifdef sgi
+#include <sys/syssgi.h>
+#endif /* sgi */
+
+static void adjclock __P((struct timeval *));
+
+/*
+ * sends to the slaves the corrections for their clocks after fixing our
+ * own
+ */
+void
+correct(avdelta)
+ long avdelta;
+{
+ struct hosttbl *htp;
+ int corr;
+ struct timeval adjlocal;
+ struct tsp to;
+ struct tsp *answer;
+
+ mstotvround(&adjlocal, avdelta);
+
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ if (htp->delta != HOSTDOWN) {
+ corr = avdelta - htp->delta;
+/* If the other machine is off in the weeds, set its time directly.
+ * If a slave gets the wrong day, the original code would simply
+ * fix the minutes. If you fix a network partition, you can get
+ * into such situations.
+ */
+ if (htp->need_set
+ || corr >= MAXADJ*1000
+ || corr <= -MAXADJ*1000) {
+ htp->need_set = 0;
+ (void)gettimeofday(&to.tsp_time,0);
+ timevaladd(&to.tsp_time, &adjlocal);
+ to.tsp_type = TSP_SETTIME;
+ } else {
+ mstotvround(&to.tsp_time, corr);
+ to.tsp_type = TSP_ADJTIME;
+ }
+ (void)strcpy(to.tsp_name, hostname);
+ answer = acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, 0);
+ if (!answer) {
+ htp->delta = HOSTDOWN;
+ syslog(LOG_WARNING,
+ "no reply to time correction from %s",
+ htp->name);
+ if (++htp->noanswer >= LOSTHOST) {
+ if (trace) {
+ fprintf(fd,
+ "purging %s for not answering\n",
+ htp->name);
+ (void)fflush(fd);
+ }
+ htp = remmach(htp);
+ }
+ }
+ }
+ }
+
+ /*
+ * adjust our own clock now that we are not sending it out
+ */
+ adjclock(&adjlocal);
+}
+
+
+static void
+adjclock(corr)
+ struct timeval *corr;
+{
+ static int passes = 0;
+ static int smoother = 0;
+ long delta; /* adjustment in usec */
+ long ndelta;
+ struct timeval now;
+ struct timeval adj;
+
+ if (!timerisset(corr))
+ return;
+
+ adj = *corr;
+ if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
+ delta = adj.tv_sec*1000000 + adj.tv_usec;
+ /* If the correction is less than the minimum round
+ * trip time for an ICMP packet, and thus
+ * less than the likely error in the measurement,
+ * do not do the entire correction. Do half
+ * or a quarter of it.
+ */
+
+ if (delta > -MIN_ROUND*1000
+ && delta < MIN_ROUND*1000) {
+ if (smoother <= 4)
+ smoother++;
+ ndelta = delta >> smoother;
+ if (trace)
+ fprintf(fd,
+ "trimming delta %ld usec to %ld\n",
+ delta, ndelta);
+ adj.tv_usec = ndelta;
+ adj.tv_sec = 0;
+ } else if (smoother > 0) {
+ smoother--;
+ }
+ if (0 > adjtime(corr, 0)) {
+ syslog(LOG_ERR, "adjtime: %m");
+ }
+ if (passes > 1
+ && (delta < -BIG_ADJ || delta > BIG_ADJ)) {
+ smoother = 0;
+ passes = 0;
+ syslog(LOG_WARNING,
+ "large time adjustment of %+.3f sec",
+ delta/1000000.0);
+ }
+ } else {
+ syslog(LOG_WARNING,
+ "clock correction %d sec too large to adjust",
+ adj.tv_sec);
+ (void) gettimeofday(&now, 0);
+ timevaladd(&now, corr);
+ if (settimeofday(&now, 0) < 0)
+ syslog(LOG_ERR, "settimeofday: %m");
+ }
+
+#ifdef sgi
+ /* Accumulate the total change, and use it to adjust the basic
+ * clock rate.
+ */
+ if (++passes > 2) {
+#define F_USEC_PER_SEC (1000000*1.0) /* reduce typos */
+#define F_NSEC_PER_SEC (F_USEC_PER_SEC*1000.0)
+
+ extern char *timetrim_fn;
+ extern char *timetrim_wpat;
+ extern long timetrim;
+ extern double tot_adj, hr_adj; /* totals in nsec */
+ extern double tot_ticks, hr_ticks;
+
+ static double nag_tick;
+ double cur_ticks, hr_delta_ticks, tot_delta_ticks;
+ double tru_tot_adj, tru_hr_adj; /* nsecs of adjustment */
+ double tot_trim, hr_trim; /* nsec/sec */
+ struct tms tm;
+ FILE *timetrim_st;
+
+ cur_ticks = times(&tm);
+ tot_adj += delta*1000.0;
+ hr_adj += delta*1000.0;
+
+ tot_delta_ticks = cur_ticks-tot_ticks;
+ if (tot_delta_ticks >= 16*SECDAY*CLK_TCK) {
+ tot_adj -= rint(tot_adj/16);
+ tot_ticks += rint(tot_delta_ticks/16);
+ tot_delta_ticks = cur_ticks-tot_ticks;
+ }
+ hr_delta_ticks = cur_ticks-hr_ticks;
+
+ tru_hr_adj = hr_adj + timetrim*rint(hr_delta_ticks/CLK_TCK);
+ tru_tot_adj = (tot_adj
+ + timetrim*rint(tot_delta_ticks/CLK_TCK));
+
+ if (hr_delta_ticks >= SECDAY*CLK_TCK
+ || (tot_delta_ticks < 4*SECDAY*CLK_TCK
+ && hr_delta_ticks >= SECHR*CLK_TCK)
+ || (trace && hr_delta_ticks >= (SECHR/10)*CLK_TCK)) {
+
+ tot_trim = rint(tru_tot_adj*CLK_TCK/tot_delta_ticks);
+ hr_trim = rint(tru_hr_adj*CLK_TCK/hr_delta_ticks);
+
+ if (trace
+ || (abs(timetrim - hr_trim) > 100000.0
+ && 0 == timetrim_fn
+ && ((cur_ticks - nag_tick)
+ >= 24*SECDAY*CLK_TCK))) {
+ nag_tick = cur_ticks;
+ syslog(LOG_NOTICE,
+ "%+.3f/%.2f or %+.3f/%.2f sec/hr; timetrim=%+.0f or %+.0f",
+ tru_tot_adj/F_NSEC_PER_SEC,
+ tot_delta_ticks/(SECHR*CLK_TCK*1.0),
+ tru_hr_adj/F_NSEC_PER_SEC,
+ hr_delta_ticks/(SECHR*CLK_TCK*1.0),
+ tot_trim,
+ hr_trim);
+ }
+
+ if (tot_trim < -MAX_TRIM || tot_trim > MAX_TRIM) {
+ tot_ticks = hr_ticks;
+ tot_adj = hr_adj;
+ } else if (0 > syssgi(SGI_SETTIMETRIM,
+ (long)tot_trim)) {
+ syslog(LOG_ERR, "SETTIMETRIM(%d): %m",
+ (long)tot_trim);
+ } else {
+ if (0 != timetrim_fn) {
+ timetrim_st = fopen(timetrim_fn, "w");
+ if (0 == timetrim_st) {
+ syslog(LOG_ERR, "fopen(%s): %m",
+ timetrim_fn);
+ } else {
+ if (0 > fprintf(timetrim_st,
+ timetrim_wpat,
+ (long)tot_trim,
+ tru_tot_adj,
+ tot_delta_ticks)) {
+ syslog(LOG_ERR,
+ "fprintf(%s): %m",
+ timetrim_fn);
+ }
+ (void)fclose(timetrim_st);
+ }
+ }
+
+ tot_adj -= ((tot_trim - timetrim)
+ * rint(tot_delta_ticks/CLK_TCK));
+ timetrim = tot_trim;
+ }
+
+ hr_ticks = cur_ticks;
+ hr_adj = 0;
+ }
+ }
+#endif /* sgi */
+}
+
+
+/* adjust the time in a message by the time it
+ * spent in the queue
+ */
+void
+adj_msg_time(msg, now)
+ struct tsp *msg;
+ struct timeval *now;
+{
+ msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
+ msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
+
+ while (msg->tsp_time.tv_usec < 0) {
+ msg->tsp_time.tv_sec--;
+ msg->tsp_time.tv_usec += 1000000;
+ }
+ while (msg->tsp_time.tv_usec >= 1000000) {
+ msg->tsp_time.tv_sec++;
+ msg->tsp_time.tv_usec -= 1000000;
+ }
+}
diff --git a/usr.sbin/timed/timed/extern.h b/usr.sbin/timed/timed/extern.h
new file mode 100644
index 0000000..09dfaaa
--- /dev/null
+++ b/usr.sbin/timed/timed/extern.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+struct hosttbl;
+struct netinfo;
+struct sockaddr_in;
+struct timeval;
+struct tsp;
+
+struct hosttbl *addmach __P((char *, struct sockaddr_in *, struct netinfo *));
+struct hosttbl *findhost __P((char *));
+struct hosttbl *remmach __P((struct hosttbl *));
+
+struct tsp *readmsg __P((int,
+ char *, struct timeval *, struct netinfo *));
+struct tsp *acksend __P((struct tsp *,
+ struct sockaddr_in *, char *, int, struct netinfo *, int));
+
+void addnetname __P((char *));
+void adj_msg_time __P((struct tsp *, struct timeval *));
+void bytehostorder __P((struct tsp *));
+void bytenetorder __P((struct tsp *));
+void byteorder __P((struct tsp *));
+long casual __P((long, long));
+int cksum __P((u_short *, int));
+void correct __P((long));
+char *date __P((void));
+void doquit __P((struct tsp *));
+int election __P((struct netinfo *));
+void get_goodgroup __P((int));
+int good_host_name __P((char *));
+void ignoreack __P((void));
+int in_cksum __P((u_short *, int));
+void lookformaster __P((struct netinfo *));
+void makeslave __P((struct netinfo *));
+int master __P((void));
+void masterack __P((void));
+void masterup __P((struct netinfo *));
+int measure __P((u_long, u_long, char *, struct sockaddr_in *, int));
+void msterup __P((struct netinfo *));
+void mstotvround __P((struct timeval *, long));
+long networkdelta __P((void));
+void newslave __P((struct tsp *));
+void print __P((struct tsp *, struct sockaddr_in *));
+void prthp __P((clock_t));
+void rmnetmachs __P((struct netinfo *));
+void setstatus __P((void));
+int slave __P((void));
+void slaveack __P((void));
+void spreadtime __P((void));
+void suppress __P((struct sockaddr_in *, char *, struct netinfo *));
+void synch __P((long));
+void timevaladd __P((struct timeval *, struct timeval *));
+void timevalsub __P((struct timeval *, struct timeval *, struct timeval *));
+void traceoff __P((char *));
+void traceon __P((void));
+void xmit __P((int, u_int, struct sockaddr_in *));
diff --git a/usr.sbin/timed/timed/globals.h b/usr.sbin/timed/timed/globals.h
new file mode 100644
index 0000000..92aed3e
--- /dev/null
+++ b/usr.sbin/timed/timed/globals.h
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)globals.h 8.1 (Berkeley) 6/6/93
+ */
+
+#ifdef sgi
+#ident "$Revision: 1.15 $"
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <protocols/timed.h>
+#ifdef sgi
+#include <bstring.h>
+#include <sys/clock.h>
+/* use the constant HZ instead of the function CLK_TCK */
+#undef CLK_TCK
+#define CLK_TCK HZ
+#else
+#define SECHR (60*60)
+#define SECDAY (24*SECHR)
+#endif /* sgi */
+
+extern int errno;
+extern int sock;
+
+/* Best expected round trip for a measurement.
+ * This is essentially the number of milliseconds per CPU tick (CLK_TCK?).
+ * All delays shorter than this are usually reported as 0.
+ */
+#define MIN_ROUND ((1000-1)/CLK_TCK)
+
+
+#define SAMPLEINTVL 240 /* synch() freq for master in sec */
+#define MAXADJ 20 /* max adjtime() correction in sec */
+
+#define MAX_TRIM 3000000 /* max drift in nsec/sec, 0.3% */
+#define BIG_ADJ (MAX_TRIM/1000*SAMPLEINTVL*2) /* max good adj */
+
+#define MINTOUT 360 /* election delays, 6-15 minutes */
+#define MAXTOUT 900
+
+#define BAD_STATUS (-1)
+#define GOOD 1
+#define UNREACHABLE 2
+#define NONSTDTIME 3
+#define HOSTDOWN 0x7fffffff
+
+#define OFF 0
+#define ON 1
+
+#define MAX_HOPCNT 10 /* max value for tsp_hpcnt */
+
+#define LOSTHOST 3 /* forget after this many failures */
+
+#define VALID_RANGE (MAXADJ*1000) /* good times in milliseconds */
+#define GOOD_RANGE (MIN_ROUND*2)
+#define VGOOD_RANGE (MIN_ROUND-1)
+
+
+/*
+ * Global and per-network states.
+ */
+#define NOMASTER 0 /* no good master */
+#define SLAVE 1
+#define MASTER 2
+#define IGNORE 4
+#define ALL (SLAVE|MASTER|IGNORE)
+#define SUBMASTER (SLAVE|MASTER)
+
+#define NHOSTS 1013 /* max of hosts controlled by timed
+ * This must be a prime number.
+ */
+struct hosttbl {
+ struct hosttbl *h_bak; /* hash chain */
+ struct hosttbl *h_fwd;
+ struct hosttbl *l_bak; /* "sequential" list */
+ struct hosttbl *l_fwd;
+ struct netinfo *ntp;
+ struct sockaddr_in addr;
+ char name[MAXHOSTNAMELEN+1];
+ u_char head; /* 1=head of hash chain */
+ u_char good; /* 0=trusted host, for averaging */
+ u_char noanswer; /* count of failures to answer */
+ u_char need_set; /* need a SETTIME */
+ u_short seq;
+ long delta;
+};
+
+/* closed hash table with internal chaining */
+extern struct hosttbl hosttbl[NHOSTS+1];
+#define self hosttbl[0]
+#define hostname (self.name)
+
+
+struct netinfo {
+ struct netinfo *next;
+ struct in_addr net;
+ u_long mask;
+ struct in_addr my_addr;
+ struct sockaddr_in dest_addr; /* broadcast addr or point-point */
+ long status;
+ struct timeval slvwait; /* delay before sending our time */
+ int quit_count; /* recent QUITs */
+};
+
+#include "extern.h"
+
+#define tvtomsround(tv) ((tv).tv_sec*1000 + ((tv).tv_usec + 500)/1000)
+
+extern struct netinfo *nettab;
+extern int status;
+extern int trace;
+extern int sock;
+extern struct sockaddr_in from;
+extern struct timeval from_when; /* when the last msg arrived */
+extern u_short sequence; /* TSP message sequence number */
+extern struct netinfo *fromnet, *slavenet;
+extern FILE *fd;
+extern long delay1, delay2;
+extern int nslavenets; /* nets were I could be a slave */
+extern int nmasternets; /* nets were I could be a master */
+extern int nignorednets; /* ignored nets */
+extern int nnets; /* nets I am connected to */
+
+
+#define trace_msg(msg) {if (trace) fprintf(fd, msg);}
+
+#define trace_sendto_err(addr) { \
+ int st_errno = errno; \
+ syslog(LOG_ERR, "%s %d: sendto %s: %m", \
+ __FILE__, __LINE__, inet_ntoa(addr)); \
+ if (trace) \
+ fprintf(fd, "%s %d: sendto %s: %d", __FILE__, __LINE__, \
+ inet_ntoa(addr), st_errno); \
+}
+
+
+# define max(a,b) (a<b ? b : a)
+# define min(a,b) (a>b ? b : a)
+# define abs(x) (x>=0 ? x : -(x))
diff --git a/usr.sbin/timed/timed/master.c b/usr.sbin/timed/timed/master.c
new file mode 100644
index 0000000..3397173
--- /dev/null
+++ b/usr.sbin/timed/timed/master.c
@@ -0,0 +1,907 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)master.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.21 $"
+#endif
+
+#include "globals.h"
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#include <setjmp.h>
+#ifdef sgi
+#include <sys/schedctl.h>
+#endif /* sgi */
+#include <utmp.h>
+#include "pathnames.h"
+
+extern int measure_delta;
+extern jmp_buf jmpenv;
+extern int Mflag;
+extern int justquit;
+
+static int dictate;
+static int slvcount; /* slaves listening to our clock */
+
+static void mchgdate __P((struct tsp *));
+
+#ifdef sgi
+extern void logwtmp __P((struct timeval *, struct timeval *));
+#else
+extern void logwtmp __P((char *, char *, char *));
+#endif /* sgi */
+
+/*
+ * The main function of `master' is to periodically compute the differences
+ * (deltas) between its clock and the clocks of the slaves, to compute the
+ * network average delta, and to send to the slaves the differences between
+ * their individual deltas and the network delta.
+ * While waiting, it receives messages from the slaves (i.e. requests for
+ * master's name, remote requests to set the network time, ...), and
+ * takes the appropriate action.
+ */
+int
+master()
+{
+ struct hosttbl *htp;
+ long pollingtime;
+#define POLLRATE 4
+ int polls;
+ struct timeval wait, ntime;
+ struct tsp *msg, *answer, to;
+ char newdate[32];
+ struct sockaddr_in taddr;
+ char tname[MAXHOSTNAMELEN];
+ struct netinfo *ntp;
+ int i;
+
+ syslog(LOG_NOTICE, "This machine is master");
+ if (trace)
+ fprintf(fd, "This machine is master\n");
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == MASTER)
+ masterup(ntp);
+ }
+ (void)gettimeofday(&ntime, 0);
+ pollingtime = ntime.tv_sec+3;
+ if (justquit)
+ polls = 0;
+ else
+ polls = POLLRATE-1;
+
+/* Process all outstanding messages before spending the long time necessary
+ * to update all timers.
+ */
+loop:
+ (void)gettimeofday(&ntime, 0);
+ wait.tv_sec = pollingtime - ntime.tv_sec;
+ if (wait.tv_sec < 0)
+ wait.tv_sec = 0;
+ wait.tv_usec = 0;
+ msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
+ if (!msg) {
+ (void)gettimeofday(&ntime, 0);
+ if (ntime.tv_sec >= pollingtime) {
+ pollingtime = ntime.tv_sec + SAMPLEINTVL;
+ get_goodgroup(0);
+
+/* If a bogus master told us to quit, we can have decided to ignore a
+ * network. Therefore, periodically try to take over everything.
+ */
+ polls = (polls + 1) % POLLRATE;
+ if (0 == polls && nignorednets > 0) {
+ trace_msg("Looking for nets to re-master\n");
+ for (ntp = nettab; ntp; ntp = ntp->next) {
+ if (ntp->status == IGNORE
+ || ntp->status == NOMASTER) {
+ lookformaster(ntp);
+ if (ntp->status == MASTER) {
+ masterup(ntp);
+ polls = POLLRATE-1;
+ }
+ }
+ if (ntp->status == MASTER
+ && --ntp->quit_count < 0)
+ ntp->quit_count = 0;
+ }
+ if (polls != 0)
+ setstatus();
+ }
+
+ synch(0L);
+
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ to.tsp_type = TSP_LOOP;
+ to.tsp_vers = TSPVERSION;
+ to.tsp_seq = sequence++;
+ to.tsp_hopcnt = MAX_HOPCNT;
+ (void)strcpy(to.tsp_name, hostname);
+ bytenetorder(&to);
+ if (sendto(sock, (char *)&to,
+ sizeof(struct tsp), 0,
+ (struct sockaddr*)&ntp->dest_addr,
+ sizeof(ntp->dest_addr)) < 0) {
+ trace_sendto_err(ntp->dest_addr.sin_addr);
+ }
+ }
+ }
+
+
+ } else {
+ switch (msg->tsp_type) {
+
+ case TSP_MASTERREQ:
+ break;
+
+ case TSP_SLAVEUP:
+ newslave(msg);
+ break;
+
+ case TSP_SETDATE:
+ /*
+ * XXX check to see it is from ourself
+ */
+#ifdef sgi
+ (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+ (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+ if (!good_host_name(msg->tsp_name)) {
+ syslog(LOG_NOTICE,
+ "attempted date change by %s to %s",
+ msg->tsp_name, newdate);
+ spreadtime();
+ break;
+ }
+
+ mchgdate(msg);
+ (void)gettimeofday(&ntime, 0);
+ pollingtime = ntime.tv_sec + SAMPLEINTVL;
+ break;
+
+ case TSP_SETDATEREQ:
+ if (!fromnet || fromnet->status != MASTER)
+ break;
+#ifdef sgi
+ (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+ (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+ htp = findhost(msg->tsp_name);
+ if (htp == 0) {
+ syslog(LOG_ERR,
+ "attempted SET DATEREQ by uncontrolled %s to %s",
+ msg->tsp_name, newdate);
+ break;
+ }
+ if (htp->seq == msg->tsp_seq)
+ break;
+ htp->seq = msg->tsp_seq;
+ if (!htp->good) {
+ syslog(LOG_NOTICE,
+ "attempted SET DATEREQ by untrusted %s to %s",
+ msg->tsp_name, newdate);
+ spreadtime();
+ break;
+ }
+
+ mchgdate(msg);
+ (void)gettimeofday(&ntime, 0);
+ pollingtime = ntime.tv_sec + SAMPLEINTVL;
+ break;
+
+ case TSP_MSITE:
+ xmit(TSP_ACK, msg->tsp_seq, &from);
+ break;
+
+ case TSP_MSITEREQ:
+ break;
+
+ case TSP_TRACEON:
+ traceon();
+ break;
+
+ case TSP_TRACEOFF:
+ traceoff("Tracing ended at %s\n");
+ break;
+
+ case TSP_ELECTION:
+ if (!fromnet)
+ break;
+ if (fromnet->status == MASTER) {
+ pollingtime = 0;
+ (void)addmach(msg->tsp_name, &from,fromnet);
+ }
+ taddr = from;
+ (void)strcpy(tname, msg->tsp_name);
+ to.tsp_type = TSP_QUIT;
+ (void)strcpy(to.tsp_name, hostname);
+ answer = acksend(&to, &taddr, tname,
+ TSP_ACK, 0, 1);
+ if (answer == NULL) {
+ syslog(LOG_ERR, "election error by %s",
+ tname);
+ }
+ break;
+
+ case TSP_CONFLICT:
+ /*
+ * After a network partition, there can be
+ * more than one master: the first slave to
+ * come up will notify here the situation.
+ */
+ if (!fromnet || fromnet->status != MASTER)
+ break;
+ (void)strcpy(to.tsp_name, hostname);
+
+ /* The other master often gets into the same state,
+ * with boring results if we stay at it forever.
+ */
+ ntp = fromnet; /* (acksend() can leave fromnet=0 */
+ for (i = 0; i < 3; i++) {
+ to.tsp_type = TSP_RESOLVE;
+ (void)strcpy(to.tsp_name, hostname);
+ answer = acksend(&to, &ntp->dest_addr,
+ ANYADDR, TSP_MASTERACK,
+ ntp, 0);
+ if (!answer)
+ break;
+ htp = addmach(answer->tsp_name,&from,ntp);
+ to.tsp_type = TSP_QUIT;
+ msg = acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, htp->noanswer);
+ if (msg == NULL) {
+ syslog(LOG_ERR,
+ "no response from %s to CONFLICT-QUIT",
+ htp->name);
+ }
+ }
+ masterup(ntp);
+ pollingtime = 0;
+ break;
+
+ case TSP_RESOLVE:
+ if (!fromnet || fromnet->status != MASTER)
+ break;
+ /*
+ * do not want to call synch() while waiting
+ * to be killed!
+ */
+ (void)gettimeofday(&ntime, (struct timezone *)0);
+ pollingtime = ntime.tv_sec + SAMPLEINTVL;
+ break;
+
+ case TSP_QUIT:
+ doquit(msg); /* become a slave */
+ break;
+
+ case TSP_LOOP:
+ if (!fromnet || fromnet->status != MASTER
+ || !strcmp(msg->tsp_name, hostname))
+ break;
+ /*
+ * We should not have received this from a net
+ * we are master on. There must be two masters.
+ */
+ htp = addmach(msg->tsp_name, &from,fromnet);
+ to.tsp_type = TSP_QUIT;
+ (void)strcpy(to.tsp_name, hostname);
+ answer = acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, 1);
+ if (!answer) {
+ syslog(LOG_WARNING,
+ "loop breakage: no reply from %s=%s to QUIT",
+ htp->name, inet_ntoa(htp->addr.sin_addr));
+ (void)remmach(htp);
+ }
+
+ case TSP_TEST:
+ if (trace) {
+ fprintf(fd,
+ "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",
+ nnets, nmasternets, nslavenets, nignorednets);
+ setstatus();
+ }
+ pollingtime = 0;
+ polls = POLLRATE-1;
+ break;
+
+ default:
+ if (trace) {
+ fprintf(fd, "garbage message: ");
+ print(msg, &from);
+ }
+ break;
+ }
+ }
+ goto loop;
+}
+
+
+/*
+ * change the system date on the master
+ */
+static void
+mchgdate(msg)
+ struct tsp *msg;
+{
+ char tname[MAXHOSTNAMELEN];
+ char olddate[32];
+ struct timeval otime, ntime;
+
+ (void)strcpy(tname, msg->tsp_name);
+
+ xmit(TSP_DATEACK, msg->tsp_seq, &from);
+
+ (void)strcpy(olddate, date());
+
+ /* adjust time for residence on the queue */
+ (void)gettimeofday(&otime, 0);
+ adj_msg_time(msg,&otime);
+
+ timevalsub(&ntime, &msg->tsp_time, &otime);
+ if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
+ /*
+ * do not change the clock if we can adjust it
+ */
+ dictate = 3;
+ synch(tvtomsround(ntime));
+ } else {
+#ifdef sgi
+ if (0 > settimeofday(&msg->tsp_time, 0)) {
+ syslog(LOG_ERR, "settimeofday(): %m");
+ }
+ logwtmp(&otime, &msg->tsp_time);
+#else
+ logwtmp("|", "date", "");
+ (void)settimeofday(&msg->tsp_time, 0);
+ logwtmp("}", "date", "");
+#endif /* sgi */
+ spreadtime();
+ }
+
+ syslog(LOG_NOTICE, "date changed by %s from %s",
+ tname, olddate);
+}
+
+
+/*
+ * synchronize all of the slaves
+ */
+void
+synch(mydelta)
+ long mydelta;
+{
+ struct hosttbl *htp;
+ int measure_status;
+ struct timeval check, stop, wait;
+#ifdef sgi
+ int pri;
+#endif /* sgi */
+
+ if (slvcount > 0) {
+ if (trace)
+ fprintf(fd, "measurements starting at %s\n", date());
+ (void)gettimeofday(&check, 0);
+#ifdef sgi
+ /* run fast to get good time */
+ pri = schedctl(NDPRI,0,NDPHIMIN);
+ if (pri < 0)
+ syslog(LOG_ERR, "schedctl(): %m");
+#endif /* sgi */
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ if (htp->noanswer != 0) {
+ measure_status = measure(500, 100,
+ htp->name,
+ &htp->addr,0);
+ } else {
+ measure_status = measure(3000, 100,
+ htp->name,
+ &htp->addr,0);
+ }
+ if (measure_status != GOOD) {
+ /* The slave did not respond. We have
+ * just wasted lots of time on it.
+ */
+ htp->delta = HOSTDOWN;
+ if (++htp->noanswer >= LOSTHOST) {
+ if (trace) {
+ fprintf(fd,
+ "purging %s for not answering ICMP\n",
+ htp->name);
+ (void)fflush(fd);
+ }
+ htp = remmach(htp);
+ }
+ } else {
+ htp->delta = measure_delta;
+ }
+ (void)gettimeofday(&stop, 0);
+ timevalsub(&stop, &stop, &check);
+ if (stop.tv_sec >= 1) {
+ if (trace)
+ (void)fflush(fd);
+ /*
+ * ack messages periodically
+ */
+ wait.tv_sec = 0;
+ wait.tv_usec = 0;
+ if (0 != readmsg(TSP_TRACEON,ANYADDR,
+ &wait,0))
+ traceon();
+ (void)gettimeofday(&check, 0);
+ }
+ }
+#ifdef sgi
+ if (pri >= 0)
+ (void)schedctl(NDPRI,0,pri);
+#endif /* sgi */
+ if (trace)
+ fprintf(fd, "measurements finished at %s\n", date());
+ }
+ if (!(status & SLAVE)) {
+ if (!dictate) {
+ mydelta = networkdelta();
+ } else {
+ dictate--;
+ }
+ }
+ if (trace && (mydelta != 0 || (status & SLAVE)))
+ fprintf(fd,"local correction of %ld ms.\n", mydelta);
+ correct(mydelta);
+}
+
+/*
+ * sends the time to each slave after the master
+ * has received the command to set the network time
+ */
+void
+spreadtime()
+{
+ struct hosttbl *htp;
+ struct tsp to;
+ struct tsp *answer;
+
+/* Do not listen to the consensus after forcing the time. This is because
+ * the consensus takes a while to reach the time we are dictating.
+ */
+ dictate = 2;
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ to.tsp_type = TSP_SETTIME;
+ (void)strcpy(to.tsp_name, hostname);
+ (void)gettimeofday(&to.tsp_time, 0);
+ answer = acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, htp->noanswer);
+ if (answer == 0) {
+ /* We client does not respond, then we have
+ * just wasted lots of time on it.
+ */
+ syslog(LOG_WARNING,
+ "no reply to SETTIME from %s", htp->name);
+ if (++htp->noanswer >= LOSTHOST) {
+ if (trace) {
+ fprintf(fd,
+ "purging %s for not answering",
+ htp->name);
+ (void)fflush(fd);
+ }
+ htp = remmach(htp);
+ }
+ }
+ }
+}
+
+void
+prthp(delta)
+ clock_t delta;
+{
+ static time_t next_time;
+ time_t this_time;
+ struct tms tm;
+ struct hosttbl *htp;
+ int length, l;
+ int i;
+
+ if (!fd) /* quit if tracing already off */
+ return;
+
+ this_time = times(&tm);
+ if (this_time + delta < next_time)
+ return;
+ next_time = this_time + CLK_TCK;
+
+ fprintf(fd, "host table: %d entries at %s\n", slvcount, date());
+ htp = self.l_fwd;
+ length = 1;
+ for (i = 1; i <= slvcount; i++, htp = htp->l_fwd) {
+ l = strlen(htp->name) + 1;
+ if (length+l >= 80) {
+ fprintf(fd, "\n");
+ length = 0;
+ }
+ length += l;
+ fprintf(fd, " %s", htp->name);
+ }
+ fprintf(fd, "\n");
+}
+
+
+static struct hosttbl *newhost_hash;
+static struct hosttbl *lasthfree = &hosttbl[0];
+
+
+struct hosttbl * /* answer or 0 */
+findhost(name)
+ char *name;
+{
+ int i, j;
+ struct hosttbl *htp;
+ char *p;
+
+ j= 0;
+ for (p = name, i = 0; i < 8 && *p != '\0'; i++, p++)
+ j = (j << 2) ^ *p;
+ newhost_hash = &hosttbl[j % NHOSTS];
+
+ htp = newhost_hash;
+ if (htp->name[0] == '\0')
+ return(0);
+ do {
+ if (!strcmp(name, htp->name))
+ return(htp);
+ htp = htp->h_fwd;
+ } while (htp != newhost_hash);
+ return(0);
+}
+
+/*
+ * add a host to the list of controlled machines if not already there
+ */
+struct hosttbl *
+addmach(name, addr, ntp)
+ char *name;
+ struct sockaddr_in *addr;
+ struct netinfo *ntp;
+{
+ struct hosttbl *ret, *p, *b, *f;
+
+ ret = findhost(name);
+ if (ret == 0) {
+ if (slvcount >= NHOSTS) {
+ if (trace) {
+ fprintf(fd, "no more slots in host table\n");
+ prthp(CLK_TCK);
+ }
+ syslog(LOG_ERR, "no more slots in host table");
+ Mflag = 0;
+ longjmp(jmpenv, 2); /* give up and be a slave */
+ }
+
+ /* if our home hash slot is occupied, find a free entry
+ * in the hash table
+ */
+ if (newhost_hash->name[0] != '\0') {
+ do {
+ ret = lasthfree;
+ if (++lasthfree > &hosttbl[NHOSTS])
+ lasthfree = &hosttbl[1];
+ } while (ret->name[0] != '\0');
+
+ if (!newhost_hash->head) {
+ /* Move an interloper using our home. Use
+ * scratch pointers in case the new head is
+ * pointing to itself.
+ */
+ f = newhost_hash->h_fwd;
+ b = newhost_hash->h_bak;
+ f->h_bak = ret;
+ b->h_fwd = ret;
+ f = newhost_hash->l_fwd;
+ b = newhost_hash->l_bak;
+ f->l_bak = ret;
+ b->l_fwd = ret;
+ bcopy(newhost_hash,ret,sizeof(*ret));
+ ret = newhost_hash;
+ ret->head = 1;
+ ret->h_fwd = ret;
+ ret->h_bak = ret;
+ } else {
+ /* link to an existing chain in our home
+ */
+ ret->head = 0;
+ p = newhost_hash->h_bak;
+ ret->h_fwd = newhost_hash;
+ ret->h_bak = p;
+ p->h_fwd = ret;
+ newhost_hash->h_bak = ret;
+ }
+ } else {
+ ret = newhost_hash;
+ ret->head = 1;
+ ret->h_fwd = ret;
+ ret->h_bak = ret;
+ }
+ ret->addr = *addr;
+ ret->ntp = ntp;
+ (void)strncpy(ret->name, name, sizeof(ret->name));
+ ret->good = good_host_name(name);
+ ret->l_fwd = &self;
+ ret->l_bak = self.l_bak;
+ self.l_bak->l_fwd = ret;
+ self.l_bak = ret;
+ slvcount++;
+
+ ret->noanswer = 0;
+ ret->need_set = 1;
+
+ } else {
+ ret->noanswer = (ret->noanswer != 0);
+ }
+
+ /* need to clear sequence number anyhow */
+ ret->seq = 0;
+ return(ret);
+}
+
+/*
+ * remove the machine with the given index in the host table.
+ */
+struct hosttbl *
+remmach(htp)
+ struct hosttbl *htp;
+{
+ struct hosttbl *lprv, *hnxt, *f, *b;
+
+ if (trace)
+ fprintf(fd, "remove %s\n", htp->name);
+
+ /* get out of the lists */
+ htp->l_fwd->l_bak = lprv = htp->l_bak;
+ htp->l_bak->l_fwd = htp->l_fwd;
+ htp->h_fwd->h_bak = htp->h_bak;
+ htp->h_bak->h_fwd = hnxt = htp->h_fwd;
+
+ /* If we are in the home slot, pull up the chain */
+ if (htp->head && hnxt != htp) {
+ if (lprv == hnxt)
+ lprv = htp;
+
+ /* Use scratch pointers in case the new head is pointing to
+ * itself.
+ */
+ f = hnxt->h_fwd;
+ b = hnxt->h_bak;
+ f->h_bak = htp;
+ b->h_fwd = htp;
+ f = hnxt->l_fwd;
+ b = hnxt->l_bak;
+ f->l_bak = htp;
+ b->l_fwd = htp;
+ hnxt->head = 1;
+ bcopy(hnxt, htp, sizeof(*htp));
+ lasthfree = hnxt;
+ } else {
+ lasthfree = htp;
+ }
+
+ lasthfree->name[0] = '\0';
+ lasthfree->h_fwd = 0;
+ lasthfree->l_fwd = 0;
+ slvcount--;
+
+ return lprv;
+}
+
+
+/*
+ * Remove all the machines from the host table that exist on the given
+ * network. This is called when a master transitions to a slave on a
+ * given network.
+ */
+void
+rmnetmachs(ntp)
+ struct netinfo *ntp;
+{
+ struct hosttbl *htp;
+
+ if (trace)
+ prthp(CLK_TCK);
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ if (ntp == htp->ntp)
+ htp = remmach(htp);
+ }
+ if (trace)
+ prthp(CLK_TCK);
+}
+
+void
+masterup(net)
+ struct netinfo *net;
+{
+ xmit(TSP_MASTERUP, 0, &net->dest_addr);
+
+ /*
+ * Do not tell new slaves our time for a while. This ensures
+ * we do not tell them to start using our time, before we have
+ * found a good master.
+ */
+ (void)gettimeofday(&net->slvwait, 0);
+}
+
+void
+newslave(msg)
+ struct tsp *msg;
+{
+ struct hosttbl *htp;
+ struct tsp *answer, to;
+ struct timeval now;
+
+ if (!fromnet || fromnet->status != MASTER)
+ return;
+
+ htp = addmach(msg->tsp_name, &from,fromnet);
+ htp->seq = msg->tsp_seq;
+ if (trace)
+ prthp(0);
+
+ /*
+ * If we are stable, send our time to the slave.
+ * Do not go crazy if the date has been changed.
+ */
+ (void)gettimeofday(&now, 0);
+ if (now.tv_sec >= fromnet->slvwait.tv_sec+3
+ || now.tv_sec < fromnet->slvwait.tv_sec) {
+ to.tsp_type = TSP_SETTIME;
+ (void)strcpy(to.tsp_name, hostname);
+ (void)gettimeofday(&to.tsp_time, 0);
+ answer = acksend(&to, &htp->addr,
+ htp->name, TSP_ACK,
+ 0, htp->noanswer);
+ if (answer) {
+ htp->need_set = 0;
+ } else {
+ syslog(LOG_WARNING,
+ "no reply to initial SETTIME from %s",
+ htp->name);
+ htp->noanswer = LOSTHOST;
+ }
+ }
+}
+
+
+/*
+ * react to a TSP_QUIT:
+ */
+void
+doquit(msg)
+ struct tsp *msg;
+{
+ if (fromnet->status == MASTER) {
+ if (!good_host_name(msg->tsp_name)) {
+ if (fromnet->quit_count <= 0) {
+ syslog(LOG_NOTICE,"untrusted %s told us QUIT",
+ msg->tsp_name);
+ suppress(&from, msg->tsp_name, fromnet);
+ fromnet->quit_count = 1;
+ return;
+ }
+ syslog(LOG_NOTICE, "untrusted %s told us QUIT twice",
+ msg->tsp_name);
+ fromnet->quit_count = 2;
+ fromnet->status = NOMASTER;
+ } else {
+ fromnet->status = SLAVE;
+ }
+ rmnetmachs(fromnet);
+ longjmp(jmpenv, 2); /* give up and be a slave */
+
+ } else {
+ if (!good_host_name(msg->tsp_name)) {
+ syslog(LOG_NOTICE, "untrusted %s told us QUIT",
+ msg->tsp_name);
+ fromnet->quit_count = 2;
+ }
+ }
+}
+
+void
+traceon()
+{
+ if (!fd) {
+ fd = fopen(_PATH_TIMEDLOG, "w");
+ if (!fd) {
+ trace = 0;
+ return;
+ }
+ fprintf(fd,"Tracing started at %s\n", date());
+ }
+ trace = 1;
+ get_goodgroup(1);
+ setstatus();
+ prthp(CLK_TCK);
+}
+
+
+void
+traceoff(msg)
+ char *msg;
+{
+ get_goodgroup(1);
+ setstatus();
+ prthp(CLK_TCK);
+ if (trace) {
+ fprintf(fd, msg, date());
+ (void)fclose(fd);
+ fd = 0;
+ }
+#ifdef GPROF
+ moncontrol(0);
+ _mcleanup();
+ moncontrol(1);
+#endif
+ trace = OFF;
+}
+
+
+#ifdef sgi
+void
+logwtmp(otime, ntime)
+ struct timeval *otime, *ntime;
+{
+ static struct utmp wtmp[2] = {
+ {"","",OTIME_MSG,0,OLD_TIME,0,0,0},
+ {"","",NTIME_MSG,0,NEW_TIME,0,0,0}
+ };
+ static char *wtmpfile = WTMP_FILE;
+ int f;
+
+ wtmp[0].ut_time = otime->tv_sec + (otime->tv_usec + 500000) / 1000000;
+ wtmp[1].ut_time = ntime->tv_sec + (ntime->tv_usec + 500000) / 1000000;
+ if (wtmp[0].ut_time == wtmp[1].ut_time)
+ return;
+
+ setutent();
+ (void)pututline(&wtmp[0]);
+ (void)pututline(&wtmp[1]);
+ endutent();
+ if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) {
+ (void) write(f, (char *)wtmp, sizeof(wtmp));
+ (void) close(f);
+ }
+}
+#endif /* sgi */
diff --git a/usr.sbin/timed/timed/measure.c b/usr.sbin/timed/timed/measure.c
new file mode 100644
index 0000000..4066d10
--- /dev/null
+++ b/usr.sbin/timed/timed/measure.c
@@ -0,0 +1,353 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)measure.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.8 $"
+#endif
+
+#include "globals.h"
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define MSEC_DAY (SECDAY*1000)
+
+#define PACKET_IN 1024
+
+#define MSGS 5 /* timestamps to average */
+#define TRIALS 10 /* max # of timestamps sent */
+
+extern int sock_raw;
+
+int measure_delta;
+
+static n_short seqno = 0;
+
+/*
+ * Measures the differences between machines' clocks using
+ * ICMP timestamp messages.
+ */
+int /* status val defined in globals.h */
+measure(maxmsec, wmsec, hname, addr, print)
+ u_long maxmsec; /* wait this many msec at most */
+ u_long wmsec; /* msec to wait for an answer */
+ char *hname;
+ struct sockaddr_in *addr;
+ int print; /* print complaints on stderr */
+{
+ int length;
+ int measure_status;
+ int rcvcount, trials;
+ int cc, count;
+ fd_set ready;
+ long sendtime, recvtime, histime1, histime2;
+ long idelta, odelta, total;
+ long min_idelta, min_odelta;
+ struct timeval tdone, tcur, ttrans, twait, tout;
+ u_char packet[PACKET_IN], opacket[64];
+ register struct icmp *icp = (struct icmp *) packet;
+ register struct icmp *oicp = (struct icmp *) opacket;
+ struct ip *ip = (struct ip *) packet;
+
+ min_idelta = min_odelta = 0x7fffffff;
+ measure_status = HOSTDOWN;
+ measure_delta = HOSTDOWN;
+ errno = 0;
+
+ /* open raw socket used to measure time differences */
+ if (sock_raw < 0) {
+ sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (sock_raw < 0) {
+ syslog(LOG_ERR, "opening raw socket: %m");
+ goto quit;
+ }
+ }
+
+
+ /*
+ * empty the icmp input queue
+ */
+ FD_ZERO(&ready);
+ for (;;) {
+ tout.tv_sec = tout.tv_usec = 0;
+ FD_SET(sock_raw, &ready);
+ if (select(sock_raw+1, &ready, 0,0, &tout)) {
+ length = sizeof(struct sockaddr_in);
+ cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
+ 0,&length);
+ if (cc < 0)
+ goto quit;
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Choose the smallest transmission time in each of the two
+ * directions. Use these two latter quantities to compute the delta
+ * between the two clocks.
+ */
+
+ oicp->icmp_type = ICMP_TSTAMP;
+ oicp->icmp_code = 0;
+ oicp->icmp_id = getpid();
+ oicp->icmp_rtime = 0;
+ oicp->icmp_ttime = 0;
+ oicp->icmp_seq = seqno;
+
+ FD_ZERO(&ready);
+
+#ifdef sgi
+ sginap(1); /* start at a clock tick */
+#endif /* sgi */
+
+ (void)gettimeofday(&tdone, 0);
+ mstotvround(&tout, maxmsec);
+ timevaladd(&tdone, &tout); /* when we give up */
+
+ mstotvround(&twait, wmsec);
+
+ rcvcount = 0;
+ trials = 0;
+ while (rcvcount < MSGS) {
+ (void)gettimeofday(&tcur, 0);
+
+ /*
+ * keep sending until we have sent the max
+ */
+ if (trials < TRIALS) {
+ trials++;
+ oicp->icmp_otime = ((tcur.tv_sec % SECDAY) * 1000
+ + tcur.tv_usec / 1000);
+ oicp->icmp_cksum = 0;
+ oicp->icmp_cksum = in_cksum((u_short*)oicp,
+ sizeof(*oicp));
+
+ count = sendto(sock_raw, opacket, sizeof(*oicp), 0,
+ (struct sockaddr*)addr,
+ sizeof(struct sockaddr));
+ if (count < 0) {
+ if (measure_status == HOSTDOWN)
+ measure_status = UNREACHABLE;
+ goto quit;
+ }
+ ++oicp->icmp_seq;
+
+ ttrans = tcur;
+ timevaladd(&ttrans, &twait);
+ } else {
+ ttrans = tdone;
+ }
+
+ while (rcvcount < trials) {
+ timevalsub(&tout, &ttrans, &tcur);
+ if (tout.tv_sec < 0)
+ tout.tv_sec = 0;
+
+ FD_SET(sock_raw, &ready);
+ count = select(sock_raw+1, &ready, (fd_set *)0,
+ (fd_set *)0, &tout);
+ (void)gettimeofday(&tcur, (struct timezone *)0);
+ if (count <= 0)
+ break;
+
+ length = sizeof(struct sockaddr_in);
+ cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
+ 0,&length);
+ if (cc < 0)
+ goto quit;
+
+ /*
+ * got something. See if it is ours
+ */
+ icp = (struct icmp *)(packet + (ip->ip_hl << 2));
+ if (cc < sizeof(*ip)
+ || icp->icmp_type != ICMP_TSTAMPREPLY
+ || icp->icmp_id != oicp->icmp_id
+ || icp->icmp_seq < seqno
+ || icp->icmp_seq >= oicp->icmp_seq)
+ continue;
+
+
+ sendtime = ntohl(icp->icmp_otime);
+ recvtime = ((tcur.tv_sec % SECDAY) * 1000 +
+ tcur.tv_usec / 1000);
+
+ total = recvtime-sendtime;
+ if (total < 0) /* do not hassle midnight */
+ continue;
+
+ rcvcount++;
+ histime1 = ntohl(icp->icmp_rtime);
+ histime2 = ntohl(icp->icmp_ttime);
+ /*
+ * a host using a time format different from
+ * msec. since midnight UT (as per RFC792) should
+ * set the high order bit of the 32-bit time
+ * value it transmits.
+ */
+ if ((histime1 & 0x80000000) != 0) {
+ measure_status = NONSTDTIME;
+ goto quit;
+ }
+ measure_status = GOOD;
+
+ idelta = recvtime-histime2;
+ odelta = histime1-sendtime;
+
+ /* do not be confused by midnight */
+ if (idelta < -MSEC_DAY/2) idelta += MSEC_DAY;
+ else if (idelta > MSEC_DAY/2) idelta -= MSEC_DAY;
+
+ if (odelta < -MSEC_DAY/2) odelta += MSEC_DAY;
+ else if (odelta > MSEC_DAY/2) odelta -= MSEC_DAY;
+
+ /* save the quantization error so that we can get a
+ * measurement finer than our system clock.
+ */
+ if (total < MIN_ROUND) {
+ measure_delta = (odelta - idelta)/2;
+ goto quit;
+ }
+
+ if (idelta < min_idelta)
+ min_idelta = idelta;
+ if (odelta < min_odelta)
+ min_odelta = odelta;
+
+ measure_delta = (min_odelta - min_idelta)/2;
+ }
+
+ if (tcur.tv_sec > tdone.tv_sec
+ || (tcur.tv_sec == tdone.tv_sec
+ && tcur.tv_usec >= tdone.tv_usec))
+ break;
+ }
+
+quit:
+ seqno += TRIALS; /* allocate our sequence numbers */
+
+ /*
+ * If no answer is received for TRIALS consecutive times,
+ * the machine is assumed to be down
+ */
+ if (measure_status == GOOD) {
+ if (trace) {
+ fprintf(fd,
+ "measured delta %4d, %d trials to %-15s %s\n",
+ measure_delta, trials,
+ inet_ntoa(addr->sin_addr), hname);
+ }
+ } else if (print) {
+ if (errno != 0)
+ fprintf(stderr, "measure %s: %s\n", hname,
+ strerror(errno));
+ } else {
+ if (errno != 0) {
+ syslog(LOG_ERR, "measure %s: %m", hname);
+ } else {
+ syslog(LOG_ERR, "measure: %s did not respond", hname);
+ }
+ if (trace) {
+ fprintf(fd,
+ "measure: %s failed after %d trials\n",
+ hname, trials);
+ (void)fflush(fd);
+ }
+ }
+
+ return(measure_status);
+}
+
+
+
+
+
+/*
+ * round a number of milliseconds into a struct timeval
+ */
+void
+mstotvround(res, x)
+ struct timeval *res;
+ long x;
+{
+#ifndef sgi
+ if (x < 0)
+ x = -((-x + 3)/5);
+ else
+ x = (x+3)/5;
+ x *= 5;
+#endif /* sgi */
+ res->tv_sec = x/1000;
+ res->tv_usec = (x-res->tv_sec*1000)*1000;
+ if (res->tv_usec < 0) {
+ res->tv_usec += 1000000;
+ res->tv_sec--;
+ }
+}
+
+void
+timevaladd(tv1, tv2)
+ struct timeval *tv1, *tv2;
+{
+ tv1->tv_sec += tv2->tv_sec;
+ tv1->tv_usec += tv2->tv_usec;
+ if (tv1->tv_usec >= 1000000) {
+ tv1->tv_sec++;
+ tv1->tv_usec -= 1000000;
+ }
+ if (tv1->tv_usec < 0) {
+ tv1->tv_sec--;
+ tv1->tv_usec += 1000000;
+ }
+}
+
+void
+timevalsub(res, tv1, tv2)
+ struct timeval *res, *tv1, *tv2;
+{
+ res->tv_sec = tv1->tv_sec - tv2->tv_sec;
+ res->tv_usec = tv1->tv_usec - tv2->tv_usec;
+ if (res->tv_usec >= 1000000) {
+ res->tv_sec++;
+ res->tv_usec -= 1000000;
+ }
+ if (res->tv_usec < 0) {
+ res->tv_sec--;
+ res->tv_usec += 1000000;
+ }
+}
diff --git a/usr.sbin/timed/timed/networkdelta.c b/usr.sbin/timed/timed/networkdelta.c
new file mode 100644
index 0000000..d64640a
--- /dev/null
+++ b/usr.sbin/timed/timed/networkdelta.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)networkdelta.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.4 $"
+#endif
+
+#include "globals.h"
+
+static long median __P((float, float *, long *, long *, unsigned int));
+
+/*
+ * Compute a corrected date.
+ * Compute the median of the reasonable differences. First compute
+ * the median of all authorized differences, and then compute the
+ * median of all differences that are reasonably close to the first
+ * median.
+ *
+ * This differs from the original BSD implementation, which looked for
+ * the largest group of machines with essentially the same date.
+ * That assumed that machines with bad clocks would be uniformly
+ * distributed. Unfortunately, in real life networks, the distribution
+ * of machines is not uniform among models of machines, and the
+ * distribution of errors in clocks tends to be quite consistent
+ * for a given model. In other words, all model VI Supre Servres
+ * from GoFast Inc. tend to have about the same error.
+ * The original BSD implementation would chose the clock of the
+ * most common model, and discard all others.
+ *
+ * Therefore, get best we can do is to try to average over all
+ * of the machines in the network, while discarding "obviously"
+ * bad values.
+ */
+long
+networkdelta()
+{
+ struct hosttbl *htp;
+ long med;
+ long lodelta, hidelta;
+ long logood, higood;
+ long x[NHOSTS];
+ long *xp;
+ int numdelta;
+ float eps;
+
+ /*
+ * compute the median of the good values
+ */
+ med = 0;
+ numdelta = 1;
+ xp = &x[0];
+ *xp = 0; /* account for ourself */
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ if (htp->good
+ && htp->noanswer == 0
+ && htp->delta != HOSTDOWN) {
+ med += htp->delta;
+ numdelta++;
+ *++xp = htp->delta;
+ }
+ }
+
+ /*
+ * If we are the only trusted time keeper, then do not change our
+ * clock. There may be another time keeping service active.
+ */
+ if (numdelta == 1)
+ return 0;
+
+ med /= numdelta;
+ eps = med - x[0];
+ if (trace)
+ fprintf(fd, "median of %d values starting at %ld is about ",
+ numdelta, med);
+ med = median(med, &eps, &x[0], xp+1, VALID_RANGE);
+
+ /*
+ * compute the median of all values near the good median
+ */
+ hidelta = med + GOOD_RANGE;
+ lodelta = med - GOOD_RANGE;
+ higood = med + VGOOD_RANGE;
+ logood = med - VGOOD_RANGE;
+ xp = &x[0];
+ htp = &self;
+ do {
+ if (htp->noanswer == 0
+ && htp->delta >= lodelta
+ && htp->delta <= hidelta
+ && (htp->good
+ || (htp->delta >= logood
+ && htp->delta <= higood))) {
+ *xp++ = htp->delta;
+ }
+ } while (&self != (htp = htp->l_fwd));
+
+ if (xp == &x[0]) {
+ if (trace)
+ fprintf(fd, "nothing close to median %ld\n", med);
+ return med;
+ }
+
+ if (xp == &x[1]) {
+ if (trace)
+ fprintf(fd, "only value near median is %ld\n", x[0]);
+ return x[0];
+ }
+
+ if (trace)
+ fprintf(fd, "median of %d values starting at %ld is ",
+ xp-&x[0], med);
+ return median(med, &eps, &x[0], xp, 1);
+}
+
+
+/*
+ * compute the median of an array of signed integers, using the idea
+ * in <<Numerical Recipes>>.
+ */
+static long
+median(a, eps_ptr, x, xlim, gnuf)
+ float a; /* initial guess for the median */
+ float *eps_ptr; /* spacing near the median */
+ long *x, *xlim; /* the data */
+ unsigned int gnuf; /* good enough estimate */
+{
+ long *xptr;
+ float ap = LONG_MAX; /* bounds on the median */
+ float am = -LONG_MAX;
+ float aa;
+ int npts; /* # of points above & below guess */
+ float xp; /* closet point above the guess */
+ float xm; /* closet point below the guess */
+ float eps;
+ float dum, sum, sumx;
+ int pass;
+#define AMP 1.5 /* smoothing constants */
+#define AFAC 1.5
+
+ eps = *eps_ptr;
+ if (eps < 1.0) {
+ eps = -eps;
+ if (eps < 1.0)
+ eps = 1.0;
+ }
+
+ for (pass = 1; ; pass++) { /* loop over the data */
+ sum = 0.0;
+ sumx = 0.0;
+ npts = 0;
+ xp = LONG_MAX;
+ xm = -LONG_MAX;
+
+ for (xptr = x; xptr != xlim; xptr++) {
+ float xx = *xptr;
+
+ dum = xx - a;
+ if (dum != 0.0) { /* avoid dividing by 0 */
+ if (dum > 0.0) {
+ npts++;
+ if (xx < xp)
+ xp = xx;
+ } else {
+ npts--;
+ if (xx > xm)
+ xm = xx;
+ dum = -dum;
+ }
+ dum = 1.0/(eps + dum);
+ sum += dum;
+ sumx += xx * dum;
+ }
+ }
+
+ if (ap-am < gnuf || sum == 0) {
+ if (trace)
+ fprintf(fd,
+ "%ld in %d passes; early out balance=%d\n",
+ (long)a, pass, npts);
+ return a; /* guess was good enough */
+ }
+
+ aa = (sumx/sum-a)*AMP;
+ if (npts >= 2) { /* guess was too low */
+ am = a;
+ aa = xp + max(0.0, aa);;
+ if (aa > ap)
+ aa = (a + ap)/2;
+
+ } else if (npts <= -2) { /* guess was two high */
+ ap = a;
+ aa = xm + min(0.0, aa);;
+ if (aa < am)
+ aa = (a + am)/2;
+
+ } else {
+ break; /* got it */
+ }
+
+ if (a == aa) {
+ if (trace)
+ fprintf(fd,
+ "%ld in %d passes; force out balance=%d\n",
+ (long)a, pass, npts);
+ return a;
+ }
+ eps = AFAC*abs(aa - a);
+ *eps_ptr = eps;
+ a = aa;
+ }
+
+ if (((x - xlim) % 2) != 0) { /* even number of points? */
+ if (npts == 0) /* yes, return an average */
+ a = (xp+xm)/2;
+ else if (npts > 0)
+ a = (a+xp)/2;
+ else
+ a = (xm+a)/2;
+
+ } else if (npts != 0) { /* odd number of points */
+ if (npts > 0)
+ a = xp;
+ else
+ a = xm;
+ }
+
+ if (trace)
+ fprintf(fd, "%ld in %d passes\n", (long)a, pass);
+ return a;
+}
diff --git a/usr.sbin/timed/timed/pathnames.h b/usr.sbin/timed/timed/pathnames.h
new file mode 100644
index 0000000..ae5e1c5
--- /dev/null
+++ b/usr.sbin/timed/timed/pathnames.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#ifdef sgi
+#define _PATH_MASTERLOG "/usr/adm/timed.masterlog"
+#define _PATH_TIMEDLOG "/usr/adm/timed.log"
+#else
+#define _PATH_MASTERLOG "/var/log/timed.masterlog"
+#define _PATH_TIMEDLOG "/var/log/timed.log"
+#endif
diff --git a/usr.sbin/timed/timed/readmsg.c b/usr.sbin/timed/timed/readmsg.c
new file mode 100644
index 0000000..3e8f4d2
--- /dev/null
+++ b/usr.sbin/timed/timed/readmsg.c
@@ -0,0 +1,488 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)readmsg.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.17 $"
+#endif
+
+#include "globals.h"
+
+extern char *tsptype[];
+
+/*
+ * LOOKAT checks if the message is of the requested type and comes from
+ * the right machine, returning 1 in case of affirmative answer
+ */
+#define LOOKAT(msg, mtype, mfrom, netp, froms) \
+ (((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) && \
+ ((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) && \
+ ((netp) == 0 || \
+ ((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr))
+
+struct timeval rtime, rwait, rtout;
+struct tsp msgin;
+static struct tsplist {
+ struct tsp info;
+ struct timeval when;
+ struct sockaddr_in addr;
+ struct tsplist *p;
+} msgslist;
+struct sockaddr_in from;
+struct netinfo *fromnet;
+struct timeval from_when;
+
+/*
+ * `readmsg' returns message `type' sent by `machfrom' if it finds it
+ * either in the receive queue, or in a linked list of previously received
+ * messages that it maintains.
+ * Otherwise it waits to see if the appropriate message arrives within
+ * `intvl' seconds. If not, it returns NULL.
+ */
+
+struct tsp *
+readmsg(type, machfrom, intvl, netfrom)
+ int type;
+ char *machfrom;
+ struct timeval *intvl;
+ struct netinfo *netfrom;
+{
+ int length;
+ fd_set ready;
+ static struct tsplist *head = &msgslist;
+ static struct tsplist *tail = &msgslist;
+ static int msgcnt = 0;
+ struct tsplist *prev;
+ register struct netinfo *ntp;
+ register struct tsplist *ptr;
+
+ if (trace) {
+ fprintf(fd, "readmsg: looking for %s from %s, %s\n",
+ tsptype[type], machfrom == NULL ? "ANY" : machfrom,
+ netfrom == NULL ? "ANYNET" : inet_ntoa(netfrom->net));
+ if (head->p != 0) {
+ length = 1;
+ for (ptr = head->p; ptr != 0; ptr = ptr->p) {
+ /* do not repeat the hundreds of messages */
+ if (++length > 3) {
+ if (ptr == tail) {
+ fprintf(fd,"\t ...%d skipped\n",
+ length);
+ } else {
+ continue;
+ }
+ }
+ fprintf(fd, length > 1 ? "\t" : "queue:\t");
+ print(&ptr->info, &ptr->addr);
+ }
+ }
+ }
+
+ ptr = head->p;
+ prev = head;
+
+ /*
+ * Look for the requested message scanning through the
+ * linked list. If found, return it and free the space
+ */
+
+ while (ptr != NULL) {
+ if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
+again:
+ msgin = ptr->info;
+ from = ptr->addr;
+ from_when = ptr->when;
+ prev->p = ptr->p;
+ if (ptr == tail)
+ tail = prev;
+ free((char *)ptr);
+ fromnet = NULL;
+ if (netfrom == NULL)
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if ((ntp->mask & from.sin_addr.s_addr) ==
+ ntp->net.s_addr) {
+ fromnet = ntp;
+ break;
+ }
+ }
+ else
+ fromnet = netfrom;
+ if (trace) {
+ fprintf(fd, "readmsg: found ");
+ print(&msgin, &from);
+ }
+
+/* The protocol can get far behind. When it does, it gets
+ * hopelessly confused. So delete duplicate messages.
+ */
+ for (ptr = prev; (ptr = ptr->p) != NULL; prev = ptr) {
+ if (ptr->addr.sin_addr.s_addr
+ == from.sin_addr.s_addr
+ && ptr->info.tsp_type == msgin.tsp_type) {
+ if (trace)
+ fprintf(fd, "\tdup ");
+ goto again;
+ }
+ }
+ msgcnt--;
+ return(&msgin);
+ } else {
+ prev = ptr;
+ ptr = ptr->p;
+ }
+ }
+
+ /*
+ * If the message was not in the linked list, it may still be
+ * coming from the network. Set the timer and wait
+ * on a select to read the next incoming message: if it is the
+ * right one, return it, otherwise insert it in the linked list.
+ */
+
+ (void)gettimeofday(&rtout, 0);
+ timevaladd(&rtout, intvl);
+ FD_ZERO(&ready);
+ for (;;) {
+ (void)gettimeofday(&rtime, 0);
+ timevalsub(&rwait, &rtout, &rtime);
+ if (rwait.tv_sec < 0)
+ rwait.tv_sec = rwait.tv_usec = 0;
+ else if (rwait.tv_sec == 0
+ && rwait.tv_usec < 1000000/CLK_TCK)
+ rwait.tv_usec = 1000000/CLK_TCK;
+
+ if (trace) {
+ fprintf(fd, "readmsg: wait %ld.%6ld at %s\n",
+ rwait.tv_sec, rwait.tv_usec, date());
+ /* Notice a full disk, as we flush trace info.
+ * It is better to flush periodically than at
+ * every line because the tracing consists of bursts
+ * of many lines. Without care, tracing slows
+ * down the code enough to break the protocol.
+ */
+ if (rwait.tv_sec != 0
+ && EOF == fflush(fd))
+ traceoff("Tracing ended for cause at %s\n");
+ }
+
+ FD_SET(sock, &ready);
+ if (!select(sock+1, &ready, (fd_set *)0, (fd_set *)0,
+ &rwait)) {
+ if (rwait.tv_sec == 0 && rwait.tv_usec == 0)
+ return(0);
+ continue;
+ }
+ length = sizeof(from);
+ if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0,
+ (struct sockaddr*)&from, &length) < 0) {
+ syslog(LOG_ERR, "recvfrom: %m");
+ exit(1);
+ }
+ (void)gettimeofday(&from_when, (struct timezone *)0);
+ bytehostorder(&msgin);
+
+ if (msgin.tsp_vers > TSPVERSION) {
+ if (trace) {
+ fprintf(fd,"readmsg: version mismatch\n");
+ /* should do a dump of the packet */
+ }
+ continue;
+ }
+
+ fromnet = NULL;
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+ if ((ntp->mask & from.sin_addr.s_addr) ==
+ ntp->net.s_addr) {
+ fromnet = ntp;
+ break;
+ }
+
+ /*
+ * drop packets from nets we are ignoring permanently
+ */
+ if (fromnet == NULL) {
+ /*
+ * The following messages may originate on
+ * this host with an ignored network address
+ */
+ if (msgin.tsp_type != TSP_TRACEON &&
+ msgin.tsp_type != TSP_SETDATE &&
+ msgin.tsp_type != TSP_MSITE &&
+ msgin.tsp_type != TSP_TEST &&
+ msgin.tsp_type != TSP_TRACEOFF) {
+ if (trace) {
+ fprintf(fd,"readmsg: discard null net ");
+ print(&msgin, &from);
+ }
+ continue;
+ }
+ }
+
+ /*
+ * Throw away messages coming from this machine,
+ * unless they are of some particular type.
+ * This gets rid of broadcast messages and reduces
+ * master processing time.
+ */
+ if (!strcmp(msgin.tsp_name, hostname)
+ && msgin.tsp_type != TSP_SETDATE
+ && msgin.tsp_type != TSP_TEST
+ && msgin.tsp_type != TSP_MSITE
+ && msgin.tsp_type != TSP_TRACEON
+ && msgin.tsp_type != TSP_TRACEOFF
+ && msgin.tsp_type != TSP_LOOP) {
+ if (trace) {
+ fprintf(fd, "readmsg: discard own ");
+ print(&msgin, &from);
+ }
+ continue;
+ }
+
+ /*
+ * Send acknowledgements here; this is faster and
+ * avoids deadlocks that would occur if acks were
+ * sent from a higher level routine. Different
+ * acknowledgements are necessary, depending on
+ * status.
+ */
+ if (fromnet == NULL) /* do not de-reference 0 */
+ ignoreack();
+ else if (fromnet->status == MASTER)
+ masterack();
+ else if (fromnet->status == SLAVE)
+ slaveack();
+ else
+ ignoreack();
+
+ if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
+ if (trace) {
+ fprintf(fd, "readmsg: ");
+ print(&msgin, &from);
+ }
+ return(&msgin);
+ } else if (++msgcnt > NHOSTS*3) {
+
+/* The protocol gets hopelessly confused if it gets too far
+* behind. However, it seems able to recover from all cases of lost
+* packets. Therefore, if we are swamped, throw everything away.
+*/
+ if (trace)
+ fprintf(fd,
+ "readmsg: discarding %d msgs\n",
+ msgcnt);
+ msgcnt = 0;
+ while ((ptr=head->p) != NULL) {
+ head->p = ptr->p;
+ free((char *)ptr);
+ }
+ tail = head;
+ } else {
+ tail->p = (struct tsplist *)
+ malloc(sizeof(struct tsplist));
+ tail = tail->p;
+ tail->p = NULL;
+ tail->info = msgin;
+ tail->addr = from;
+ /* timestamp msgs so SETTIMEs are correct */
+ tail->when = from_when;
+ }
+ }
+}
+
+/*
+ * Send the necessary acknowledgements:
+ * only the type ACK is to be sent by a slave
+ */
+void
+slaveack()
+{
+ switch(msgin.tsp_type) {
+
+ case TSP_ADJTIME:
+ case TSP_SETTIME:
+ case TSP_ACCEPT:
+ case TSP_REFUSE:
+ case TSP_TRACEON:
+ case TSP_TRACEOFF:
+ case TSP_QUIT:
+ if (trace) {
+ fprintf(fd, "Slaveack: ");
+ print(&msgin, &from);
+ }
+ xmit(TSP_ACK,msgin.tsp_seq, &from);
+ break;
+
+ default:
+ if (trace) {
+ fprintf(fd, "Slaveack: no ack: ");
+ print(&msgin, &from);
+ }
+ break;
+ }
+}
+
+/*
+ * Certain packets may arrive from this machine on ignored networks.
+ * These packets should be acknowledged.
+ */
+void
+ignoreack()
+{
+ switch(msgin.tsp_type) {
+
+ case TSP_TRACEON:
+ case TSP_TRACEOFF:
+ case TSP_QUIT:
+ if (trace) {
+ fprintf(fd, "Ignoreack: ");
+ print(&msgin, &from);
+ }
+ xmit(TSP_ACK,msgin.tsp_seq, &from);
+ break;
+
+ default:
+ if (trace) {
+ fprintf(fd, "Ignoreack: no ack: ");
+ print(&msgin, &from);
+ }
+ break;
+ }
+}
+
+/*
+ * `masterack' sends the necessary acknowledgments
+ * to the messages received by a master
+ */
+void
+masterack()
+{
+ struct tsp resp;
+
+ resp = msgin;
+ resp.tsp_vers = TSPVERSION;
+ (void)strcpy(resp.tsp_name, hostname);
+
+ switch(msgin.tsp_type) {
+
+ case TSP_QUIT:
+ case TSP_TRACEON:
+ case TSP_TRACEOFF:
+ case TSP_MSITEREQ:
+ if (trace) {
+ fprintf(fd, "Masterack: ");
+ print(&msgin, &from);
+ }
+ xmit(TSP_ACK,msgin.tsp_seq, &from);
+ break;
+
+ case TSP_RESOLVE:
+ case TSP_MASTERREQ:
+ if (trace) {
+ fprintf(fd, "Masterack: ");
+ print(&msgin, &from);
+ }
+ xmit(TSP_MASTERACK,msgin.tsp_seq, &from);
+ break;
+
+ default:
+ if (trace) {
+ fprintf(fd,"Masterack: no ack: ");
+ print(&msgin, &from);
+ }
+ break;
+ }
+}
+
+/*
+ * Print a TSP message
+ */
+void
+print(msg, addr)
+ struct tsp *msg;
+ struct sockaddr_in *addr;
+{
+ char tm[26];
+ switch (msg->tsp_type) {
+
+ case TSP_LOOP:
+ fprintf(fd, "%s %d %-6u #%d %-15s %s\n",
+ tsptype[msg->tsp_type],
+ msg->tsp_vers,
+ msg->tsp_seq,
+ msg->tsp_hopcnt,
+ inet_ntoa(addr->sin_addr),
+ msg->tsp_name);
+ break;
+
+ case TSP_SETTIME:
+ case TSP_SETDATE:
+ case TSP_SETDATEREQ:
+#ifdef sgi
+ (void)cftime(tm, "%D %T", &msg->tsp_time.tv_sec);
+#else
+ strncpy(tm, ctime(&msg->tsp_time.tv_sec)+3+1, sizeof(tm));
+ tm[15] = '\0'; /* ugh */
+#endif /* sgi */
+ fprintf(fd, "%s %d %-6u %s %-15s %s\n",
+ tsptype[msg->tsp_type],
+ msg->tsp_vers,
+ msg->tsp_seq,
+ tm,
+ inet_ntoa(addr->sin_addr),
+ msg->tsp_name);
+ break;
+
+ case TSP_ADJTIME:
+ fprintf(fd, "%s %d %-6u (%ld,%ld) %-15s %s\n",
+ tsptype[msg->tsp_type],
+ msg->tsp_vers,
+ msg->tsp_seq,
+ msg->tsp_time.tv_sec,
+ msg->tsp_time.tv_usec,
+ inet_ntoa(addr->sin_addr),
+ msg->tsp_name);
+ break;
+
+ default:
+ fprintf(fd, "%s %d %-6u %-15s %s\n",
+ tsptype[msg->tsp_type],
+ msg->tsp_vers,
+ msg->tsp_seq,
+ inet_ntoa(addr->sin_addr),
+ msg->tsp_name);
+ break;
+ }
+}
diff --git a/usr.sbin/timed/timed/slave.c b/usr.sbin/timed/timed/slave.c
new file mode 100644
index 0000000..3bb6d85
--- /dev/null
+++ b/usr.sbin/timed/timed/slave.c
@@ -0,0 +1,715 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.20 $"
+#endif
+
+#include "globals.h"
+#include <setjmp.h>
+#include "pathnames.h"
+
+extern jmp_buf jmpenv;
+extern int Mflag;
+extern int justquit;
+
+extern u_short sequence;
+
+static char master_name[MAXHOSTNAMELEN+1];
+static struct netinfo *old_slavenet;
+static int old_status;
+
+static void schgdate __P((struct tsp *, char *));
+static void setmaster __P((struct tsp *));
+static void answerdelay __P((void));
+
+#ifdef sgi
+extern void logwtmp __P((struct timeval *, struct timeval *));
+#else
+extern void logwtmp __P((char *, char *, char *));
+#endif /* sgi */
+
+int
+slave()
+{
+ int tries;
+ long electiontime, refusetime, looktime, looptime, adjtime;
+ u_short seq;
+ long fastelection;
+#define FASTTOUT 3
+ struct in_addr cadr;
+ struct timeval otime;
+ struct sockaddr_in taddr;
+ char tname[MAXHOSTNAMELEN];
+ struct tsp *msg, to;
+ struct timeval ntime, wait;
+ struct tsp *answer;
+ int timeout();
+ char olddate[32];
+ char newdate[32];
+ struct netinfo *ntp;
+ struct hosttbl *htp;
+
+
+ old_slavenet = 0;
+ seq = 0;
+ refusetime = 0;
+ adjtime = 0;
+
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ fastelection = ntime.tv_sec + FASTTOUT;
+ if (justquit)
+ looktime = electiontime;
+ else
+ looktime = fastelection;
+ looptime = fastelection;
+
+ if (slavenet)
+ xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr);
+ if (status & MASTER) {
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == MASTER)
+ masterup(ntp);
+ }
+ }
+
+loop:
+ get_goodgroup(0);
+ (void)gettimeofday(&ntime, (struct timezone *)0);
+ if (ntime.tv_sec > electiontime) {
+ if (trace)
+ fprintf(fd, "election timer expired\n");
+ longjmp(jmpenv, 1);
+ }
+
+ if (ntime.tv_sec >= looktime) {
+ if (trace)
+ fprintf(fd, "Looking for nets to master\n");
+
+ if (Mflag && nignorednets > 0) {
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == IGNORE
+ || ntp->status == NOMASTER) {
+ lookformaster(ntp);
+ if (ntp->status == MASTER) {
+ masterup(ntp);
+ } else if (ntp->status == MASTER) {
+ ntp->status = NOMASTER;
+ }
+ }
+ if (ntp->status == MASTER
+ && --ntp->quit_count < 0)
+ ntp->quit_count = 0;
+ }
+ makeslave(slavenet); /* prune extras */
+ setstatus();
+ }
+ (void)gettimeofday(&ntime, 0);
+ looktime = ntime.tv_sec + delay2;
+ }
+ if (ntime.tv_sec >= looptime) {
+ if (trace)
+ fprintf(fd, "Looking for loops\n");
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == MASTER) {
+ to.tsp_type = TSP_LOOP;
+ to.tsp_vers = TSPVERSION;
+ to.tsp_seq = sequence++;
+ to.tsp_hopcnt = MAX_HOPCNT;
+ (void)strcpy(to.tsp_name, hostname);
+ bytenetorder(&to);
+ if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
+ (struct sockaddr*)&ntp->dest_addr,
+ sizeof(ntp->dest_addr)) < 0) {
+ trace_sendto_err(ntp->dest_addr.sin_addr);
+ }
+ }
+ }
+ (void)gettimeofday(&ntime, 0);
+ looptime = ntime.tv_sec + delay2;
+ }
+
+ wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec;
+ if (wait.tv_sec < 0)
+ wait.tv_sec = 0;
+ wait.tv_sec += FASTTOUT;
+ wait.tv_usec = 0;
+ msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
+
+ if (msg != NULL) {
+ /*
+ * filter stuff not for us
+ */
+ switch (msg->tsp_type) {
+ case TSP_SETDATE:
+ case TSP_TRACEOFF:
+ case TSP_TRACEON:
+ /*
+ * XXX check to see they are from ourself
+ */
+ break;
+
+ case TSP_TEST:
+ case TSP_MSITE:
+ break;
+
+ case TSP_MASTERUP:
+ if (!fromnet) {
+ if (trace) {
+ fprintf(fd, "slave ignored: ");
+ print(msg, &from);
+ }
+ goto loop;
+ }
+ break;
+
+ default:
+ if (!fromnet
+ || fromnet->status == IGNORE
+ || fromnet->status == NOMASTER) {
+ if (trace) {
+ fprintf(fd, "slave ignored: ");
+ print(msg, &from);
+ }
+ goto loop;
+ }
+ break;
+ }
+
+
+ /*
+ * now process the message
+ */
+ switch (msg->tsp_type) {
+
+ case TSP_ADJTIME:
+ if (fromnet != slavenet)
+ break;
+ if (!good_host_name(msg->tsp_name)) {
+ syslog(LOG_NOTICE,
+ "attempted time adjustment by %s",
+ msg->tsp_name);
+ suppress(&from, msg->tsp_name, fromnet);
+ break;
+ }
+ /*
+ * Speed up loop detection in case we have a loop.
+ * Otherwise the clocks can race until the loop
+ * is found.
+ */
+ (void)gettimeofday(&otime, 0);
+ if (adjtime < otime.tv_sec)
+ looptime -= (looptime-otime.tv_sec)/2 + 1;
+
+ setmaster(msg);
+ if (seq != msg->tsp_seq) {
+ seq = msg->tsp_seq;
+ synch(tvtomsround(msg->tsp_time));
+ }
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ fastelection = ntime.tv_sec + FASTTOUT;
+ adjtime = ntime.tv_sec + SAMPLEINTVL*2;
+ break;
+
+ case TSP_SETTIME:
+ if (fromnet != slavenet)
+ break;
+ if (seq == msg->tsp_seq)
+ break;
+ seq = msg->tsp_seq;
+
+ /* adjust time for residence on the queue */
+ (void)gettimeofday(&otime, 0);
+ adj_msg_time(msg,&otime);
+#ifdef sgi
+ (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+ (void)cftime(olddate, "%D %T", &otime.tv_sec);
+#else
+ /*
+ * the following line is necessary due to syslog
+ * calling ctime() which clobbers the static buffer
+ */
+ (void)strcpy(olddate, date());
+ (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+
+ if (!good_host_name(msg->tsp_name)) {
+ syslog(LOG_NOTICE,
+ "attempted time setting by untrusted %s to %s",
+ msg->tsp_name, newdate);
+ suppress(&from, msg->tsp_name, fromnet);
+ break;
+ }
+
+ setmaster(msg);
+ timevalsub(&ntime, &msg->tsp_time, &otime);
+ if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
+ /*
+ * do not change the clock if we can adjust it
+ */
+ synch(tvtomsround(ntime));
+ } else {
+#ifdef sgi
+ if (0 > settimeofday(&msg->tsp_time, 0)) {
+ syslog(LOG_ERR,"settimeofdate(): %m");
+ break;
+ }
+ logwtmp(&otime, &msg->tsp_time);
+#else
+ logwtmp("|", "date", "");
+ (void)settimeofday(&msg->tsp_time, 0);
+ logwtmp("}", "date", "");
+#endif /* sgi */
+ syslog(LOG_NOTICE,
+ "date changed by %s from %s",
+ msg->tsp_name, olddate);
+ if (status & MASTER)
+ spreadtime();
+ }
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ fastelection = ntime.tv_sec + FASTTOUT;
+
+/* This patches a bad protocol bug. Imagine a system with several networks,
+ * where there are a pair of redundant gateways between a pair of networks,
+ * each running timed. Assume that we start with a third machine mastering
+ * one of the networks, and one of the gateways mastering the other.
+ * Imagine that the third machine goes away and the non-master gateway
+ * decides to replace it. If things are timed just 'right,' we will have
+ * each gateway mastering one network for a little while. If a SETTIME
+ * message gets into the network at that time, perhaps from the newly
+ * masterful gateway as it was taking control, the SETTIME will loop
+ * forever. Each time a gateway receives it on its slave side, it will
+ * call spreadtime to forward it on its mastered network. We are now in
+ * a permanent loop, since the SETTIME msgs will keep any clock
+ * in the network from advancing. Normally, the 'LOOP' stuff will detect
+ * and correct the situation. However, with the clocks stopped, the
+ * 'looptime' timer cannot expire. While they are in this state, the
+ * masters will try to saturate the network with SETTIME packets.
+ */
+ looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1;
+ break;
+
+ case TSP_MASTERUP:
+ if (slavenet && fromnet != slavenet)
+ break;
+ if (!good_host_name(msg->tsp_name)) {
+ suppress(&from, msg->tsp_name, fromnet);
+ if (electiontime > fastelection)
+ electiontime = fastelection;
+ break;
+ }
+ makeslave(fromnet);
+ setmaster(msg);
+ setstatus();
+ answerdelay();
+ xmit(TSP_SLAVEUP, 0, &from);
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ fastelection = ntime.tv_sec + FASTTOUT;
+ refusetime = 0;
+ break;
+
+ case TSP_MASTERREQ:
+ if (fromnet->status != SLAVE)
+ break;
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ break;
+
+ case TSP_SETDATE:
+#ifdef sgi
+ (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+ (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+ schgdate(msg, newdate);
+ break;
+
+ case TSP_SETDATEREQ:
+ if (fromnet->status != MASTER)
+ break;
+#ifdef sgi
+ (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+ (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+ htp = findhost(msg->tsp_name);
+ if (0 == htp) {
+ syslog(LOG_WARNING,
+ "DATEREQ from uncontrolled machine");
+ break;
+ }
+ if (!htp->good) {
+ syslog(LOG_WARNING,
+ "attempted date change by untrusted %s to %s",
+ htp->name, newdate);
+ spreadtime();
+ break;
+ }
+ schgdate(msg, newdate);
+ break;
+
+ case TSP_TRACEON:
+ traceon();
+ break;
+
+ case TSP_TRACEOFF:
+ traceoff("Tracing ended at %s\n");
+ break;
+
+ case TSP_SLAVEUP:
+ newslave(msg);
+ break;
+
+ case TSP_ELECTION:
+ if (fromnet->status == SLAVE) {
+ (void)gettimeofday(&ntime, 0);
+ electiontime = ntime.tv_sec + delay2;
+ fastelection = ntime.tv_sec + FASTTOUT;
+ seq = 0;
+ if (!good_host_name(msg->tsp_name)) {
+ syslog(LOG_NOTICE,
+ "suppress election of %s",
+ msg->tsp_name);
+ to.tsp_type = TSP_QUIT;
+ electiontime = fastelection;
+ } else if (cadr.s_addr != from.sin_addr.s_addr
+ && ntime.tv_sec < refusetime) {
+/* if the candidate has to repeat itself, the old code would refuse it
+ * the second time. That would prevent elections.
+ */
+ to.tsp_type = TSP_REFUSE;
+ } else {
+ cadr.s_addr = from.sin_addr.s_addr;
+ to.tsp_type = TSP_ACCEPT;
+ refusetime = ntime.tv_sec + 30;
+ }
+ taddr = from;
+ (void)strcpy(tname, msg->tsp_name);
+ (void)strcpy(to.tsp_name, hostname);
+ answerdelay();
+ if (!acksend(&to, &taddr, tname,
+ TSP_ACK, 0, 0))
+ syslog(LOG_WARNING,
+ "no answer from candidate %s\n",
+ tname);
+
+ } else { /* fromnet->status == MASTER */
+ htp = addmach(msg->tsp_name, &from,fromnet);
+ to.tsp_type = TSP_QUIT;
+ (void)strcpy(to.tsp_name, hostname);
+ if (!acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, htp->noanswer)) {
+ syslog(LOG_ERR,
+ "no reply from %s to ELECTION-QUIT",
+ htp->name);
+ (void)remmach(htp);
+ }
+ }
+ break;
+
+ case TSP_CONFLICT:
+ if (fromnet->status != MASTER)
+ break;
+ /*
+ * After a network partition, there can be
+ * more than one master: the first slave to
+ * come up will notify here the situation.
+ */
+ (void)strcpy(to.tsp_name, hostname);
+
+ /* The other master often gets into the same state,
+ * with boring results.
+ */
+ ntp = fromnet; /* (acksend() can leave fromnet=0 */
+ for (tries = 0; tries < 3; tries++) {
+ to.tsp_type = TSP_RESOLVE;
+ answer = acksend(&to, &ntp->dest_addr,
+ ANYADDR, TSP_MASTERACK,
+ ntp, 0);
+ if (answer == NULL)
+ break;
+ htp = addmach(answer->tsp_name,&from,ntp);
+ to.tsp_type = TSP_QUIT;
+ answer = acksend(&to, &htp->addr, htp->name,
+ TSP_ACK, 0, htp->noanswer);
+ if (!answer) {
+ syslog(LOG_WARNING,
+ "conflict error: no reply from %s to QUIT",
+ htp->name);
+ (void)remmach(htp);
+ }
+ }
+ masterup(ntp);
+ break;
+
+ case TSP_MSITE:
+ if (!slavenet)
+ break;
+ taddr = from;
+ to.tsp_type = TSP_MSITEREQ;
+ to.tsp_vers = TSPVERSION;
+ to.tsp_seq = 0;
+ (void)strcpy(to.tsp_name, hostname);
+ answer = acksend(&to, &slavenet->dest_addr,
+ ANYADDR, TSP_ACK,
+ slavenet, 0);
+ if (answer != NULL
+ && good_host_name(answer->tsp_name)) {
+ setmaster(answer);
+ to.tsp_type = TSP_ACK;
+ (void)strcpy(to.tsp_name, answer->tsp_name);
+ bytenetorder(&to);
+ if (sendto(sock, (char *)&to,
+ sizeof(struct tsp), 0,
+ (struct sockaddr*)&taddr, sizeof(taddr)) < 0) {
+ trace_sendto_err(taddr.sin_addr);
+ }
+ }
+ break;
+
+ case TSP_MSITEREQ:
+ break;
+
+ case TSP_ACCEPT:
+ case TSP_REFUSE:
+ case TSP_RESOLVE:
+ break;
+
+ case TSP_QUIT:
+ doquit(msg); /* become a slave */
+ break;
+
+ case TSP_TEST:
+ electiontime = 0;
+ break;
+
+ case TSP_LOOP:
+ /* looking for loops of masters */
+ if (!(status & MASTER))
+ break;
+ if (fromnet->status == SLAVE) {
+ if (!strcmp(msg->tsp_name, hostname)) {
+ /*
+ * Someone forwarded our message back to
+ * us. There must be a loop. Tell the
+ * master of this network to quit.
+ *
+ * The other master often gets into
+ * the same state, with boring results.
+ */
+ ntp = fromnet;
+ for (tries = 0; tries < 3; tries++) {
+ to.tsp_type = TSP_RESOLVE;
+ answer = acksend(&to, &ntp->dest_addr,
+ ANYADDR, TSP_MASTERACK,
+ ntp,0);
+ if (answer == NULL)
+ break;
+ taddr = from;
+ (void)strcpy(tname, answer->tsp_name);
+ to.tsp_type = TSP_QUIT;
+ (void)strcpy(to.tsp_name, hostname);
+ if (!acksend(&to, &taddr, tname,
+ TSP_ACK, 0, 1)) {
+ syslog(LOG_ERR,
+ "no reply from %s to slave LOOP-QUIT",
+ tname);
+ } else {
+ electiontime = 0;
+ }
+ }
+ (void)gettimeofday(&ntime, 0);
+ looptime = ntime.tv_sec + FASTTOUT;
+ } else {
+ if (msg->tsp_hopcnt-- < 1)
+ break;
+ bytenetorder(msg);
+ for (ntp = nettab; ntp != 0; ntp = ntp->next) {
+ if (ntp->status == MASTER
+ && 0 > sendto(sock, (char *)msg,
+ sizeof(struct tsp), 0,
+ (struct sockaddr*)&ntp->dest_addr,
+ sizeof(ntp->dest_addr)))
+ trace_sendto_err(ntp->dest_addr.sin_addr);
+ }
+ }
+ } else { /* fromnet->status == MASTER */
+ /*
+ * We should not have received this from a net
+ * we are master on. There must be two masters,
+ * unless the packet was really from us.
+ */
+ if (from.sin_addr.s_addr
+ == fromnet->my_addr.s_addr) {
+ if (trace)
+ fprintf(fd,"discarding forwarded LOOP\n");
+ break;
+ }
+
+ /*
+ * The other master often gets into the same
+ * state, with boring results.
+ */
+ ntp = fromnet;
+ for (tries = 0; tries < 3; tries++) {
+ to.tsp_type = TSP_RESOLVE;
+ answer = acksend(&to, &ntp->dest_addr,
+ ANYADDR, TSP_MASTERACK,
+ ntp,0);
+ if (!answer)
+ break;
+ htp = addmach(answer->tsp_name,
+ &from,ntp);
+ to.tsp_type = TSP_QUIT;
+ (void)strcpy(to.tsp_name, hostname);
+ if (!acksend(&to,&htp->addr,htp->name,
+ TSP_ACK, 0, htp->noanswer)) {
+ syslog(LOG_ERR,
+ "no reply from %s to master LOOP-QUIT",
+ htp->name);
+ (void)remmach(htp);
+ }
+ }
+ (void)gettimeofday(&ntime, 0);
+ looptime = ntime.tv_sec + FASTTOUT;
+ }
+ break;
+ default:
+ if (trace) {
+ fprintf(fd, "garbage message: ");
+ print(msg, &from);
+ }
+ break;
+ }
+ }
+ goto loop;
+}
+
+
+/*
+ * tell the world who our master is
+ */
+static void
+setmaster(msg)
+ struct tsp *msg;
+{
+ if (slavenet
+ && (slavenet != old_slavenet
+ || strcmp(msg->tsp_name, master_name)
+ || old_status != status)) {
+ (void)strcpy(master_name, msg->tsp_name);
+ old_slavenet = slavenet;
+ old_status = status;
+
+ if (status & MASTER) {
+ syslog(LOG_NOTICE, "submaster to %s", master_name);
+ if (trace)
+ fprintf(fd, "submaster to %s\n", master_name);
+
+ } else {
+ syslog(LOG_NOTICE, "slave to %s", master_name);
+ if (trace)
+ fprintf(fd, "slave to %s\n", master_name);
+ }
+ }
+}
+
+
+
+/*
+ * handle date change request on a slave
+ */
+static void
+schgdate(msg, newdate)
+ struct tsp *msg;
+ char *newdate;
+{
+ struct tsp to;
+ u_short seq;
+ struct sockaddr_in taddr;
+ struct timeval otime;
+
+ if (!slavenet)
+ return; /* no where to forward */
+
+ taddr = from;
+ seq = msg->tsp_seq;
+
+ syslog(LOG_INFO,
+ "forwarding date change by %s to %s",
+ msg->tsp_name, newdate);
+
+ /* adjust time for residence on the queue */
+ (void)gettimeofday(&otime, 0);
+ adj_msg_time(msg, &otime);
+
+ to.tsp_type = TSP_SETDATEREQ;
+ to.tsp_time = msg->tsp_time;
+ (void)strcpy(to.tsp_name, hostname);
+ if (!acksend(&to, &slavenet->dest_addr,
+ ANYADDR, TSP_DATEACK,
+ slavenet, 0))
+ return; /* no answer */
+
+ xmit(TSP_DATEACK, seq, &taddr);
+}
+
+
+/*
+ * Used before answering a broadcast message to avoid network
+ * contention and likely collisions.
+ */
+static void
+answerdelay()
+{
+#ifdef sgi
+ sginap(delay1);
+#else
+ struct timeval timeout;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = delay1;
+
+ (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
+ &timeout);
+ return;
+#endif /* sgi */
+}
diff --git a/usr.sbin/timed/timed/timed.8 b/usr.sbin/timed/timed/timed.8
new file mode 100644
index 0000000..8f8798d
--- /dev/null
+++ b/usr.sbin/timed/timed/timed.8
@@ -0,0 +1,219 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timed.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TIMED 8
+.Os BSD 4.3
+.Sh NAME
+.Nm timed
+.Nd time server daemon
+.Sh SYNOPSIS
+.Nm timed
+.Op Fl M
+.Op Fl t
+.Op Fl d
+.Op Fl i Ar network
+.Op Fl n Ar network
+.Op Fl F Ar host1 host2 ...
+.Sh DESCRIPTION
+This
+is a time server daemon and is normally invoked
+at boot time from the
+.Xr rc 8
+file.
+It synchronizes the host's time with the time of other
+machines in a local area network running
+.Nm timed 8 .
+These time servers will slow down the clocks of some machines
+and speed up the clocks of others to bring them to the average network time.
+The average network time is computed from measurements of clock differences
+using the
+.Tn ICMP
+timestamp request message.
+.Pp
+The service provided by
+.Nm timed
+is based on a master-slave
+scheme.
+When
+.Nm timed 8
+is started on a machine, it asks the master for the network time
+and sets the host's clock to that time.
+After that, it accepts synchronization messages periodically sent by
+the master and calls
+.Xr adjtime 2
+to perform the needed corrections on the host's clock.
+.Pp
+It also communicates with
+.Xr date 1
+in order to set the date globally,
+and with
+.Xr timedc 8 ,
+a timed control program.
+If the machine running the master crashes, then the slaves will elect
+a new master from among slaves running with the
+.Fl M
+flag.
+A
+.Nm timed
+running without the
+.Fl M
+or
+.Fl F
+flags will remain a slave.
+The
+.Fl t
+flag enables
+.Nm timed
+to trace the messages it receives in the
+file
+.Pa /var/log/timed.log .
+Tracing can be turned on or off by the program
+.Xr timedc 8 .
+The
+.Fl d
+flag is for debugging the daemon.
+It causes the program to not put itself into the background.
+Normally
+.Nm timed
+checks for a master time server on each network to which
+it is connected, except as modified by the options described below.
+It will request synchronization service from the first master server
+located.
+If permitted by the
+.Fl M
+flag, it will provide synchronization service on any attached networks
+on which no current master server was detected.
+Such a server propagates the time computed by the top-level master.
+The
+.Fl n
+flag, followed by the name of a network which the host is connected to
+(see
+.Xr networks 5 ) ,
+overrides the default choice of the
+network addresses made by the program.
+Each time the
+.Fl n
+flag appears, that network name is added to a list of valid networks.
+All other networks are ignored.
+The
+.Fl i
+flag, followed by the name of a network to which the host is connected
+(see
+.Xr networks 5 ) ,
+overrides the default choice of the network addresses made by the program.
+Each time the
+.Fl i
+flag appears, that network name is added to a list of networks to ignore.
+All other networks are used by the time daemon.
+The
+.Fl n
+and
+.Fl i
+flags are meaningless if used together.
+.Pp
+.Nm Timed
+checks for a master time server on each network to which
+it is connected, except as modified by the
+.Fl n
+and
+.Fl i
+options described above.
+If it finds masters on more than one network, it chooses one network
+on which to be a "slave," and then periodically checks the other
+networks to see if the masters there have disappeared.
+.Pp
+One way to synchronize a group of machines is to use an NTP daemon to
+synchronize the clock of one machine to a distant standard or a radio
+receiver and
+.Fl F Ar hostname
+to tell its timed daemon to trust only itself.
+.Pp
+Messages printed by the kernel on the system console occur with
+interrupts disabled.
+This means that the clock stops while they are printing.
+A machine with many disk or network hardware problems and consequent
+messages cannot keep good time by itself. Each message typically causes
+the clock to lose a dozen milliseconds. A time daemon can
+correct the result.
+.Pp
+Messages in the system log about machines that failed to respond
+usually indicate machines that crashed or were turned off.
+Complaints about machines that failed to respond to initial time
+settings are often associated with "multi-homed" machines
+that looked for time masters on more than one network and eventually
+chose to become a slave on the other network.
+.SH WARNING
+If two or more time daemons, whether
+.Nm timed ,
+.Xr NTP ,
+try to adjust the same clock, temporal chaos will result.
+If both
+.Nm
+and another time daemon are run on the same machine,
+ensure that the
+.Fl F
+flag is used, so that
+.Nm timed
+never attempts to adjust the local clock.
+.Pp
+The protocol is based on UDP/IP broadcasts. All machines within
+the range of a broadcast that are using the TSP protocol must cooperate.
+There cannot be more than a single administrative domain using the
+.Fl F
+flag among all machines reached by a broadcast packet.
+Failure to follow this rule is usually indicated by complaints concerning
+"untrusted" machines in the system log.
+.Sh FILES
+.Bl -tag -width /var/log/timed.masterlog -compact
+.It Pa /var/log/timed.log
+tracing file for timed
+.It Pa /var/log/timed.masterlog
+log file for master timed
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr adjtime 2 ,
+.Xr gettimeofday 2 ,
+.Xr icmp 4 ,
+.Xr timedc 8 ,
+.Rs
+.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
+.%A R. Gusella
+.%A S. Zatti
+.Re
+.Sh HISTORY
+The
+.Nm
+daemon appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/timed/timed/timed.c b/usr.sbin/timed/timed/timed.c
new file mode 100644
index 0000000..b8f7dc7
--- /dev/null
+++ b/usr.sbin/timed/timed/timed.c
@@ -0,0 +1,980 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)timed.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.25 $"
+#endif /* sgi */
+
+#define TSPTYPES
+#include "globals.h"
+#include <net/if.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <setjmp.h>
+#include "pathnames.h"
+#include <math.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#ifdef sgi
+#include <unistd.h>
+#include <sys/syssgi.h>
+#include <sys/schedctl.h>
+#endif /* sgi */
+
+int trace = 0;
+int sock, sock_raw = -1;
+int status = 0;
+u_short sequence; /* sequence number */
+long delay1;
+long delay2;
+
+int nslavenets; /* nets were I could be a slave */
+int nmasternets; /* nets were I could be a master */
+int nignorednets; /* ignored nets */
+int nnets; /* nets I am connected to */
+
+FILE *fd; /* trace file FD */
+
+jmp_buf jmpenv;
+
+struct netinfo *nettab = 0;
+struct netinfo *slavenet;
+int Mflag;
+int justquit = 0;
+int debug;
+
+static struct nets {
+ char *name;
+ long net;
+ struct nets *next;
+} *nets = 0;
+
+struct hosttbl hosttbl[NHOSTS+1]; /* known hosts */
+
+static struct goodhost { /* hosts that we trust */
+ char name[MAXHOSTNAMELEN+1];
+ struct goodhost *next;
+ char perm;
+} *goodhosts;
+
+static char *goodgroup; /* net group of trusted hosts */
+static void checkignorednets __P((void));
+static void pickslavenet __P((struct netinfo *));
+static void add_good_host __P((char *, int));
+
+#ifdef sgi
+char *timetrim_fn;
+char *timetrim_wpat = "long timetrim = %ld;\ndouble tot_adj = %.0f;\ndouble tot_ticks = %.0f;\n/* timed version 2 */\n";
+char *timetrim_rpat = "long timetrim = %ld;\ndouble tot_adj = %lf;\ndouble tot_ticks = %lf;";
+long timetrim;
+double tot_adj, hr_adj; /* totals in nsec */
+double tot_ticks, hr_ticks;
+
+int bufspace = 60*1024;
+#endif
+
+
+/*
+ * The timedaemons synchronize the clocks of hosts in a local area network.
+ * One daemon runs as master, all the others as slaves. The master
+ * performs the task of computing clock differences and sends correction
+ * values to the slaves.
+ * Slaves start an election to choose a new master when the latter disappears
+ * because of a machine crash, network partition, or when killed.
+ * A resolution protocol is used to kill all but one of the masters
+ * that happen to exist in segments of a partitioned network when the
+ * network partition is fixed.
+ *
+ * Authors: Riccardo Gusella & Stefano Zatti
+ *
+ * overhauled at Silicon Graphics
+ */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int on;
+ int ret;
+ int nflag, iflag;
+ struct timeval ntime;
+ struct servent *srvp;
+ char buf[BUFSIZ], *cp, *cplim;
+ struct ifconf ifc;
+ struct ifreq ifreq, ifreqf, *ifr;
+ register struct netinfo *ntp;
+ struct netinfo *ntip;
+ struct netinfo *savefromnet;
+ struct netent *nentp;
+ struct nets *nt;
+ struct sockaddr_in server;
+ u_short port;
+ char c;
+ extern char *optarg;
+ extern int optind, opterr;
+#ifdef sgi
+ FILE *timetrim_st;
+#endif
+
+#define IN_MSG "timed: -i and -n make no sense together\n"
+#ifdef sgi
+ struct tms tms;
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp] [-P trimfile]\n"
+#else
+#ifdef HAVENIS
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n"
+#else
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...]\n"
+#endif /* HAVENIS */
+#endif /* sgi */
+
+#ifdef lint
+ ntip = NULL;
+#endif
+
+ on = 1;
+ nflag = OFF;
+ iflag = OFF;
+
+#ifdef sgi
+ if (0 > syssgi(SGI_GETTIMETRIM, &timetrim)) {
+ perror("timed: syssgi(GETTIMETRIM)");
+ timetrim = 0;
+ }
+ tot_ticks = hr_ticks = times(&tms);
+#endif /* sgi */
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != EOF) {
+ switch (c) {
+ case 'M':
+ Mflag = 1;
+ break;
+
+ case 't':
+ trace = 1;
+ break;
+
+ case 'n':
+ if (iflag) {
+ fprintf(stderr, IN_MSG);
+ exit(1);
+ } else {
+ nflag = ON;
+ addnetname(optarg);
+ }
+ break;
+
+ case 'i':
+ if (nflag) {
+ fprintf(stderr, IN_MSG);
+ exit(1);
+ } else {
+ iflag = ON;
+ addnetname(optarg);
+ }
+ break;
+
+ case 'F':
+ add_good_host(optarg,1);
+ while (optind < argc && argv[optind][0] != '-')
+ add_good_host(argv[optind++], 1);
+ break;
+
+ case 'd':
+ debug = 1;
+ break;
+ case 'G':
+ if (goodgroup != 0) {
+ fprintf(stderr,"timed: only one net group\n");
+ exit(1);
+ }
+ goodgroup = optarg;
+ break;
+#ifdef sgi
+ case 'P':
+ timetrim_fn = optarg;
+ timetrim_st = fopen(timetrim_fn, "r+");
+ if (0 == timetrim_st) {
+ if (errno != ENOENT) {
+ (void)fprintf(stderr,"timed: ");
+ perror(timetrim_fn);
+ timetrim_fn = 0;
+ }
+ } else {
+ int i;
+ long trim;
+ double adj, ticks;
+
+ i = fscanf(timetrim_st, timetrim_rpat,
+ &trim, &adj, &ticks);
+ if (i < 1
+ || trim > MAX_TRIM
+ || trim < -MAX_TRIM
+ || i == 2
+ || (i == 3
+ && trim != rint(adj*CLK_TCK/ticks))) {
+ if (trace && i != EOF)
+ (void)fprintf(stderr,
+ "timed: unrecognized contents in %s\n",
+ timetrim_fn);
+ } else {
+ if (0 > syssgi(SGI_SETTIMETRIM,
+ trim)) {
+ perror("timed: syssgi(SETTIMETRIM)");
+ } else {
+ timetrim = trim;
+ }
+ if (i == 3) {
+ tot_adj = adj;
+ tot_ticks -= ticks;
+ }
+ }
+ (void)fclose(timetrim_st);
+ }
+ break;
+#endif /* sgi */
+
+ default:
+ fprintf(stderr, USAGE);
+ exit(1);
+ break;
+ }
+ }
+ if (optind < argc) {
+ fprintf(stderr, USAGE);
+ exit(1);
+ }
+
+ /* If we care about which machine is the master, then we must
+ * be willing to be a master
+ */
+ if (0 != goodgroup || 0 != goodhosts)
+ Mflag = 1;
+
+ if (gethostname(hostname, sizeof(hostname) - 1) < 0) {
+ perror("gethostname");
+ exit(1);
+ }
+ self.l_bak = &self;
+ self.l_fwd = &self;
+ self.h_bak = &self;
+ self.h_fwd = &self;
+ self.head = 1;
+ self.good = 1;
+
+ if (goodhosts != 0) /* trust ourself */
+ add_good_host(hostname,1);
+
+ srvp = getservbyname("timed", "udp");
+ if (srvp == 0) {
+ fprintf(stderr, "unknown service 'timed/udp'\n");
+ exit(1);
+ }
+ port = srvp->s_port;
+ server.sin_port = srvp->s_port;
+ server.sin_family = AF_INET;
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ exit(1);
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,
+ sizeof(on)) < 0) {
+ perror("setsockopt");
+ exit(1);
+ }
+ if (bind(sock, (struct sockaddr*)&server, sizeof(server))) {
+ if (errno == EADDRINUSE)
+ fprintf(stderr,"timed: time daemon already running\n");
+ else
+ perror("bind");
+ exit(1);
+ }
+#ifdef sgi
+ /*
+ * handle many slaves with our buffer
+ */
+ if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,
+ sizeof(bufspace))) {
+ perror("setsockopt");
+ exit(1);
+ }
+#endif /* sgi */
+
+ /* choose a unique seed for random number generation */
+ (void)gettimeofday(&ntime, 0);
+ srandom(ntime.tv_sec + ntime.tv_usec);
+
+ sequence = random(); /* initial seq number */
+
+#ifndef sgi
+ /* rounds kernel variable time to multiple of 5 ms. */
+ ntime.tv_sec = 0;
+ ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000;
+ (void)adjtime(&ntime, (struct timeval *)0);
+#endif /* sgi */
+
+ for (nt = nets; nt; nt = nt->next) {
+ nentp = getnetbyname(nt->name);
+ if (nentp == 0) {
+ nt->net = inet_network(nt->name);
+ if (nt->net != INADDR_NONE)
+ nentp = getnetbyaddr(nt->net, AF_INET);
+ }
+ if (nentp != 0) {
+ nt->net = nentp->n_net;
+ } else if (nt->net == INADDR_NONE) {
+ fprintf(stderr, "timed: unknown net %s\n", nt->name);
+ exit(1);
+ } else if (nt->net == INADDR_ANY) {
+ fprintf(stderr, "timed: bad net %s\n", nt->name);
+ exit(1);
+ } else {
+ fprintf(stderr,
+ "timed: warning: %s unknown in /etc/networks\n",
+ nt->name);
+ }
+
+ if (0 == (nt->net & 0xff000000))
+ nt->net <<= 8;
+ if (0 == (nt->net & 0xff000000))
+ nt->net <<= 8;
+ if (0 == (nt->net & 0xff000000))
+ nt->net <<= 8;
+ }
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("timed: get interface configuration");
+ exit(1);
+ }
+ ntp = NULL;
+#ifdef sgi
+#define size(p) (sizeof(*ifr) - sizeof(ifr->ifr_name)) /* XXX hack. kludge */
+#else
+#define size(p) max((p).sa_len, sizeof(p))
+#endif
+ cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+ for (cp = buf; cp < cplim;
+ cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+ ifr = (struct ifreq *)cp;
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ if (!ntp)
+ ntp = (struct netinfo*)malloc(sizeof(struct netinfo));
+ bzero(ntp,sizeof(*ntp));
+ ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+ ntp->status = NOMASTER;
+ ifreq = *ifr;
+ ifreqf = *ifr;
+
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) {
+ perror("get interface flags");
+ continue;
+ }
+ if ((ifreqf.ifr_flags & IFF_UP) == 0)
+ continue;
+ if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 &&
+ (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) {
+ continue;
+ }
+
+
+ if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+ perror("get netmask");
+ continue;
+ }
+ ntp->mask = ((struct sockaddr_in *)
+ &ifreq.ifr_addr)->sin_addr.s_addr;
+
+ if (ifreqf.ifr_flags & IFF_BROADCAST) {
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+ perror("get broadaddr");
+ continue;
+ }
+ ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
+ /* What if the broadcast address is all ones?
+ * So we cannot just mask ntp->dest_addr. */
+ ntp->net = ntp->my_addr;
+ ntp->net.s_addr &= ntp->mask;
+ } else {
+ if (ioctl(sock, SIOCGIFDSTADDR,
+ (char *)&ifreq) < 0) {
+ perror("get destaddr");
+ continue;
+ }
+ ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr;
+ ntp->net = ntp->dest_addr.sin_addr;
+ }
+
+ ntp->dest_addr.sin_port = port;
+
+ for (nt = nets; nt; nt = nt->next) {
+ if (ntp->net.s_addr == nt->net)
+ break;
+ }
+ if (nflag && !nt || iflag && nt)
+ continue;
+
+ ntp->next = NULL;
+ if (nettab == NULL) {
+ nettab = ntp;
+ } else {
+ ntip->next = ntp;
+ }
+ ntip = ntp;
+ ntp = NULL;
+ }
+ if (ntp)
+ (void) free((char *)ntp);
+ if (nettab == NULL) {
+ fprintf(stderr, "timed: no network usable\n");
+ exit(1);
+ }
+
+
+#ifdef sgi
+ (void)schedctl(RENICE,0,10); /* run fast to get good time */
+
+ /* ticks to delay before responding to a broadcast */
+ delay1 = casual(0, CLK_TCK/10);
+#else
+
+ /* microseconds to delay before responding to a broadcast */
+ delay1 = casual(1, 100*1000);
+#endif /* sgi */
+
+ /* election timer delay in secs. */
+ delay2 = casual(MINTOUT, MAXTOUT);
+
+
+#ifdef sgi
+ (void)_daemonize(debug ? _DF_NOFORK|_DF_NOCHDIR : 0, sock, -1, -1);
+#else
+ if (!debug)
+ daemon(debug, 0);
+#endif /* sgi */
+
+ if (trace)
+ traceon();
+ openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON);
+
+ /*
+ * keep returning here
+ */
+ ret = setjmp(jmpenv);
+ savefromnet = fromnet;
+ setstatus();
+
+ if (Mflag) {
+ switch (ret) {
+
+ case 0:
+ checkignorednets();
+ pickslavenet(0);
+ break;
+ case 1:
+ /* Just lost our master */
+ if (slavenet != 0)
+ slavenet->status = election(slavenet);
+ if (!slavenet || slavenet->status == MASTER) {
+ checkignorednets();
+ pickslavenet(0);
+ } else {
+ makeslave(slavenet); /* prune extras */
+ }
+ break;
+
+ case 2:
+ /* Just been told to quit */
+ justquit = 1;
+ pickslavenet(savefromnet);
+ break;
+ }
+
+ setstatus();
+ if (!(status & MASTER) && sock_raw != -1) {
+ /* sock_raw is not being used now */
+ (void)close(sock_raw);
+ sock_raw = -1;
+ }
+
+ if (status == MASTER)
+ master();
+ else
+ slave();
+
+ } else {
+ if (sock_raw != -1) {
+ (void)close(sock_raw);
+ sock_raw = -1;
+ }
+
+ if (ret) {
+ /* we just lost our master or were told to quit */
+ justquit = 1;
+ }
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == MASTER)
+ rmnetmachs(ntp);
+ ntp->status = NOMASTER;
+ }
+ checkignorednets();
+ pickslavenet(0);
+ setstatus();
+
+ slave();
+ }
+ /* NOTREACHED */
+#ifdef lint
+ return(0);
+#endif
+}
+
+/*
+ * suppress an upstart, untrustworthy, self-appointed master
+ */
+void
+suppress(addr, name,net)
+ struct sockaddr_in *addr;
+ char *name;
+ struct netinfo *net;
+{
+ struct sockaddr_in tgt;
+ char tname[MAXHOSTNAMELEN];
+ struct tsp msg;
+ static struct timeval wait;
+
+ if (trace)
+ fprintf(fd, "suppress: %s\n", name);
+ tgt = *addr;
+ (void)strcpy(tname, name);
+
+ while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) {
+ if (trace)
+ fprintf(fd, "suppress:\tdiscarded packet from %s\n",
+ name);
+ }
+
+ syslog(LOG_NOTICE, "suppressing false master %s", tname);
+ msg.tsp_type = TSP_QUIT;
+ (void)strcpy(msg.tsp_name, hostname);
+ (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1);
+}
+
+void
+lookformaster(ntp)
+ struct netinfo *ntp;
+{
+ struct tsp resp, conflict, *answer;
+ struct timeval ntime;
+ char mastername[MAXHOSTNAMELEN];
+ struct sockaddr_in masteraddr;
+
+ get_goodgroup(0);
+ ntp->status = SLAVE;
+
+ /* look for master */
+ resp.tsp_type = TSP_MASTERREQ;
+ (void)strcpy(resp.tsp_name, hostname);
+ answer = acksend(&resp, &ntp->dest_addr, ANYADDR,
+ TSP_MASTERACK, ntp, 0);
+ if (answer != 0 && !good_host_name(answer->tsp_name)) {
+ suppress(&from, answer->tsp_name, ntp);
+ ntp->status = NOMASTER;
+ answer = 0;
+ }
+ if (answer == 0) {
+ /*
+ * Various conditions can cause conflict: races between
+ * two just started timedaemons when no master is
+ * present, or timedaemons started during an election.
+ * A conservative approach is taken. Give up and became a
+ * slave, postponing election of a master until first
+ * timer expires.
+ */
+ ntime.tv_sec = ntime.tv_usec = 0;
+ answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp);
+ if (answer != 0) {
+ if (!good_host_name(answer->tsp_name)) {
+ suppress(&from, answer->tsp_name, ntp);
+ ntp->status = NOMASTER;
+ }
+ return;
+ }
+
+ ntime.tv_sec = ntime.tv_usec = 0;
+ answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp);
+ if (answer != 0) {
+ if (!good_host_name(answer->tsp_name)) {
+ suppress(&from, answer->tsp_name, ntp);
+ ntp->status = NOMASTER;
+ }
+ return;
+ }
+
+ ntime.tv_sec = ntime.tv_usec = 0;
+ answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp);
+ if (answer != 0) {
+ if (!good_host_name(answer->tsp_name)) {
+ suppress(&from, answer->tsp_name, ntp);
+ ntp->status = NOMASTER;
+ }
+ return;
+ }
+
+ if (Mflag)
+ ntp->status = MASTER;
+ else
+ ntp->status = NOMASTER;
+ return;
+ }
+
+ ntp->status = SLAVE;
+ (void)strcpy(mastername, answer->tsp_name);
+ masteraddr = from;
+
+ /*
+ * If network has been partitioned, there might be other
+ * masters; tell the one we have just acknowledged that
+ * it has to gain control over the others.
+ */
+ ntime.tv_sec = 0;
+ ntime.tv_usec = 300000;
+ answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp);
+ /*
+ * checking also not to send CONFLICT to ack'ed master
+ * due to duplicated MASTERACKs
+ */
+ if (answer != NULL &&
+ strcmp(answer->tsp_name, mastername) != 0) {
+ conflict.tsp_type = TSP_CONFLICT;
+ (void)strcpy(conflict.tsp_name, hostname);
+ if (!acksend(&conflict, &masteraddr, mastername,
+ TSP_ACK, 0, 0)) {
+ syslog(LOG_ERR,
+ "error on sending TSP_CONFLICT");
+ }
+ }
+}
+
+/*
+ * based on the current network configuration, set the status, and count
+ * networks;
+ */
+void
+setstatus()
+{
+ struct netinfo *ntp;
+
+ status = 0;
+ nmasternets = nslavenets = nnets = nignorednets = 0;
+ if (trace)
+ fprintf(fd, "Net status:\n");
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ switch ((int)ntp->status) {
+ case MASTER:
+ nmasternets++;
+ break;
+ case SLAVE:
+ nslavenets++;
+ break;
+ case NOMASTER:
+ case IGNORE:
+ nignorednets++;
+ break;
+ }
+ if (trace) {
+ fprintf(fd, "\t%-16s", inet_ntoa(ntp->net));
+ switch ((int)ntp->status) {
+ case NOMASTER:
+ fprintf(fd, "NOMASTER\n");
+ break;
+ case MASTER:
+ fprintf(fd, "MASTER\n");
+ break;
+ case SLAVE:
+ fprintf(fd, "SLAVE\n");
+ break;
+ case IGNORE:
+ fprintf(fd, "IGNORE\n");
+ break;
+ default:
+ fprintf(fd, "invalid state %d\n",
+ (int)ntp->status);
+ break;
+ }
+ }
+ nnets++;
+ status |= ntp->status;
+ }
+ status &= ~IGNORE;
+ if (trace)
+ fprintf(fd,
+ "\tnets=%d masters=%d slaves=%d ignored=%d delay2=%d\n",
+ nnets, nmasternets, nslavenets, nignorednets, delay2);
+}
+
+void
+makeslave(net)
+ struct netinfo *net;
+{
+ register struct netinfo *ntp;
+
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (ntp->status == SLAVE && ntp != net)
+ ntp->status = IGNORE;
+ }
+ slavenet = net;
+}
+
+/*
+ * Try to become master over ignored nets..
+ */
+static void
+checkignorednets()
+{
+ register struct netinfo *ntp;
+
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+ if (!Mflag && ntp->status == SLAVE)
+ break;
+
+ if (ntp->status == IGNORE || ntp->status == NOMASTER) {
+ lookformaster(ntp);
+ if (!Mflag && ntp->status == SLAVE)
+ break;
+ }
+ }
+}
+
+/*
+ * choose a good network on which to be a slave
+ * The ignored networks must have already been checked.
+ * Take a hint about for a good network.
+ */
+static void
+pickslavenet(ntp)
+ struct netinfo *ntp;
+{
+ if (slavenet != 0 && slavenet->status == SLAVE) {
+ makeslave(slavenet); /* prune extras */
+ return;
+ }
+
+ if (ntp == 0 || ntp->status != SLAVE) {
+ for (ntp = nettab; ntp != 0; ntp = ntp->next) {
+ if (ntp->status == SLAVE)
+ break;
+ }
+ }
+ makeslave(ntp);
+}
+
+/*
+ * returns a random number in the range [inf, sup]
+ */
+long
+casual(inf, sup)
+ long inf, sup;
+{
+ double value;
+
+ value = ((double)(random() & 0x7fffffff)) / (0x7fffffff*1.0);
+ return(inf + (sup - inf)*value);
+}
+
+char *
+date()
+{
+#ifdef sgi
+ struct timeval tv;
+ static char tm[32];
+
+ (void)gettimeofday(&tv, (struct timezone *)0);
+ (void)cftime(tm, "%D %T", &tv.tv_sec);
+ return (tm);
+#else
+ struct timeval tv;
+
+ (void)gettimeofday(&tv, (struct timezone *)0);
+ return (ctime(&tv.tv_sec));
+#endif /* sgi */
+}
+
+void
+addnetname(name)
+ char *name;
+{
+ register struct nets **netlist = &nets;
+
+ while (*netlist)
+ netlist = &((*netlist)->next);
+ *netlist = (struct nets *)malloc(sizeof **netlist);
+ if (*netlist == 0) {
+ fprintf(stderr,"malloc failed\n");
+ exit(1);
+ }
+ bzero((char *)*netlist, sizeof(**netlist));
+ (*netlist)->name = name;
+}
+
+/* note a host as trustworthy */
+static void
+add_good_host(name, perm)
+ char *name;
+ int perm; /* 1=not part of the netgroup */
+{
+ register struct goodhost *ghp;
+ register struct hostent *hentp;
+
+ ghp = (struct goodhost*)malloc(sizeof(*ghp));
+ if (!ghp) {
+ syslog(LOG_ERR, "malloc failed");
+ exit(1);
+ }
+
+ bzero((char*)ghp, sizeof(*ghp));
+ (void)strncpy(&ghp->name[0], name, sizeof(ghp->name));
+ ghp->next = goodhosts;
+ ghp->perm = perm;
+ goodhosts = ghp;
+
+ hentp = gethostbyname(name);
+ if (0 == hentp && perm)
+ (void)fprintf(stderr, "unknown host %s\n", name);
+}
+
+
+/* update our image of the net-group of trustworthy hosts
+ */
+void
+get_goodgroup(force)
+ int force;
+{
+# define NG_DELAY (30*60*CLK_TCK) /* 30 minutes */
+ static unsigned long last_update = -NG_DELAY;
+ unsigned long new_update;
+ struct hosttbl *htp;
+ struct goodhost *ghp, **ghpp;
+ char *mach, *usr, *dom;
+ struct tms tm;
+
+
+ /* if no netgroup, then we are finished */
+ if (goodgroup == 0 || !Mflag)
+ return;
+
+ /* Do not chatter with the netgroup master too often.
+ */
+ new_update = times(&tm);
+ if (new_update < last_update + NG_DELAY
+ && !force)
+ return;
+ last_update = new_update;
+
+ /* forget the old temporary entries */
+ ghpp = &goodhosts;
+ while (0 != (ghp = *ghpp)) {
+ if (!ghp->perm) {
+ *ghpp = ghp->next;
+ free((char*)ghp);
+ } else {
+ ghpp = &ghp->next;
+ }
+ }
+
+#ifdef HAVENIS
+ /* quit now if we are not one of the trusted masters
+ */
+ if (!innetgr(goodgroup, &hostname[0], 0,0)) {
+ if (trace)
+ (void)fprintf(fd, "get_goodgroup: %s not in %s\n",
+ &hostname[0], goodgroup);
+ return;
+ }
+ if (trace)
+ (void)fprintf(fd, "get_goodgroup: %s in %s\n",
+ &hostname[0], goodgroup);
+
+ /* mark the entire netgroup as trusted */
+ (void)setnetgrent(goodgroup);
+ while (getnetgrent(&mach,&usr,&dom)) {
+ if (0 != mach)
+ add_good_host(mach,0);
+ }
+ (void)endnetgrent();
+
+ /* update list of slaves */
+ for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+ htp->good = good_host_name(&htp->name[0]);
+ }
+#endif /* HAVENIS */
+}
+
+
+/* see if a machine is trustworthy
+ */
+int /* 1=trust hp to change our date */
+good_host_name(name)
+ char *name;
+{
+ register struct goodhost *ghp = goodhosts;
+ register char c;
+
+ if (!ghp || !Mflag) /* trust everyone if no one named */
+ return 1;
+
+ c = *name;
+ do {
+ if (c == ghp->name[0]
+ && !strcasecmp(name, ghp->name))
+ return 1; /* found him, so say so */
+ } while (0 != (ghp = ghp->next));
+
+ if (!strcasecmp(name,hostname)) /* trust ourself */
+ return 1;
+
+ return 0; /* did not find him */
+}
diff --git a/usr.sbin/timed/timedc/Makefile b/usr.sbin/timed/timedc/Makefile
new file mode 100644
index 0000000..a0b41ef
--- /dev/null
+++ b/usr.sbin/timed/timedc/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= timedc
+SRCS= cmds.c cmdtab.c timedc.c byteorder.c measure.c cksum.c
+MAN8= timedc.0
+BINOWN= root
+BINMODE=4555
+.PATH: ${.CURDIR}/../timed
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/timed/timedc/cmds.c b/usr.sbin/timed/timedc/cmds.c
new file mode 100644
index 0000000..557f721
--- /dev/null
+++ b/usr.sbin/timed/timedc/cmds.c
@@ -0,0 +1,526 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.10 $"
+#endif
+
+#include "timedc.h"
+#include <sys/file.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define TSPTYPES
+#include <protocols/timed.h>
+
+#ifdef sgi
+#include <bstring.h>
+#include <sys/clock.h>
+#else
+#define SECHR (60*60)
+#define SECDAY (24*SECHR)
+#endif /* sgi */
+
+# define DATE_PROTO "udp"
+# define DATE_PORT "time"
+
+
+int sock;
+int sock_raw;
+char myname[MAXHOSTNAMELEN];
+struct hostent *hp;
+struct sockaddr_in server;
+struct sockaddr_in dayaddr;
+extern int measure_delta;
+
+void bytenetorder(struct tsp *);
+void bytehostorder(struct tsp *);
+
+
+#define BU ((unsigned long)2208988800) /* seconds before UNIX epoch */
+
+
+/* compute the difference between our date and another machine
+ */
+static int /* difference in days from our time */
+daydiff(hostname)
+ char *hostname;
+{
+ int i;
+ int trials;
+ struct timeval tout, now;
+ fd_set ready;
+ struct sockaddr from;
+ int fromlen;
+ unsigned long sec;
+
+
+ /* wait 2 seconds between 10 tries */
+ tout.tv_sec = 2;
+ tout.tv_usec = 0;
+ for (trials = 0; trials < 10; trials++) {
+ /* ask for the time */
+ sec = 0;
+ if (sendto(sock, &sec, sizeof(sec), 0,
+ (struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) {
+ perror("sendto(sock)");
+ return 0;
+ }
+
+ for (;;) {
+ FD_ZERO(&ready);
+ FD_SET(sock, &ready);
+ i = select(sock+1, &ready, (fd_set *)0,
+ (fd_set *)0, &tout);
+ if (i < 0) {
+ if (errno = EINTR)
+ continue;
+ perror("select(date read)");
+ return 0;
+ }
+ if (0 == i)
+ break;
+
+ fromlen = sizeof(from);
+ if (recvfrom(sock,&sec,sizeof(sec),0,
+ &from,&fromlen) < 0) {
+ perror("recvfrom(date read)");
+ return 0;
+ }
+
+ sec = ntohl(sec);
+ if (sec < BU) {
+ fprintf(stderr,
+ "%s says it is before 1970: %lu",
+ hostname, sec);
+ return 0;
+ }
+ sec -= BU;
+
+ (void)gettimeofday(&now, (struct timezone*)0);
+ return (sec - now.tv_sec);
+ }
+ }
+
+ /* if we get here, we tried too many times */
+ fprintf(stderr,"%s will not tell us the date\n", hostname);
+ return 0;
+}
+
+
+/*
+ * Clockdiff computes the difference between the time of the machine on
+ * which it is called and the time of the machines given as argument.
+ * The time differences measured by clockdiff are obtained using a sequence
+ * of ICMP TSTAMP messages which are returned to the sender by the IP module
+ * in the remote machine.
+ * In order to compare clocks of machines in different time zones, the time
+ * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
+ * If a hosts uses a different time format, it should set the high order
+ * bit of the 32-bit quantity it transmits.
+ * However, VMS apparently transmits the time in milliseconds since midnight
+ * local time (rather than GMT) without setting the high order bit.
+ * Furthermore, it does not understand daylight-saving time. This makes
+ * clockdiff behaving inconsistently with hosts running VMS.
+ *
+ * In order to reduce the sensitivity to the variance of message transmission
+ * time, clockdiff sends a sequence of messages. Yet, measures between
+ * two `distant' hosts can be affected by a small error. The error can,
+ * however, be reduced by increasing the number of messages sent in each
+ * measurement.
+ */
+void
+clockdiff(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int measure_status;
+ extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
+ register int avg_cnt;
+ register long avg;
+ struct servent *sp;
+
+ if (argc < 2) {
+ printf("Usage: clockdiff host ... \n");
+ return;
+ }
+
+ (void)gethostname(myname,sizeof(myname));
+
+ /* get the address for the date ready */
+ sp = getservbyname(DATE_PORT, DATE_PROTO);
+ if (!sp) {
+ (void)fprintf(stderr, "%s/%s is an unknown service\n",
+ DATE_PORT, DATE_PROTO);
+ dayaddr.sin_port = 0;
+ } else {
+ dayaddr.sin_port = sp->s_port;
+ }
+
+ while (argc > 1) {
+ argc--; argv++;
+ hp = gethostbyname(*argv);
+ if (hp == NULL) {
+ fprintf(stderr, "timedc: %s: ", *argv);
+ herror(0);
+ continue;
+ }
+
+ server.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length);
+ for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) {
+ measure_status = measure(10000,100, *argv, &server, 1);
+ if (measure_status != GOOD)
+ break;
+ avg += measure_delta;
+ }
+ if (measure_status == GOOD)
+ measure_delta = avg/avg_cnt;
+
+ switch (measure_status) {
+ case HOSTDOWN:
+ printf("%s is down\n", hp->h_name);
+ continue;
+ case NONSTDTIME:
+ printf("%s transmitts a non-standard time format\n",
+ hp->h_name);
+ continue;
+ case UNREACHABLE:
+ printf("%s is unreachable\n", hp->h_name);
+ continue;
+ }
+
+ /*
+ * Try to get the date only after using ICMP timestamps to
+ * get the time. This is because the date protocol
+ * is optional.
+ */
+ if (dayaddr.sin_port != 0) {
+ dayaddr.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr,
+ hp->h_length);
+ avg = daydiff(*argv);
+ if (avg > SECDAY) {
+ printf("time on %s is %ld days ahead %s\n",
+ hp->h_name, avg/SECDAY, myname);
+ continue;
+ } else if (avg < -SECDAY) {
+ printf("time on %s is %ld days behind %s\n",
+ hp->h_name, -avg/SECDAY, myname);
+ continue;
+ }
+ }
+
+ if (measure_delta > 0) {
+ printf("time on %s is %d ms. ahead of time on %s\n",
+ hp->h_name, measure_delta, myname);
+ } else if (measure_delta == 0) {
+ printf("%s and %s have the same time\n",
+ hp->h_name, myname);
+ } else {
+ printf("time on %s is %d ms. behind time on %s\n",
+ hp->h_name, -measure_delta, myname);
+ }
+ }
+ return;
+}
+
+
+/*
+ * finds location of master timedaemon
+ */
+void
+msite(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int cc;
+ fd_set ready;
+ struct sockaddr_in dest;
+ int i, length;
+ struct sockaddr from;
+ struct timeval tout;
+ struct tsp msg;
+ struct servent *srvp;
+ char *tgtname;
+
+ if (argc < 1) {
+ printf("Usage: msite [hostname]\n");
+ return;
+ }
+
+ srvp = getservbyname("timed", "udp");
+ if (srvp == 0) {
+ fprintf(stderr, "udp/timed: unknown service\n");
+ return;
+ }
+ dest.sin_port = srvp->s_port;
+ dest.sin_family = AF_INET;
+
+ (void)gethostname(myname, sizeof(myname));
+ i = 1;
+ do {
+ tgtname = (i >= argc) ? myname : argv[i];
+ hp = gethostbyname(tgtname);
+ if (hp == 0) {
+ fprintf(stderr, "timedc: %s: ", tgtname);
+ herror(0);
+ continue;
+ }
+ bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
+
+ (void)strcpy(msg.tsp_name, myname);
+ msg.tsp_type = TSP_MSITE;
+ msg.tsp_vers = TSPVERSION;
+ bytenetorder(&msg);
+ if (sendto(sock, &msg, sizeof(struct tsp), 0,
+ (struct sockaddr*)&dest,
+ sizeof(struct sockaddr)) < 0) {
+ perror("sendto");
+ continue;
+ }
+
+ tout.tv_sec = 15;
+ tout.tv_usec = 0;
+ FD_ZERO(&ready);
+ FD_SET(sock, &ready);
+ if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
+ &tout)) {
+ length = sizeof(struct sockaddr);
+ cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
+ &from, &length);
+ if (cc < 0) {
+ perror("recvfrom");
+ continue;
+ }
+ bytehostorder(&msg);
+ if (msg.tsp_type == TSP_ACK) {
+ printf("master timedaemon at %s is %s\n",
+ tgtname, msg.tsp_name);
+ } else {
+ printf("received wrong ack: %s\n",
+ tsptype[msg.tsp_type]);
+ }
+ } else {
+ printf("communication error with %s\n", tgtname);
+ }
+ } while (++i < argc);
+}
+
+/*
+ * quits timedc
+ */
+void
+quit()
+{
+ exit(0);
+}
+
+
+/*
+ * Causes the election timer to expire on the selected hosts
+ * It sends just one udp message per machine, relying on
+ * reliability of communication channel.
+ */
+void
+testing(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct servent *srvp;
+ struct sockaddr_in sin;
+ struct tsp msg;
+
+ if (argc < 2) {
+ printf("Usage: election host1 [host2 ...]\n");
+ return;
+ }
+
+ srvp = getservbyname("timed", "udp");
+ if (srvp == 0) {
+ fprintf(stderr, "udp/timed: unknown service\n");
+ return;
+ }
+
+ while (argc > 1) {
+ argc--; argv++;
+ hp = gethostbyname(*argv);
+ if (hp == NULL) {
+ fprintf(stderr, "timedc: %s: ", *argv);
+ herror(0);
+ argc--; argv++;
+ continue;
+ }
+ sin.sin_port = srvp->s_port;
+ sin.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length);
+
+ msg.tsp_type = TSP_TEST;
+ msg.tsp_vers = TSPVERSION;
+ (void)gethostname(myname, sizeof(myname));
+ (void)strncpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
+ bytenetorder(&msg);
+ if (sendto(sock, &msg, sizeof(struct tsp), 0,
+ (struct sockaddr*)&sin,
+ sizeof(struct sockaddr)) < 0) {
+ perror("sendto");
+ }
+ }
+}
+
+
+/*
+ * Enables or disables tracing on local timedaemon
+ */
+void
+tracing(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int onflag;
+ int length;
+ int cc;
+ fd_set ready;
+ struct sockaddr_in dest;
+ struct sockaddr from;
+ struct timeval tout;
+ struct tsp msg;
+ struct servent *srvp;
+
+ if (argc != 2) {
+ printf("Usage: tracing { on | off }\n");
+ return;
+ }
+
+ srvp = getservbyname("timed", "udp");
+ if (srvp == 0) {
+ fprintf(stderr, "udp/timed: unknown service\n");
+ return;
+ }
+ dest.sin_port = srvp->s_port;
+ dest.sin_family = AF_INET;
+
+ (void)gethostname(myname,sizeof(myname));
+ hp = gethostbyname(myname);
+ bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
+
+ if (strcmp(argv[1], "on") == 0) {
+ msg.tsp_type = TSP_TRACEON;
+ onflag = ON;
+ } else {
+ msg.tsp_type = TSP_TRACEOFF;
+ onflag = OFF;
+ }
+
+ (void)strcpy(msg.tsp_name, myname);
+ msg.tsp_vers = TSPVERSION;
+ bytenetorder(&msg);
+ if (sendto(sock, &msg, sizeof(struct tsp), 0,
+ (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
+ perror("sendto");
+ return;
+ }
+
+ tout.tv_sec = 5;
+ tout.tv_usec = 0;
+ FD_ZERO(&ready);
+ FD_SET(sock, &ready);
+ if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
+ length = sizeof(struct sockaddr);
+ cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
+ &from, &length);
+ if (cc < 0) {
+ perror("recvfrom");
+ return;
+ }
+ bytehostorder(&msg);
+ if (msg.tsp_type == TSP_ACK)
+ if (onflag)
+ printf("timed tracing enabled\n");
+ else
+ printf("timed tracing disabled\n");
+ else
+ printf("wrong ack received: %s\n",
+ tsptype[msg.tsp_type]);
+ } else
+ printf("communication error\n");
+}
+
+int
+priv_resources()
+{
+ int port;
+ struct sockaddr_in sin;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("opening socket");
+ return(-1);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = 0;
+ for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
+ sin.sin_port = htons((u_short)port);
+ if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
+ break;
+ if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
+ perror("bind");
+ (void) close(sock);
+ return(-1);
+ }
+ }
+ if (port == IPPORT_RESERVED / 2) {
+ fprintf(stderr, "all reserved ports in use\n");
+ (void) close(sock);
+ return(-1);
+ }
+
+ sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (sock_raw < 0) {
+ perror("opening raw socket");
+ (void) close(sock);
+ return(-1);
+ }
+ return(1);
+}
diff --git a/usr.sbin/timed/timedc/cmdtab.c b/usr.sbin/timed/timedc/cmdtab.c
new file mode 100644
index 0000000..ad5bbb6
--- /dev/null
+++ b/usr.sbin/timed/timedc/cmdtab.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "timedc.h"
+
+char clockdiffhelp[] = "measures clock differences between machines";
+char helphelp[] = "gets help on commands";
+char msitehelp[] = "finds location of master";
+char quithelp[] = "exits timedc";
+char testinghelp[] = "causes election timers to expire";
+char tracinghelp[] = "turns tracing on or off";
+
+struct cmd cmdtab[] = {
+ { "clockdiff", clockdiffhelp, clockdiff, 0 },
+ { "election", testinghelp, testing, 1 },
+ { "help", helphelp, help, 0 },
+ { "msite", msitehelp, msite, 0 },
+ { "quit", quithelp, quit, 0 },
+ { "trace", tracinghelp, tracing, 1 },
+ { "?", helphelp, help, 0 },
+};
+
+int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]);
diff --git a/usr.sbin/timed/timedc/extern.h b/usr.sbin/timed/timedc/extern.h
new file mode 100644
index 0000000..7f33362
--- /dev/null
+++ b/usr.sbin/timed/timedc/extern.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ */
+
+#if __STDC__
+struct tsp;
+#endif
+
+extern struct cmd cmdtab[];
+
+void bytehostorder __P((struct tsp *));
+void bytenetorder __P((struct tsp *));
+void clockdiff __P((int, char *[]));
+void help __P((int, char *[]));
+void intr __P((int));
+void makeargv __P((void));
+void msite __P((int, char *[]));
+int priv_resources __P((void));
+void quit __P((void));
+void testing __P((int, char *[]));
+void tracing __P((int, char *[]));
diff --git a/usr.sbin/timed/timedc/timedc.8 b/usr.sbin/timed/timedc/timedc.8
new file mode 100644
index 0000000..fd495e7
--- /dev/null
+++ b/usr.sbin/timed/timedc/timedc.8
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timedc.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TIMEDC 8
+.Os BSD 4.3
+.ad
+.Sh NAME
+.Nm timedc
+.Nd timed control program
+.Sh SYNOPSIS
+.Nm timedc
+.Oo Ar command\ \&
+.Op Ar argument ...
+.Oc
+.Sh DESCRIPTION
+.Nm Timedc
+is used to control the operation of the
+.Xr timed 8
+program.
+It may be used to:
+.Bl -bullet
+.It
+Measure the differences between machines' clocks,
+.It
+Find the location where the master time server is running,
+.It
+Enable or disable tracing of messages received by
+.Xr timed ,
+and
+.It
+Perform various debugging actions.
+.El
+.Pp
+Without any arguments,
+.Nm timedc
+will prompt for commands from the standard input.
+If arguments are supplied,
+.Nm timedc
+interprets the first argument as a command and the remaining
+arguments as parameters to the command. The standard input
+may be redirected causing
+.Nm timedc
+to read commands from a file.
+Commands may be abbreviated;
+recognized commands are:
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic \&? Op Ar command ...
+.Pp
+.It Ic help Op Ar command ...
+Print a short description of each command specified in the argument list,
+or, if no arguments are given, a list of the recognized commands.
+.Pp
+.It Ic clockdiff Ar host ...
+Compute the differences between the clock of the host machine
+and the clocks of the machines given as arguments.
+.Pp
+.It Ic msite Op Ar host ...
+Show the master time server for specified host(s).
+.Pp
+.It Xo
+.Ic trace
+.Li \&{ Ar on Li \&|
+.Ar off \&}
+.Xc
+Enable or disable the tracing of incoming messages to
+.Xr timed
+in the file
+.Pa /var/log/timed.log.
+.Pp
+.It Ic election Ar host
+Asks the daemon
+on the target host to reset its "election" timers and to ensure that
+a time master has been elected.
+.Pp
+.It Ic quit
+Exit from timedc.
+.El
+.Pp
+Other commands may be included for use in testing and debugging
+.Xr timed ;
+the help command and
+the program source may be consulted for details.
+.Sh FILES
+.Bl -tag -width /var/log/timed.masterlog -compact
+.It Pa /var/log/timed.log
+tracing file for timed
+.It Pa /var/log/timed.masterlog
+log file for master timed
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr adjtime 2 ,
+.Xr icmp 4 ,
+.Xr timed 8 ,
+.Rs
+.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
+.%A R. Gusella
+.%A S. Zatti
+.Re
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds -compact
+.It ?Ambiguous command
+abbreviation matches more than one command
+.It ?Invalid command
+no match found
+.It ?Privileged command
+command can be executed by root only
+.El
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/timed/timedc/timedc.c b/usr.sbin/timed/timedc/timedc.c
new file mode 100644
index 0000000..02d086a
--- /dev/null
+++ b/usr.sbin/timed/timedc/timedc.c
@@ -0,0 +1,261 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.6 $"
+#endif
+
+#include "timedc.h"
+#include <strings.h>
+#include <signal.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+int trace = 0;
+FILE *fd = 0;
+int margc;
+int fromatty;
+char *margv[20];
+char cmdline[200];
+jmp_buf toplevel;
+static struct cmd *getcmd __P((char *));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct cmd *c;
+
+ openlog("timedc", LOG_ODELAY, LOG_AUTH);
+
+ /*
+ * security dictates!
+ */
+ if (priv_resources() < 0) {
+ fprintf(stderr, "Could not get privileged resources\n");
+ exit(1);
+ }
+ (void) setuid(getuid());
+
+ if (--argc > 0) {
+ c = getcmd(*++argv);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ exit(1);
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ exit(1);
+ }
+ if (c->c_priv && getuid()) {
+ printf("?Privileged command\n");
+ exit(1);
+ }
+ (*c->c_handler)(argc, argv);
+ exit(0);
+ }
+
+ fromatty = isatty(fileno(stdin));
+ if (setjmp(toplevel))
+ putchar('\n');
+ (void) signal(SIGINT, intr);
+ for (;;) {
+ if (fromatty) {
+ printf("timedc> ");
+ (void) fflush(stdout);
+ }
+ if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
+ quit();
+ if (cmdline[0] == 0)
+ break;
+ makeargv();
+ if (margv[0] == 0)
+ continue;
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->c_priv && getuid()) {
+ printf("?Privileged command\n");
+ continue;
+ }
+ (*c->c_handler)(margc, margv);
+ }
+ return 0;
+}
+
+void
+intr(signo)
+ int signo;
+{
+ if (!fromatty)
+ exit(0);
+ longjmp(toplevel, 1);
+}
+
+
+static struct cmd *
+getcmd(name)
+ char *name;
+{
+ register char *p, *q;
+ register struct cmd *c, *found;
+ register int nmatches, longest;
+ extern int NCMDS;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+ p = c->c_name;
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return(c);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return((struct cmd *)-1);
+ return(found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+void
+makeargv()
+{
+ register char *cp;
+ register char **argp = margv;
+
+ margc = 0;
+ for (cp = cmdline; *cp;) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *cp++ = '\0';
+ }
+ *argp++ = 0;
+}
+
+#define HELPINDENT (sizeof ("directory"))
+
+/*
+ * Help command.
+ */
+void
+help(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct cmd *c;
+
+ if (argc == 1) {
+ register int i, j, w;
+ int columns, width = 0, lines;
+ extern int NCMDS;
+
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+ int len = strlen(c->c_name);
+
+ if (len > width)
+ width = len;
+ }
+ width = (width + 8) &~ 7;
+ columns = 80 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < columns; j++) {
+ c = cmdtab + j * lines + i;
+ printf("%s", c->c_name);
+ if (c + lines >= &cmdtab[NCMDS]) {
+ printf("\n");
+ break;
+ }
+ w = strlen(c->c_name);
+ while (w < width) {
+ w = (w + 8) &~ 7;
+ putchar('\t');
+ }
+ }
+ }
+ return;
+ }
+ while (--argc > 0) {
+ register char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%-*s\t%s\n", (int)HELPINDENT,
+ c->c_name, c->c_help);
+ }
+}
diff --git a/usr.sbin/timed/timedc/timedc.h b/usr.sbin/timed/timedc/timedc.h
new file mode 100644
index 0000000..6771680
--- /dev/null
+++ b/usr.sbin/timed/timedc/timedc.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)timedc.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#ifdef sgi
+#include <sys/uio.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+
+extern int errno;
+
+#define ON 1
+#define OFF 0
+
+#define GOOD 1
+#define UNREACHABLE 2
+#define NONSTDTIME 3
+#define HOSTDOWN 0x7fffffff
+
+struct cmd {
+ char *c_name; /* command name */
+ char *c_help; /* help message */
+ void (*c_handler)(); /* routine to do the work */
+ int c_priv; /* privileged command */
+};
+
+#include "extern.h"
diff --git a/usr.sbin/traceroute/Makefile b/usr.sbin/traceroute/Makefile
new file mode 100644
index 0000000..6f89a2c
--- /dev/null
+++ b/usr.sbin/traceroute/Makefile
@@ -0,0 +1,8 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= traceroute
+MAN8= traceroute.0
+BINOWN= root
+BINMODE=4555
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/traceroute/README b/usr.sbin/traceroute/README
new file mode 100644
index 0000000..6d33c6c
--- /dev/null
+++ b/usr.sbin/traceroute/README
@@ -0,0 +1,126 @@
+Tue Dec 27 06:24:24 PST 1988
+
+Traceroute is a system administrators utility to trace the route
+ip packets from the current system take in getting to some
+destination system. See the comments at the front of the
+program for a description of its use.
+
+This program
+
+ a) can only be run by root (it uses raw ip sockets).
+
+ b) REQUIRES A KERNEL MOD to the raw ip output code to run.
+
+If you want to hack on your kernel, my modified version of the
+routine rip_output (in file /sys/netinet/raw_ip.c) is attached.
+This code may or may not resemble the code in your kernel.
+It may offer you a place to start but I make no promises.
+If you do hack your kernel, remember to test everything that uses
+raw ip sockets (e.g., ping and egpup/gated) & make sure they still
+work. I wish you the best of luck and you're on your own.
+
+If your system has the ttl bug mentioned in the source, you
+might want to fix it while you're in the kernel. (This bug
+appears in all releases of BSD up to but not including 4.3tahoe.
+If your version of netinet/ip_icmp.c is any earlier than 7.3
+(April, '87), it has the bug.) The fix is just to add the line
+ ip->ip_ttl = MAXTTL;
+after the line
+ ip->ip_src = t;
+(or anywhere before the call to icmp_send) in routine icmp_reflect.
+
+If you're running this on a pre-4.3bsd system (e.g., Sun 3.x,
+Ultrix) that strips ip headers from icmp messages, add -DARCHAIC
+to CFLAGS in the Makefile. Also note that rip_output contains
+a conditional for a 4.2/4.3 change in the location of a raw
+socket's protocol number. I've checked this under 4.3 & Sun OS
+3.5 but you should double-check your system to make sure the
+appropriate branch of the #if is taken (check the line that
+assigned to ip->ip_p in your system's original rip_output).
+
+A couple of awk programs to massage the traceroute output are
+included. "mean.awk" and "median.awk" compute the mean and median
+time to each hop, respectively. I've found that something like
+
+ traceroute -q 7 foo.somewhere >t
+ awk -f median.awk t | graph
+
+can give you a quick picture of the bad spots on a long
+path (median is usually a better noise filter than mean).
+
+Enjoy.
+
+ - Van Jacobson (van@helios.ee.lbl.gov)
+
+-------------------- rip_output from /sys/netinet/raw_ip.c
+rip_output(m, so)
+ register struct mbuf *m;
+ struct socket *so;
+{
+ register struct ip *ip;
+ int error;
+ struct rawcb *rp = sotorawcb(so);
+ struct sockaddr_in *sin;
+#if BSD>=43
+ short proto = rp->rcb_proto.sp_protocol;
+#else
+ short proto = so->so_proto->pr_protocol;
+#endif
+ /*
+ * if the protocol is IPPROTO_RAW, the user handed us a
+ * complete IP packet. Otherwise, allocate an mbuf for a
+ * header and fill it in as needed.
+ */
+ if (proto != IPPROTO_RAW) {
+ /*
+ * Calculate data length and get an mbuf
+ * for IP header.
+ */
+ int len = 0;
+ struct mbuf *m0;
+
+ for (m0 = m; m; m = m->m_next)
+ len += m->m_len;
+
+ m = m_get(M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ m = m0;
+ error = ENOBUFS;
+ goto bad;
+ }
+ m->m_off = MMAXOFF - sizeof(struct ip);
+ m->m_len = sizeof(struct ip);
+ m->m_next = m0;
+
+ ip = mtod(m, struct ip *);
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_p = proto;
+ ip->ip_len = sizeof(struct ip) + len;
+ ip->ip_ttl = MAXTTL;
+ } else
+ ip = mtod(m, struct ip *);
+
+ if (rp->rcb_flags & RAW_LADDR) {
+ sin = (struct sockaddr_in *)&rp->rcb_laddr;
+ if (sin->sin_family != AF_INET) {
+ error = EAFNOSUPPORT;
+ goto bad;
+ }
+ ip->ip_src.s_addr = sin->sin_addr.s_addr;
+ } else
+ ip->ip_src.s_addr = 0;
+
+ ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr;
+
+#if BSD>=43
+ return (ip_output(m, rp->rcb_options, &rp->rcb_route,
+ (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
+#else
+ return (ip_output(m, (struct mbuf *)0, &rp->rcb_route,
+ (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
+#endif
+bad:
+ m_freem(m);
+ return (error);
+}
diff --git a/usr.sbin/traceroute/mean.awk b/usr.sbin/traceroute/mean.awk
new file mode 100644
index 0000000..e97a56f
--- /dev/null
+++ b/usr.sbin/traceroute/mean.awk
@@ -0,0 +1,50 @@
+#!/bin/awk -f
+#
+# Copyright (c) 1990, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Van Jacobson.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)mean.awk 8.1 (Berkeley) 6/6/93
+#
+/^ *[0-9]/ {
+ # print out the average time to each hop along a route.
+ tottime = 0; n = 0;
+ for (f = 5; f <= NF; ++f) {
+ if ($f == "ms") {
+ tottime += $(f - 1)
+ ++n
+ }
+ }
+ if (n > 0)
+ print $1, tottime/n, median
+}
diff --git a/usr.sbin/traceroute/median.awk b/usr.sbin/traceroute/median.awk
new file mode 100644
index 0000000..1a8d81d
--- /dev/null
+++ b/usr.sbin/traceroute/median.awk
@@ -0,0 +1,67 @@
+#!/bin/awk -f
+#
+# Copyright (c) 1990, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Van Jacobson.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)median.awk 8.1 (Berkeley) 6/6/93
+#
+/^ *[0-9]/ {
+ # print out the median time to each hop along a route.
+ tottime = 0; n = 0;
+ for (f = 5; f <= NF; ++f) {
+ if ($f == "ms") {
+ ++n
+ time[n] = $(f - 1)
+ }
+ }
+ if (n > 0) {
+ # insertion sort the times to find the median
+ for (i = 2; i <= n; ++i) {
+ v = time[i]; j = i - 1;
+ while (time[j] > v) {
+ time[j+1] = time[j];
+ j = j - 1;
+ if (j < 0)
+ break;
+ }
+ time[j+1] = v;
+ }
+ if (n > 1 && (n % 2) == 0)
+ median = (time[n/2] + time[(n/2) + 1]) / 2
+ else
+ median = time[(n+1)/2]
+
+ print $1, median
+ }
+}
diff --git a/usr.sbin/traceroute/traceroute.8 b/usr.sbin/traceroute/traceroute.8
new file mode 100644
index 0000000..c1e13bb
--- /dev/null
+++ b/usr.sbin/traceroute/traceroute.8
@@ -0,0 +1,336 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Van Jacobson.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)traceroute.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TRACEROUTE 8
+.Os BSD 4.3
+.Sh NAME
+.Nm traceroute
+.Nd print the route packets take to network host
+.Sh SYNOPSIS
+.Nm traceroute
+.Op Fl m Ar max_ttl
+.Op Fl n
+.Op Fl p Ar port
+.Op Fl q Ar nqueries
+.Op Fl r
+.Bk -words
+.Op Fl s Ar src_addr
+.Ek
+.Op Fl t Ar tos
+.Op Fl w Ar waittime
+.Ar host
+.Op Ar packetsize
+.Sh DESCRIPTION
+The Internet is a large and complex aggregation of
+network hardware, connected together by gateways.
+Tracking the route one's packets follow (or finding the miscreant
+gateway that's discarding your packets) can be difficult.
+.Nm Traceroute
+utilizes the IP protocol `time to live' field and attempts to elicit an
+.Tn ICMP
+.Dv TIME_EXCEEDED
+response from each gateway along the path to some
+host.
+.Pp
+The only mandatory parameter is the destination host name or IP number.
+The default probe datagram length is 38 bytes, but this may be increased
+by specifying a packet size (in bytes) after the destination host
+name.
+.Pp
+Other options are:
+.Bl -tag -width Ds
+.It Fl m Ar max_ttl
+Set the max time-to-live (max number of hops) used in outgoing probe
+packets. The default is 30 hops (the same default used for
+.Tn TCP
+connections).
+.It Fl n
+Print hop addresses numerically rather than symbolically and numerically
+(saves a nameserver address-to-name lookup for each gateway found on the
+path).
+.It Fl p Ar port
+Set the base
+.Tn UDP
+.Ar port
+number used in probes (default is 33434).
+.Nm Traceroute
+hopes that nothing is listening on
+.Tn UDP
+ports
+.Em base
+to
+.Em base+nhops-1
+at the destination host (so an
+.Tn ICMP
+.Dv PORT_UNREACHABLE
+message will
+be returned to terminate the route tracing). If something is
+listening on a port in the default range, this option can be used
+to pick an unused port range.
+.It Fl q Ar nqueries
+Set the number of probes per ``ttl'' to
+.Ar nqueries
+(default is three probes).
+.It Fl r
+Bypass the normal routing tables and send directly to a host on an attached
+network.
+If the host is not on a directly-attached network,
+an error is returned.
+This option can be used to ping a local host through an interface
+that has no route through it (e.g., after the interface was dropped by
+.Xr routed 8 ) .
+.It Fl s Ar src_addr
+Use the following IP address
+(which must be given as an IP number, not
+a hostname) as the source address in outgoing probe packets. On
+hosts with more than one IP address, this option can be used to
+force the source address to be something other than the IP address
+of the interface the probe packet is sent on. If the IP address
+is not one of this machine's interface addresses, an error is
+returned and nothing is sent.
+.It Fl t Ar tos
+Set the
+.Em type-of-service
+in probe packets to the following value (default zero). The value must be
+a decimal integer in the range 0 to 255. This option can be used to
+see if different types-of-service result in different paths. (If you
+are not running a
+.Bx 4.3 tahoe
+or later system, this may be academic since the normal network
+services like telnet and ftp don't let you control the
+.Dv TOS ) .
+Not all values of
+.Dv TOS
+are legal or
+meaningful \- see the IP spec for definitions. Useful values are
+probably
+.Ql \-t 16
+(low delay) and
+.Ql \-t 8
+(high throughput).
+.It Fl v
+Verbose output. Received
+.Tn ICMP
+packets other than
+.Dv TIME_EXCEEDED
+and
+.Dv UNREACHABLE Ns s
+are listed.
+.It Fl w
+Set the time (in seconds) to wait for a response to a probe (default 3
+sec.).
+.El
+.Pp
+This program attempts to trace the route an IP packet would follow to some
+internet host by launching
+.Tn UDP
+probe
+packets with a small ttl (time to live) then listening for an
+.Tn ICMP
+"time exceeded" reply from a gateway. We start our probes
+with a ttl of one and increase by one until we get an
+.Tn ICMP
+"port unreachable"
+(which means we got to "host") or hit a max (which
+defaults to 30 hops & can be changed with the
+.Fl m
+flag). Three
+probes (changed with
+.Fl q
+flag) are sent at each ttl setting and a
+line is printed showing the ttl, address of the gateway and
+round trip time of each probe. If the probe answers come from
+different gateways, the address of each responding system will
+be printed. If there is no response within a 3 sec. timeout
+interval (changed with the
+.Fl w
+flag), a "*" is printed for that
+probe.
+.Pp
+We don't want the destination
+host to process the
+.Tn UDP
+probe packets so the destination port is set to an
+unlikely value (if some clod on the destination is using that
+value, it can be changed with the
+.Fl p
+flag).
+.Pp
+A sample use and output might be:
+.Bd -literal
+[yak 71]% traceroute nis.nsf.net.
+traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
+2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
+5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
+6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
+7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
+8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
+9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
+10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
+11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
+
+.Ed
+Note that lines 2 & 3 are the same. This is due to a buggy
+kernel on the 2nd hop system \- lbl-csam.arpa \- that forwards
+packets with a zero ttl (a bug in the distributed version
+of 4.3
+.Tn BSD ) .
+Note that you have to guess what path
+the packets are taking cross-country since the
+.Tn NSFNet
+(129.140)
+doesn't supply address-to-name translations for its
+.Tn NSS Ns es .
+.Pp
+A more interesting example is:
+.Bd -literal
+[yak 72]% traceroute allspice.lcs.mit.edu.
+traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
+3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
+4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
+5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
+6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
+7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
+8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
+9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
+10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
+11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
+12 * * *
+13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
+14 * * *
+15 * * *
+16 * * *
+17 * * *
+18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
+
+.Ed
+Note that the gateways 12, 14, 15, 16 & 17 hops away
+either don't send
+.Tn ICMP
+"time exceeded" messages or send them
+with a ttl too small to reach us. 14 \- 17 are running the
+.Tn MIT
+C Gateway code that doesn't send "time exceeded"s. God
+only knows what's going on with 12.
+.Pp
+The silent gateway 12 in the above may be the result of a bug in
+the 4.[23]
+.Tn BSD
+network code (and its derivatives): 4.x (x <= 3)
+sends an unreachable message using whatever ttl remains in the
+original datagram. Since, for gateways, the remaining ttl is
+zero, the
+.Tn ICMP
+"time exceeded" is guaranteed to not make it back
+to us. The behavior of this bug is slightly more interesting
+when it appears on the destination system:
+.Bd -literal
+1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
+3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
+4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
+5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
+6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
+7 * * *
+8 * * *
+9 * * *
+10 * * *
+11 * * *
+12 * * *
+13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
+
+.Ed
+Notice that there are 12 "gateways" (13 is the final
+destination) and exactly the last half of them are "missing".
+What's really happening is that rip (a Sun-3 running Sun OS3.5)
+is using the ttl from our arriving datagram as the ttl in its
+.Tn ICMP
+reply. So, the reply will time out on the return path
+(with no notice sent to anyone since
+.Tn ICMP's
+aren't sent for
+.Tn ICMP's )
+until we probe with a ttl that's at least twice the path
+length. I.e., rip is really only 7 hops away. A reply that
+returns with a ttl of 1 is a clue this problem exists.
+.Nm Traceroute
+prints a "!" after the time if the ttl is <= 1.
+Since vendors ship a lot of obsolete
+.Pf ( Tn DEC Ns \'s
+Ultrix, Sun 3.x) or
+non-standard
+.Pq Tn HPUX
+software, expect to see this problem
+frequently and/or take care picking the target host of your
+probes.
+Other possible annotations after the time are
+.Sy !H ,
+.Sy !N ,
+.Sy !P
+(got a host, network or protocol unreachable, respectively),
+.Sy !S
+or
+.Sy !F
+(source route failed or fragmentation needed \- neither of these should
+ever occur and the associated gateway is busted if you see one). If
+almost all the probes result in some kind of unreachable,
+.Nm traceroute
+will give up and exit.
+.Pp
+This program is intended for use in network testing, measurement
+and management.
+It should be used primarily for manual fault isolation.
+Because of the load it could impose on the network, it is unwise to use
+.Nm traceroute
+during normal operations or from automated scripts.
+.Sh AUTHOR
+Implemented by Van Jacobson from a suggestion by Steve Deering. Debugged
+by a cast of thousands with particularly cogent suggestions or fixes from
+C. Philip Wood, Tim Seaver and Ken Adelman.
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr ping 8
+.Sh HISTORY
+The
+.Nm
+command
+.Bt
diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c
new file mode 100644
index 0000000..2ae83ba
--- /dev/null
+++ b/usr.sbin/traceroute/traceroute.c
@@ -0,0 +1,835 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * traceroute host - trace the route ip packets follow going to "host".
+ *
+ * Attempt to trace the route an ip packet would follow to some
+ * internet host. We find out intermediate hops by launching probe
+ * packets with a small ttl (time to live) then listening for an
+ * icmp "time exceeded" reply from a gateway. We start our probes
+ * with a ttl of one and increase by one until we get an icmp "port
+ * unreachable" (which means we got to "host") or hit a max (which
+ * defaults to 30 hops & can be changed with the -m flag). Three
+ * probes (change with -q flag) are sent at each ttl setting and a
+ * line is printed showing the ttl, address of the gateway and
+ * round trip time of each probe. If the probe answers come from
+ * different gateways, the address of each responding system will
+ * be printed. If there is no response within a 5 sec. timeout
+ * interval (changed with the -w flag), a "*" is printed for that
+ * probe.
+ *
+ * Probe packets are UDP format. We don't want the destination
+ * host to process them so the destination port is set to an
+ * unlikely value (if some clod on the destination is using that
+ * value, it can be changed with the -p flag).
+ *
+ * A sample use might be:
+ *
+ * [yak 71]% traceroute nis.nsf.net.
+ * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+ * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
+ * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
+ * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
+ * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
+ * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
+ * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
+ * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
+ * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
+ *
+ * Note that lines 2 & 3 are the same. This is due to a buggy
+ * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
+ * packets with a zero ttl.
+ *
+ * A more interesting example is:
+ *
+ * [yak 72]% traceroute allspice.lcs.mit.edu.
+ * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+ * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
+ * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
+ * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
+ * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
+ * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
+ * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
+ * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
+ * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
+ * 12 * * *
+ * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
+ * 14 * * *
+ * 15 * * *
+ * 16 * * *
+ * 17 * * *
+ * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
+ *
+ * (I start to see why I'm having so much trouble with mail to
+ * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
+ * either don't send ICMP "time exceeded" messages or send them
+ * with a ttl too small to reach us. 14 - 17 are running the
+ * MIT C Gateway code that doesn't send "time exceeded"s. God
+ * only knows what's going on with 12.
+ *
+ * The silent gateway 12 in the above may be the result of a bug in
+ * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
+ * sends an unreachable message using whatever ttl remains in the
+ * original datagram. Since, for gateways, the remaining ttl is
+ * zero, the icmp "time exceeded" is guaranteed to not make it back
+ * to us. The behavior of this bug is slightly more interesting
+ * when it appears on the destination system:
+ *
+ * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
+ * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
+ * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
+ * 7 * * *
+ * 8 * * *
+ * 9 * * *
+ * 10 * * *
+ * 11 * * *
+ * 12 * * *
+ * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
+ *
+ * Notice that there are 12 "gateways" (13 is the final
+ * destination) and exactly the last half of them are "missing".
+ * What's really happening is that rip (a Sun-3 running Sun OS3.5)
+ * is using the ttl from our arriving datagram as the ttl in its
+ * icmp reply. So, the reply will time out on the return path
+ * (with no notice sent to anyone since icmp's aren't sent for
+ * icmp's) until we probe with a ttl that's at least twice the path
+ * length. I.e., rip is really only 7 hops away. A reply that
+ * returns with a ttl of 1 is a clue this problem exists.
+ * Traceroute prints a "!" after the time if the ttl is <= 1.
+ * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
+ * non-standard (HPUX) software, expect to see this problem
+ * frequently and/or take care picking the target host of your
+ * probes.
+ *
+ * Other possible annotations after the time are !H, !N, !P (got a host,
+ * network or protocol unreachable, respectively), !S or !F (source
+ * route failed or fragmentation needed -- neither of these should
+ * ever occur and the associated gateway is busted if you see one). If
+ * almost all the probes result in some kind of unreachable, traceroute
+ * will give up and exit.
+ *
+ * Notes
+ * -----
+ * This program must be run by root or be setuid. (I suggest that
+ * you *don't* make it setuid -- casual use could result in a lot
+ * of unnecessary traffic on our poor, congested nets.)
+ *
+ * This program requires a kernel mod that does not appear in any
+ * system available from Berkeley: A raw ip socket using proto
+ * IPPROTO_RAW must interpret the data sent as an ip datagram (as
+ * opposed to data to be wrapped in a ip datagram). See the README
+ * file that came with the source to this program for a description
+ * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
+ * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
+ * MODIFIED TO RUN THIS PROGRAM.
+ *
+ * The udp port usage may appear bizarre (well, ok, it is bizarre).
+ * The problem is that an icmp message only contains 8 bytes of
+ * data from the original datagram. 8 bytes is the size of a udp
+ * header so, if we want to associate replies with the original
+ * datagram, the necessary information must be encoded into the
+ * udp header (the ip id could be used but there's no way to
+ * interlock with the kernel's assignment of ip id's and, anyway,
+ * it would have taken a lot more kernel hacking to allow this
+ * code to set the ip id). So, to allow two or more users to
+ * use traceroute simultaneously, we use this task's pid as the
+ * source port (the high bit is set to move the port number out
+ * of the "likely" range). To keep track of which probe is being
+ * replied to (so times and/or hop counts don't get confused by a
+ * reply that was delayed in transit), we increment the destination
+ * port number before each probe.
+ *
+ * Don't use this as a coding example. I was trying to find a
+ * routing problem and this code sort-of popped out after 48 hours
+ * without sleep. I was amazed it ever compiled, much less ran.
+ *
+ * I stole the idea for this program from Steve Deering. Since
+ * the first release, I've learned that had I attended the right
+ * IETF working group meetings, I also could have stolen it from Guy
+ * Almes or Matt Mathis. I don't know (or care) who came up with
+ * the idea first. I envy the originators' perspicacity and I'm
+ * glad they didn't keep the idea a secret.
+ *
+ * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
+ * enhancements to the original distribution.
+ *
+ * I've hacked up a round-trip-route version of this that works by
+ * sending a loose-source-routed udp datagram through the destination
+ * back to yourself. Unfortunately, SO many gateways botch source
+ * routing, the thing is almost worthless. Maybe one day...
+ *
+ * -- Van Jacobson (van@helios.ee.lbl.gov)
+ * Tue Dec 20 03:50:13 PST 1988
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAXPACKET 65535 /* max ip packet size */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef FD_SET
+#define NFDBITS (8*sizeof(fd_set))
+#define FD_SETSIZE NFDBITS
+#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
+#endif
+
+#define Fprintf (void)fprintf
+#define Sprintf (void)sprintf
+#define Printf (void)printf
+
+/*
+ * format of a (udp) probe packet.
+ */
+struct opacket {
+ struct ip ip;
+ struct udphdr udp;
+ u_char seq; /* sequence number of this packet */
+ u_char ttl; /* ttl packet left with */
+ struct timeval tv; /* time packet left */
+};
+
+u_char packet[512]; /* last inbound (icmp) packet */
+struct opacket *outpacket; /* last output (udp) packet */
+
+int wait_for_reply __P((int, struct sockaddr_in *));
+void send_probe __P((int, int));
+double deltaT __P((struct timeval *, struct timeval *));
+int packet_ok __P((u_char *, int, struct sockaddr_in *, int));
+void print __P((u_char *, int, struct sockaddr_in *));
+void tvsub __P((struct timeval *, struct timeval *));
+char *inetname __P((struct in_addr));
+void usage __P(());
+
+int s; /* receive (icmp) socket file descriptor */
+int sndsock; /* send (udp) socket file descriptor */
+struct timezone tz; /* leftover */
+
+struct sockaddr whereto; /* Who to try to reach */
+int datalen; /* How much data */
+
+char *source = 0;
+char *hostname;
+
+int nprobes = 3;
+int max_ttl = 30;
+u_short ident;
+u_short port = 32768+666; /* start udp dest port # for probe packets */
+int options; /* socket options */
+int verbose;
+int waittime = 5; /* time to wait for response (in seconds) */
+int nflag; /* print addresses numerically */
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ struct hostent *hp;
+ struct protoent *pe;
+ struct sockaddr_in from, *to;
+ int ch, i, on, probe, seq, tos, ttl;
+
+ on = 1;
+ seq = tos = 0;
+ to = (struct sockaddr_in *)&whereto;
+ while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
+ switch(ch) {
+ case 'd':
+ options |= SO_DEBUG;
+ break;
+ case 'm':
+ max_ttl = atoi(optarg);
+ if (max_ttl <= 1) {
+ Fprintf(stderr,
+ "traceroute: max ttl must be >1.\n");
+ exit(1);
+ }
+ break;
+ case 'n':
+ nflag++;
+ break;
+ case 'p':
+ port = atoi(optarg);
+ if (port < 1) {
+ Fprintf(stderr,
+ "traceroute: port must be >0.\n");
+ exit(1);
+ }
+ break;
+ case 'q':
+ nprobes = atoi(optarg);
+ if (nprobes < 1) {
+ Fprintf(stderr,
+ "traceroute: nprobes must be >0.\n");
+ exit(1);
+ }
+ break;
+ case 'r':
+ options |= SO_DONTROUTE;
+ break;
+ case 's':
+ /*
+ * set the ip source address of the outbound
+ * probe (e.g., on a multi-homed host).
+ */
+ source = optarg;
+ break;
+ case 't':
+ tos = atoi(optarg);
+ if (tos < 0 || tos > 255) {
+ Fprintf(stderr,
+ "traceroute: tos must be 0 to 255.\n");
+ exit(1);
+ }
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'w':
+ waittime = atoi(optarg);
+ if (waittime <= 1) {
+ Fprintf(stderr,
+ "traceroute: wait must be >1 sec.\n");
+ exit(1);
+ }
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ setlinebuf (stdout);
+
+ (void) bzero((char *)&whereto, sizeof(struct sockaddr));
+ to->sin_family = AF_INET;
+ to->sin_addr.s_addr = inet_addr(*argv);
+ if (to->sin_addr.s_addr != -1)
+ hostname = *argv;
+ else {
+ hp = gethostbyname(*argv);
+ if (hp) {
+ to->sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
+ hostname = hp->h_name;
+ } else {
+ (void)fprintf(stderr,
+ "traceroute: unknown host %s\n", *argv);
+ exit(1);
+ }
+ }
+ if (*++argv)
+ datalen = atoi(*argv);
+ if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
+ Fprintf(stderr,
+ "traceroute: packet size must be 0 <= s < %ld.\n",
+ MAXPACKET - sizeof(struct opacket));
+ exit(1);
+ }
+ datalen += sizeof(struct opacket);
+ outpacket = (struct opacket *)malloc((unsigned)datalen);
+ if (! outpacket) {
+ perror("traceroute: malloc");
+ exit(1);
+ }
+ (void) bzero((char *)outpacket, datalen);
+ outpacket->ip.ip_dst = to->sin_addr;
+ outpacket->ip.ip_tos = tos;
+ outpacket->ip.ip_v = IPVERSION;
+ outpacket->ip.ip_id = 0;
+
+ ident = (getpid() & 0xffff) | 0x8000;
+
+ if ((pe = getprotobyname("icmp")) == NULL) {
+ Fprintf(stderr, "icmp: unknown protocol\n");
+ exit(10);
+ }
+ if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
+ perror("traceroute: icmp socket");
+ exit(5);
+ }
+ if (options & SO_DEBUG)
+ (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ (char *)&on, sizeof(on));
+ if (options & SO_DONTROUTE)
+ (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
+ (char *)&on, sizeof(on));
+
+ if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
+ perror("traceroute: raw socket");
+ exit(5);
+ }
+#ifdef SO_SNDBUF
+ if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
+ sizeof(datalen)) < 0) {
+ perror("traceroute: SO_SNDBUF");
+ exit(6);
+ }
+#endif SO_SNDBUF
+#ifdef IP_HDRINCL
+ if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
+ sizeof(on)) < 0) {
+ perror("traceroute: IP_HDRINCL");
+ exit(6);
+ }
+#endif IP_HDRINCL
+ if (options & SO_DEBUG)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
+ (char *)&on, sizeof(on));
+ if (options & SO_DONTROUTE)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
+ (char *)&on, sizeof(on));
+
+ if (source) {
+ (void) bzero((char *)&from, sizeof(struct sockaddr));
+ from.sin_family = AF_INET;
+ from.sin_addr.s_addr = inet_addr(source);
+ if (from.sin_addr.s_addr == -1) {
+ Printf("traceroute: unknown host %s\n", source);
+ exit(1);
+ }
+ outpacket->ip.ip_src = from.sin_addr;
+#ifndef IP_HDRINCL
+ if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
+ perror ("traceroute: bind:");
+ exit (1);
+ }
+#endif IP_HDRINCL
+ }
+
+ Fprintf(stderr, "traceroute to %s (%s)", hostname,
+ inet_ntoa(to->sin_addr));
+ if (source)
+ Fprintf(stderr, " from %s", source);
+ Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
+ (void) fflush(stderr);
+
+ for (ttl = 1; ttl <= max_ttl; ++ttl) {
+ u_long lastaddr = 0;
+ int got_there = 0;
+ int unreachable = 0;
+
+ Printf("%2d ", ttl);
+ for (probe = 0; probe < nprobes; ++probe) {
+ int cc;
+ struct timeval t1, t2;
+ struct timezone tz;
+ struct ip *ip;
+
+ (void) gettimeofday(&t1, &tz);
+ send_probe(++seq, ttl);
+ while (cc = wait_for_reply(s, &from)) {
+ (void) gettimeofday(&t2, &tz);
+ if ((i = packet_ok(packet, cc, &from, seq))) {
+ if (from.sin_addr.s_addr != lastaddr) {
+ print(packet, cc, &from);
+ lastaddr = from.sin_addr.s_addr;
+ }
+ Printf(" %g ms", deltaT(&t1, &t2));
+ switch(i - 1) {
+ case ICMP_UNREACH_PORT:
+#ifndef ARCHAIC
+ ip = (struct ip *)packet;
+ if (ip->ip_ttl <= 1)
+ Printf(" !");
+#endif ARCHAIC
+ ++got_there;
+ break;
+ case ICMP_UNREACH_NET:
+ ++unreachable;
+ Printf(" !N");
+ break;
+ case ICMP_UNREACH_HOST:
+ ++unreachable;
+ Printf(" !H");
+ break;
+ case ICMP_UNREACH_PROTOCOL:
+ ++got_there;
+ Printf(" !P");
+ break;
+ case ICMP_UNREACH_NEEDFRAG:
+ ++unreachable;
+ Printf(" !F");
+ break;
+ case ICMP_UNREACH_SRCFAIL:
+ ++unreachable;
+ Printf(" !S");
+ break;
+ }
+ break;
+ }
+ }
+ if (cc == 0)
+ Printf(" *");
+ (void) fflush(stdout);
+ }
+ putchar('\n');
+ if (got_there || unreachable >= nprobes-1)
+ exit(0);
+ }
+}
+
+int
+wait_for_reply(sock, from)
+ int sock;
+ struct sockaddr_in *from;
+{
+ fd_set fds;
+ struct timeval wait;
+ int cc = 0;
+ int fromlen = sizeof (*from);
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ wait.tv_sec = waittime; wait.tv_usec = 0;
+
+ if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
+ cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
+ (struct sockaddr *)from, &fromlen);
+
+ return(cc);
+}
+
+
+void
+send_probe(seq, ttl)
+ int seq, ttl;
+{
+ struct opacket *op = outpacket;
+ struct ip *ip = &op->ip;
+ struct udphdr *up = &op->udp;
+ int i;
+
+ ip->ip_off = 0;
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_len = datalen;
+ ip->ip_ttl = ttl;
+ ip->ip_v = IPVERSION;
+ ip->ip_id = htons(ident+seq);
+
+ up->uh_sport = htons(ident);
+ up->uh_dport = htons(port+seq);
+ up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip)));
+ up->uh_sum = 0;
+
+ op->seq = seq;
+ op->ttl = ttl;
+ (void) gettimeofday(&op->tv, &tz);
+
+ i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
+ sizeof(struct sockaddr));
+ if (i < 0 || i != datalen) {
+ if (i<0)
+ perror("sendto");
+ Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
+ datalen, i);
+ (void) fflush(stdout);
+ }
+}
+
+
+double
+deltaT(t1p, t2p)
+ struct timeval *t1p, *t2p;
+{
+ register double dt;
+
+ dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
+ (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
+ return (dt);
+}
+
+
+/*
+ * Convert an ICMP "type" field to a printable string.
+ */
+char *
+pr_type(t)
+ u_char t;
+{
+ static char *ttab[] = {
+ "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
+ "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
+ "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
+ "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
+ "Info Reply"
+ };
+
+ if(t > 16)
+ return("OUT-OF-RANGE");
+
+ return(ttab[t]);
+}
+
+
+int
+packet_ok(buf, cc, from, seq)
+ u_char *buf;
+ int cc;
+ struct sockaddr_in *from;
+ int seq;
+{
+ register struct icmp *icp;
+ u_char type, code;
+ int hlen;
+#ifndef ARCHAIC
+ struct ip *ip;
+
+ ip = (struct ip *) buf;
+ hlen = ip->ip_hl << 2;
+ if (cc < hlen + ICMP_MINLEN) {
+ if (verbose)
+ Printf("packet too short (%d bytes) from %s\n", cc,
+ inet_ntoa(from->sin_addr));
+ return (0);
+ }
+ cc -= hlen;
+ icp = (struct icmp *)(buf + hlen);
+#else
+ icp = (struct icmp *)buf;
+#endif ARCHAIC
+ type = icp->icmp_type; code = icp->icmp_code;
+ if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
+ type == ICMP_UNREACH) {
+ struct ip *hip;
+ struct udphdr *up;
+
+ hip = &icp->icmp_ip;
+ hlen = hip->ip_hl << 2;
+ up = (struct udphdr *)((u_char *)hip + hlen);
+ if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
+ up->uh_sport == htons(ident) &&
+ up->uh_dport == htons(port+seq))
+ return (type == ICMP_TIMXCEED? -1 : code+1);
+ }
+#ifndef ARCHAIC
+ if (verbose) {
+ int i;
+ u_long *lp = (u_long *)&icp->icmp_ip;
+
+ Printf("\n%d bytes from %s to %s", cc,
+ inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
+ Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
+ icp->icmp_code);
+ for (i = 4; i < cc ; i += sizeof(long))
+ Printf("%2d: x%8.8lx\n", i, *lp++);
+ }
+#endif ARCHAIC
+ return(0);
+}
+
+
+void
+print(buf, cc, from)
+ u_char *buf;
+ int cc;
+ struct sockaddr_in *from;
+{
+ struct ip *ip;
+ int hlen;
+
+ ip = (struct ip *) buf;
+ hlen = ip->ip_hl << 2;
+ cc -= hlen;
+
+ if (nflag)
+ Printf(" %s", inet_ntoa(from->sin_addr));
+ else
+ Printf(" %s (%s)", inetname(from->sin_addr),
+ inet_ntoa(from->sin_addr));
+
+ if (verbose)
+ Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
+}
+
+
+#ifdef notyet
+/*
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+u_short
+in_cksum(addr, len)
+ u_short *addr;
+ int len;
+{
+ register int nleft = len;
+ register u_short *w = addr;
+ register u_short answer;
+ register int sum = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum),
+ * we add sequential 16 bit words to it, and at the end, fold
+ * back all the carry bits from the top 16 bits into the lower
+ * 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if (nleft == 1)
+ sum += *(u_char *)w;
+
+ /*
+ * add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return (answer);
+}
+#endif notyet
+
+/*
+ * Subtract 2 timeval structs: out = out - in.
+ * Out is assumed to be >= in.
+ */
+void
+tvsub(out, in)
+ register struct timeval *out, *in;
+{
+ if ((out->tv_usec -= in->tv_usec) < 0) {
+ out->tv_sec--;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(in)
+ struct in_addr in;
+{
+ register char *cp;
+ static char line[50];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN + 1];
+ static int first = 1;
+
+ if (first && !nflag) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = index(domain, '.')))
+ (void) strcpy(domain, cp + 1);
+ else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!nflag && in.s_addr != INADDR_ANY) {
+ hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
+ if (hp) {
+ if ((cp = index(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (cp)
+ (void) strcpy(line, cp);
+ else {
+ in.s_addr = ntohl(in.s_addr);
+#define C(x) ((x) & 0xff)
+ Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24),
+ C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
+ }
+ return (line);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+"usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
+[-s src_addr] [-t tos] [-w wait] host [data size]\n");
+ exit(1);
+}
diff --git a/usr.sbin/trpt/Makefile b/usr.sbin/trpt/Makefile
new file mode 100644
index 0000000..9057f65
--- /dev/null
+++ b/usr.sbin/trpt/Makefile
@@ -0,0 +1,8 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= trpt
+MAN8= trpt.0
+BINGRP= kmem
+BINMODE=2555
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/trpt/trpt.8 b/usr.sbin/trpt/trpt.8
new file mode 100644
index 0000000..8cc6c2a
--- /dev/null
+++ b/usr.sbin/trpt/trpt.8
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)trpt.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt TRPT 8
+.Os BSD 4.2
+.Sh NAME
+.Nm trpt
+.Nd transliterate protocol trace
+.Sh SYNOPSIS
+.Nm trpt
+.Op Fl a
+.Op Fl f
+.Op Fl j
+.Op Fl p Ar hex-address
+.Op Fl s
+.Op Fl t
+.Oo
+.Ar system Op Ar core
+.Oc
+.Sh DESCRIPTION
+.Nm Trpt
+interrogates the buffer of
+.Tn TCP
+trace records created
+when a socket is marked for
+.Dq debugging
+(see
+.Xr setsockopt 2 ) ,
+and prints a readable description of these records.
+When no options are supplied,
+.Nm trpt
+prints all the trace records found in the system
+grouped according to
+.Tn TCP
+connection protocol control
+block
+.Pq Tn PCB .
+The following options may be used to
+alter this behavior.
+.Bl -tag -width Ds
+.It Fl a
+In addition to the normal output,
+print the values of the source and destination
+addresses for each packet recorded.
+.It Fl f
+Follow the trace as it occurs, waiting a short time for additional records
+each time the end of the log is reached.
+.It Fl j
+Just give a list of the protocol control block
+addresses for which there are trace records.
+.It Fl p
+Show only trace records associated with the protocol
+control block at the given address
+.Ar hex-address .
+.It Fl s
+In addition to the normal output,
+print a detailed description of the packet
+sequencing information.
+.It Fl t
+in addition to the normal output,
+print the values for all timers at each
+point in the trace.
+.El
+.Pp
+The recommended use of
+.Nm trpt
+is as follows.
+Isolate the problem and enable debugging on the
+socket(s) involved in the connection.
+Find the address of the protocol control blocks
+associated with the sockets using the
+.Fl A
+option to
+.Xr netstat 1 .
+Then run
+.Nm trpt
+with the
+.Fl p
+option, supplying the associated
+protocol control block addresses.
+The
+.Fl f
+option can be used to follow the trace log once the trace is located.
+If there are
+many sockets using the debugging option, the
+.Fl j
+option may be useful in checking to see if
+any trace records are present for the socket in
+question.
+.Pp
+If debugging is being performed on a system or
+core file other than the default, the last two
+arguments may be used to supplant the defaults.
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+.It Pa /dev/kmem
+.El
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr setsockopt 2 ,
+.Xr trsp 8
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy no namelist
+When the system image doesn't
+contain the proper symbols to find the trace buffer;
+others which should be self explanatory.
+.El
+.Sh BUGS
+Should also print the data for each input or output,
+but this is not saved in the race record.
+.Pp
+The output format is inscrutable and should be described
+here.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/trpt/trpt.c b/usr.sbin/trpt/trpt.c
new file mode 100644
index 0000000..7452cdd
--- /dev/null
+++ b/usr.sbin/trpt/trpt.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#if BSD >= 199103
+#define NEWVM
+#endif
+#ifndef NEWVM
+#include <machine/pte.h>
+#include <sys/vmmac.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#define PRUREQUESTS
+#include <sys/protosw.h>
+#include <sys/file.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#define TCPTIMERS
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#define TANAMES
+#include <netinet/tcp_debug.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <nlist.h>
+#include <paths.h>
+
+struct nlist nl[] = {
+#define N_TCP_DEBUG 0
+ { "_tcp_debug" },
+#define N_TCP_DEBX 1
+ { "_tcp_debx" },
+#ifndef NEWVM
+#define N_SYSMAP 2
+ { "_Sysmap" },
+#define N_SYSSIZE 3
+ { "_Syssize" },
+#endif
+ { "" },
+};
+
+#ifndef NEWVM
+static struct pte *Sysmap;
+#endif
+static caddr_t tcp_pcbs[TCP_NDEBUG];
+static n_time ntime;
+static int aflag, kflag, memf, follow, sflag, tflag;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char *optarg;
+ extern int optind;
+ int ch, i, jflag, npcbs, numeric();
+ char *system, *core, *malloc();
+ off_t lseek();
+
+ jflag = npcbs = 0;
+ while ((ch = getopt(argc, argv, "afjp:st")) != EOF)
+ switch (ch) {
+ case 'a':
+ ++aflag;
+ break;
+ case 'f':
+ ++follow;
+ setlinebuf(stdout);
+ break;
+ case 'j':
+ ++jflag;
+ break;
+ case 'p':
+ if (npcbs >= TCP_NDEBUG) {
+ fputs("trpt: too many pcb's specified\n",
+ stderr);
+ exit(1);
+ }
+ (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]);
+ break;
+ case 's':
+ ++sflag;
+ break;
+ case 't':
+ ++tflag;
+ break;
+ case '?':
+ default:
+ (void)fprintf(stderr,
+"usage: trpt [-afjst] [-p hex-address] [system [core]]\n");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ core = _PATH_KMEM;
+ if (argc > 0) {
+ system = *argv;
+ argc--, argv++;
+ if (argc > 0) {
+ core = *argv;
+ argc--, argv++;
+ ++kflag;
+ }
+ /*
+ * Discard setgid privileges if not the running kernel so that
+ * bad guys can't print interesting stuff from kernel memory.
+ */
+ setgid(getgid());
+ }
+ else
+ system = _PATH_UNIX;
+
+ if (nlist(system, nl) < 0 || !nl[0].n_value) {
+ fprintf(stderr, "trpt: %s: no namelist\n", system);
+ exit(1);
+ }
+ if ((memf = open(core, O_RDONLY)) < 0) {
+ perror(core);
+ exit(2);
+ }
+ if (kflag) {
+#ifdef NEWVM
+ fputs("trpt: can't do core files yet\n", stderr);
+ exit(1);
+#else
+ off_t off;
+
+ Sysmap = (struct pte *)
+ malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
+ if (!Sysmap) {
+ fputs("trpt: can't get memory for Sysmap.\n", stderr);
+ exit(1);
+ }
+ off = nl[N_SYSMAP].n_value & ~KERNBASE;
+ (void)lseek(memf, off, L_SET);
+ (void)read(memf, (char *)Sysmap,
+ (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
+#endif
+ }
+ (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
+ if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
+ sizeof(tcp_debx)) {
+ perror("trpt: tcp_debx");
+ exit(3);
+ }
+ (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
+ if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
+ sizeof(tcp_debug)) {
+ perror("trpt: tcp_debug");
+ exit(3);
+ }
+ /*
+ * If no control blocks have been specified, figure
+ * out how many distinct one we have and summarize
+ * them in tcp_pcbs for sorting the trace records
+ * below.
+ */
+ if (!npcbs) {
+ for (i = 0; i < TCP_NDEBUG; i++) {
+ register struct tcp_debug *td = &tcp_debug[i];
+ register int j;
+
+ if (td->td_tcb == 0)
+ continue;
+ for (j = 0; j < npcbs; j++)
+ if (tcp_pcbs[j] == td->td_tcb)
+ break;
+ if (j >= npcbs)
+ tcp_pcbs[npcbs++] = td->td_tcb;
+ }
+ if (!npcbs)
+ exit(0);
+ }
+ qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric);
+ if (jflag) {
+ for (i = 0;;) {
+ printf("%x", (int)tcp_pcbs[i]);
+ if (++i == npcbs)
+ break;
+ fputs(", ", stdout);
+ }
+ putchar('\n');
+ }
+ else for (i = 0; i < npcbs; i++) {
+ printf("\n%x:\n", (int)tcp_pcbs[i]);
+ dotrace(tcp_pcbs[i]);
+ }
+ exit(0);
+}
+
+dotrace(tcpcb)
+ register caddr_t tcpcb;
+{
+ register struct tcp_debug *td;
+ register int i;
+ int prev_debx = tcp_debx;
+
+again: if (--tcp_debx < 0)
+ tcp_debx = TCP_NDEBUG - 1;
+ for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
+ td = &tcp_debug[i];
+ if (tcpcb && td->td_tcb != tcpcb)
+ continue;
+ ntime = ntohl(td->td_time);
+ tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
+ &td->td_ti, td->td_req);
+ if (i == tcp_debx)
+ goto done;
+ }
+ for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) {
+ td = &tcp_debug[i];
+ if (tcpcb && td->td_tcb != tcpcb)
+ continue;
+ ntime = ntohl(td->td_time);
+ tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
+ &td->td_ti, td->td_req);
+ }
+done: if (follow) {
+ prev_debx = tcp_debx + 1;
+ if (prev_debx >= TCP_NDEBUG)
+ prev_debx = 0;
+ do {
+ sleep(1);
+ (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
+ if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
+ sizeof(tcp_debx)) {
+ perror("trpt: tcp_debx");
+ exit(3);
+ }
+ } while (tcp_debx == prev_debx);
+ (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
+ if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
+ sizeof(tcp_debug)) {
+ perror("trpt: tcp_debug");
+ exit(3);
+ }
+ goto again;
+ }
+}
+
+/*
+ * Tcp debug routines
+ */
+/*ARGSUSED*/
+tcp_trace(act, ostate, atp, tp, ti, req)
+ short act, ostate;
+ struct tcpcb *atp, *tp;
+ struct tcpiphdr *ti;
+ int req;
+{
+ tcp_seq seq, ack;
+ int flags, len, win, timer;
+
+ printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate],
+ tanames[act]);
+ switch (act) {
+ case TA_INPUT:
+ case TA_OUTPUT:
+ case TA_DROP:
+ if (aflag) {
+ printf("(src=%s,%u, ",
+ inet_ntoa(ti->ti_src), ntohs(ti->ti_sport));
+ printf("dst=%s,%u)",
+ inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport));
+ }
+ seq = ti->ti_seq;
+ ack = ti->ti_ack;
+ len = ti->ti_len;
+ win = ti->ti_win;
+ if (act == TA_OUTPUT) {
+ seq = ntohl(seq);
+ ack = ntohl(ack);
+ len = ntohs(len);
+ win = ntohs(win);
+ }
+ if (act == TA_OUTPUT)
+ len -= sizeof(struct tcphdr);
+ if (len)
+ printf("[%lx..%lx)", seq, seq + len);
+ else
+ printf("%lx", seq);
+ printf("@%lx", ack);
+ if (win)
+ printf("(win=%x)", win);
+ flags = ti->ti_flags;
+ if (flags) {
+ register char *cp = "<";
+#define pf(flag, string) { \
+ if (ti->ti_flags&flag) { \
+ (void)printf("%s%s", cp, string); \
+ cp = ","; \
+ } \
+}
+ pf(TH_SYN, "SYN");
+ pf(TH_ACK, "ACK");
+ pf(TH_FIN, "FIN");
+ pf(TH_RST, "RST");
+ pf(TH_PUSH, "PUSH");
+ pf(TH_URG, "URG");
+ printf(">");
+ }
+ break;
+ case TA_USER:
+ timer = req >> 8;
+ req &= 0xff;
+ printf("%s", prurequests[req]);
+ if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
+ printf("<%s>", tcptimers[timer]);
+ break;
+ }
+ printf(" -> %s", tcpstates[tp->t_state]);
+ /* print out internal state of tp !?! */
+ printf("\n");
+ if (sflag) {
+ printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n",
+ tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
+ tp->snd_max);
+ printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1,
+ tp->snd_wl2, tp->snd_wnd);
+ }
+ /* print out timers? */
+ if (tflag) {
+ register char *cp = "\t";
+ register int i;
+
+ for (i = 0; i < TCPT_NTIMERS; i++) {
+ if (tp->t_timer[i] == 0)
+ continue;
+ printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
+ if (i == TCPT_REXMT)
+ printf(" (t_rxtshft=%d)", tp->t_rxtshift);
+ cp = ", ";
+ }
+ if (*cp != '\t')
+ putchar('\n');
+ }
+}
+
+numeric(c1, c2)
+ caddr_t *c1, *c2;
+{
+ return(*c1 - *c2);
+}
+
+klseek(fd, base, off)
+ int fd, off;
+ off_t base;
+{
+ off_t lseek();
+
+#ifndef NEWVM
+ if (kflag) { /* get kernel pte */
+ base &= ~KERNBASE;
+ base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
+ }
+#endif
+ (void)lseek(fd, base, off);
+}
diff --git a/usr.sbin/trsp/Makefile b/usr.sbin/trsp/Makefile
new file mode 100644
index 0000000..a0e4db6
--- /dev/null
+++ b/usr.sbin/trsp/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= trsp
+MAN8= trsp.0
+BINGRP= kmem
+BINMODE=2555
+
+.include <bsd.prog.mk>
+
diff --git a/usr.sbin/trsp/trsp.8 b/usr.sbin/trsp/trsp.8
new file mode 100644
index 0000000..19c23b4
--- /dev/null
+++ b/usr.sbin/trsp/trsp.8
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)trsp.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TRSP 8
+.Os BSD 4.2
+.Sh NAME
+.Nm trsp
+.Nd transliterate sequenced packet protocol trace
+.Sh SYNOPSIS
+.Nm trsp
+.Op Fl a
+.Op Fl s
+.Op Fl t
+.Op Fl j
+.Op Fl p Ar hex-address
+.Oo
+.Ar system Op Ar core
+.Oc
+.Sh DESCRIPTION
+.Xr Trpt
+interrogates the buffer of
+.Tn SPP
+trace records created
+when a socket is marked for
+.Dq debugging
+(see
+.Xr setsockopt 2 ) ,
+and prints a readable description of these records.
+When no options are supplied,
+.Nm trsp
+prints all the trace records found in the system
+grouped according to
+.Tn SPP
+connection protocol control
+block
+.Pq Tn PCB .
+The following options may be used to
+alter this behavior.
+.Bl -tag -width Ds
+.It Fl a
+In addition to the normal output,
+print the values of the source and destination
+addresses for each packet recorded.
+.It Fl j
+Just give a list of the protocol control block
+addresses for which there are trace records.
+.It Fl p
+Show only trace records associated with the protocol
+control block at the given address,
+.Ar hex-address .
+.It Fl s
+in addition to the normal output,
+print a detailed description of the packet
+sequencing information.
+.It Fl t
+in addition to the normal output,
+print the values for all timers at each
+point in the trace,
+.El
+.Pp
+The recommended use of
+.Nm trsp
+is as follows.
+Isolate the problem and enable debugging on the
+socket(s) involved in the connection.
+Find the address of the protocol control blocks
+associated with the sockets using the
+.Fl A
+option to
+.Xr netstat 1 .
+Then run
+.Nm trsp
+with the
+.Fl p
+option, supplying the associated
+protocol control block addresses. If there are
+many sockets using the debugging option, the
+.Fl j
+option may be useful in checking to see if
+any trace records are present for the socket in
+question.
+.Pp
+If debugging is being performed on a system or
+core file other than the default, the last two
+arguments may be used to supplant the defaults.
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+.It Pa /dev/kmem
+.El
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr setsockopt 2
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy no namelist
+When the system image doesn't
+contain the proper symbols to find the trace buffer;
+others which should be self explanatory.
+.Sh BUGS
+Should also print the data for each input or output,
+but this is not saved in the race record.
+.Pp
+The output format is inscrutable and should be described
+here.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/trsp/trsp.c b/usr.sbin/trsp/trsp.c
new file mode 100644
index 0000000..c2c0267
--- /dev/null
+++ b/usr.sbin/trsp/trsp.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)trsp.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#define PRUREQUESTS
+#include <sys/protosw.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#define TCPTIMERS
+#include <netinet/tcp_timer.h>
+
+#include <netns/ns.h>
+#include <netns/sp.h>
+#include <netns/idp.h>
+#include <netns/spidp.h>
+#include <netns/spp_timer.h>
+#include <netns/spp_var.h>
+#include <netns/ns_pcb.h>
+#include <netns/idp_var.h>
+#define SANAMES
+#include <netns/spp_debug.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <nlist.h>
+#include <paths.h>
+
+unsigned long ntime;
+int sflag;
+int tflag;
+int jflag;
+int aflag;
+int zflag;
+int numeric();
+struct nlist nl[] = {
+ { "_spp_debug" },
+ { "_spp_debx" },
+ 0
+};
+struct spp_debug spp_debug[SPP_NDEBUG];
+caddr_t spp_pcbs[SPP_NDEBUG];
+int spp_debx;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int i, mask = 0, npcbs = 0;
+ char *system, *core;
+
+ system = _PATH_UNIX;
+ core = _PATH_KMEM;
+
+ argc--, argv++;
+again:
+ if (argc > 0 && !strcmp(*argv, "-a")) {
+ aflag++, argc--, argv++;
+ goto again;
+ }
+ if (argc > 0 && !strcmp(*argv, "-z")) {
+ zflag++, argc--, argv++;
+ goto again;
+ }
+ if (argc > 0 && !strcmp(*argv, "-s")) {
+ sflag++, argc--, argv++;
+ goto again;
+ }
+ if (argc > 0 && !strcmp(*argv, "-t")) {
+ tflag++, argc--, argv++;
+ goto again;
+ }
+ if (argc > 0 && !strcmp(*argv, "-j")) {
+ jflag++, argc--, argv++;
+ goto again;
+ }
+ if (argc > 0 && !strcmp(*argv, "-p")) {
+ argc--, argv++;
+ if (argc < 1) {
+ fprintf(stderr, "-p: missing sppcb address\n");
+ exit(1);
+ }
+ if (npcbs >= SPP_NDEBUG) {
+ fprintf(stderr, "-p: too many pcb's specified\n");
+ exit(1);
+ }
+ sscanf(*argv, "%x", &spp_pcbs[npcbs++]);
+ argc--, argv++;
+ goto again;
+ }
+ if (argc > 0) {
+ system = *argv;
+ argc--, argv++;
+ mask++;
+ /*
+ * Discard setgid privileges if not the running kernel so that
+ * bad guys can't print interesting stuff from kernel memory.
+ */
+ setgid(getgid());
+ }
+ if (argc > 0) {
+ core = *argv;
+ argc--, argv++;
+ mask++;
+ setgid(getgid());
+ }
+ (void) nlist(system, nl);
+ if (nl[0].n_value == 0) {
+ fprintf(stderr, "trsp: %s: no namelist\n", system);
+ exit(1);
+ }
+ (void) close(0);
+ if (open(core, 0) < 0) {
+ fprintf(stderr, "trsp: "); perror(core);
+ exit(2);
+ }
+ if (mask) {
+ nl[0].n_value &= 0x7fffffff;
+ nl[1].n_value &= 0x7fffffff;
+ }
+ (void) lseek(0, nl[1].n_value, 0);
+ if (read(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) {
+ fprintf(stderr, "trsp: "); perror("spp_debx");
+ exit(3);
+ }
+ printf("spp_debx=%d\n", spp_debx);
+ (void) lseek(0, nl[0].n_value, 0);
+ if (read(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) {
+ fprintf(stderr, "trsp: "); perror("spp_debug");
+ exit(3);
+ }
+ /*
+ * Here, we just want to clear out the old trace data and start over.
+ */
+ if (zflag) {
+ char *cp = (char *) spp_debug,
+ *cplim = cp + sizeof(spp_debug);
+ (void) close(0);
+ if (open(core, 2) < 0) {
+ fprintf(stderr, "trsp: "); perror(core);
+ exit(2);
+ }
+ while(cp < cplim) *cp++ = 0;
+ (void) lseek(0, nl[0].n_value, 0);
+ if (write(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) {
+ fprintf(stderr, "trsp: "); perror("spp_debug");
+ exit(3);
+ }
+ (void) lseek(0, nl[1].n_value, 0);
+ spp_debx = 0;
+ if (write(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) {
+ fprintf(stderr, "trsp: "); perror("spp_debx");
+ exit(3);
+ }
+ exit(0);
+ }
+ /*
+ * If no control blocks have been specified, figure
+ * out how many distinct one we have and summarize
+ * them in spp_pcbs for sorting the trace records
+ * below.
+ */
+ if (npcbs == 0) {
+ for (i = 0; i < SPP_NDEBUG; i++) {
+ register int j;
+ register struct spp_debug *sd = &spp_debug[i];
+
+ if (sd->sd_cb == 0)
+ continue;
+ for (j = 0; j < npcbs; j++)
+ if (spp_pcbs[j] == sd->sd_cb)
+ break;
+ if (j >= npcbs)
+ spp_pcbs[npcbs++] = sd->sd_cb;
+ }
+ }
+ qsort(spp_pcbs, npcbs, sizeof (caddr_t), numeric);
+ if (jflag) {
+ char *cp = "";
+
+ for (i = 0; i < npcbs; i++) {
+ printf("%s%x", cp, spp_pcbs[i]);
+ cp = ", ";
+ }
+ if (*cp)
+ putchar('\n');
+ exit(0);
+ }
+ for (i = 0; i < npcbs; i++) {
+ printf("\n%x:\n", spp_pcbs[i]);
+ dotrace(spp_pcbs[i]);
+ }
+ exit(0);
+}
+
+dotrace(sppcb)
+ register caddr_t sppcb;
+{
+ register int i;
+ register struct spp_debug *sd;
+
+ for (i = spp_debx % SPP_NDEBUG; i < SPP_NDEBUG; i++) {
+ sd = &spp_debug[i];
+ if (sppcb && sd->sd_cb != sppcb)
+ continue;
+ ntime = ntohl(sd->sd_time);
+ spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp,
+ &sd->sd_si, sd->sd_req);
+ }
+ for (i = 0; i < spp_debx % SPP_NDEBUG; i++) {
+ sd = &spp_debug[i];
+ if (sppcb && sd->sd_cb != sppcb)
+ continue;
+ ntime = ntohl(sd->sd_time);
+ spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp,
+ &sd->sd_si, sd->sd_req);
+ }
+}
+
+ptime(ms)
+ int ms;
+{
+
+ printf("%03d ", (ms/10) % 1000);
+}
+
+numeric(c1, c2)
+ caddr_t *c1, *c2;
+{
+
+ return (*c1 - *c2);
+}
+
+spp_trace(act, ostate, asp, sp, si, req)
+ short act, ostate;
+ struct sppcb *asp, *sp;
+ struct spidp *si;
+ int req;
+{
+ u_short seq, ack, len, alo;
+ int flags, timer;
+ char *cp;
+
+ if(ostate >= TCP_NSTATES) ostate = 0;
+ if(act > SA_DROP) act = SA_DROP;
+ printf("\n");
+ ptime(ntime);
+ printf("%s:%s", tcpstates[ostate], sanames[act]);
+
+ if (si != 0) {
+ seq = si->si_seq;
+ ack = si->si_ack;
+ alo = si->si_alo;
+ len = si->si_len;
+ switch (act) {
+ case SA_RESPOND:
+ case SA_OUTPUT:
+ seq = ntohs(seq);
+ ack = ntohs(ack);
+ alo = ntohs(alo);
+ len = ntohs(len);
+ case SA_INPUT:
+ case SA_DROP:
+ if (aflag) {
+ printf("\n\tsna=");
+ ns_printhost(&si->si_sna);
+ printf("\tdna=");
+ ns_printhost(&si->si_dna);
+ }
+ printf("\n\t");
+#define p1(name, f) { \
+ printf("%s = %x, ", name, f); \
+ }
+ p1("seq", seq);
+ p1("ack", ack);
+ p1("alo", alo);
+ p1("len", len);
+ flags = si->si_cc;
+ printf("flags=%x", flags);
+#define pf(name, f) { \
+ if (flags & f) { \
+ printf("%s%s", cp, name); \
+ cp = ","; \
+ } \
+}
+ if (flags) {
+ char *cp = "<";
+ pf("SP_SP", SP_SP);
+ pf("SP_SA", SP_SA);
+ pf("SP_OB", SP_OB);
+ pf("SP_EM", SP_EM);
+ printf(">");
+ }
+ printf(", ");
+#define p2(name, f) { \
+ printf("%s = %x, ", name, f); \
+}
+ p2("sid", si->si_sid);
+ p2("did", si->si_did);
+ p2("dt", si->si_dt);
+ printf("\n\tsna=");
+ ns_printhost(&si->si_sna);
+ printf("\tdna=");
+ ns_printhost(&si->si_dna);
+ }
+ }
+ if(act == SA_USER) {
+ printf("\treq=%s", prurequests[req&0xff]);
+ if ((req & 0xff) == PRU_SLOWTIMO)
+ printf("<%s>", tcptimers[req>>8]);
+ }
+ printf(" -> %s", tcpstates[sp->s_state]);
+
+ /* print out internal state of sp !?! */
+ printf("\n");
+ if (sp == 0)
+ return;
+#define p3(name, f) { \
+ printf("%s = %x, ", name, f); \
+}
+ if (sflag) {
+ printf("\t");
+ p3("rack", sp->s_rack);
+ p3("ralo", sp->s_ralo);
+ p3("smax", sp->s_smax);
+ p3("snxt", sp->s_snxt);
+ p3("flags", sp->s_flags);
+#undef pf
+#define pf(name, f) { \
+ if (flags & f) { \
+ printf("%s%s", cp, name); \
+ cp = ","; \
+ } \
+}
+ flags = sp->s_flags;
+ if (flags || sp->s_oobflags) {
+ char *cp = "<";
+ pf("ACKNOW", SF_ACKNOW);
+ pf("DELACK", SF_DELACK);
+ pf("HI", SF_HI);
+ pf("HO", SF_HO);
+ pf("PI", SF_PI);
+ pf("WIN", SF_WIN);
+ pf("RXT", SF_RXT);
+ pf("RVD", SF_RVD);
+ flags = sp->s_oobflags;
+ pf("SOOB", SF_SOOB);
+ pf("IOOB", SF_IOOB);
+ printf(">");
+ }
+ }
+ /* print out timers? */
+ if (tflag) {
+ char *cp = "\t";
+ register int i;
+
+ printf("\n\tTIMERS: ");
+ p3("idle", sp->s_idle);
+ p3("force", sp->s_force);
+ p3("rtseq", sp->s_rtseq);
+ for (i = 0; i < TCPT_NTIMERS; i++) {
+ if (sp->s_timer[i] == 0)
+ continue;
+ printf("%s%s=%d", cp, tcptimers[i], sp->s_timer[i]);
+ if (i == TCPT_REXMT)
+ printf(" (s_rxtshft=%d)", sp->s_rxtshift);
+ cp = ", ";
+ }
+ if (*cp != '\t')
+ putchar('\n');
+ }
+}
+
+ns_printhost(p)
+register struct ns_addr *p;
+{
+
+ printf("<net:%x%x,host:%4.4x%4.4x%4.4x,port:%x>",
+ p->x_net.s_net[0],
+ p->x_net.s_net[1],
+ p->x_host.s_host[0],
+ p->x_host.s_host[1],
+ p->x_host.s_host[2],
+ p->x_port);
+
+}
+
diff --git a/usr.sbin/update/Makefile b/usr.sbin/update/Makefile
new file mode 100644
index 0000000..ea20d05
--- /dev/null
+++ b/usr.sbin/update/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= update
+MAN8= update.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/update/update.8 b/usr.sbin/update/update.8
new file mode 100644
index 0000000..78665fa
--- /dev/null
+++ b/usr.sbin/update/update.8
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)update.8 8.3 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt UPDATE 8
+.Os
+.Sh NAME
+.Nm update
+.Nd flush internal filesystem caches to disk frequently
+.Sh SYNOPSIS
+.Nm update
+.Sh DESCRIPTION
+The
+.Nm update
+command helps protect the integrity of disk volumes
+by flushing
+volatile cached filesystem data
+to disk at thirty second intervals.
+.Nm Update
+uses the
+.Xr sync 2
+function call to do the task.
+.Pp
+.Nm Update
+is commonly invoked at startup time by
+.Xr rc 8
+when the system goes multi-user.
+.Sh SEE ALSO
+.Xr sync 2 ,
+.Xr fsck 8 ,
+.Xr init 8 ,
+.Xr rc 8 ,
+.Xr sync 8
+.Sh BUGS
+It is possible on some systems that a
+.Xr sync
+occurring simultaneously with a crash may cause
+file system damage. See
+.Xr fsck 8 .
+.Sh HISTORY
+An
+.Nm update
+command appeared in
+.At v6 .
diff --git a/usr.sbin/update/update.c b/usr.sbin/update/update.c
new file mode 100644
index 0000000..ae83ad1
--- /dev/null
+++ b/usr.sbin/update/update.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1987, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)update.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/time.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+main()
+{
+ struct itimerval value;
+ void mysync();
+
+ daemon(0, 0);
+
+ (void)signal(SIGALRM, mysync);
+
+ value.it_interval.tv_sec = 30;
+ value.it_interval.tv_usec = 0;
+ value.it_value = value.it_interval;
+ if (setitimer(ITIMER_REAL, &value, NULL)) {
+ perror("update: setitimer");
+ exit(1);
+ }
+ for (;;)
+ sigpause(sigblock(0L));
+ /* NOTREACHED */
+}
+
+void
+mysync()
+{
+ (void)sync();
+}
diff --git a/usr.sbin/vipw/Makefile b/usr.sbin/vipw/Makefile
new file mode 100644
index 0000000..03a187e
--- /dev/null
+++ b/usr.sbin/vipw/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= vipw
+SRCS= pw_util.c vipw.c
+MAN8= vipw.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/vipw/pw_util.c b/usr.sbin/vipw/pw_util.c
new file mode 100644
index 0000000..9873f74
--- /dev/null
+++ b/usr.sbin/vipw/pw_util.c
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+/*
+ * This file is used by all the "password" programs; vipw(8), chpass(1),
+ * and passwd(1).
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_util.h"
+
+extern char *tempname;
+
+void
+pw_init()
+{
+ struct rlimit rlim;
+
+ /* Unlimited resource limits. */
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ (void)setrlimit(RLIMIT_CPU, &rlim);
+ (void)setrlimit(RLIMIT_FSIZE, &rlim);
+ (void)setrlimit(RLIMIT_STACK, &rlim);
+ (void)setrlimit(RLIMIT_DATA, &rlim);
+ (void)setrlimit(RLIMIT_RSS, &rlim);
+
+ /* Don't drop core (not really necessary, but GP's). */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ (void)setrlimit(RLIMIT_CORE, &rlim);
+
+ /* Turn off signals. */
+ (void)signal(SIGALRM, SIG_IGN);
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGPIPE, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
+ (void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGTSTP, SIG_IGN);
+ (void)signal(SIGTTOU, SIG_IGN);
+
+ /* Create with exact permissions. */
+ (void)umask(0);
+}
+
+static int lockfd;
+
+int
+pw_lock()
+{
+ /*
+ * If the master password file doesn't exist, the system is hosed.
+ * Might as well try to build one. Set the close-on-exec bit so
+ * that users can't get at the encrypted passwords while editing.
+ * Open should allow flock'ing the file; see 4.4BSD. XXX
+ */
+ lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
+ if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
+ err(1, "%s", _PATH_MASTERPASSWD);
+ if (flock(lockfd, LOCK_EX|LOCK_NB))
+ errx(1, "the password db file is busy");
+ return (lockfd);
+}
+
+int
+pw_tmp()
+{
+ static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
+ int fd;
+ char *p;
+
+ if (p = strrchr(path, '/'))
+ ++p;
+ else
+ p = path;
+ strcpy(p, "pw.XXXXXX");
+ if ((fd = mkstemp(path)) == -1)
+ err(1, "%s", path);
+ tempname = path;
+ return (fd);
+}
+
+int
+pw_mkdb()
+{
+ int pstat;
+ pid_t pid;
+
+ warnx("rebuilding the database...");
+ (void)fflush(stderr);
+ if (!(pid = vfork())) {
+ execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
+ pw_error(_PATH_PWD_MKDB, 1, 1);
+ }
+ pid = waitpid(pid, &pstat, 0);
+ if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
+ return (0);
+ warnx("done");
+ return (1);
+}
+
+void
+pw_edit(notsetuid)
+ int notsetuid;
+{
+ int pstat;
+ pid_t pid;
+ char *p, *editor;
+
+ if (!(editor = getenv("EDITOR")))
+ editor = _PATH_VI;
+ if (p = strrchr(editor, '/'))
+ ++p;
+ else
+ p = editor;
+
+ if (!(pid = vfork())) {
+ if (notsetuid) {
+ (void)setgid(getgid());
+ (void)setuid(getuid());
+ }
+ execlp(editor, p, tempname, NULL);
+ _exit(1);
+ }
+ pid = waitpid(pid, (int *)&pstat, 0);
+ if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
+ pw_error(editor, 1, 1);
+}
+
+void
+pw_prompt()
+{
+ int c;
+
+ (void)printf("re-edit the password file? [y]: ");
+ (void)fflush(stdout);
+ c = getchar();
+ if (c != EOF && c != '\n')
+ while (getchar() != '\n');
+ if (c == 'n')
+ pw_error(NULL, 0, 0);
+}
+
+void
+pw_error(name, err, eval)
+ char *name;
+ int err, eval;
+{
+ if (err)
+ warn(name);
+
+ warnx("%s: unchanged", _PATH_MASTERPASSWD);
+ (void)unlink(tempname);
+ exit(eval);
+}
diff --git a/usr.sbin/vipw/pw_util.h b/usr.sbin/vipw/pw_util.h
new file mode 100644
index 0000000..9ea3672
--- /dev/null
+++ b/usr.sbin/vipw/pw_util.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pw_util.h 8.2 (Berkeley) 4/1/94
+ */
+
+void pw_edit __P((int));
+void pw_error __P((char *, int, int));
+void pw_init __P((void));
+int pw_lock __P((void));
+int pw_mkdb __P((void));
+void pw_prompt __P((void));
+int pw_tmp __P((void));
diff --git a/usr.sbin/vipw/vipw.8 b/usr.sbin/vipw/vipw.8
new file mode 100644
index 0000000..18ef5ed
--- /dev/null
+++ b/usr.sbin/vipw/vipw.8
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)vipw.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt VIPW 8
+.Os BSD 4
+.Sh NAME
+.Nm vipw
+.Nd edit the password file
+.Sh SYNOPSIS
+.Nm vipw
+.Sh DESCRIPTION
+.Nm Vipw
+edits the password file after setting the appropriate locks,
+and does any necessary processing after the password file is unlocked.
+If the password file is already locked for editing by another user,
+.Nm vipw
+will ask you
+to try again later. The default editor for
+.Nm vipw
+is
+.Xr vi 1 .
+.Pp
+.Nm Vipw
+performs a number of consistency checks on the password entries,
+and will not allow a password file with a
+.Dq mangled
+entry to be
+installed.
+If
+.Nm vipw
+rejects the new password file, the user is prompted to re-enter
+the edit session.
+.Pp
+Once the information has been verified,
+.Nm vipw
+uses
+.Xr pwd_mkdb 8
+to update the user database. This is run in the background, and,
+at very large sites could take several minutes. Until this update
+is completed, the password file is unavailable for other updates
+and the new information is not available to programs.
+.Sh ENVIRONMENT
+If the following environment variable exists it will be utilized by
+.Nm vipw :
+.Bl -tag -width EDITOR
+.It Ev EDITOR
+The editor specified by the string
+.Ev EDITOR
+will be invoked instead of the default editor
+.Xr vi 1 .
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr passwd 1 ,
+.Xr passwd 5 ,
+.Xr adduser 8 ,
+.Xr pwd_mkdb 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/vipw/vipw.c b/usr.sbin/vipw/vipw.c
new file mode 100644
index 0000000..c671623
--- /dev/null
+++ b/usr.sbin/vipw/vipw.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)vipw.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_util.h"
+
+char *tempname;
+
+void copyfile __P((int, int));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int pfd, tfd;
+ struct stat begin, end;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ usage();
+
+ pw_init();
+ pfd = pw_lock();
+ tfd = pw_tmp();
+ copyfile(pfd, tfd);
+ (void)close(tfd);
+
+ for (;;) {
+ if (stat(tempname, &begin))
+ pw_error(tempname, 1, 1);
+ pw_edit(0);
+ if (stat(tempname, &end))
+ pw_error(tempname, 1, 1);
+ if (begin.st_mtime == end.st_mtime) {
+ warnx("no changes made");
+ pw_error((char *)NULL, 0, 0);
+ }
+ if (pw_mkdb())
+ break;
+ pw_prompt();
+ }
+ exit(0);
+}
+
+void
+copyfile(from, to)
+ int from, to;
+{
+ int nr, nw, off;
+ char buf[8*1024];
+
+ while ((nr = read(from, buf, sizeof(buf))) > 0)
+ for (off = 0; off < nr; nr -= nw, off += nw)
+ if ((nw = write(to, buf + off, nr)) < 0)
+ pw_error(tempname, 1, 1);
+ if (nr < 0)
+ pw_error(_PATH_MASTERPASSWD, 1, 1);
+}
+
+void
+usage()
+{
+
+ (void)fprintf(stderr, "usage: vipw\n");
+ exit(1);
+}
OpenPOWER on IntegriCloud