xref: /csrg-svn/sys/hp/hpux/hpux_compat.c (revision 45923)
141486Smckusick /*
241486Smckusick  * Copyright (c) 1988 University of Utah.
341486Smckusick  * Copyright (c) 1990 The Regents of the University of California.
441486Smckusick  * All rights reserved.
541486Smckusick  *
641486Smckusick  * This code is derived from software contributed to Berkeley by
741486Smckusick  * the Systems Programming Group of the University of Utah Computer
841486Smckusick  * Science Department.
941486Smckusick  *
1041486Smckusick  * %sccs.include.redist.c%
1141486Smckusick  *
1245753Smckusick  * from: Utah $Hdr: hpux_compat.c 1.3 90/09/17$
1341486Smckusick  *
14*45923Smckusick  *	@(#)hpux_compat.c	7.12 (Berkeley) 01/11/91
1541486Smckusick  */
1641486Smckusick 
1741486Smckusick /*
1841486Smckusick  * Various HPUX compatibility routines
1941486Smckusick  */
2041486Smckusick 
2141486Smckusick #ifdef HPUXCOMPAT
2241486Smckusick 
2345788Sbostic #include "sys/param.h"
2445788Sbostic #include "sys/systm.h"
2545788Sbostic #include "sys/user.h"
2645788Sbostic #include "sys/kernel.h"
27*45923Smckusick #include "sys/filedesc.h"
2845788Sbostic #include "sys/proc.h"
2945788Sbostic #include "sys/buf.h"
3045788Sbostic #include "sys/wait.h"
3145788Sbostic #include "sys/file.h"
3245788Sbostic #include "sys/vnode.h"
3345788Sbostic #include "sys/ioctl.h"
3445788Sbostic #include "sys/uio.h"
3545788Sbostic #include "sys/ptrace.h"
3645788Sbostic #include "sys/stat.h"
3745788Sbostic #include "sys/syslog.h"
3845788Sbostic #include "sys/malloc.h"
3945788Sbostic #include "sys/mount.h"
4045788Sbostic #include "sys/ipc.h"
4141486Smckusick 
4245788Sbostic #include "../include/cpu.h"
4345788Sbostic #include "../include/reg.h"
4445788Sbostic #include "../include/psl.h"
4545788Sbostic #include "../include/vmparam.h"
4641486Smckusick #include "hpux.h"
4741486Smckusick #include "hpux_termio.h"
4841486Smckusick 
4941486Smckusick #ifdef DEBUG
5041486Smckusick int unimpresponse = 0;
5141486Smckusick #endif
5241486Smckusick 
5341486Smckusick /* SYS5 style UTSNAME info */
5441486Smckusick struct hpuxutsname protoutsname = {
5541486Smckusick 	"4.4bsd", "", "2.0", "B", "9000/3?0", ""
5641486Smckusick };
5741486Smckusick 
5841486Smckusick /* 6.0 and later style context */
5941486Smckusick #ifdef FPCOPROC
6041486Smckusick char hpuxcontext[] =
6141486Smckusick 	"standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default";
6241486Smckusick #else
6341486Smckusick char hpuxcontext[] =
6441486Smckusick 	"standalone HP-MC68020 HP-MC68010 localroot default";
6541486Smckusick #endif
6641486Smckusick 
6741486Smckusick /* YP domainname */
6841486Smckusick char	domainname[MAXHOSTNAMELEN] = "unknown";
6941486Smckusick int	domainnamelen = 7;
7041486Smckusick 
7141486Smckusick #define NERR	79
7241486Smckusick #define BERR	1000
7341486Smckusick 
7441486Smckusick /* indexed by BSD errno */
7541486Smckusick short bsdtohpuxerrnomap[NERR] = {
7641486Smckusick /*00*/	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
7741486Smckusick /*10*/	 10,  45,  12,  13,  14,  15,  16,  17,  18,  19,
7841486Smckusick /*20*/	 20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
7941486Smckusick /*30*/	 30,  31,  32,  33,  34, 246, 245, 244, 216, 217,
8041486Smckusick /*40*/	218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
8141486Smckusick /*50*/	228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
8241486Smckusick /*60*/	238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,
8341486Smckusick /*70*/   70,  71,BERR,BERR,BERR,BERR,BERR,  46,BERR
8441486Smckusick };
8541486Smckusick 
8643452Shibler notimp(p, uap, retval, code, nargs)
8743452Shibler 	struct proc *p;
8843452Shibler 	int *uap, *retval;
8943452Shibler 	int code, nargs;
9041486Smckusick {
9143452Shibler 	int error = 0;
9241486Smckusick #ifdef DEBUG
9343452Shibler 	register int *argp = uap;
9441486Smckusick 	extern char *hpuxsyscallnames[];
9541486Smckusick 
9641486Smckusick 	printf("HPUX %s(", hpuxsyscallnames[code]);
9741486Smckusick 	if (nargs)
9841486Smckusick 		while (nargs--)
9941486Smckusick 			printf("%x%c", *argp++, nargs? ',' : ')');
10041486Smckusick 	else
10141486Smckusick 		printf(")");
10241486Smckusick 	printf("\n");
10341486Smckusick 	switch (unimpresponse) {
10441486Smckusick 	case 0:
10543452Shibler 		error = nosys(p, uap, retval);
10641486Smckusick 		break;
10741486Smckusick 	case 1:
10843452Shibler 		error = EINVAL;
10941486Smckusick 		break;
11041486Smckusick 	}
11141486Smckusick #else
11243452Shibler 	error = nosys(p, uap, retval);
11341486Smckusick #endif
11443452Shibler 	uprintf("HP-UX system call %d not implemented\n", code);
11544421Skarels 	return (error);
11641486Smckusick }
11741486Smckusick 
11841486Smckusick /*
11941486Smckusick  * HPUX versions of wait and wait3 actually pass the parameters
12041486Smckusick  * (status pointer, options, rusage) into the kernel rather than
12142352Smckusick  * handling it in the C library stub.  We also need to map any
12242352Smckusick  * termination signal from BSD to HPUX.
12341486Smckusick  */
12443452Shibler hpuxwait3(p, uap, retval)
12543452Shibler 	struct proc *p;
12643452Shibler 	struct args {
12741486Smckusick 		int	*status;
12841486Smckusick 		int	options;
12941486Smckusick 		int	rusage;
13043452Shibler 	} *uap;
13143452Shibler 	int *retval;
13243452Shibler {
13341486Smckusick 	/* rusage pointer must be zero */
13443452Shibler 	if (uap->rusage)
13544421Skarels 		return (EINVAL);
13641486Smckusick 	u.u_ar0[PS] = PSL_ALLCC;
13741486Smckusick 	u.u_ar0[R0] = uap->options;
13841486Smckusick 	u.u_ar0[R1] = uap->rusage;
13944421Skarels 	return (hpuxwait(p, uap, retval));
14041486Smckusick }
14141486Smckusick 
14243452Shibler hpuxwait(p, uap, retval)
14343452Shibler 	struct proc *p;
14443452Shibler 	struct args {
14543452Shibler 		int	*status;
14643452Shibler 	} *uap;
14743452Shibler 	int *retval;
14841486Smckusick {
14943452Shibler 	int sig, *statp, error;
15041486Smckusick 
15141486Smckusick 	statp = uap->status;	/* owait clobbers first arg */
15243452Shibler 	error = owait(p, uap, retval);
15341486Smckusick 	/*
15441486Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
15541486Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
15641486Smckusick 	 */
15743452Shibler 	if (error == ERESTART)
15843452Shibler 		error = EINTR;
15943452Shibler 	if (error)
16044421Skarels 		return (error);
16143452Shibler 	sig = retval[1] & 0xFF;
16241486Smckusick 	if (sig == WSTOPPED) {
16343452Shibler 		sig = (retval[1] >> 8) & 0xFF;
16443452Shibler 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
16541486Smckusick 	} else if (sig)
16643452Shibler 		retval[1] = (retval[1] & 0xFF00) |
16741486Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
16841486Smckusick 	if (statp)
16943452Shibler 		if (suword((caddr_t)statp, retval[1]))
17043452Shibler 			error = EFAULT;
17144421Skarels 	return (error);
17241486Smckusick }
17341486Smckusick 
17443452Shibler hpuxwaitpid(p, uap, retval)
17543452Shibler 	struct proc *p;
17643452Shibler 	struct args {
17742352Smckusick 		int	pid;
17842352Smckusick 		int	*status;
17942352Smckusick 		int	options;
18042352Smckusick 		struct	rusage *rusage;	/* wait4 arg */
18143452Shibler 	} *uap;
18243452Shibler 	int *retval;
18343452Shibler {
18443452Shibler 	int sig, *statp, error;
18542352Smckusick 
18642352Smckusick 	uap->rusage = 0;
18743452Shibler 	error = wait4(p, uap, retval);
18842352Smckusick 	/*
18942352Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
19042352Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
19142352Smckusick 	 */
19243452Shibler 	if (error == ERESTART)
19343452Shibler 		error = EINTR;
19443452Shibler 	if (error)
19544421Skarels 		return (error);
19643452Shibler 	sig = retval[1] & 0xFF;
19742352Smckusick 	if (sig == WSTOPPED) {
19843452Shibler 		sig = (retval[1] >> 8) & 0xFF;
19943452Shibler 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
20042352Smckusick 	} else if (sig)
20143452Shibler 		retval[1] = (retval[1] & 0xFF00) |
20242352Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
20342352Smckusick 	if (statp)
20443452Shibler 		if (suword((caddr_t)statp, retval[1]))
20543452Shibler 			error = EFAULT;
20644421Skarels 	return (error);
20742352Smckusick }
20842352Smckusick 
20941486Smckusick /*
21041486Smckusick  * Must remap some bits in the mode mask.
21141486Smckusick  * O_CREAT, O_TRUNC, and O_EXCL must be remapped,
21241486Smckusick  * O_SYNCIO (0100000) is removed entirely.
21341486Smckusick  */
21443067Skarels hpuxopen(p, uap, retval)
21543067Skarels 	struct proc *p;
21643452Shibler 	register struct args {
21741486Smckusick 		char	*fname;
21841486Smckusick 		int	mode;
21941486Smckusick 		int	crtmode;
22043067Skarels 	} *uap;
22143067Skarels 	int *retval;
22243067Skarels {
22341486Smckusick 	int mode;
22441486Smckusick 
22541486Smckusick 	mode = uap->mode;
22641486Smckusick 	uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT);
22741486Smckusick 	if (mode & HPUXFCREAT) {
22841486Smckusick 		/*
22941486Smckusick 		 * simulate the pre-NFS behavior that opening a
23041486Smckusick 		 * file for READ+CREATE ignores the CREATE (unless
23141486Smckusick 		 * EXCL is set in which case we will return the
23241486Smckusick 		 * proper error).
23341486Smckusick 		 */
23441486Smckusick 		if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE))
23541486Smckusick 			uap->mode |= FCREAT;
23641486Smckusick 	}
23741486Smckusick 	if (mode & HPUXFTRUNC)
23841486Smckusick 		uap->mode |= FTRUNC;
23941486Smckusick 	if (mode & HPUXFEXCL)
24041486Smckusick 		uap->mode |= FEXCL;
24144421Skarels 	return (open(p, uap, retval));
24241486Smckusick }
24341486Smckusick 
24443452Shibler hpuxfcntl(p, uap, retval)
24543452Shibler 	struct proc *p;
24643452Shibler 	register struct args {
24741486Smckusick 		int	fdes;
24841486Smckusick 		int	cmd;
24941486Smckusick 		int	arg;
25043452Shibler 	} *uap;
25143452Shibler 	int *retval;
25243452Shibler {
25343452Shibler 	int mode, error;
25441486Smckusick 
25541486Smckusick 	switch (uap->cmd) {
25641486Smckusick 	case F_SETFL:
25741486Smckusick 		uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE);
25841486Smckusick 		break;
25941486Smckusick 	case F_GETFL:
26041486Smckusick 	case F_DUPFD:
26141486Smckusick 	case F_GETFD:
26241486Smckusick 	case F_SETFD:
26341486Smckusick 		break;
26441486Smckusick 	default:
26544421Skarels 		return (EINVAL);
26641486Smckusick 	}
26743452Shibler 	error = fcntl(p, uap, retval);
26843452Shibler 	if (error == 0 && uap->arg == F_GETFL) {
26943452Shibler 		mode = *retval;
27043452Shibler 		*retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE);
27141486Smckusick 		if (mode & FCREAT)
27243452Shibler 			*retval |= HPUXFCREAT;
27341486Smckusick 		if (mode & FTRUNC)
27443452Shibler 			*retval |= HPUXFTRUNC;
27541486Smckusick 		if (mode & FEXCL)
27643452Shibler 			*retval |= HPUXFEXCL;
27741486Smckusick 	}
27844421Skarels 	return (error);
27941486Smckusick }
28041486Smckusick 
28141486Smckusick /*
28241486Smckusick  * Read and write should return a 0 count when an operation
28341486Smckusick  * on a VNODE would block, not an error.  Sockets appear to
28441486Smckusick  * return EWOULDBLOCK (at least in 6.2).  This is probably
28541486Smckusick  * not entirely correct, since the behavior is only defined
28641486Smckusick  * for pipes and tty type devices.
28741486Smckusick  */
28843452Shibler hpuxread(p, uap, retval)
28943452Shibler 	struct proc *p;
29043452Shibler 	struct args {
29143452Shibler 		int	fd;
29243452Shibler 	} *uap;
29343452Shibler 	int *retval;
29441486Smckusick {
29543452Shibler 	int error;
29641486Smckusick 
29743452Shibler 	error = read(p, uap, retval);
29843452Shibler 	if (error == EWOULDBLOCK &&
299*45923Smckusick 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
30043452Shibler 		error = 0;
30143452Shibler 		*retval = 0;
30241486Smckusick 	}
30344421Skarels 	return (error);
30441486Smckusick }
30541486Smckusick 
30643452Shibler hpuxwrite(p, uap, retval)
30743452Shibler 	struct proc *p;
30843452Shibler 	struct args {
30943452Shibler 		int	fd;
31043452Shibler 	} *uap;
31143452Shibler 	int *retval;
31241486Smckusick {
31343452Shibler 	int error;
31441486Smckusick 
31543452Shibler 	error = write(p, uap, retval);
31643452Shibler 	if (error == EWOULDBLOCK &&
317*45923Smckusick 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
31843452Shibler 		error = 0;
31943452Shibler 		*retval = 0;
32041486Smckusick 	}
32144421Skarels 	return (error);
32241486Smckusick }
32341486Smckusick 
32443452Shibler hpuxreadv(p, uap, retval)
32543452Shibler 	struct proc *p;
32643452Shibler 	struct args {
32743452Shibler 		int	fd;
32843452Shibler 	} *uap;
32943452Shibler 	int *retval;
33041486Smckusick {
33143452Shibler 	int error;
33241486Smckusick 
33343452Shibler 	error = readv(p, uap, retval);
33443452Shibler 	if (error == EWOULDBLOCK &&
335*45923Smckusick 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
33643452Shibler 		error = 0;
33743452Shibler 		*retval = 0;
33841486Smckusick 	}
33944421Skarels 	return (error);
34041486Smckusick }
34141486Smckusick 
34243452Shibler hpuxwritev(p, uap, retval)
34343452Shibler 	struct proc *p;
34443452Shibler 	struct args {
34543452Shibler 		int	fd;
34643452Shibler 	} *uap;
34743452Shibler 	int *retval;
34841486Smckusick {
34943452Shibler 	int error;
35041486Smckusick 
35143452Shibler 	error = writev(p, uap, retval);
35243452Shibler 	if (error == EWOULDBLOCK &&
353*45923Smckusick 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
35443452Shibler 		error = 0;
35543452Shibler 		*retval = 0;
35641486Smckusick 	}
35744421Skarels 	return (error);
35841486Smckusick }
35941486Smckusick 
36041486Smckusick /*
36141486Smckusick  * 4.3bsd dup allows dup2 to come in on the same syscall entry
36241486Smckusick  * and hence allows two arguments.  HPUX dup has only one arg.
36341486Smckusick  */
36443452Shibler hpuxdup(p, uap, retval)
36543452Shibler 	struct proc *p;
36643452Shibler 	register struct args {
36743452Shibler 		int	i;
36843452Shibler 	} *uap;
36943452Shibler 	int *retval;
37041486Smckusick {
371*45923Smckusick 	register struct filedesc *fdp = p->p_fd;
37241486Smckusick 	struct file *fp;
37343452Shibler 	int fd, error;
37441486Smckusick 
375*45923Smckusick 	if (((unsigned)uap->i) >= fdp->fd_maxfiles ||
376*45923Smckusick 	    (fp = OFILE(fdp, uap->i)) == NULL)
37744421Skarels 		return (EBADF);
378*45923Smckusick 	if (error = ufalloc(fdp, 0, &fd))
37944421Skarels 		return (error);
380*45923Smckusick 	OFILE(fdp, fd) = fp;
381*45923Smckusick 	OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE;
382*45923Smckusick 	fp->f_count++;
383*45923Smckusick 	if (fd > fdp->fd_lastfile)
384*45923Smckusick 		fdp->fd_lastfile = fd;
38543452Shibler 	*retval = fd;
38644421Skarels 	return (0);
38741486Smckusick }
38841486Smckusick 
38945753Smckusick hpuxutssys(p, uap, retval)
39043452Shibler 	struct proc *p;
39143452Shibler 	register struct args {
39241486Smckusick 		struct hpuxutsname *uts;
39341486Smckusick 		int dev;
39441486Smckusick 		int request;
39543452Shibler 	} *uap;
39643452Shibler 	int *retval;
39743452Shibler {
39841486Smckusick 	register int i;
39943452Shibler 	int error;
40041486Smckusick 
40141486Smckusick 	switch (uap->request) {
40241486Smckusick 	/* uname */
40341486Smckusick 	case 0:
40441486Smckusick 		/* fill in machine type */
40541486Smckusick 		switch (machineid) {
40641486Smckusick 		case HP_320:
40741486Smckusick 			protoutsname.machine[6] = '2';
40841486Smckusick 			break;
40941486Smckusick 		/* includes 318 and 319 */
41041486Smckusick 		case HP_330:
41141486Smckusick 			protoutsname.machine[6] = '3';
41241486Smckusick 			break;
41341486Smckusick 		case HP_340:
41441486Smckusick 			protoutsname.machine[6] = '4';
41541486Smckusick 			break;
41641486Smckusick 		case HP_350:
41741486Smckusick 			protoutsname.machine[6] = '5';
41841486Smckusick 			break;
41941486Smckusick 		case HP_360:
42041486Smckusick 			protoutsname.machine[6] = '6';
42141486Smckusick 			break;
42241486Smckusick 		case HP_370:
42341486Smckusick 			protoutsname.machine[6] = '7';
42441486Smckusick 			break;
42543452Shibler 		/* includes 345 */
42643452Shibler 		case HP_375:
42743452Shibler 			protoutsname.machine[6] = '7';
42843452Shibler 			protoutsname.machine[7] = '5';
42943452Shibler 			break;
43041486Smckusick 		}
43141486Smckusick 		/* copy hostname (sans domain) to nodename */
43241486Smckusick 		for (i = 0; i < 9 && hostname[i] != '.'; i++)
43341486Smckusick 			protoutsname.nodename[i] = hostname[i];
43443452Shibler 		error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts,
43543452Shibler 				sizeof(struct hpuxutsname));
43641486Smckusick 		break;
43745753Smckusick 
43845753Smckusick 	/* gethostname */
43945753Smckusick 	case 5:
44045753Smckusick 		/* uap->dev is length */
44145753Smckusick 		if (uap->dev > hostnamelen + 1)
44245753Smckusick 			uap->dev = hostnamelen + 1;
44345753Smckusick 		error = copyout((caddr_t)hostname, (caddr_t)uap->uts,
44445753Smckusick 				uap->dev);
44545753Smckusick 		break;
44645753Smckusick 
44745753Smckusick 	case 1:	/* ?? */
44845753Smckusick 	case 2:	/* ustat */
44945753Smckusick 	case 3:	/* ?? */
45045753Smckusick 	case 4:	/* sethostname */
45141486Smckusick 	default:
45243452Shibler 		error = EINVAL;
45341486Smckusick 		break;
45441486Smckusick 	}
45544421Skarels 	return (error);
45641486Smckusick }
45741486Smckusick 
45843452Shibler hpuxstat(p, uap, retval)
45943452Shibler 	struct proc *p;
46043452Shibler 	struct args {
46141486Smckusick 		char	*fname;
46241486Smckusick 		struct hpuxstat *hsb;
46343452Shibler 	} *uap;
46443452Shibler 	int *retval;
46543452Shibler {
46644421Skarels 	return (hpuxstat1(uap->fname, uap->hsb, FOLLOW));
46741486Smckusick }
46841486Smckusick 
46943452Shibler hpuxlstat(p, uap, retval)
47043452Shibler 	struct proc *p;
47143452Shibler 	struct args {
47243452Shibler 		char	*fname;
47343452Shibler 		struct hpuxstat *hsb;
47443452Shibler 	} *uap;
47543452Shibler 	int *retval;
47641486Smckusick {
47744421Skarels 	return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW));
47841486Smckusick }
47941486Smckusick 
48043452Shibler hpuxfstat(p, uap, retval)
48143452Shibler 	struct proc *p;
48243452Shibler 	register struct args {
48343452Shibler 		int	fdes;
48443452Shibler 		struct	hpuxstat *hsb;
48543452Shibler 	} *uap;
48643452Shibler 	int *retval;
48741486Smckusick {
488*45923Smckusick 	register struct filedesc *fdp = p->p_fd;
48941486Smckusick 	register struct file *fp;
49041486Smckusick 	struct stat sb;
49143452Shibler 	int error;
49241486Smckusick 
493*45923Smckusick 	if (((unsigned)uap->fdes) >= fdp->fd_maxfiles ||
494*45923Smckusick 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
49544421Skarels 		return (EBADF);
49643452Shibler 
49741486Smckusick 	switch (fp->f_type) {
49841486Smckusick 
49941486Smckusick 	case DTYPE_VNODE:
50043452Shibler 		error = vn_stat((struct vnode *)fp->f_data, &sb);
50141486Smckusick 		break;
50241486Smckusick 
50341486Smckusick 	case DTYPE_SOCKET:
50443452Shibler 		error = soo_stat((struct socket *)fp->f_data, &sb);
50541486Smckusick 		break;
50641486Smckusick 
50741486Smckusick 	default:
50841486Smckusick 		panic("fstat");
50941486Smckusick 		/*NOTREACHED*/
51041486Smckusick 	}
51141486Smckusick 	/* is this right for sockets?? */
51243452Shibler 	if (error == 0)
51343452Shibler 		error = bsdtohpuxstat(&sb, uap->hsb);
51444421Skarels 	return (error);
51541486Smckusick }
51641486Smckusick 
51743452Shibler hpuxulimit(p, uap, retval)
51843452Shibler 	struct proc *p;
51943452Shibler 	register struct args {
52041486Smckusick 		int	cmd;
52141486Smckusick 		long	newlimit;
52243452Shibler 	} *uap;
52343713Smckusick 	off_t *retval;
52443452Shibler {
52541486Smckusick 	struct rlimit *limp;
52643452Shibler 	int error = 0;
52741486Smckusick 
52841486Smckusick 	limp = &u.u_rlimit[RLIMIT_FSIZE];
52941486Smckusick 	switch (uap->cmd) {
53041486Smckusick 	case 2:
53141486Smckusick 		uap->newlimit *= 512;
53241486Smckusick 		if (uap->newlimit > limp->rlim_max &&
53343452Shibler 		    (error = suser(u.u_cred, &u.u_acflag)))
53441486Smckusick 			break;
53541486Smckusick 		limp->rlim_cur = limp->rlim_max = uap->newlimit;
53641486Smckusick 		/* else fall into... */
53741486Smckusick 
53841486Smckusick 	case 1:
53945753Smckusick 		*retval = limp->rlim_max / 512;
54041486Smckusick 		break;
54141486Smckusick 
54241486Smckusick 	case 3:
54341486Smckusick 		limp = &u.u_rlimit[RLIMIT_DATA];
54445753Smckusick 		*retval = ctob(u.u_tsize) + limp->rlim_max;
54541486Smckusick 		break;
54641486Smckusick 
54741486Smckusick 	default:
54843452Shibler 		error = EINVAL;
54941486Smckusick 		break;
55041486Smckusick 	}
55144421Skarels 	return (error);
55241486Smckusick }
55341486Smckusick 
55441486Smckusick /*
55541486Smckusick  * Map "real time" priorities 0 (high) thru 127 (low) into nice
55641486Smckusick  * values -16 (high) thru -1 (low).
55741486Smckusick  */
55843452Shibler hpuxrtprio(cp, uap, retval)
55943452Shibler 	struct proc *cp;
56043452Shibler 	register struct args {
56141486Smckusick 		int pid;
56241486Smckusick 		int prio;
56343452Shibler 	} *uap;
56443452Shibler 	int *retval;
56543452Shibler {
56641486Smckusick 	struct proc *p;
56743452Shibler 	int nice, error;
56841486Smckusick 
56941486Smckusick 	if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX &&
57043452Shibler 	    uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF)
57144421Skarels 		return (EINVAL);
57241486Smckusick 	if (uap->pid == 0)
57343452Shibler 		p = cp;
57443452Shibler 	else if ((p = pfind(uap->pid)) == 0)
57544421Skarels 		return (ESRCH);
57641486Smckusick 	nice = p->p_nice;
57741486Smckusick 	if (nice < NZERO)
57843452Shibler 		*retval = (nice + 16) << 3;
57941486Smckusick 	else
58043452Shibler 		*retval = RTPRIO_RTOFF;
58141486Smckusick 	switch (uap->prio) {
58241486Smckusick 
58341486Smckusick 	case RTPRIO_NOCHG:
58444421Skarels 		return (0);
58541486Smckusick 
58641486Smckusick 	case RTPRIO_RTOFF:
58741486Smckusick 		if (nice >= NZERO)
58844421Skarels 			return (0);
58941486Smckusick 		nice = NZERO;
59041486Smckusick 		break;
59141486Smckusick 
59241486Smckusick 	default:
59341486Smckusick 		nice = (uap->prio >> 3) - 16;
59441486Smckusick 		break;
59541486Smckusick 	}
59643452Shibler 	error = donice(cp, p, nice);
59743452Shibler 	if (error == EACCES)
59843452Shibler 		error = EPERM;
59944421Skarels 	return (error);
60041486Smckusick }
60141486Smckusick 
60243452Shibler hpuxadvise(p, uap, retval)
60343452Shibler 	struct proc *p;
60443452Shibler 	struct args {
60543452Shibler 		int	arg;
60643452Shibler 	} *uap;
60743452Shibler 	int *retval;
60841486Smckusick {
60943452Shibler 	int error = 0;
61041486Smckusick 
61141486Smckusick 	switch (uap->arg) {
61241486Smckusick 	case 0:
61341486Smckusick 		u.u_pcb.pcb_flags |= PCB_HPUXMMAP;
61441486Smckusick 		break;
61541486Smckusick 	case 1:
61641486Smckusick 		ICIA();
61741486Smckusick 		break;
61841486Smckusick 	case 2:
61941486Smckusick 		DCIA();
62041486Smckusick 		break;
62141486Smckusick 	default:
62243452Shibler 		error = EINVAL;
62341486Smckusick 		break;
62441486Smckusick 	}
62544421Skarels 	return (error);
62641486Smckusick }
62741486Smckusick 
62843452Shibler hpuxptrace(p, uap, retval)
62943452Shibler 	struct proc *p;
63043452Shibler 	struct args {
63141486Smckusick 		int	req;
63241486Smckusick 		int	pid;
63341486Smckusick 		int	*addr;
63441486Smckusick 		int	data;
63543452Shibler 	} *uap;
63643452Shibler 	int *retval;
63743452Shibler {
63843452Shibler 	int error;
63941486Smckusick 
64041486Smckusick 	if (uap->req == PT_STEP || uap->req == PT_CONTINUE) {
64141486Smckusick 		if (uap->data) {
64241486Smckusick 			uap->data = hpuxtobsdsig(uap->data);
64341486Smckusick 			if (uap->data == 0)
64441486Smckusick 				uap->data = NSIG;
64541486Smckusick 		}
64641486Smckusick 	}
64743452Shibler 	error = ptrace(p, uap, retval);
64844421Skarels 	return (error);
64941486Smckusick }
65041486Smckusick 
65143452Shibler hpuxgetdomainname(p, uap, retval)
65243452Shibler 	struct proc *p;
65343452Shibler 	register struct args {
65441486Smckusick 		char	*domainname;
65541486Smckusick 		u_int	len;
65643452Shibler 	} *uap;
65743452Shibler 	int *retval;
65843452Shibler {
65941486Smckusick 	if (uap->len > domainnamelen + 1)
66041486Smckusick 		uap->len = domainnamelen + 1;
66144421Skarels 	return (copyout(domainname, uap->domainname, uap->len));
66241486Smckusick }
66341486Smckusick 
66443452Shibler hpuxsetdomainname(p, uap, retval)
66543452Shibler 	struct proc *p;
66643452Shibler 	register struct args {
66741486Smckusick 		char	*domainname;
66841486Smckusick 		u_int	len;
66943452Shibler 	} *uap;
67043452Shibler 	int *retval;
67143452Shibler {
67243452Shibler 	int error;
67341486Smckusick 
67443452Shibler 	if (error = suser(u.u_cred, &u.u_acflag))
67544421Skarels 		return (error);
67643452Shibler 	if (uap->len > sizeof (domainname) - 1)
67744421Skarels 		return (EINVAL);
67841486Smckusick 	domainnamelen = uap->len;
67943452Shibler 	error = copyin(uap->domainname, domainname, uap->len);
68041486Smckusick 	domainname[domainnamelen] = 0;
68144421Skarels 	return (error);
68241486Smckusick }
68341486Smckusick 
68441486Smckusick #ifdef SYSVSHM
68543452Shibler hpuxshmat(p, uap, retval)
68643452Shibler 	struct proc *p;
68743452Shibler 	int *uap, *retval;
68841486Smckusick {
68944421Skarels 	return (shmat(p, uap, retval));
69041486Smckusick }
69141486Smckusick 
69243452Shibler hpuxshmctl(p, uap, retval)
69343452Shibler 	struct proc *p;
69443452Shibler 	int *uap, *retval;
69541486Smckusick {
69644421Skarels 	return (shmctl(p, uap, retval));
69741486Smckusick }
69841486Smckusick 
69943452Shibler hpuxshmdt(p, uap, retval)
70043452Shibler 	struct proc *p;
70143452Shibler 	int *uap, *retval;
70241486Smckusick {
70344421Skarels 	return (shmdt(p, uap, retval));
70441486Smckusick }
70541486Smckusick 
70643452Shibler hpuxshmget(p, uap, retval)
70743452Shibler 	struct proc *p;
70843452Shibler 	int *uap, *retval;
70941486Smckusick {
71044421Skarels 	return (shmget(p, uap, retval));
71141486Smckusick }
71241486Smckusick #endif
71341486Smckusick 
71441486Smckusick /*
71541486Smckusick  * Fake semaphore routines, just don't return an error.
71641486Smckusick  * Should be adequate for starbase to run.
71741486Smckusick  */
71843452Shibler hpuxsemctl(p, uap, retval)
71943452Shibler 	struct proc *p;
72043452Shibler 	struct args {
72141486Smckusick 		int semid;
72241486Smckusick 		u_int semnum;
72341486Smckusick 		int cmd;
72441486Smckusick 		int arg;
72543452Shibler 	} *uap;
72643452Shibler 	int *retval;
72743452Shibler {
72841486Smckusick 	/* XXX: should do something here */
72944421Skarels 	return (0);
73041486Smckusick }
73141486Smckusick 
73243452Shibler hpuxsemget(p, uap, retval)
73343452Shibler 	struct proc *p;
73443452Shibler 	struct args {
73541486Smckusick 		key_t key;
73641486Smckusick 		int nsems;
73741486Smckusick 		int semflg;
73843452Shibler 	} *uap;
73943452Shibler 	int *retval;
74043452Shibler {
74141486Smckusick 	/* XXX: should do something here */
74244421Skarels 	return (0);
74341486Smckusick }
74441486Smckusick 
74543452Shibler hpuxsemop(p, uap, retval)
74643452Shibler 	struct proc *p;
74743452Shibler 	struct args {
74841486Smckusick 		int semid;
74941486Smckusick 		struct sembuf *sops;
75041486Smckusick 		u_int nsops;
75143452Shibler 	} *uap;
75243452Shibler 	int *retval;
75343452Shibler {
75441486Smckusick 	/* XXX: should do something here */
75544421Skarels 	return (0);
75641486Smckusick }
75741486Smckusick 
75841486Smckusick /* convert from BSD to HPUX errno */
75941486Smckusick bsdtohpuxerrno(err)
76041486Smckusick 	int err;
76141486Smckusick {
76241486Smckusick 	if (err < 0 || err >= NERR)
76341486Smckusick 		return(BERR);
76441486Smckusick 	return((int)bsdtohpuxerrnomap[err]);
76541486Smckusick }
76641486Smckusick 
76741486Smckusick hpuxstat1(fname, hsb, follow)
76841486Smckusick 	char *fname;
76941486Smckusick 	struct hpuxstat *hsb;
77041486Smckusick 	int follow;
77141486Smckusick {
77241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
77341486Smckusick 	struct stat sb;
77441486Smckusick 	int error;
77541486Smckusick 
77641486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
77741486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
77841486Smckusick 	ndp->ni_dirp = fname;
77941486Smckusick 	if (error = namei(ndp))
78041486Smckusick 		return (error);
78141486Smckusick 	error = vn_stat(ndp->ni_vp, &sb);
78241486Smckusick 	vput(ndp->ni_vp);
78341486Smckusick 	if (error == 0)
78441486Smckusick 		error = bsdtohpuxstat(&sb, hsb);
78541486Smckusick 	return (error);
78641486Smckusick }
78741486Smckusick 
78841486Smckusick #include "grf.h"
78941486Smckusick 
79041486Smckusick bsdtohpuxstat(sb, hsb)
79141486Smckusick 	struct stat *sb;
79241486Smckusick 	struct hpuxstat *hsb;
79341486Smckusick {
79441486Smckusick 	struct hpuxstat ds;
79541486Smckusick 
79641486Smckusick 	bzero((caddr_t)&ds, sizeof(ds));
79741486Smckusick 	ds.hst_dev = sb->st_dev;
79841486Smckusick 	ds.hst_ino = (u_long)sb->st_ino;
79941486Smckusick 	ds.hst_mode = sb->st_mode;
80041486Smckusick 	ds.hst_nlink = sb->st_nlink;
80141486Smckusick 	ds.hst_uid = (u_short)sb->st_uid;
80241486Smckusick 	ds.hst_gid = (u_short)sb->st_gid;
80341486Smckusick #if NGRF > 0
80441486Smckusick 	/* XXX: I don't want to talk about it... */
80541486Smckusick 	if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10)
80641486Smckusick 		ds.hst_rdev = grfdevno(sb->st_rdev);
80741486Smckusick 	else
80841486Smckusick #endif
80941486Smckusick 		ds.hst_rdev = bsdtohpuxdev(sb->st_rdev);
81041486Smckusick 	ds.hst_size = sb->st_size;
81141486Smckusick 	ds.hst_atime = sb->st_atime;
81241486Smckusick 	ds.hst_mtime = sb->st_mtime;
81341486Smckusick 	ds.hst_ctime = sb->st_ctime;
81441486Smckusick 	ds.hst_blksize = sb->st_blksize;
81541486Smckusick 	ds.hst_blocks = sb->st_blocks;
81641486Smckusick 	return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds)));
81741486Smckusick }
81841486Smckusick 
81941486Smckusick hpuxtobsdioctl(com)
82041486Smckusick 	int com;
82141486Smckusick {
82241486Smckusick 	switch (com) {
82341486Smckusick 	case HPUXTIOCSLTC:
82441486Smckusick 		com = TIOCSLTC; break;
82541486Smckusick 	case HPUXTIOCGLTC:
82641486Smckusick 		com = TIOCGLTC; break;
82741486Smckusick 	case HPUXTIOCSPGRP:
82841486Smckusick 		com = TIOCSPGRP; break;
82941486Smckusick 	case HPUXTIOCGPGRP:
83041486Smckusick 		com = TIOCGPGRP; break;
83141486Smckusick 	case HPUXTIOCLBIS:
83241486Smckusick 		com = TIOCLBIS; break;
83341486Smckusick 	case HPUXTIOCLBIC:
83441486Smckusick 		com = TIOCLBIC; break;
83541486Smckusick 	case HPUXTIOCLSET:
83641486Smckusick 		com = TIOCLSET; break;
83741486Smckusick 	case HPUXTIOCLGET:
83841486Smckusick 		com = TIOCLGET; break;
83941486Smckusick 	}
84041486Smckusick 	return(com);
84141486Smckusick }
84241486Smckusick 
84341486Smckusick /*
84441486Smckusick  * HPUX ioctl system call.  The differences here are:
84541486Smckusick  *	IOC_IN also means IOC_VOID if the size portion is zero.
84641486Smckusick  *	no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN
84741486Smckusick  *	the sgttyb struct is 2 bytes longer
84841486Smckusick  */
84943452Shibler hpuxioctl(p, uap, retval)
85043452Shibler 	struct proc *p;
85143452Shibler 	register struct args {
85241486Smckusick 		int	fdes;
85341486Smckusick 		int	cmd;
85441486Smckusick 		caddr_t	cmarg;
85543452Shibler 	} *uap;
85643452Shibler 	int *retval;
85743452Shibler {
858*45923Smckusick 	register struct filedesc *fdp = p->p_fd;
85943452Shibler 	register struct file *fp;
86043452Shibler 	register int com, error;
86141486Smckusick 	register u_int size;
86241486Smckusick 	caddr_t memp = 0;
86341486Smckusick #define STK_PARAMS	128
86441486Smckusick 	char stkbuf[STK_PARAMS];
86541486Smckusick 	caddr_t data = stkbuf;
86641486Smckusick 
86741486Smckusick 	com = uap->cmd;
86841486Smckusick 
86941486Smckusick 	/* XXX */
87043452Shibler 	if (com == HPUXTIOCGETP || com == HPUXTIOCSETP)
871*45923Smckusick 		return (getsettty(p, uap->fdes, com, uap->cmarg));
87241486Smckusick 
873*45923Smckusick 	if (((unsigned)uap->fdes) >= fdp->fd_maxfiles ||
874*45923Smckusick 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
87544421Skarels 		return (EBADF);
87643452Shibler 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
87744421Skarels 		return (EBADF);
87841486Smckusick 
87941486Smckusick 	/*
88041486Smckusick 	 * Interpret high order word to find
88141486Smckusick 	 * amount of data to be copied to/from the
88241486Smckusick 	 * user's address space.
88341486Smckusick 	 */
88441486Smckusick 	size = IOCPARM_LEN(com);
88543452Shibler 	if (size > IOCPARM_MAX)
88644421Skarels 		return (ENOTTY);
88741486Smckusick 	if (size > sizeof (stkbuf)) {
88843452Shibler 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
88941486Smckusick 		data = memp;
89041486Smckusick 	}
89141486Smckusick 	if (com&IOC_IN) {
89241486Smckusick 		if (size) {
89343452Shibler 			error = copyin(uap->cmarg, data, (u_int)size);
89443452Shibler 			if (error) {
89541486Smckusick 				if (memp)
89641486Smckusick 					free(memp, M_IOCTLOPS);
89744421Skarels 				return (error);
89841486Smckusick 			}
89941486Smckusick 		} else
90041486Smckusick 			*(caddr_t *)data = uap->cmarg;
90141486Smckusick 	} else if ((com&IOC_OUT) && size)
90241486Smckusick 		/*
90343452Shibler 		 * Zero the buffer so the user always
90443452Shibler 		 * gets back something deterministic.
90541486Smckusick 		 */
90641486Smckusick 		bzero(data, size);
90741486Smckusick 	else if (com&IOC_VOID)
90841486Smckusick 		*(caddr_t *)data = uap->cmarg;
90941486Smckusick 
91041486Smckusick 	switch (com) {
91141486Smckusick 
91241486Smckusick 	case HPUXTIOCCONS:
91341486Smckusick 		*(int *)data = 1;
91443452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data);
91541486Smckusick 		break;
91641486Smckusick 
91741486Smckusick 	/* BSD-style job control ioctls */
91841486Smckusick 	case HPUXTIOCLBIS:
91941486Smckusick 	case HPUXTIOCLBIC:
92041486Smckusick 	case HPUXTIOCLSET:
92141486Smckusick 		*(int *)data &= HPUXLTOSTOP;
92241486Smckusick 		if (*(int *)data & HPUXLTOSTOP)
92341486Smckusick 			*(int *)data = LTOSTOP;
92441486Smckusick 		/* fall into */
92541486Smckusick 	case HPUXTIOCLGET:
92641486Smckusick 	case HPUXTIOCSLTC:
92741486Smckusick 	case HPUXTIOCGLTC:
92841486Smckusick 	case HPUXTIOCSPGRP:
92941486Smckusick 	case HPUXTIOCGPGRP:
93043452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data);
93143452Shibler 		if (error == 0 && com == HPUXTIOCLGET) {
93241486Smckusick 			*(int *)data &= LTOSTOP;
93341486Smckusick 			if (*(int *)data & LTOSTOP)
93441486Smckusick 				*(int *)data = HPUXLTOSTOP;
93541486Smckusick 		}
93641486Smckusick 		break;
93741486Smckusick 
93841486Smckusick 	/* SYS 5 termio */
93941486Smckusick 	case HPUXTCGETA:
94041486Smckusick 	case HPUXTCSETA:
94141486Smckusick 	case HPUXTCSETAW:
94241486Smckusick 	case HPUXTCSETAF:
94343452Shibler 		error = hpuxtermio(fp, com, data);
94441486Smckusick 		break;
94541486Smckusick 
94641486Smckusick 	default:
94743452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
94841486Smckusick 		break;
94941486Smckusick 	}
95041486Smckusick 	/*
95141486Smckusick 	 * Copy any data to user, size was
95241486Smckusick 	 * already set and checked above.
95341486Smckusick 	 */
95443452Shibler 	if (error == 0 && (com&IOC_OUT) && size)
95543452Shibler 		error = copyout(data, uap->cmarg, (u_int)size);
95641486Smckusick 	if (memp)
95741486Smckusick 		free(memp, M_IOCTLOPS);
95844421Skarels 	return (error);
95941486Smckusick }
96041486Smckusick 
96141486Smckusick /*
96241486Smckusick  * Man page lies, behaviour here is based on observed behaviour.
96341486Smckusick  */
96443452Shibler hpuxgetcontext(p, uap, retval)
96543452Shibler 	struct proc *p;
96643452Shibler 	struct args {
96741486Smckusick 		char *buf;
96841486Smckusick 		int len;
96943452Shibler 	} *uap;
97043452Shibler 	int *retval;
97143452Shibler {
97241486Smckusick 	int error = 0;
97341486Smckusick 	register int len;
97441486Smckusick 
97541486Smckusick 	len = MIN(uap->len, sizeof(hpuxcontext));
97641486Smckusick 	if (len)
97741486Smckusick 		error = copyout(hpuxcontext, uap->buf, (u_int)len);
97843452Shibler 	if (error == 0)
97943452Shibler 		*retval = sizeof(hpuxcontext);
98044421Skarels 	return (error);
98141486Smckusick }
98241486Smckusick 
98341486Smckusick /*
98441486Smckusick  * This is the equivalent of BSD getpgrp but with more restrictions.
98541486Smckusick  * Note we do not check the real uid or "saved" uid.
98641486Smckusick  */
98743452Shibler hpuxgetpgrp2(cp, uap, retval)
98843452Shibler 	struct proc *cp;
98943452Shibler 	register struct args {
99043452Shibler 		int pid;
99143452Shibler 	} *uap;
99243452Shibler 	int *retval;
99341486Smckusick {
99441486Smckusick 	register struct proc *p;
99541486Smckusick 
99641486Smckusick 	if (uap->pid == 0)
99743452Shibler 		uap->pid = cp->p_pid;
99841486Smckusick 	p = pfind(uap->pid);
99943452Shibler 	if (p == 0)
100044421Skarels 		return (ESRCH);
100143452Shibler 	if (u.u_uid && p->p_uid != u.u_uid && !inferior(p))
100244421Skarels 		return (EPERM);
100343452Shibler 	*retval = p->p_pgid;
100444421Skarels 	return (0);
100541486Smckusick }
100641486Smckusick 
100741486Smckusick /*
100841486Smckusick  * This is the equivalent of BSD setpgrp but with more restrictions.
100941486Smckusick  * Note we do not check the real uid or "saved" uid or pgrp.
101041486Smckusick  */
101143452Shibler hpuxsetpgrp2(p, uap, retval)
101243452Shibler 	struct proc *p;
101343452Shibler 	struct args {
101441486Smckusick 		int	pid;
101541486Smckusick 		int	pgrp;
101643452Shibler 	} *uap;
101743452Shibler 	int *retval;
101843452Shibler {
101941486Smckusick 	/* empirically determined */
102043452Shibler 	if (uap->pgrp < 0 || uap->pgrp >= 30000)
102144421Skarels 		return (EINVAL);
102244421Skarels 	return (setpgrp(p, uap, retval));
102341486Smckusick }
102441486Smckusick 
102541486Smckusick /*
102645753Smckusick  * XXX Same as BSD setre[ug]id right now.  Need to consider saved ids.
102745753Smckusick  */
102845753Smckusick hpuxsetresuid(p, uap, retval)
102945753Smckusick 	struct proc *p;
103045753Smckusick 	struct args {
103145753Smckusick 		int	ruid;
103245753Smckusick 		int	euid;
103345753Smckusick 		int	suid;
103445753Smckusick 	} *uap;
103545753Smckusick 	int *retval;
103645753Smckusick {
103745753Smckusick 	return (osetreuid(p, uap, retval));
103845753Smckusick }
103945753Smckusick 
104045753Smckusick hpuxsetresgid(p, uap, retval)
104145753Smckusick 	struct proc *p;
104245753Smckusick 	struct args {
104345753Smckusick 		int	rgid;
104445753Smckusick 		int	egid;
104545753Smckusick 		int	sgid;
104645753Smckusick 	} *uap;
104745753Smckusick 	int *retval;
104845753Smckusick {
104945753Smckusick 	return (osetregid(p, uap, retval));
105045753Smckusick }
105145753Smckusick 
105245753Smckusick /*
105345753Smckusick  * XXX: simple recognition hack to see if we can make grmd work.
105445753Smckusick  */
105545753Smckusick hpuxlockf(p, uap, retval)
105645753Smckusick 	struct proc *p;
105745753Smckusick 	struct args {
105845753Smckusick 		int fd;
105945753Smckusick 		int func;
106045753Smckusick 		long size;
106145753Smckusick 	} *uap;
106245753Smckusick 	int *retval;
106345753Smckusick {
106445753Smckusick #ifdef DEBUG
106545753Smckusick 	log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n",
106645753Smckusick 	    p->p_pid, uap->fd, uap->func, uap->size);
106745753Smckusick #endif
106845753Smckusick 	return (0);
106945753Smckusick }
107045753Smckusick 
107145753Smckusick hpuxgetaccess(p, uap, retval)
107245753Smckusick 	register struct proc *p;
107345753Smckusick 	register struct args {
107445753Smckusick 		char	*path;
107545753Smckusick 		int	uid;
107645753Smckusick 		int	ngroups;
107745753Smckusick 		int	*gidset;
107845753Smckusick 		void	*label;
107945753Smckusick 		void	*privs;
108045753Smckusick 	} *uap;
108145753Smckusick 	int *retval;
108245753Smckusick {
108345753Smckusick 	struct nameidata *ndp = &u.u_nd;
108445753Smckusick 	int lgroups[NGROUPS];
108545753Smckusick 	int error = 0;
108645753Smckusick 	register struct ucred *cred;
108745753Smckusick 	register struct vnode *vp;
108845753Smckusick 
108945753Smckusick 	/*
109045753Smckusick 	 * Build an appropriate credential structure
109145753Smckusick 	 */
109245753Smckusick 	cred = crdup(ndp->ni_cred);
109345753Smckusick 	switch (uap->uid) {
109445753Smckusick 	case 65502:	/* UID_EUID */
109545753Smckusick 		break;
109645753Smckusick 	case 65503:	/* UID_RUID */
109745753Smckusick 		cred->cr_uid = p->p_ruid;
109845753Smckusick 		break;
109945753Smckusick 	case 65504:	/* UID_SUID */
110045753Smckusick 		error = EINVAL;
110145753Smckusick 		break;
110245753Smckusick 	default:
110345753Smckusick 		if (uap->uid > 65504)
110445753Smckusick 			error = EINVAL;
110545753Smckusick 		cred->cr_uid = uap->uid;
110645753Smckusick 		break;
110745753Smckusick 	}
110845753Smckusick 	switch (uap->ngroups) {
110945753Smckusick 	case -1:	/* NGROUPS_EGID */
111045753Smckusick 		cred->cr_ngroups = 1;
111145753Smckusick 		break;
111245753Smckusick 	case -5:	/* NGROUPS_EGID_SUPP */
111345753Smckusick 		break;
111445753Smckusick 	case -2:	/* NGROUPS_RGID */
111545753Smckusick 		cred->cr_ngroups = 1;
111645753Smckusick 		cred->cr_gid = p->p_rgid;
111745753Smckusick 		break;
111845753Smckusick 	case -6:	/* NGROUPS_RGID_SUPP */
111945753Smckusick 		cred->cr_gid = p->p_rgid;
112045753Smckusick 		break;
112145753Smckusick 	case -3:	/* NGROUPS_SGID */
112245753Smckusick 	case -7:	/* NGROUPS_SGID_SUPP */
112345753Smckusick 		error = EINVAL;
112445753Smckusick 		break;
112545753Smckusick 	case -4:	/* NGROUPS_SUPP */
112645753Smckusick 		if (cred->cr_ngroups > 1)
112745753Smckusick 			cred->cr_gid = cred->cr_groups[1];
112845753Smckusick 		else
112945753Smckusick 			error = EINVAL;
113045753Smckusick 		break;
113145753Smckusick 	default:
113245753Smckusick 		if (uap->ngroups > 0 && uap->ngroups <= NGROUPS)
113345753Smckusick 			error = copyin((caddr_t)uap->gidset,
113445753Smckusick 				       (caddr_t)&lgroups[0],
113545753Smckusick 				       uap->ngroups * sizeof(lgroups[0]));
113645753Smckusick 		else
113745753Smckusick 			error = EINVAL;
113845753Smckusick 		if (error == 0) {
113945753Smckusick 			int gid;
114045753Smckusick 
114145753Smckusick 			for (gid = 0; gid < uap->ngroups; gid++)
114245753Smckusick 				cred->cr_groups[gid] = lgroups[gid];
114345753Smckusick 			cred->cr_ngroups = uap->ngroups;
114445753Smckusick 		}
114545753Smckusick 		break;
114645753Smckusick 	}
114745753Smckusick 	/*
114845753Smckusick 	 * Lookup file using caller's effective IDs.
114945753Smckusick 	 */
115045753Smckusick 	if (error == 0) {
115145753Smckusick 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
115245753Smckusick 		ndp->ni_segflg = UIO_USERSPACE;
115345753Smckusick 		ndp->ni_dirp = uap->path;
115445753Smckusick 		error = namei(ndp);
115545753Smckusick 	}
115645753Smckusick 	if (error) {
115745753Smckusick 		crfree(cred);
115845753Smckusick 		return (error);
115945753Smckusick 	}
116045753Smckusick 	/*
116145753Smckusick 	 * Use the constructed credentials for access checks.
116245753Smckusick 	 */
116345753Smckusick 	vp = ndp->ni_vp;
116445753Smckusick 	*retval = 0;
116545753Smckusick 	if (VOP_ACCESS(vp, VREAD, cred) == 0)
116645753Smckusick 		*retval |= R_OK;
116745753Smckusick 	if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred) == 0)
116845753Smckusick 		*retval |= W_OK;
116945753Smckusick 	/* XXX we return X_OK for root on VREG even if not */
117045753Smckusick 	if (VOP_ACCESS(vp, VEXEC, cred) == 0)
117145753Smckusick 		*retval |= X_OK;
117245753Smckusick 	vput(vp);
117345753Smckusick 	crfree(cred);
117445753Smckusick 	return (error);
117545753Smckusick }
117645753Smckusick 
117745753Smckusick /*
117841486Smckusick  * Brutal hack!  Map HPUX u-area offsets into BSD u offsets.
117941486Smckusick  * No apologies offered, if you don't like it, rewrite it!
118041486Smckusick  */
118141486Smckusick 
118241486Smckusick #define UOFF(f)		((int)&((struct user *)0)->f)
118341486Smckusick #define HPUOFF(f)	((int)&((struct hpuxuser *)0)->f)
118441486Smckusick 
118541486Smckusick /* simplified FP structure */
118641486Smckusick struct bsdfp {
118741486Smckusick 	int save[54];
118841486Smckusick 	int reg[24];
118941486Smckusick 	int ctrl[3];
119041486Smckusick };
119141486Smckusick 
119241486Smckusick hpuxtobsduoff(off)
119341486Smckusick 	int *off;
119441486Smckusick {
119541486Smckusick 	struct hpuxfp *hp;
119641486Smckusick 	struct bsdfp *bp;
119741486Smckusick 	register u_int raddr;
119841486Smckusick 
119941486Smckusick 	/* u_ar0 field */
120041486Smckusick 	if ((int)off == HPUOFF(hpuxu_ar0))
120141486Smckusick 		return(UOFF(u_ar0));
120241486Smckusick 
120341486Smckusick #ifdef FPCOPROC
120441486Smckusick 	/* 68881 registers from PCB */
120541486Smckusick 	hp = (struct hpuxfp *)HPUOFF(hpuxu_fp);
120641486Smckusick 	bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
120741486Smckusick 	if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
120841486Smckusick 		return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
120941486Smckusick 	if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
121041486Smckusick 		return((int)&bp->reg[off - hp->hpfp_reg]);
121141486Smckusick #endif
121241486Smckusick 
121341486Smckusick 	/*
121441486Smckusick 	 * Everything else we recognize comes from the kernel stack,
121541486Smckusick 	 * so we convert off to an absolute address (if not already)
121641486Smckusick 	 * for simplicity.
121741486Smckusick 	 */
121841486Smckusick 	if (off < (int *)ctob(UPAGES))
121941486Smckusick 		off = (int *)((u_int)off + (u_int)&u);
122041486Smckusick 
122141486Smckusick 	/*
122241486Smckusick 	 * 68020 registers.
122341486Smckusick 	 * We know that the HPUX registers are in the same order as ours.
122441486Smckusick 	 * The only difference is that their PS is 2 bytes instead of a
122541486Smckusick 	 * padded 4 like ours throwing the alignment off.
122641486Smckusick 	 */
122741486Smckusick 	if (off >= u.u_ar0 && off < &u.u_ar0[18]) {
122841486Smckusick 		/*
122941486Smckusick 		 * PS: return low word and high word of PC as HP-UX would
123041486Smckusick 		 * (e.g. &u.u_ar0[16.5]).
123141486Smckusick 		 */
123241486Smckusick 		if (off == &u.u_ar0[PS])
123341486Smckusick 			raddr = (u_int) &((short *)u.u_ar0)[PS*2+1];
123441486Smckusick 		/*
123541486Smckusick 		 * PC: off will be &u.u_ar0[16.5]
123641486Smckusick 		 */
123741486Smckusick 		else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1]))
123841486Smckusick 			raddr = (u_int) &u.u_ar0[PC];
123941486Smckusick 		/*
124041486Smckusick 		 * D0-D7, A0-A7: easy
124141486Smckusick 		 */
124241486Smckusick 		else
124341486Smckusick 			raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)];
124441486Smckusick 		return((int)(raddr - (u_int)&u));
124541486Smckusick 	}
124641486Smckusick 
124741486Smckusick 	/* everything else */
124841486Smckusick 	return(-1);
124941486Smckusick }
125041486Smckusick 
125141486Smckusick /*
125241486Smckusick  * Kludge up a uarea dump so that HPUX debuggers can find out
125341486Smckusick  * what they need.  IMPORTANT NOTE: we do not EVEN attempt to
125441486Smckusick  * convert the entire user struct.
125541486Smckusick  */
125641486Smckusick hpuxdumpu(vp, cred)
125741486Smckusick 	struct vnode *vp;
125841486Smckusick 	struct ucred *cred;
125941486Smckusick {
126041486Smckusick 	int error;
126141486Smckusick 	struct hpuxuser *faku;
126241486Smckusick 	struct bsdfp *bp;
126341486Smckusick 	short *foop;
126441486Smckusick 
126541486Smckusick 	faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK);
126641486Smckusick 	/*
126741486Smckusick 	 * Make sure there is no mistake about this
126841486Smckusick 	 * being a real user structure.
126941486Smckusick 	 */
127041486Smckusick 	bzero((caddr_t)faku, ctob(1));
127141486Smckusick 	/*
127241486Smckusick 	 * Fill in the process sizes.
127341486Smckusick 	 */
127441486Smckusick 	faku->hpuxu_tsize = u.u_tsize;
127541486Smckusick 	faku->hpuxu_dsize = u.u_dsize;
127641486Smckusick 	faku->hpuxu_ssize = u.u_ssize;
127741486Smckusick 	/*
127841486Smckusick 	 * Fill in the exec header for CDB.
127941486Smckusick 	 * This was saved back in exec().  As far as I can tell CDB
128041486Smckusick 	 * only uses this information to verify that a particular
128141486Smckusick 	 * core file goes with a particular binary.
128241486Smckusick 	 */
128341486Smckusick 	bcopy((caddr_t)u.u_pcb.pcb_exec,
128441486Smckusick 	      (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec));
128541486Smckusick 	/*
128641486Smckusick 	 * Adjust user's saved registers (on kernel stack) to reflect
128741486Smckusick 	 * HPUX order.  Note that HPUX saves the SR as 2 bytes not 4
128841486Smckusick 	 * so we have to move it up.
128941486Smckusick 	 */
129041486Smckusick 	faku->hpuxu_ar0 = u.u_ar0;
129141486Smckusick 	foop = (short *) u.u_ar0;
129241486Smckusick 	foop[32] = foop[33];
129341486Smckusick 	foop[33] = foop[34];
129441486Smckusick 	foop[34] = foop[35];
129541486Smckusick #ifdef FPCOPROC
129641486Smckusick 	/*
129741486Smckusick 	 * Copy 68881 registers from our PCB format to HPUX format
129841486Smckusick 	 */
129941486Smckusick 	bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs;
130041486Smckusick 	bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save,
130141486Smckusick 	      sizeof(bp->save));
130241486Smckusick 	bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl,
130341486Smckusick 	      sizeof(bp->ctrl));
130441486Smckusick 	bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg,
130541486Smckusick 	      sizeof(bp->reg));
130641486Smckusick #endif
130741486Smckusick 	/*
130841486Smckusick 	 * Slay the dragon
130941486Smckusick 	 */
131041486Smckusick 	faku->hpuxu_dragon = -1;
131141486Smckusick 	/*
131241486Smckusick 	 * Dump this artfully constructed page in place of the
131341486Smckusick 	 * user struct page.
131441486Smckusick 	 */
131541486Smckusick 	error = vn_rdwr(UIO_WRITE, vp,
131641486Smckusick 			(caddr_t)faku, ctob(1), (off_t)0,
131741486Smckusick 			UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0);
131841486Smckusick 	/*
131941486Smckusick 	 * Dump the remaining UPAGES-1 pages normally
132041486Smckusick 	 */
132141486Smckusick 	if (!error)
132241486Smckusick 		error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1),
132341486Smckusick 				ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE,
132441486Smckusick 				IO_NODELOCKED|IO_UNIT, cred, (int *)0);
132541486Smckusick 	free((caddr_t)faku, M_TEMP);
132641486Smckusick 	return(error);
132741486Smckusick }
132841486Smckusick 
132941486Smckusick /*
133041486Smckusick  * The remaining routines are essentially the same as those in kern_xxx.c
133141486Smckusick  * and vfs_xxx.c as defined under "#ifdef COMPAT".  We replicate them here
133241486Smckusick  * to avoid HPUXCOMPAT dependencies in those files and to make sure that
133341486Smckusick  * HP-UX compatibility still works even when COMPAT is not defined.
133441486Smckusick  */
133541486Smckusick /* #ifdef COMPAT */
133641486Smckusick 
133745753Smckusick #define HPUX_HZ	50
133845753Smckusick 
133945788Sbostic #include "sys/times.h"
134041486Smckusick 
134141486Smckusick /* from old timeb.h */
134241486Smckusick struct hpuxtimeb {
134341486Smckusick 	time_t	time;
134441486Smckusick 	u_short	millitm;
134541486Smckusick 	short	timezone;
134641486Smckusick 	short	dstflag;
134741486Smckusick };
134841486Smckusick 
134941486Smckusick /* ye ole stat structure */
135041486Smckusick struct	ohpuxstat {
135141486Smckusick 	dev_t	ohst_dev;
135241486Smckusick 	u_short	ohst_ino;
135341486Smckusick 	u_short ohst_mode;
135441486Smckusick 	short  	ohst_nlink;
135541486Smckusick 	short  	ohst_uid;
135641486Smckusick 	short  	ohst_gid;
135741486Smckusick 	dev_t	ohst_rdev;
135841486Smckusick 	int	ohst_size;
135941486Smckusick 	int	ohst_atime;
136041486Smckusick 	int	ohst_mtime;
136141486Smckusick 	int	ohst_ctime;
136241486Smckusick };
136341486Smckusick 
136441486Smckusick /*
136541486Smckusick  * SYS V style setpgrp()
136641486Smckusick  */
136743452Shibler ohpuxsetpgrp(p, uap, retval)
136843452Shibler 	register struct proc *p;
136943452Shibler 	int *uap, *retval;
137041486Smckusick {
137141486Smckusick 	if (p->p_pid != p->p_pgid)
137241486Smckusick 		pgmv(p, p->p_pid, 0);
137343452Shibler 	*retval = p->p_pgid;
137445753Smckusick 	return (0);
137541486Smckusick }
137641486Smckusick 
137743452Shibler ohpuxtime(p, uap, retval)
137843452Shibler 	struct proc *p;
137943452Shibler 	register struct args {
138043452Shibler 		long	*tp;
138143452Shibler 	} *uap;
138243713Smckusick 	time_t *retval;
138341486Smckusick {
138445753Smckusick 	int error = 0;
138541486Smckusick 
138641486Smckusick 	if (uap->tp)
138743452Shibler 		error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp,
138843452Shibler 				sizeof (long));
138945753Smckusick 	*retval = time.tv_sec;
139044421Skarels 	return (error);
139141486Smckusick }
139241486Smckusick 
139343452Shibler ohpuxstime(p, uap, retval)
139443452Shibler 	struct proc *p;
139543452Shibler 	register struct args {
139643452Shibler 		int	time;
139743452Shibler 	} *uap;
139843452Shibler 	int *retval;
139941486Smckusick {
140041486Smckusick 	struct timeval tv;
140143452Shibler 	int s, error;
140241486Smckusick 
140341486Smckusick 	tv.tv_sec = uap->time;
140441486Smckusick 	tv.tv_usec = 0;
140543452Shibler 	if (error = suser(u.u_cred, &u.u_acflag))
140644421Skarels 		return (error);
140741486Smckusick 
140841486Smckusick 	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
140941486Smckusick 	boottime.tv_sec += tv.tv_sec - time.tv_sec;
141041486Smckusick 	s = splhigh(); time = tv; splx(s);
141141486Smckusick 	resettodr();
141244421Skarels 	return (0);
141341486Smckusick }
141441486Smckusick 
141543452Shibler ohpuxftime(p, uap, retval)
141643452Shibler 	struct proc *p;
141743452Shibler 	register struct args {
141841486Smckusick 		struct	hpuxtimeb *tp;
141941486Smckusick 	} *uap;
142043452Shibler 	int *retval;
142143452Shibler {
142241486Smckusick 	struct hpuxtimeb tb;
142341486Smckusick 	int s;
142441486Smckusick 
142541486Smckusick 	s = splhigh();
142641486Smckusick 	tb.time = time.tv_sec;
142741486Smckusick 	tb.millitm = time.tv_usec / 1000;
142841486Smckusick 	splx(s);
142941486Smckusick 	tb.timezone = tz.tz_minuteswest;
143041486Smckusick 	tb.dstflag = tz.tz_dsttime;
143144421Skarels 	return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)));
143241486Smckusick }
143341486Smckusick 
143443452Shibler ohpuxalarm(p, uap, retval)
143543452Shibler 	register struct proc *p;
143643452Shibler 	register struct args {
143743452Shibler 		int	deltat;
143843452Shibler 	} *uap;
143943452Shibler 	int *retval;
144041486Smckusick {
144141486Smckusick 	int s = splhigh();
144241486Smckusick 
144341486Smckusick 	untimeout(realitexpire, (caddr_t)p);
144441486Smckusick 	timerclear(&p->p_realtimer.it_interval);
144543452Shibler 	*retval = 0;
144641486Smckusick 	if (timerisset(&p->p_realtimer.it_value) &&
144741486Smckusick 	    timercmp(&p->p_realtimer.it_value, &time, >))
144843452Shibler 		*retval = p->p_realtimer.it_value.tv_sec - time.tv_sec;
144941486Smckusick 	if (uap->deltat == 0) {
145041486Smckusick 		timerclear(&p->p_realtimer.it_value);
145141486Smckusick 		splx(s);
145244421Skarels 		return (0);
145341486Smckusick 	}
145441486Smckusick 	p->p_realtimer.it_value = time;
145541486Smckusick 	p->p_realtimer.it_value.tv_sec += uap->deltat;
145641486Smckusick 	timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value));
145741486Smckusick 	splx(s);
145844421Skarels 	return (0);
145941486Smckusick }
146041486Smckusick 
146143452Shibler ohpuxnice(p, uap, retval)
146243452Shibler 	register struct proc *p;
146343452Shibler 	register struct args {
146443452Shibler 		int	niceness;
146543452Shibler 	} *uap;
146643452Shibler 	int *retval;
146741486Smckusick {
146843452Shibler 	int error;
146941486Smckusick 
147043452Shibler 	error = donice(p, p, (p->p_nice-NZERO)+uap->niceness);
147143452Shibler 	if (error == 0)
147243452Shibler 		*retval = p->p_nice - NZERO;
147344421Skarels 	return (error);
147441486Smckusick }
147541486Smckusick 
147643452Shibler ohpuxtimes(p, uap, retval)
147743452Shibler 	struct proc *p;
147843452Shibler 	register struct args {
147943452Shibler 		struct	tms *tmsb;
148043452Shibler 	} *uap;
148143713Smckusick 	time_t *retval;
148241486Smckusick {
148341486Smckusick 	struct tms atms;
148443452Shibler 	int error;
148541486Smckusick 
148645753Smckusick 	atms.tms_utime = hpuxscale(&u.u_ru.ru_utime);
148745753Smckusick 	atms.tms_stime = hpuxscale(&u.u_ru.ru_stime);
148845753Smckusick 	atms.tms_cutime = hpuxscale(&u.u_cru.ru_utime);
148945753Smckusick 	atms.tms_cstime = hpuxscale(&u.u_cru.ru_stime);
149043452Shibler 	error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms));
149143452Shibler 	if (error == 0)
149245753Smckusick 		*retval = hpuxscale(&time) - hpuxscale(&boottime);
149344421Skarels 	return (error);
149441486Smckusick }
149541486Smckusick 
149645753Smckusick /*
149745753Smckusick  * Doesn't exactly do what the documentation says.
149845753Smckusick  * What we really do is return 1/HPUX_HZ-th of a second since that
149945753Smckusick  * is what HP-UX returns.
150045753Smckusick  */
150145753Smckusick hpuxscale(tvp)
150241486Smckusick 	register struct timeval *tvp;
150341486Smckusick {
150445753Smckusick 	return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000);
150541486Smckusick }
150641486Smckusick 
150741486Smckusick /*
150841486Smckusick  * Set IUPD and IACC times on file.
150941486Smckusick  * Can't set ICHG.
151041486Smckusick  */
151143452Shibler ohpuxutime(p, uap, retval)
151243452Shibler 	struct proc *p;
151341486Smckusick 	register struct a {
151441486Smckusick 		char	*fname;
151541486Smckusick 		time_t	*tptr;
151643452Shibler 	} *uap;
151743452Shibler 	int *retval;
151843452Shibler {
151941486Smckusick 	struct vattr vattr;
152041486Smckusick 	time_t tv[2];
152141486Smckusick 	register struct vnode *vp;
152241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
152343452Shibler 	int error;
152441486Smckusick 
152541486Smckusick 	if (uap->tptr) {
152643452Shibler 		error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
152743452Shibler 		if (error)
152844421Skarels 			return (error);
152941486Smckusick 	} else
153041486Smckusick 		tv[0] = tv[1] = time.tv_sec;
153141486Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
153241486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
153341486Smckusick 	ndp->ni_dirp = uap->fname;
153441486Smckusick 	vattr_null(&vattr);
153541486Smckusick 	vattr.va_atime.tv_sec = tv[0];
153641486Smckusick 	vattr.va_atime.tv_usec = 0;
153741486Smckusick 	vattr.va_mtime.tv_sec = tv[1];
153841486Smckusick 	vattr.va_mtime.tv_usec = 0;
153943452Shibler 	if (error = namei(ndp))
154044421Skarels 		return (error);
154141486Smckusick 	vp = ndp->ni_vp;
154242154Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
154343452Shibler 		error = EROFS;
154441486Smckusick 	else
154543452Shibler 		error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
154641486Smckusick 	vput(vp);
154744421Skarels 	return (error);
154841486Smckusick }
154941486Smckusick 
155043452Shibler ohpuxpause(p, uap, retval)
155143452Shibler 	struct proc *p;
155243452Shibler 	int *uap, *retval;
155341486Smckusick {
155442155Skarels 	(void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0);
155542155Skarels 	/* always return EINTR rather than ERESTART... */
155644421Skarels 	return (EINTR);
155741486Smckusick }
155841486Smckusick 
155941486Smckusick /*
156041486Smckusick  * The old fstat system call.
156141486Smckusick  */
156243452Shibler ohpuxfstat(p, uap, retval)
156343452Shibler 	struct proc *p;
156443452Shibler 	register struct args {
156541486Smckusick 		int	fd;
156641486Smckusick 		struct ohpuxstat *sb;
156743452Shibler 	} *uap;
156843452Shibler 	int *retval;
156943452Shibler {
1570*45923Smckusick 	register struct filedesc *fdp = p->p_fd;
157141486Smckusick 	struct file *fp;
157241486Smckusick 
1573*45923Smckusick 	if (((unsigned)uap->fd) >= fdp->fd_maxfiles ||
1574*45923Smckusick 	    (fp = OFILE(fdp, uap->fd)) == NULL)
157544421Skarels 		return (EBADF);
157643452Shibler 	if (fp->f_type != DTYPE_VNODE)
157744421Skarels 		return (EINVAL);
157844421Skarels 	return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb));
157941486Smckusick }
158041486Smckusick 
158141486Smckusick /*
158241486Smckusick  * Old stat system call.  This version follows links.
158341486Smckusick  */
158443452Shibler ohpuxstat(p, uap, retval)
158543452Shibler 	struct proc *p;
158643452Shibler 	register struct args {
158741486Smckusick 		char	*fname;
158841486Smckusick 		struct ohpuxstat *sb;
158943452Shibler 	} *uap;
159043452Shibler 	int *retval;
159143452Shibler {
159241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
159343452Shibler 	int error;
159441486Smckusick 
159541486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
159641486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
159741486Smckusick 	ndp->ni_dirp = uap->fname;
159843452Shibler 	if (error = namei(ndp))
159944421Skarels 		return (error);
160043452Shibler 	error = ohpuxstat1(ndp->ni_vp, uap->sb);
160141486Smckusick 	vput(ndp->ni_vp);
160244421Skarels 	return (error);
160341486Smckusick }
160441486Smckusick 
160541486Smckusick int
160641486Smckusick ohpuxstat1(vp, ub)
160741486Smckusick 	register struct vnode *vp;
160841486Smckusick 	struct ohpuxstat *ub;
160941486Smckusick {
161041486Smckusick 	struct ohpuxstat ds;
161141486Smckusick 	struct vattr vattr;
161241486Smckusick 	register int error;
161341486Smckusick 
161441486Smckusick 	error = VOP_GETATTR(vp, &vattr, u.u_cred);
161541486Smckusick 	if (error)
161641486Smckusick 		return(error);
161741486Smckusick 	/*
161841486Smckusick 	 * Copy from inode table
161941486Smckusick 	 */
162041486Smckusick 	ds.ohst_dev = vattr.va_fsid;
162141486Smckusick 	ds.ohst_ino = (short)vattr.va_fileid;
162241486Smckusick 	ds.ohst_mode = (u_short)vattr.va_mode;
162341486Smckusick 	ds.ohst_nlink = vattr.va_nlink;
162441486Smckusick 	ds.ohst_uid = (short)vattr.va_uid;
162541486Smckusick 	ds.ohst_gid = (short)vattr.va_gid;
162641486Smckusick 	ds.ohst_rdev = (dev_t)vattr.va_rdev;
162741486Smckusick 	ds.ohst_size = (int)vattr.va_size;
162841486Smckusick 	ds.ohst_atime = (int)vattr.va_atime.tv_sec;
162941486Smckusick 	ds.ohst_mtime = (int)vattr.va_mtime.tv_sec;
163041486Smckusick 	ds.ohst_ctime = (int)vattr.va_ctime.tv_sec;
163141486Smckusick 	return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)));
163241486Smckusick }
163341486Smckusick /* #endif */
163441486Smckusick 
163541486Smckusick #endif
1636