Subject: seteuid(2), hk(4) & xp(4), sethostname(2) (#397 3 of 3)
Index:	sys,lib,man/many 2.11BSD

Description:
	1) seteuid,setegid(2) do not exist (no 'saved ids').

	2) hk(4) doesn't implement disklabels.

	3) xp(4) can put a crash dump on a non-swap partition.

	4) gethostname(2) and sethostname(2) dupliate _sysctl(2) functionality.

Repeat-By:
	1) The saved uid (gid) capability does not exist.  This is new in
	   4.4BSD and has not previously been ported.  In 4.2/3BSD 'setreuid'
	   (gid) were used (imperfectly) to allow a setuid (gid) program to
	   switch back and forth between uids.  With 4.4BSD setreuid was dropped
	   and 'saved ids' were implemented with seteuid/gid.

	2) Observation.  Alternatively give "hk(0,0)" to the standalone 
	   disklabel program and be rewarded with an error.

	3) The check for the partition type when writing the memory image 
	   of a crash dump to a 'xp' drive was made before the pointer to the
	   partition information was calculated.  This could have allowed a
	   crash dump to be written to a file system by mistake.

	4) Note that 'sysctl' has the ability to set and get the hostname.  
	   There is no longer any need for separate system calls.  A previous
	   update placed the 'gethostid' and 'sethostid' with their sysctl
	   counterparts, now it is time to do the same for set/gethosthame

Fix:
	This is #397 and is part 3 of 3.  Make sure you have all 3 parts
	before proceeding.  

	When all three parts have been collected cut where indicated in each 
	and save to tmp files (the instructions assume /tmp/395, /tmp/396 and
	/tmp/397 respectively).

	The instructions are in part 1 (#395).

============================cut here================================
*** /usr/src/sys/h/acct.h.old	Fri Feb 14 22:04:56 1997
--- /usr/src/sys/h/acct.h	Fri Nov 28 16:23:16 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)acct.h	2.0	(2.11BSD) 1997/2/14
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)acct.h	2.1	(2.11BSD) 1997/11/28
   */
  
  /*
***************
*** 34,39 ****
--- 34,40 ----
  #define	ACOMPAT	0004		/* used compatibility mode */
  #define	ACORE	0010		/* dumped core */
  #define	AXSIG	0020		/* killed by a signal */
+ #define	ASUGID	0040		/* setuser/group id privileges used */
  
  /*
   * 1/AHZ is the granularity of the data encoded in the various
*** /usr/src/sys/h/user.h.old	Tue Sep  2 19:00:10 1997
--- /usr/src/sys/h/user.h	Fri Nov 28 16:21:56 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)user.h	1.4 (2.11BSD) 1997/8/28
   */
  
  #ifdef KERNEL
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)user.h	1.5 (2.11BSD) 1997/11/28
   */
  
  #ifdef KERNEL
***************
*** 66,73 ****
  
  /* 1.1 - processes and protection */
  	uid_t	u_uid;			/* effective user id */
  	uid_t	u_ruid;			/* real user id */
! 	gid_t	u_gid;			/* effective group id */
  	gid_t	u_rgid;			/* real group id */
  	gid_t	u_groups[NGROUPS];	/* groups, 0 terminated */
  
--- 66,74 ----
  
  /* 1.1 - processes and protection */
  	uid_t	u_uid;			/* effective user id */
+ 	uid_t	u_svuid;		/* saved user id */
  	uid_t	u_ruid;			/* real user id */
! 	gid_t	u_svgid;		/* saved group id */
  	gid_t	u_rgid;			/* real group id */
  	gid_t	u_groups[NGROUPS];	/* groups, 0 terminated */
  
***************
*** 138,144 ****
  		ino_t nc_inumber;	/* inum of cached directory */
  		dev_t nc_dev;		/* dev of cached directory */
  	} u_ncache;
! 	char	u_login[MAXLOGNAME];	/* future use (setlogin/getlogin) */
  	short	u_stack[1];		/* kernel stack per user
  					 * extends from u + USIZE*64
  					 * backward not to reach here
--- 139,146 ----
  		ino_t nc_inumber;	/* inum of cached directory */
  		dev_t nc_dev;		/* dev of cached directory */
  	} u_ncache;
! 	short	u_xxxx[2];		/* spare */
! 	char	u_login[MAXLOGNAME];	/* setlogin/getlogin */
  	short	u_stack[1];		/* kernel stack per user
  					 * extends from u + USIZE*64
  					 * backward not to reach here
*** /usr/src/sys/pdp/conf.c.old	Sat May 31 14:38:53 1997
--- /usr/src/sys/pdp/conf.c	Wed Nov 12 20:29:41 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)conf.c	3.1 (2.11BSD GTE) 1997/5/31
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)conf.c	3.2 (2.11BSD GTE) 1997/11/12
   */
  
  #include "param.h"
***************
*** 45,53 ****
  
  #include "hk.h"
  #if NHK > 0
! int	hkopen(), hkstrategy(), hkroot();
  daddr_t	hksize();
- #define	hkclose		nulldev
  #else
  #define	hkopen		nodev
  #define	hkclose		nodev
--- 45,52 ----
  
  #include "hk.h"
  #if NHK > 0
! int	hkopen(), hkstrategy(), hkroot(), hkclose();
  daddr_t	hksize();
  #else
  #define	hkopen		nodev
  #define	hkclose		nodev
*** /usr/src/sys/pdpstand/conf.c.old	Fri Mar  8 21:24:28 1996
--- /usr/src/sys/pdpstand/conf.c	Fri Nov  7 19:49:28 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)conf.c	2.6 (2.11BSD) 1996/3/8
   */
  
  #include "../h/param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)conf.c	2.7 (2.11BSD) 1997/11/7
   */
  
  #include "../h/param.h"
***************
*** 15,21 ****
  extern	int	brstrategy(), bropen();
  extern	int	rkstrategy(), rkopen();
  extern  int	rxstrategy(), rxopen();
! extern	int	hkstrategy(), hkopen();
  extern	int	rlstrategy(), rlopen(), rllabel();
  extern	int	sistrategy(), siopen();
  extern	int	rastrategy(), raopen(), raclose(), ralabel();
--- 15,21 ----
  extern	int	brstrategy(), bropen();
  extern	int	rkstrategy(), rkopen();
  extern  int	rxstrategy(), rxopen();
! extern	int	hkstrategy(), hkopen(), hklabel();
  extern	int	rlstrategy(), rlopen(), rllabel();
  extern	int	sistrategy(), siopen();
  extern	int	rastrategy(), raopen(), raclose(), ralabel();
***************
*** 42,48 ****
  	"ram",	nullsys,	nullsys,	nullsys,	0,     /* 3 */
  	nullsys, nullsys,
  	"hk",	hkstrategy,	hkopen,		nullsys,	HKcsr, /* 4 */
! 	nullsys, nullsys,
  	"ra",	rastrategy,	raopen,		raclose,	RAcsr, /* 5 */
  	ralabel, nullsys,
  	"rk",	rkstrategy,	rkopen,		nullsys,	RKcsr, /* 6 */
--- 42,48 ----
  	"ram",	nullsys,	nullsys,	nullsys,	0,     /* 3 */
  	nullsys, nullsys,
  	"hk",	hkstrategy,	hkopen,		nullsys,	HKcsr, /* 4 */
! 	hklabel, nullsys,
  	"ra",	rastrategy,	raopen,		raclose,	RAcsr, /* 5 */
  	ralabel, nullsys,
  	"rk",	rkstrategy,	rkopen,		nullsys,	RKcsr, /* 6 */
*** /usr/src/sys/pdpstand/hk.c.old	Fri Mar  8 16:33:15 1996
--- /usr/src/sys/pdpstand/hk.c	Fri Nov  7 20:04:14 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	2.2 (2.11BSD) 1996/3/8
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	2.3 (2.11BSD) 1997/11/7
   */
  
  /*
***************
*** 17,22 ****
--- 17,24 ----
  #define	NHK	2
  #define	NSECT	22
  #define	NTRAC	3
+ #define	N7CYL	815
+ #define	N6CYL	411
  
  	struct	hkdevice *HKcsr[NHK + 1] =
  		{
***************
*** 25,69 ****
  		(struct hkdevice *)-1
  		};
  
! int hk_drvtyp[NHK][8];
! char hk_mntflg[NHK][8];
  
  hkstrategy(io, func)
  	register struct iob *io;
! {
! 	register unit, com;
  	register struct hkdevice *hkaddr;
  	daddr_t bn;
  	int sn, cn, tn, ctlr, bae, lo16;
  
  	unit = io->i_unit;
  	ctlr = io->i_ctlr;
  	hkaddr = HKcsr[ctlr];
! 	if (hk_mntflg[ctlr][unit] != '1') {
! 		hk_drvtyp[ctlr][unit] = 0;
! 		hkaddr->hkcs2 = unit;
! 		hkaddr->hkcs1 = HK_SELECT|HK_GO;
! 		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
! 			continue;
! 		if (hkaddr->hkcs1 & HK_CERR && hkaddr->hker & HKER_DTYE) {
! 			hk_drvtyp[ctlr][unit] = 02000;
! 		}
! 		hk_mntflg[ctlr][unit] = '1';
! 	}
  	bn = io->i_bn;
  	hkaddr->hkcs2 = HKCS2_SCLR;
  	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  	hkaddr->hkcs2 = unit;
! 	hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_SELECT|HK_GO;
  	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if ((hkaddr->hkds & HKDS_VV) == 0) {
! 		hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_PACK|HK_GO;
! 		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  			continue;
! 	}
  	cn = bn/(NSECT*NTRAC);
  	sn = bn%(NSECT*NTRAC);
  	tn = sn/NSECT;
--- 27,72 ----
  		(struct hkdevice *)-1
  		};
  
! 	u_char	hk_mntflg[NHK];		/* Type known bitmap, 0 = unknown */
! 	u_char	hk_drvtyp[NHK];		/* Drive type.  0 = RK06, 1 = RK07 */
  
  hkstrategy(io, func)
  	register struct iob *io;
! 	{
! 	int unit, com;
  	register struct hkdevice *hkaddr;
  	daddr_t bn;
+ 	int	hktyp, drvbit, i;
  	int sn, cn, tn, ctlr, bae, lo16;
  
+ 	i = deveovchk(io);
+ 	if	(i < 0)
+ 		return(i);
  	unit = io->i_unit;
  	ctlr = io->i_ctlr;
  	hkaddr = HKcsr[ctlr];
! 
! 	drvbit = 1 << unit;
! 	if	(hk_drvtyp[ctlr] & drvbit)
! 		hktyp = 02000;
! 	else
! 		hktyp = 0;
! 
  	bn = io->i_bn;
  	hkaddr->hkcs2 = HKCS2_SCLR;
  	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  	hkaddr->hkcs2 = unit;
! 	hkaddr->hkcs1 = hktyp|HK_SELECT|HK_GO;
  	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if	((hkaddr->hkds & HKDS_VV) == 0)
! 		{
! 		hkaddr->hkcs1 = hktyp|HK_PACK|HK_GO;
! 		while	((hkaddr->hkcs1 & HK_CRDY) == 0)
  			continue;
! 		}
  	cn = bn/(NSECT*NTRAC);
  	sn = bn%(NSECT*NTRAC);
  	tn = sn/NSECT;
***************
*** 74,99 ****
  	hkaddr->hkda = (tn<<8) | sn;
  	hkaddr->hkba = (caddr_t)lo16;
  	hkaddr->hkwc = -(io->i_cc>>1);
! 	com = hk_drvtyp[ctlr][unit]|(bae << 8) | HK_GO;
! 	if (func == READ)
  		com |= HK_READ;
  	else if (func == WRITE)
  		com |= HK_WRITE;
  	hkaddr->hkcs1 = com;
  
! 	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if (hkaddr->hkcs1 & HK_CERR) {
  		printf("%s err: cy=%d tr=%d sc=%d cs2=%d er=%o\n",
  			devname(io), cn, tn, sn, hkaddr->hkcs2, hkaddr->hker);
  		return(-1);
! 	}
  	return(io->i_cc);
! }
  
  hkopen(io)
! 	struct iob *io;
! {
! 	return(genopen(NHK, io));
! }
--- 77,152 ----
  	hkaddr->hkda = (tn<<8) | sn;
  	hkaddr->hkba = (caddr_t)lo16;
  	hkaddr->hkwc = -(io->i_cc>>1);
! 	com = hktyp|(bae << 8) | HK_GO;
! 	if	(func == READ)
  		com |= HK_READ;
  	else if (func == WRITE)
  		com |= HK_WRITE;
  	hkaddr->hkcs1 = com;
  
! 	while	((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if	(hkaddr->hkcs1 & HK_CERR)
! 		{
  		printf("%s err: cy=%d tr=%d sc=%d cs2=%d er=%o\n",
  			devname(io), cn, tn, sn, hkaddr->hkcs2, hkaddr->hker);
  		return(-1);
! 		}
  	return(io->i_cc);
! 	}
  
  hkopen(io)
! 	register struct iob *io;
! 	{
! 	register struct hkdevice *hkaddr;
! 	int	drvbit;
! 	int	unit, ctlr;
! 
! 	drvbit = 1 << io->i_unit;
! 
! 	if	(genopen(NHK, io) < 0)
! 		return(-1);
! 
! 	if	((hk_mntflg[ctlr] & drvbit) == 0)
! 		{
! 		hkaddr = HKcsr[ctlr];
! 		hkaddr->hkcs2 = unit;
! 		hkaddr->hkcs1 = HK_SELECT|HK_GO;
! 		while	((hkaddr->hkcs1 & HK_CRDY) == 0)
! 			continue;
! 		if	(hkaddr->hkcs1 & HK_CERR && hkaddr->hker & HKER_DTYE)
! 			hk_drvtyp[ctlr] |= drvbit;
! 		else
! 			hk_drvtyp[ctlr] &= ~drvbit;
! 		hk_mntflg[ctlr] |= drvbit;
! 		}
! 	if	(devlabel(io, READLABEL) < 0)
! 		return(-1);
! 	io->i_boff = io->i_label.d_partitions[io->i_part].p_offset;
! 	return(0);
! 	}
! 
! /*
!  * This generates a default label.  'hkopen' has already been called and
!  * determined the drive type.
! */
! 
! hklabel(io)
! 	register struct iob *io;
! 	{
! 	register struct disklabel *lp = &io->i_label;
! 	u_short ncyl, nblks;
! 
! 	if	(hk_drvtyp[io->i_ctlr] && (1 << io->i_unit))
! 		ncyl = N7CYL;
! 	else
! 		ncyl = N6CYL;
! 	lp->d_partitions[0].p_size = lp->d_secperunit = NSECT * NTRAC * ncyl;
! 	lp->d_type = DTYPE_DEC;
! 	lp->d_nsectors = NSECT;
! 	lp->d_ntracks = NTRAC;
! 	lp->d_secpercyl = NSECT * NTRAC;
! 	lp->d_ncylinders = ncyl;
! 	return(0);
! 	}
*** /usr/src/sys/pdpstand/rl.c.old	Fri Mar  8 16:36:18 1996
--- /usr/src/sys/pdpstand/rl.c	Fri Nov  7 20:06:30 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)rl.c	2.5 (2.11BSD) 1996/3/8
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)rl.c	2.6 (2.11BSD) 1997/11/7
   */
  
  /*
***************
*** 134,141 ****
  rlopen(io)
  	register struct iob *io;
  	{
- 	register struct	disklabel *lp = &io->i_label;
- 	register int part = io->i_part;
  
  	if	(io->i_unit > 3)
  		return(-1);
--- 134,139 ----
***************
*** 144,150 ****
  	rlgsts(io);		/* get status and head position */
  	if	(devlabel(io, READLABEL) < 0)
  		return(-1);
! 	io->i_boff = lp->d_partitions[part].p_offset;
  	return(0);
  	}
  
--- 142,148 ----
  	rlgsts(io);		/* get status and head position */
  	if	(devlabel(io, READLABEL) < 0)
  		return(-1);
! 	io->i_boff = io->i_label.d_partitions[io->i_part].p_offset;
  	return(0);
  	}
  
***************
*** 221,227 ****
  	lp->d_nsectors = 20;		/* sectors per track */
  	lp->d_ntracks = 2;		/* tracks per cylinder */
  	lp->d_secpercyl = 40;		/* sectors per cylinder */
! 	lp->d_ncylinders = nblks / (lp->d_nsectors * lp->d_ntracks);
  	lp->d_secperunit = nblks;
  	return(0);
  	}
--- 219,225 ----
  	lp->d_nsectors = 20;		/* sectors per track */
  	lp->d_ntracks = 2;		/* tracks per cylinder */
  	lp->d_secpercyl = 40;		/* sectors per cylinder */
! 	lp->d_ncylinders = nblks / (20 * 2);
  	lp->d_secperunit = nblks;
  	return(0);
  	}
*** /usr/src/sys/pdpuba/hk.c.old	Thu Apr 13 22:33:02 1995
--- /usr/src/sys/pdpuba/hk.c	Wed Nov 12 21:07:59 1997
***************
*** 3,14 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	2.1 (2.11BSD GTE) 1995/04/13
   */
  
  /*
   * RK611/RK0[67] disk driver
   *
   * This driver mimics the 4.1bsd rk driver.
   * It does overlapped seeks, ECC, and bad block handling.
   * 	salkind@nyu
--- 3,17 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	2.2 (2.11BSD GTE) 1997/11/11
   */
  
  /*
   * RK611/RK0[67] disk driver
   *
+  * Heavily modified for disklabel support.  Still only supports 1 controller
+  * (but who'd have more than one of these on a system anyhow?) - 1997/11/11 sms
+  *
   * This driver mimics the 4.1bsd rk driver.
   * It does overlapped seeks, ECC, and bad block handling.
   * 	salkind@nyu
***************
*** 15,23 ****
   *
   * dkunit() takes a 'dev_t' now instead of 'buf *'.  1995/04/13 - sms
   *
-  * Modified to correctly handle 22 bit addressing available on DILOG
-  * DQ615 controller. 05/31/90 -- tymann@oswego.edu
-  *
   * Removed ifdefs on both Q22 and UNIBUS_MAP, substituting a runtime
   * test for presence of a Unibus Map.  Reworked the partition logic,
   * the 'e' partiton no longer overlaps the 'a'+'b' partitions - a separate
--- 18,23 ----
***************
*** 24,29 ****
--- 24,33 ----
   * 'b' partition is now present.  Old root filesystems can still be used
   * because the size is the same, but user data will have to be saved and
   * then reloaded.  12/28/92 -- sms@wlv.iipo.gtegsc.com
+  *
+  * Modified to correctly handle 22 bit addressing available on DILOG
+  * DQ615 controller. 05/31/90 -- tymann@oswego.edu
+  *
   */
  
  #include "hk.h"
***************
*** 31,36 ****
--- 35,41 ----
  #include "param.h"
  #include "systm.h"
  #include "buf.h"
+ #include "machine/seg.h"
  #include "conf.h"
  #include "user.h"
  #include "map.h"
***************
*** 38,43 ****
--- 43,50 ----
  #include "hkreg.h"
  #include "dkbad.h"
  #include "dk.h"
+ #include "stat.h"
+ #include "file.h"
  #include "disklabel.h"
  #include "disk.h"
  #include "syslog.h"
***************
*** 49,205 ****
  #define	HK_NSPC		(HK_NTRAC*HK_NSECT)
  
  struct	hkdevice *HKADDR;
- struct size {
- 	daddr_t	nblocks;
- 	int	cyloff;
- } hk6_sizes[8] =
- 	{
- 	8316,	0,	/* a: cyl    0 - 125 */
- 	8316,	90,	/* b: cyl  126 - 251 */
- 	27126,	0,	/* c: cyl    0 - 410, whole RK06 */
- 	0,	0,	/* d: Not Defined */
- 	0,	0,	/* e: Not Defined */
- 	0,	0,	/* f: Not Defined */
- 	10428,	252,	/* g: cyl  252 - 409 */
- 	27126,	0,	/* h: cyl   0 - 409, whole RK06 less 1 track */
- 	},
- hk7_sizes[8] =
- 	{
- 	8316,	0,	/* a: cyl   0 -  125 */
- 	8316,	126,	/* b: cyl  126 - 251 */
- 	53790,	0,	/* c: cyl   0 - 814, whole RK07 */
- 	0,	0,	/* d: Not Defined */
- 	0,	0,	/* e: Not Defined */
- 	0,	0,	/* f: Not Defined */
- 	37092,	0,	/* g: cyl   252 - 813 */
- 	53724,	0	/* h: cyl   0 - 813, whole RK07 less 1 track */
- };
  
  /* Can be u_char because all are less than 0377 */
  u_char	hk_offset[] =
! {
  	HKAS_P400,	HKAS_M400,	HKAS_P400,	HKAS_M400,
  	HKAS_P800,	HKAS_M800,	HKAS_P800,	HKAS_M800,
  	HKAS_P1200,	HKAS_M1200,	HKAS_P1200,	HKAS_M1200,
  	0,		0,		0,		0,
! };
  
! int	hk_type[NHK];
! int	hk_cyl[NHK];
! struct	size *hk_sizes[NHK];
! char	hk_pack[NHK];
  
! struct hk_softc {
  	int	sc_softas;
  	int	sc_recal;
! } hk;
  
! struct	buf	hktab;
! struct	buf	hkutab[NHK];
  #ifdef BADSECT
! struct	dkbad	hkbad[NHK];
! struct	buf	bhkbuf[NHK];
  #endif
  
  #ifdef UCB_METER
! static	int		hk_dkn = -1;	/* number for iostat */
  #endif
  
  #define	hkwait(hkaddr)		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  #define	hkncyl(unit)		(hk_type[unit] ? NHK7CYL : NHK6CYL)
- #define	hkunit(dev)		(((dev) >> 3) & 07)
  
  void
  hkroot()
! {
  	hkattach((struct hkdevice *)0177440, 0);
! }
  
  hkattach(addr, unit)
  struct hkdevice *addr;
! {
  #ifdef UCB_METER
! 	if (hk_dkn < 0) {
  		dk_alloc(&hk_dkn, NHK+1, "hk", 60L * (long)HK_NSECT * 256L);
! 		if (hk_dkn >= 0)
  			dk_wps[hk_dkn+NHK] = 0L;
! 	}
  #endif
  	if (unit != 0)
  		return(0);
  	HKADDR = addr;
  	return(1);
! }
  
! hkopen(dev, flag)
! 	dev_t dev;
! 	int flag;
! {
! 	register int unit = hkunit(dev);
  	register struct hkdevice *hkaddr = HKADDR;
  
! 	if (unit >= NHK || !HKADDR)
! 		return (ENXIO);
  
! 	hk_type[unit] = 0;
! 	hkaddr->hkcs1 = HK_CCLR;
! 	hkaddr->hkcs2 = unit;
! 	hkaddr->hkcs1 = HK_DCLR | HK_GO;
! 	hkwait(hkaddr);
! 	if((hkaddr->hkcs2&HKCS2_NED) || (hkaddr->hkds&HKDS_SVAL) == 0) {
  		hkaddr->hkcs1 = HK_CCLR;
  		hkwait(hkaddr);
  		return(ENXIO);
! 	}
! 	if((hkaddr->hkcs1&HK_CERR) && (hkaddr->hker&HKER_DTYE)) {
! 		hk_type[unit] = HK_CDT;
! 		hkaddr->hkcs1 = HK_CCLR;
! 		hkwait(hkaddr);
! 		hk_sizes[unit] = hk7_sizes;
! 	}
  	else
! 		hk_sizes[unit] = hk6_sizes;
! 	hk_cyl[unit] = -1;
  	return(0);
! }
  
  hkstrategy(bp)
  register struct buf *bp;
  {
  	register struct buf *dp;
! 	register unit;
! 	int s, part;
! 	long bn;
! 	long sz;
! 	struct size *szp;
  
! 	unit = dkunit(bp->b_dev);
! 	part = bp->b_dev & 7;
! 	if (unit >= NHK || !HKADDR  || !(szp = hk_sizes[unit])) {
  		bp->b_error = ENXIO;
  		goto bad;
! 	}
! 	sz = (bp->b_bcount + (NBPG-1)) >> PGSHIFT;
! 	if (bp->b_blkno < 0 || (bn = bp->b_blkno)+sz > szp[part].nblocks) {
! 		bp->b_error = EINVAL;
  		goto bad;
! 	}
! 	bp->b_cylin = bn / HK_NSPC + szp[part].cyloff;
  	mapalloc(bp);
! 	dp = &hkutab[unit];
  	s = splbio();
  	disksort(dp, bp);
! 	if (dp->b_active == 0) {
! 		hkustart(unit);
! 		if (hktab.b_active == 0)
  			hkstart();
! 	}
  	splx(s);
  	return;
  bad:
  	bp->b_flags |= B_ERROR;
  	iodone(bp);
! }
  
  hkustart(unit)
  	int unit;
--- 56,397 ----
  #define	HK_NSPC		(HK_NTRAC*HK_NSECT)
  
  struct	hkdevice *HKADDR;
  
+ 	daddr_t	hksize();
+ 	void	hkdfltlbl();
+ 	int	hkstrategy();
+ 
  /* Can be u_char because all are less than 0377 */
  u_char	hk_offset[] =
! 	{
  	HKAS_P400,	HKAS_M400,	HKAS_P400,	HKAS_M400,
  	HKAS_P800,	HKAS_M800,	HKAS_P800,	HKAS_M800,
  	HKAS_P1200,	HKAS_M1200,	HKAS_P1200,	HKAS_M1200,
  	0,		0,		0,		0,
! 	};
  
! 	int	hk_type[NHK];
! 	int	hk_cyl[NHK];
  
! struct hk_softc
! 	{
  	int	sc_softas;
  	int	sc_recal;
! 	} hk;
  
! 	struct	buf	hktab;
! 	struct	buf	hkutab[NHK];
! 	struct	dkdevice hk_dk[NHK];
! 
  #ifdef BADSECT
! 	struct	dkbad	hkbad[NHK];
! 	struct	buf	bhkbuf[NHK];
  #endif
  
  #ifdef UCB_METER
! 	static	int		hk_dkn = -1;	/* number for iostat */
  #endif
  
  #define	hkwait(hkaddr)		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  #define	hkncyl(unit)		(hk_type[unit] ? NHK7CYL : NHK6CYL)
  
  void
  hkroot()
! 	{
  	hkattach((struct hkdevice *)0177440, 0);
! 	}
  
  hkattach(addr, unit)
  struct hkdevice *addr;
! 	{
  #ifdef UCB_METER
! 	if	(hk_dkn < 0)
! 		{
  		dk_alloc(&hk_dkn, NHK+1, "hk", 60L * (long)HK_NSECT * 256L);
! 		if	(hk_dkn >= 0)
  			dk_wps[hk_dkn+NHK] = 0L;
! 		}
  #endif
  	if (unit != 0)
  		return(0);
  	HKADDR = addr;
  	return(1);
! 	}
  
! hkopen(dev, flag, mode)
! 	dev_t	dev;
! 	int	flag;
! 	int	mode;
! 	{
! 	register int unit = dkunit(dev);
  	register struct hkdevice *hkaddr = HKADDR;
+ 	register struct	dkdevice *disk;
+ 	int	i, mask;
  
! 	if	(unit >= NHK || !HKADDR)
! 		return(ENXIO);
! 	disk = &hk_dk[unit];
  
! 	if	((disk->dk_flags & DKF_ALIVE) == 0)
! 		{
! 		hk_type[unit] = 0;
  		hkaddr->hkcs1 = HK_CCLR;
+ 		hkaddr->hkcs2 = unit;
+ 		hkaddr->hkcs1 = HK_DCLR | HK_GO;
  		hkwait(hkaddr);
+ 		if	(hkaddr->hkcs2&HKCS2_NED || !(hkaddr->hkds&HKDS_SVAL))
+ 			{
+ 			hkaddr->hkcs1 = HK_CCLR;
+ 			hkwait(hkaddr);
+ 			return(ENXIO);
+ 			}
+ 		disk->dk_flags |= DKF_ALIVE;
+ 		if	((hkaddr->hkcs1&HK_CERR) && (hkaddr->hker&HKER_DTYE))
+ 			{
+ 			hk_type[unit] = HK_CDT;
+ 			hkaddr->hkcs1 = HK_CCLR;
+ 			hkwait(hkaddr);
+ 			}
+ 		}
+ /*
+  * The drive has responded to a probe (is alive).  Now we read the
+  * label.  Allocate an external label structure if one has not already
+  * been assigned to this drive.  First wait for any pending opens/closes
+  * to complete.
+ */
+ 	while	(disk->dk_flags & (DKF_OPENING | DKF_CLOSING))
+ 		sleep(disk, PRIBIO);
+ 
+ /*
+  * Next if an external label buffer has not already been allocated do so now.
+  * This "can not fail" because if the initial pool of label buffers has
+  * been exhausted the allocation takes place from main memory.  The return
+  * value is the 'click' address to be used when mapping in the label.
+ */
+ 
+ 	if	(disk->dk_label == 0)
+ 		disk->dk_label = disklabelalloc();
+ 
+ /*
+  * On first open get label and partition info.  We may block reading the
+  * label so be careful to stop any other opens.
+ */
+ 	if	(disk->dk_openmask == 0)
+ 		{
+ 		disk->dk_flags |= DKF_OPENING;
+ 		hkgetinfo(disk, dev);
+ 		disk->dk_flags &= ~DKF_OPENING;
+ 		wakeup(disk);
+ 		hk_cyl[unit] = -1;
+ 		}
+ /*
+  * Need to make sure the partition is not out of bounds.  This requires
+  * mapping in the external label.  This only happens when a partition
+  * is opened (at mount time) and isn't an efficiency problem.
+ */
+ 	mapseg5(disk->dk_label, LABELDESC);
+ 	i = ((struct disklabel *)SEG5)->d_npartitions;
+ 	normalseg5();
+ 	if	(dkpart(dev) >= i)
  		return(ENXIO);
! 	mask = 1 << dkpart(dev);
! 	dkoverlapchk(disk->dk_openmask, dev, disk->dk_label, "hk");
! 	if	(mode == S_IFCHR)
! 		disk->dk_copenmask |= mask;
! 	else if (mode == S_IFBLK)
! 		disk->dk_bopenmask |= mask;
  	else
! 		return(EINVAL);
! 	disk->dk_openmask |= mask;
  	return(0);
! 	}
! 
! /*
!  * Disk drivers now have to have close entry points in order to keep
!  * track of what partitions are still active on a drive.
! */
! hkclose(dev, flag, mode)
! register dev_t  dev;
! 	int     flag, mode;
! 	{
! 	int     s, drive = dkunit(dev);
! 	register int    mask;
! 	register struct dkdevice *disk;
  
+ 	disk = &hk_dk[drive];
+ 	mask = 1 << dkpart(dev);
+ 	if	(mode == S_IFCHR)
+ 		disk->dk_copenmask &= ~mask;
+ 	else if (mode == S_IFBLK)
+ 		disk->dk_bopenmask &= ~mask;
+ 	else
+ 		return(EINVAL);
+ 	disk->dk_openmask = disk->dk_bopenmask | disk->dk_copenmask;
+ 	if	(disk->dk_openmask == 0)
+ 		{
+ 		disk->dk_flags |= DKF_CLOSING;
+ 		s = splbio();
+ 		while   (hkutab[drive].b_actf)
+ 			{
+ 			disk->dk_flags |= DKF_WANTED;
+ 			sleep(&hkutab[drive], PRIBIO);
+ 			}
+ 		splx(s);
+ /*
+  * On last close of a drive we declare it not alive and offline to force a
+  * probe on the next open in order to handle diskpack changes.
+ */
+ 		disk->dk_flags &= 
+ 			~(DKF_CLOSING | DKF_WANTED | DKF_ALIVE | DKF_ONLINE);
+ 		wakeup(disk);
+ 		}
+ 	return(0);
+ 	}
+ 
+ /*
+  * This code moved here from hkgetinfo() because it is fairly large and used
+  * twice - once to initialize for reading the label and a second time if
+  * there is no valid label present on the drive and the default one must be
+  * used to span the drive.
+ */
+ 
+ void
+ hkdfltlbl(disk, lp, dev)
+ 	struct dkdevice *disk;
+ 	register struct disklabel *lp;
+ 	dev_t	dev;
+ 	{
+ 	register struct partition *pi = &lp->d_partitions[0];
+ 
+ 	bzero(lp, sizeof (*lp));
+         lp->d_type = DTYPE_DEC;
+ 	lp->d_secsize = 512;            /* XXX */
+ 	lp->d_nsectors = HK_NSECT;
+ 	lp->d_ntracks = HK_NTRAC;
+ 	lp->d_secpercyl = HK_NSPC;
+ 	lp->d_npartitions = 1;          /* 'a' */
+ 	lp->d_ncylinders = hkncyl(dkunit(dev));
+ 	pi->p_size = lp->d_ncylinders * lp->d_secpercyl;     /* entire volume */
+ 	pi->p_fstype = FS_V71K;
+ 	pi->p_frag = 1;
+ 	pi->p_fsize = 1024;
+ /*
+  * Put where hkstrategy() will look.
+ */
+ 	bcopy(pi, disk->dk_parts, sizeof (lp->d_partitions));
+ 	}
+ 
+ /*
+  * Read disklabel.  It is tempting to generalize this routine so that
+  * all disk drivers could share it.  However by the time all of the
+  * necessary parameters are setup and passed the savings vanish.  Also,
+  * each driver has a different method of calculating the number of blocks
+  * to use if one large partition must cover the disk.
+  *
+  * This routine used to always return success and callers carefully checked
+  * the return status.  Silly.  This routine will fake a label (a single
+  * partition spanning the drive) if necessary but will never return an error.
+  *
+  * It is the caller's responsibility to check the validity of partition
+  * numbers, etc.
+ */
+ 
+ void
+ hkgetinfo(disk, dev)
+ register struct dkdevice *disk;
+ 	dev_t   dev;
+ 	{
+ 	struct  disklabel locallabel;
+ 	char    *msg;
+ 	register struct disklabel *lp = &locallabel;
+ /*
+  * NOTE: partition 0 ('a') is used to read the label.  Therefore 'a' must
+  * start at the beginning of the disk!  If there is no label or the label
+  * is corrupted then 'a' will span the entire disk
+ */
+ 	hkdfltlbl(disk, lp, dev);
+ 	msg = readdisklabel((dev & ~7) | 0, hkstrategy, lp);    /* 'a' */
+ 	if      (msg != 0)
+ 		{
+ 		log(LOG_NOTICE, "hk%da is entire disk: %s\n", dkunit(dev), msg);
+ 		hkdfltlbl(disk, lp, dev);
+ 		}
+ 	mapseg5(disk->dk_label, LABELDESC)
+ 	bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel));
+ 	normalseg5();
+ 	bcopy(lp->d_partitions, disk->dk_parts, sizeof (lp->d_partitions));
+ 	return;
+ 	}
+ 
  hkstrategy(bp)
  register struct buf *bp;
  {
  	register struct buf *dp;
! 	int s, drive, part;
! 	daddr_t sz;
! 	register struct dkdevice *disk;
! 	struct partition *pi;
  
! 	drive = dkunit(bp->b_dev);
! 	part = dkpart(bp->b_dev);
! 	disk = &hk_dk[drive];
! 
! 	if	(drive >= NHK || !HKADDR  || !(disk->dk_flags & DKF_ALIVE))
! 		{
  		bp->b_error = ENXIO;
  		goto bad;
! 		}
! 	pi = &disk->dk_parts[part];
! 
!         /* Valid block in device partition */
! 	sz = (bp->b_bcount + 511) >> 9;
! 	if      (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size)
! 		{
! 		sz = pi->p_size - bp->b_blkno;
! 		/* if exactly at end of disk, return an EOF */
! 		if      (sz == 0)
! 			{
! 			bp->b_resid = bp->b_bcount;
! 			goto done;
! 			}
! 		/* or truncate if part of it fits */
! 		if      (sz < 0)
! 			{
! 			bp->b_error = EINVAL;
! 			goto bad;
! 			}
! 		bp->b_bcount = dbtob(sz);       /* compute byte count */
! 		}
! /*
!  * Check for write to write-protected label area.  This does not include
!  * sector 0 which is the boot block.
! */
! 	if      (bp->b_blkno + pi->p_offset <= LABELSECTOR &&
! 		bp->b_blkno + pi->p_offset + sz > LABELSECTOR &&
! 		!(bp->b_flags & B_READ) && !(disk->dk_flags & DKF_WLABEL))
! 		{
! 		bp->b_error = EROFS;
  		goto bad;
! 		}
! 
! 	bp->b_cylin = bp->b_blkno / HK_NSPC;
  	mapalloc(bp);
! 	dp = &hkutab[drive];
  	s = splbio();
  	disksort(dp, bp);
! 	if	(dp->b_active == 0)
! 		{
! 		hkustart(drive);
! 		if	(hktab.b_active == 0)
  			hkstart();
! 		}
  	splx(s);
  	return;
  bad:
  	bp->b_flags |= B_ERROR;
+ done:
  	iodone(bp);
! 	}
  
  hkustart(unit)
  	int unit;
***************
*** 206,211 ****
--- 398,404 ----
  {
  	register struct hkdevice *hkaddr = HKADDR;
  	register struct buf *bp, *dp;
+ 	struct dkdevice *disk;
  	int didie = 0;
  
  #ifdef UCB_METER
***************
*** 223,234 ****
  	hkwait(hkaddr);
  
  	dp = &hkutab[unit];
  	if ((bp = dp->b_actf) == NULL)
  		return(0);
  	if (dp->b_active)
  		goto done;
  	dp->b_active = 1;
! 	if ((hkaddr->hkds & HKDS_VV) == 0 || hk_pack[unit] == 0) {
  		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
  #ifdef BADSECT
  		struct buf *bbp = &bhkbuf[unit];
--- 416,429 ----
  	hkwait(hkaddr);
  
  	dp = &hkutab[unit];
+ 	disk = &hk_dk[unit];
  	if ((bp = dp->b_actf) == NULL)
  		return(0);
  	if (dp->b_active)
  		goto done;
  	dp->b_active = 1;
! 	if	(!(hkaddr->hkds & HKDS_VV) || !(disk->dk_flags & DKF_ONLINE))
! 		{
  		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
  #ifdef BADSECT
  		struct buf *bbp = &bhkbuf[unit];
***************
*** 235,244 ****
  #endif
  
  		hkaddr->hkcs1 = hk_type[unit]|HK_PACK|HK_GO;
! 		hk_pack[unit]++;
  #ifdef BADSECT
  		bbp->b_flags = B_READ|B_BUSY|B_PHYS;
! 		bbp->b_dev = bp->b_dev;
  		bbp->b_bcount = sizeof(struct dkbad);
  		bbp->b_un.b_addr = (caddr_t)&hkbad[unit];
  		bbp->b_blkno = (long)hkncyl(unit)*HK_NSPC - HK_NSECT;
--- 430,446 ----
  #endif
  
  		hkaddr->hkcs1 = hk_type[unit]|HK_PACK|HK_GO;
! 		disk->dk_flags |= DKF_ONLINE;
! /*
!  * XXX - The 'c' partition is used below to access the bad block area.  This
!  * XXX - is DIFFERENT than the XP driver (which should have used 'c' but could
!  * XXX - not due to historical reasons).  The 'c' partition MUST span the entire
!  * XXX - disk including the bad sector track.  The 'h' partition should be 
!  * XXX - used for user data.
! */
  #ifdef BADSECT
  		bbp->b_flags = B_READ|B_BUSY|B_PHYS;
! 		bbp->b_dev = (bp->b_dev & ~7) | ('c' - 'a');
  		bbp->b_bcount = sizeof(struct dkbad);
  		bbp->b_un.b_addr = (caddr_t)&hkbad[unit];
  		bbp->b_blkno = (long)hkncyl(unit)*HK_NSPC - HK_NSECT;
***************
*** 249,257 ****
  		bp = bbp;
  #endif
  		hkwait(hkaddr);
! 	}
! 	if ((hkaddr->hkds & HKDS_DREADY) != HKDS_DREADY)
  		goto done;
  #ifdef NHK > 1
  	if (bp->b_cylin == hk_cyl[unit])
  		goto done;
--- 451,462 ----
  		bp = bbp;
  #endif
  		hkwait(hkaddr);
! 		}
! 	if	((hkaddr->hkds & HKDS_DREADY) != HKDS_DREADY)
! 		{
! 		disk->dk_flags &= ~DKF_ONLINE;
  		goto done;
+ 		}
  #ifdef NHK > 1
  	if (bp->b_cylin == hk_cyl[unit])
  		goto done;
***************
*** 287,292 ****
--- 492,498 ----
  {
  	register struct buf *bp, *dp;
  	register struct hkdevice *hkaddr = HKADDR;
+ 	register struct dkdevice *disk;
  	daddr_t bn;
  	int sn, tn, cmd, unit;
  
***************
*** 294,304 ****
--- 500,524 ----
  	if ((dp = hktab.b_actf) == NULL)
  		return(0);
  	if ((bp = dp->b_actf) == NULL) {
+ /*
+  * No more requests for this drive, remove from controller queue and
+  * look at next drive.  We know we're at the head of the controller queue.
+  * The drive may not need anything, in which case it might be shutting
+  * down in hkclose() and a wakeup is done.
+ */
  		hktab.b_actf = dp->b_forw;
+ 		unit = dp - hkutab;
+ 		disk = &hk_dk[unit];
+ 		if	(disk->dk_flags & DKF_WANTED)
+ 			{
+ 			disk->dk_flags &= ~DKF_WANTED;
+ 			wakeup(dp);	/* finish the close protocol */
+ 			}
  		goto loop;
  	}
  	hktab.b_active++;
  	unit = dkunit(bp->b_dev);
+ 	disk = &hk_dk[unit];
  	bn = bp->b_blkno;
  
  	sn = bn % HK_NSPC;
***************
*** 315,323 ****
  	if (hkaddr->hkds & HKDS_PIP)
  		goto retry;
  	if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
! 		log(LOG_WARNING, "hk%d: not ready\n", unit);
  		if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
- 			printf("\n");
  			hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
  			hkwait(hkaddr);
  			hkaddr->hkcs1 = HK_CCLR;
--- 535,543 ----
  	if (hkaddr->hkds & HKDS_PIP)
  		goto retry;
  	if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
! 		disk->dk_flags &= ~DKF_ONLINE;
! 		log(LOG_WARNING, "hk%d: !ready\n", unit);
  		if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) {
  			hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
  			hkwait(hkaddr);
  			hkaddr->hkcs1 = HK_CCLR;
***************
*** 331,336 ****
--- 551,557 ----
  			goto loop;
  		}
  	}
+ 	disk->dk_flags |= DKF_ONLINE;
  nosval:
  	hkaddr->hkcyl = bp->b_cylin;
  	hk_cyl[unit] = bp->b_cylin;
***************
*** 387,393 ****
  			u_short er = hkaddr->hker;
  
  			if (er & HKER_WLE) {
! 				log(LOG_WARNING, "hk%d: write locked\n", unit);
  				bp->b_flags |= B_ERROR;
  			} else if (++hktab.b_errcnt > 28 ||
  			    ds&HKDS_HARD || er&HKER_HARD || cs2&HKCS2_HARD) {
--- 608,614 ----
  			u_short er = hkaddr->hker;
  
  			if (er & HKER_WLE) {
! 				log(LOG_WARNING, "hk%d: wrtlck\n", unit);
  				bp->b_flags |= B_ERROR;
  			} else if (++hktab.b_errcnt > 28 ||
  			    ds&HKDS_HARD || er&HKER_HARD || cs2&HKCS2_HARD) {
***************
*** 472,478 ****
  	}
  	for (unit = 0; as; as >>= 1, unit++)
  		if (as & 1) {
! 			if (unit < NHK && hk_sizes[unit]) {
  				if (hkustart(unit))
  					needie = 0;
  			} else {
--- 693,699 ----
  	}
  	for (unit = 0; as; as >>= 1, unit++)
  		if (as & 1) {
! 			if (unit < NHK && (hk_dk[unit].dk_flags & DKF_ALIVE)) {
  				if (hkustart(unit))
  					needie = 0;
  			} else {
***************
*** 500,522 ****
  
  hkdump(dev)
  	dev_t dev;
! {
  	register struct hkdevice *hkaddr = HKADDR;
  	daddr_t	bn, dumpsize;
  	long paddr;
- 	register count;
  	register struct ubmap *ubp;
  	int com, cn, tn, sn, unit;
- 	struct size *szp;
  
! 	unit = hkunit(dev);
! 	szp = hk_sizes[unit];
! 	if (unit >= NHK || !szp)
  		return(EINVAL);
! 	dumpsize = szp[dev & 7]->nblocks;
! 	if ((dumplo < 0) || (dumplo >= dumpsize))
  		return(EINVAL);
! 	dumpsize -= dumplo;
  
  	hkaddr->hkcs1 = HK_CCLR;
  	hkwait(hkaddr);
--- 721,752 ----
  
  hkdump(dev)
  	dev_t dev;
! 	{
  	register struct hkdevice *hkaddr = HKADDR;
  	daddr_t	bn, dumpsize;
  	long paddr;
  	register struct ubmap *ubp;
+ 	int	count, memblks;
+ 	register struct partition *pi;
+ 	struct dkdevice *disk;
  	int com, cn, tn, sn, unit;
  
! 	unit = dkunit(dev);
! 	if	(unit >= NHK)
  		return(EINVAL);
! 
! 	disk = &hk_dk[unit];
! 	if	((disk->dk_flags & DKF_ALIVE) == 0)
! 		return(ENXIO);
! 	pi = &disk->dk_parts[dkpart(dev)];
! 	if	(pi->p_fstype != FS_SWAP)
! 		return(EFTYPE);
! 
! 	dumpsize = hksize(dev) - dumplo;
! 	memblks = ctod(physmem);
! 	if	(dumplo < 0 || dumpsize <= 0)
  		return(EINVAL);
! 	bn = dumplo + pi->p_offset;
  
  	hkaddr->hkcs1 = HK_CCLR;
  	hkwait(hkaddr);
***************
*** 523,537 ****
  	hkaddr->hkcs2 = unit;
  	hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
  	hkwait(hkaddr);
! 	if ((hkaddr->hkds & HKDS_VV) == 0) {
  		hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_PACK|HK_GO;
  		hkwait(hkaddr);
! 	}
  	ubp = &UBMAP[0];
! 	for (paddr = 0L; dumpsize > 0; dumpsize -= count) {
! 		count = dumpsize>DBSIZE? DBSIZE: dumpsize;
! 		bn = dumplo + (paddr >> PGSHIFT);
! 		cn = (bn/HK_NSPC) + szp[dev & 7]->cyloff;
  		sn = bn%HK_NSPC;
  		tn = sn/HK_NSECT;
  		sn = sn%HK_NSECT;
--- 753,768 ----
  	hkaddr->hkcs2 = unit;
  	hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO;
  	hkwait(hkaddr);
! 	if	((hkaddr->hkds & HKDS_VV) == 0)
! 		{
  		hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_PACK|HK_GO;
  		hkwait(hkaddr);
! 		}
  	ubp = &UBMAP[0];
! 	for	(paddr = 0L; memblks > 0; )
! 		{
! 		count = MIN(memblks, DBSIZE);
! 		cn = bn/HK_NSPC;
  		sn = bn%HK_NSPC;
  		tn = sn/HK_NSECT;
  		sn = sn%HK_NSECT;
***************
*** 539,564 ****
  		hkaddr->hkda = (tn << 8) | sn;
  		hkaddr->hkwc = -(count << (PGSHIFT-1));
  		com = hk_type[unit]|HK_GO|HK_WRITE;
! 		if (ubmap) {
  			ubp->ub_lo = loint(paddr);
  			ubp->ub_hi = hiint(paddr);
  			hkaddr->hkba = 0;
! 		} else {
  			/* non UNIBUS map */
  			hkaddr->hkba = loint(paddr);
  			hkaddr->hkxmem = hiint(paddr);
  			com |= ((paddr >> 8) & (03 << 8));
! 		}
  		hkaddr->hkcs2 = unit;
  		hkaddr->hkcs1 = com;
  		hkwait(hkaddr);
! 		if (hkaddr->hkcs1 & HK_CERR) {
  			if (hkaddr->hkcs2 & HKCS2_NEM)
  				return(0);	/* made it to end of memory */
  			return(EIO);
  		}
- 		paddr += (DBSIZE << PGSHIFT);
- 	}
  	return(0);		/* filled disk minor dev */
  }
  #endif HK_DUMP
--- 770,801 ----
  		hkaddr->hkda = (tn << 8) | sn;
  		hkaddr->hkwc = -(count << (PGSHIFT-1));
  		com = hk_type[unit]|HK_GO|HK_WRITE;
! 		if	(ubmap)
! 			{
  			ubp->ub_lo = loint(paddr);
  			ubp->ub_hi = hiint(paddr);
  			hkaddr->hkba = 0;
! 			}
! 		else
! 			{
  			/* non UNIBUS map */
  			hkaddr->hkba = loint(paddr);
  			hkaddr->hkxmem = hiint(paddr);
  			com |= ((paddr >> 8) & (03 << 8));
! 			}
  		hkaddr->hkcs2 = unit;
  		hkaddr->hkcs1 = com;
  		hkwait(hkaddr);
! 		if	(hkaddr->hkcs1 & HK_CERR)
! 			{
  			if (hkaddr->hkcs2 & HKCS2_NEM)
  				return(0);	/* made it to end of memory */
  			return(EIO);
+ 			}
+ 		paddr += (count << PGSHIFT);
+ 		bn += count;
+ 		memblks -= count;
  		}
  	return(0);		/* filled disk minor dev */
  }
  #endif HK_DUMP
***************
*** 697,713 ****
  }
  
  /*
!  * Assumes the 'open' entry point has already been called to validate
!  * the unit number.
  */
  daddr_t
  hksize(dev)
! 	register dev_t dev;
  	{
! 	register struct size *szp = hk_sizes[hkunit(dev)];
  
! 	if	(!szp)
! 		return(-1);
! 	return(szp[dev & 7].nblocks);
  	}
  #endif NHK > 0
--- 934,968 ----
  }
  
  /*
!  * Return the number of blocks in a partition.  Call hkopen() to read the
!  * label if necessary.  If an open is necessary then a matching close
!  * will be done.
  */
+ 
  daddr_t
  hksize(dev)
! register dev_t dev;
  	{
! 	register struct dkdevice *disk;
! 	daddr_t psize;
! 	int     didopen = 0;
  
! 	disk = &hk_dk[dkunit(dev)];
! /*
!  * This should never happen but if we get called early in the kernel's
!  * life (before opening the swap or root devices) then we have to do
!  * the open here.
! */
! 
! 	if      (disk->dk_openmask == 0)
! 		{
! 		if      (hkopen(dev, FREAD|FWRITE, S_IFBLK))
! 			return(-1);
! 		didopen = 1;
! 		}
! 	psize = disk->dk_parts[dkpart(dev)].p_size;
! 	if      (didopen)
! 		hkclose(dev, FREAD|FWRITE, S_IFBLK);
! 	return(psize);
  	}
  #endif NHK > 0
*** /usr/src/sys/pdpuba/xp.c.old	Mon Jan  8 20:13:52 1996
--- /usr/src/sys/pdpuba/xp.c	Tue Nov 11 21:20:36 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)xp.c	2.4 (2.11BSD GTE) 1996/1/8
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)xp.c	2.5 (2.11BSD GTE) 1997/11/11
   */
  
  /*
***************
*** 995,1004 ****
  		return(EINVAL);
  	if	(!(xd->xp_flags & DKF_ALIVE))
  		return(ENXIO);
  	if	(pi->p_fstype != FS_SWAP)
  		return(EFTYPE);
  
- 	pi = &xd->xp_parts[dkpart(dev)];
  	xpaddr = xd->xp_ctlr->xp_addr;
  
  	dumpsize = xpsize(dev) - dumplo;
--- 995,1005 ----
  		return(EINVAL);
  	if	(!(xd->xp_flags & DKF_ALIVE))
  		return(ENXIO);
+ 
+ 	pi = &xd->xp_parts[dkpart(dev)];
  	if	(pi->p_fstype != FS_SWAP)
  		return(EFTYPE);
  
  	xpaddr = xd->xp_ctlr->xp_addr;
  
  	dumpsize = xpsize(dev) - dumplo;
***************
*** 1052,1058 ****
  			continue;
  		if	(xpaddr->hpcs1.w & HP_TRE)
  			return(EIO);
! 		paddr += (DBSIZE << PGSHIFT);
  		bn += count;
  		memblks -= count;
  		}
--- 1053,1059 ----
  			continue;
  		if	(xpaddr->hpcs1.w & HP_TRE)
  			return(EIO);
! 		paddr += (count << PGSHIFT);
  		bn += count;
  		memblks -= count;
  		}
*** /usr/src/sys/sys/init_sysent.c.old	Fri Sep 26 19:45:56 1997
--- /usr/src/sys/sys/init_sysent.c	Sun Nov 30 20:27:18 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)init_sysent.c	1.11 (2.11BSD GTE) 1997/9/26
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)init_sysent.c	1.12 (2.11BSD GTE) 1997/11/28
   */
  
  /*
***************
*** 16,26 ****
  int	nosys();
  
  /* 1.1 processes and protection */
! int	sethostid(),gethostid(),sethostname(),gethostname(),getpid();
! int	getppid(), fork(),rexit(),execv(),execve(),owait(),wait4();
! int	getuid(),setreuid(),getgid(),getgroups(),setregid(),setgroups();
  int	geteuid(), getegid(), getlogin();
  int	getpgrp(),setpgrp(), setlogin();
  int	ucall();					/* 2BSD calls */
  
  /* 1.2 memory management */
--- 16,30 ----
  int	nosys();
  
  /* 1.1 processes and protection */
! int	sethostid(),gethostid(),sethostname(),gethostname();	/* COMPAT-43 */
! int	getpid();
! int	getppid(), fork(),rexit(),execv(),execve();
! int	owait();					/* COMPAT-43 */
! int	wait4(), getuid(),getgid(),getgroups(),setgroups();
  int	geteuid(), getegid(), getlogin();
  int	getpgrp(),setpgrp(), setlogin();
+ int	setgid(), setegid(), setuid(), seteuid();
+ int	setregid(), setreuid();				/* COMPAT-43 */
  int	ucall();					/* 2BSD calls */
  
  /* 1.2 memory management */
***************
*** 152,163 ****
  	0, pipe,			/*  42 = pipe */
  	1, setlogin,			/*  43 = setlogin */
  	4, profil,			/*  44 = profil */
! 	0, nosys,			/*  45 = nosys */
! 	0, nosys,			/*  46 = unused */
  	0, getgid,			/*  47 = getgid */
  	0, getegid,			/*  48 = getegid */
! 	0, nosys,			/*  49 = unused */
! 	0, nosys,			/*  50 = unused */
  	1, sysacct,			/*  51 = turn acct off/on */
  	3, phys,			/*  52 = (2.9) set phys addr */
  	1, lock,			/*  53 = (2.9) lock in core */
--- 156,167 ----
  	0, pipe,			/*  42 = pipe */
  	1, setlogin,			/*  43 = setlogin */
  	4, profil,			/*  44 = profil */
! 	1, setuid,			/*  45 = setuid */
! 	1, seteuid,			/*  46 = seteuid */
  	0, getgid,			/*  47 = getgid */
  	0, getegid,			/*  48 = getegid */
! 	1, setgid,			/*  49 = setgid */
! 	1, setegid,			/*  50 = setegid */
  	1, sysacct,			/*  51 = turn acct off/on */
  	3, phys,			/*  52 = (2.9) set phys addr */
  	1, lock,			/*  53 = (2.9) lock in core */
***************
*** 191,201 ****
  	1, getpgrp,			/*  81 = getpgrp */
  	2, setpgrp,			/*  82 = setpgrp */
  	3, setitimer,			/*  83 = setitimer */
! 	0, owait,			/*  84 = wait,wait3 COMPAT */
  	0, nosys,			/*  85 = unused */
  	2, getitimer,			/*  86 = getitimer */
! 	2, gethostname,			/*  87 = gethostname */
! 	2, sethostname,			/*  88 = sethostname */
  	0, getdtablesize,		/*  89 = getdtablesize */
  	2, dup2,			/*  90 = dup2 */
  	0, nosys,			/*  91 = unused */
--- 195,205 ----
  	1, getpgrp,			/*  81 = getpgrp */
  	2, setpgrp,			/*  82 = setpgrp */
  	3, setitimer,			/*  83 = setitimer */
! 	0, owait,			/*  84 = wait,wait3 COMPAT-43 */
  	0, nosys,			/*  85 = unused */
  	2, getitimer,			/*  86 = getitimer */
! 	2, gethostname,			/*  87 = gethostname COMPAT-43 */
! 	2, sethostname,			/*  88 = sethostname COMPAT-43 */
  	0, getdtablesize,		/*  89 = getdtablesize */
  	2, dup2,			/*  90 = dup2 */
  	0, nosys,			/*  91 = unused */
***************
*** 233,240 ****
  	3, fchown,			/* 123 = fchown */
  	2, fchmod,			/* 124 = fchmod */
  	ifnet(6, recvfrom),		/* 125 = recvfrom */
! 	2, setreuid,			/* 126 = setreuid */
! 	2, setregid,			/* 127 = setregid */
  	2, rename,			/* 128 = rename */
  	3, truncate,			/* 129 = truncate */
  	3, ftruncate,			/* 130 = ftruncate */
--- 237,244 ----
  	3, fchown,			/* 123 = fchown */
  	2, fchmod,			/* 124 = fchmod */
  	ifnet(6, recvfrom),		/* 125 = recvfrom */
! 	2, setreuid,			/* 126 = setreuid - COMPAT43 */
! 	2, setregid,			/* 127 = setregid - COMPAT43 */
  	2, rename,			/* 128 = rename */
  	3, truncate,			/* 129 = truncate */
  	3, ftruncate,			/* 130 = ftruncate */
*** /usr/src/sys/sys/kern_exec.c.old	Sat Aug 30 14:05:14 1997
--- /usr/src/sys/sys/kern_exec.c	Fri Nov 28 17:59:46 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_exec.c	1.6 (2.11BSD GTE) 1997/8/28
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_exec.c	1.7 (2.11BSD GTE) 1997/11/28
   */
  
  #include "param.h"
***************
*** 71,77 ****
  	bp = 0;
  	indir = 0;
  	uid = u.u_uid;
! 	gid = u.u_gid;
  	if (ip->i_fs->fs_flags & MNT_NOEXEC) {
  		u.u_error = EACCES;
  		goto bad;
--- 71,77 ----
  	bp = 0;
  	indir = 0;
  	uid = u.u_uid;
! 	gid = u.u_groups[0];
  	if (ip->i_fs->fs_flags & MNT_NOEXEC) {
  		u.u_error = EACCES;
  		goto bad;
***************
*** 138,143 ****
--- 138,149 ----
  			u.u_error = ENOEXEC;
  			goto bad;
  		}
+ /*
+  * If setuid/gid scripts were to be disallowed this is where it would
+  * have to be done.
+  *		u.u_uid = uid;
+  *		u.u_gid = u_groups[0];
+ */
  		cp = &exdata.ex_shell[2];		/* skip "#!" */
  		while (cp < &exdata.ex_shell[SHSIZE]) {
  			if (*cp == '\t')
***************
*** 600,608 ****
  		if ((u.u_procp->p_flag&STRC)==0) {
  			u.u_uid = uid;
  			u.u_procp->p_uid = uid;
! 			u.u_gid = gid;
  		} else
  			psignal(u.u_procp, SIGTRAP);
  	}
  	u.u_tsize = ts;
  	u.u_dsize = ds;
--- 606,617 ----
  		if ((u.u_procp->p_flag&STRC)==0) {
  			u.u_uid = uid;
  			u.u_procp->p_uid = uid;
! 			u.u_groups[0] = gid;
  		} else
  			psignal(u.u_procp, SIGTRAP);
+ 		u.u_svuid = u.u_uid;
+ 		u.u_svgid = u.u_groups[0];
+ 		u.u_acflag &= ~ASUGID;	/* start fresh setuid/gid priv use */
  	}
  	u.u_tsize = ts;
  	u.u_dsize = ds;
*** /usr/src/sys/sys/kern_fork.c.old	Fri Dec 31 23:28:03 1993
--- /usr/src/sys/sys/kern_fork.c	Fri Nov 28 15:56:12 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_fork.c	1.4 (2.11BSD GTE) 12/31/93
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_fork.c	1.5 (2.11BSD GTE) 1997/11/28
   */
  
  #include "param.h"
***************
*** 76,82 ****
  		u.u_r.r_val2 = 1;  /* child */
  #endif
  		u.u_start = time.tv_sec;
! 		u.u_acflag = AFORK;
  		bzero(&u.u_ru, sizeof(u.u_ru));
  		bzero(&u.u_cru, sizeof(u.u_cru));
  		return;
--- 76,83 ----
  		u.u_r.r_val2 = 1;  /* child */
  #endif
  		u.u_start = time.tv_sec;
! 		/* set forked but preserve suid/gid state */
! 		u.u_acflag = AFORK | (u.u_acflag & ASUGID); 
  		bzero(&u.u_ru, sizeof(u.u_ru));
  		bzero(&u.u_cru, sizeof(u.u_cru));
  		return;
*** /usr/src/sys/sys/kern_prot.c.old	Fri Sep 26 19:55:22 1997
--- /usr/src/sys/sys/kern_prot.c	Fri Nov 28 16:49:17 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_prot.c	1.3 (2.11BSD GTE) 1997/09/26
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_prot.c	1.4 (2.11BSD GTE) 1997/11/28
   */
  
  /*
***************
*** 65,77 ****
  {
  
  	u.u_r.r_val1 = u.u_rgid;
! 	u.u_r.r_val2 = u.u_gid;		/* XXX */
  }
  
  getegid()
  {
  
! 	u.u_r.r_val1 = u.u_gid;
  }
  
  /*
--- 65,77 ----
  {
  
  	u.u_r.r_val1 = u.u_rgid;
! 	u.u_r.r_val2 = u.u_groups[0];		/* XXX */
  }
  
  getegid()
  {
  
! 	u.u_r.r_val1 = u.u_groups[0];
  }
  
  /*
***************
*** 124,191 ****
  	p->p_pgrp = uap->pgrp;
  }
  
- setreuid()
- {
- 	struct a {
- 		int	ruid;
- 		int	euid;
- 	} *uap;
- 	register int ruid, euid;
- 
- 	uap = (struct a *)u.u_ap;
- 	ruid = uap->ruid;
- 	if (ruid == -1)
- 		ruid = u.u_ruid;
- 	if (u.u_ruid != ruid && u.u_uid != ruid && !suser())
- 		return;
- 	euid = uap->euid;
- 	if (euid == -1)
- 		euid = u.u_uid;
- 	if (u.u_ruid != euid && u.u_uid != euid && !suser())
- 		return;
- 	/*
- 	 * Everything's okay, do it.
- 	 */
- #ifdef QUOTA
- 	QUOTAMAP();
- 	if (u.u_quota->q_uid != ruid) {
- 		qclean();
- 		qstart(getquota((uid_t)ruid, 0, 0));
- 	}
- 	QUOTAUNMAP();
- #endif
- 	u.u_procp->p_uid = euid;
- 	u.u_ruid = ruid;
- 	u.u_uid = euid;
- }
- 
- setregid()
- {
- 	register struct a {
- 		int	rgid;
- 		int	egid;
- 	} *uap;
- 	register int rgid, egid;
- 
- 	uap = (struct a *)u.u_ap;
- 	rgid = uap->rgid;
- 	if (rgid == -1)
- 		rgid = u.u_rgid;
- 	if (u.u_rgid != rgid && u.u_gid != rgid && !suser())
- 		return;
- 	egid = uap->egid;
- 	if (egid == -1)
- 		egid = u.u_gid;
- 	if (u.u_rgid != egid && u.u_gid != egid && !suser())
- 		return;
- 	if (u.u_rgid != rgid) {
- 		leavegroup(u.u_rgid);
- 		(void) entergroup(rgid);
- 		u.u_rgid = rgid;
- 	}
- 	u.u_gid = egid;
- }
- 
  setgroups()
  {
  	register struct	a {
--- 124,129 ----
***************
*** 209,255 ****
  }
  
  /*
-  * Group utility functions.
-  */
- 
- /*
-  * Delete gid from the group set.
-  */
- leavegroup(gid)
- 	int gid;
- {
- 	register gid_t *gp;
- 
- 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
- 		if (*gp == gid)
- 			goto found;
- 	return;
- found:
- 	for (; gp < &u.u_groups[NGROUPS-1]; gp++)
- 		*gp = *(gp+1);
- 	*gp = NOGROUP;
- }
- 
- /*
-  * Add gid to the group set.
-  */
- entergroup(gid)
- 	int gid;
- {
- 	register gid_t *gp;
- 
- 	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) {
- 		if (*gp == gid)
- 			return (0);
- 		if (*gp == NOGROUP) {
- 			*gp = gid;
- 			return (0);
- 		}
- 	}
- 	return (-1);
- }
- 
- /*
   * Check if gid is a member of the group set.
   */
  groupmember(gid)
--- 147,152 ----
***************
*** 257,264 ****
  {
  	register gid_t *gp;
  
- 	if (u.u_gid == gid)
- 		return (1);
  	for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
  		if (*gp == gid)
  			return (1);
--- 154,159 ----
*** /usr/src/sys/sys/kern_sig.c.old	Fri Sep 12 20:19:59 1997
--- /usr/src/sys/sys/kern_sig.c	Fri Nov 28 16:19:54 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_sig.c	1.8 (2.11BSD GTE) 1997/8/29
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_sig.c	1.9 (2.11BSD GTE) 1997/11/28
   */
  
  #include "param.h"
***************
*** 743,750 ****
  	register char *np;
  	char	*cp, name[MAXCOMLEN + 6];
  
! 	if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid)
! 		return (0);
  	if (ctob(USIZE+u.u_dsize+u.u_ssize) >=
  	    u.u_rlimit[RLIMIT_CORE].rlim_cur)
  		return (0);
--- 743,754 ----
  	register char *np;
  	char	*cp, name[MAXCOMLEN + 6];
  
! 	/*
! 	 * Don't dump if not root and the process has used set user or
! 	 * group privileges.
! 	*/
! 	if	(u.u_acflag & ASUGID && !suser())
! 		return(0);
  	if (ctob(USIZE+u.u_dsize+u.u_ssize) >=
  	    u.u_rlimit[RLIMIT_CORE].rlim_cur)
  		return (0);
*** /usr/src/sys/sys/syscalls.c.old	Fri Sep 26 19:46:38 1997
--- /usr/src/sys/sys/syscalls.c	Fri Nov 28 16:13:42 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)syscalls.c	1.8 (2.11BSD GTE) 1997/9/26
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)syscalls.c	1.9 (2.11BSD GTE) 1997/11/28
   */
  
  /*
***************
*** 56,67 ****
  	"pipe",			/*  42 = pipe */
  	"setlogin",		/*  43 = setlogin */
  	"profil",		/*  44 = profil */
! 	"#45",			/*  45 = unused */
! 	"#46",			/*  46 = unused */
  	"getgid",		/*  47 = getgid */
  	"getegid",		/*  48 = getegid */
! 	"#49",			/*  49 = unused */
! 	"#50",			/*  50 = unused */
  	"acct",			/*  51 = turn acct off/on */
  	"phys",			/*  52 = (2.9) set phys addr */
  	"lock",			/*  53 = (2.9) lock in core */
--- 56,67 ----
  	"pipe",			/*  42 = pipe */
  	"setlogin",		/*  43 = setlogin */
  	"profil",		/*  44 = profil */
! 	"setuid",		/*  45 = setuid */
! 	"seteuid",		/*  46 = seteuid */
  	"getgid",		/*  47 = getgid */
  	"getegid",		/*  48 = getegid */
! 	"setgid",		/*  49 = setgid */
! 	"setegid",		/*  50 = setegid */
  	"acct",			/*  51 = turn acct off/on */
  	"phys",			/*  52 = (2.9) set phys addr */
  	"lock",			/*  53 = (2.9) lock in core */
***************
*** 137,144 ****
  	"fchown",		/* 123 = fchown */
  	"fchmod",		/* 124 = fchmod */
  	"recvfrom",		/* 125 = recvfrom */
! 	"setreuid",		/* 126 = setreuid */
! 	"setregid",		/* 127 = setregid */
  	"rename",		/* 128 = rename */
  	"truncate",		/* 129 = truncate */
  	"ftruncate",		/* 130 = ftruncate */
--- 137,144 ----
  	"fchown",		/* 123 = fchown */
  	"fchmod",		/* 124 = fchmod */
  	"recvfrom",		/* 125 = recvfrom */
! 	"setreuid",		/* 126 = setreuid COMPAT43 */
! 	"setregid",		/* 127 = setregid COMPAT43 */
  	"rename",		/* 128 = rename */
  	"truncate",		/* 129 = truncate */
  	"ftruncate",		/* 130 = ftruncate */
*** /usr/src/sys/sys/ufs_fio.c.old	Thu Jul  3 19:47:42 1997
--- /usr/src/sys/sys/ufs_fio.c	Fri Nov 28 16:48:04 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_fio.c	1.5 (2.11BSD GTE) 1997/7/3
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_fio.c	1.6 (2.11BSD GTE) 1997/11/28
   */
  
  #include "param.h"
***************
*** 82,89 ****
  	 */
  	if (u.u_uid != ip->i_uid) {
  		m >>= 3;
- 		if (u.u_gid == ip->i_gid)
- 			goto found;
  		gp = u.u_groups;
  		for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
  			if (ip->i_gid == *gp)
--- 82,87 ----
*** /usr/src/sys/sys/ufs_syscalls.c.old	Tue Aug  5 21:06:27 1997
--- /usr/src/sys/sys/ufs_syscalls.c	Fri Nov 28 16:51:33 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_syscalls.c	1.11 (2.11BSD GTE) 1997/8/5
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_syscalls.c	1.12 (2.11BSD GTE) 1997/11/28
   */
  
  #include "param.h"
***************
*** 399,406 ****
   */
  saccess()
  {
! 	uid_t svuid;
! 	gid_t svgid;
  	register struct inode *ip;
  	register struct a {
  		char	*fname;
--- 399,406 ----
   */
  saccess()
  {
! 	uid_t t_uid;
! 	gid_t t_gid;
  	register struct inode *ip;
  	register struct a {
  		char	*fname;
***************
*** 409,418 ****
  	struct	nameidata nd;
  	register struct	nameidata *ndp = &nd;
  
! 	svuid = u.u_uid;
! 	svgid = u.u_gid;
  	u.u_uid = u.u_ruid;
! 	u.u_gid = u.u_rgid;
  	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname);
  	ip = namei(ndp);
  	if (ip != NULL) {
--- 409,418 ----
  	struct	nameidata nd;
  	register struct	nameidata *ndp = &nd;
  
! 	t_uid = u.u_uid;
! 	t_gid = u.u_groups[0];
  	u.u_uid = u.u_ruid;
! 	u.u_groups[0] = u.u_rgid;
  	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname);
  	ip = namei(ndp);
  	if (ip != NULL) {
***************
*** 425,432 ****
  done:
  		iput(ip);
  	}
! 	u.u_uid = svuid;
! 	u.u_gid = svgid;
  }
  
  /*
--- 425,432 ----
  done:
  		iput(ip);
  	}
! 	u.u_uid = t_uid;
! 	u.u_groups[0] = t_gid;
  }
  
  /*
*** /usr/src/ucb/Mail/fio.c.old	Sat Jan 27 00:57:55 1996
--- /usr/src/ucb/Mail/fio.c	Mon Nov  3 21:54:25 1997
***************
*** 32,38 ****
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)fio.c	5.24.1 (2.11BSD) 1996/1/27";
  #endif
  
  #include "rcv.h"
--- 32,38 ----
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)fio.c	5.24.2 (2.11BSD) 1997/11/3";
  #endif
  
  #include "rcv.h"
***************
*** 42,50 ****
  #include <paths.h>
  #include <errno.h>
  
- #define	S_ISREG(m)	((m & S_IFMT) == S_IFREG)	/* regular file */
- extern int errno;
- 
  /*
   * Mail -- a mail program
   *
--- 42,47 ----
***************
*** 145,151 ****
   * characters written, including the newline.
   */
  putline(obuf, linebuf)
! 	FILE *obuf;
  	char *linebuf;
  {
  	register int c;
--- 142,148 ----
   * characters written, including the newline.
   */
  putline(obuf, linebuf)
! 	register FILE *obuf;
  	char *linebuf;
  {
  	register int c;
***************
*** 165,171 ****
   */
  readline(ibuf, linebuf, linesize)
  	FILE *ibuf;
! 	char *linebuf;
  {
  	register int n;
  
--- 162,168 ----
   */
  readline(ibuf, linebuf, linesize)
  	FILE *ibuf;
! 	register char *linebuf;
  {
  	register int n;
  
***************
*** 203,209 ****
  	FILE *f;
  {
  	register size = (msgCount + 1) * sizeof (struct message);
- 	off_t lseek();
  
  	if (message != 0)
  		free((char *) message);
--- 200,205 ----
***************
*** 391,397 ****
  getfold(name)
  	char *name;
  {
! 	char *folder;
  
  	if ((folder = value("folder")) == NOSTR)
  		return (-1);
--- 387,393 ----
  getfold(name)
  	char *name;
  {
! 	register char *folder;
  
  	if ((folder = value("folder")) == NOSTR)
  		return (-1);
*** /usr/src/usr.sbin/pstat/pstat.c.old	Fri Sep 12 19:25:53 1997
--- /usr/src/usr.sbin/pstat/pstat.c	Fri Nov 28 17:11:29 1997
***************
*** 9,15 ****
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)pstat.c	5.8.4 (2.11BSD GTE) 1997/9/1";
  #endif
  
  /*
--- 9,15 ----
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)pstat.c	5.8.5 (2.11BSD GTE) 1997/11/28";
  #endif
  
  /*
***************
*** 544,550 ****
  	printf("r_val2\t%.1o\n", U.u_r.r_val2);
  	printf("error\t%d\n", U.u_error);
  	printf("eosys\t%d\n", U.u_eosys);
! 	printf("uids\t%d,%d,%d,%d\n", U.u_uid, U.u_gid, U.u_ruid, U.u_rgid);
  	printf("groups");
  	for	(i = 0; (i < NGROUPS) && (U.u_groups[i] != NOGROUP); i++)
  		{
--- 544,551 ----
  	printf("r_val2\t%.1o\n", U.u_r.r_val2);
  	printf("error\t%d\n", U.u_error);
  	printf("eosys\t%d\n", U.u_eosys);
! 	printf("uids\t%d,%d,%d,%d,%d\n", U.u_uid, U.u_svuid, U.u_ruid,
! 		U.u_svgid, U.u_rgid);
  	printf("groups");
  	for	(i = 0; (i < NGROUPS) && (U.u_groups[i] != NOGROUP); i++)
  		{
*** /VERSION.old	Fri Oct 31 16:06:14 1997
--- /VERSION	Tue Dec 16 20:46:40 1997
***************
*** 1,5 ****
! Current Patch Level: 394
! Date: October 31, 1997
  
  2.11 BSD
  ============
--- 1,5 ----
! Current Patch Level: 397
! Date: December 16, 1997
  
  2.11 BSD
  ============
