xref: /csrg-svn/sys/hp/hpux/hpux_compat.c (revision 42352)
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  *
1241486Smckusick  * from: Utah $Hdr: hpux_compat.c 1.33 89/08/23$
1341486Smckusick  *
14*42352Smckusick  *	@(#)hpux_compat.c	7.5 (Berkeley) 05/25/90
1541486Smckusick  */
1641486Smckusick 
1741486Smckusick /*
1841486Smckusick  * Various HPUX compatibility routines
1941486Smckusick  */
2041486Smckusick 
2141486Smckusick #ifdef HPUXCOMPAT
2241486Smckusick 
2341486Smckusick #include "param.h"
2441486Smckusick #include "systm.h"
2541486Smckusick #include "syscontext.h"
2641486Smckusick #include "kernel.h"
2741486Smckusick #include "proc.h"
2841486Smckusick #include "buf.h"
2941486Smckusick #include "wait.h"
3041486Smckusick #include "file.h"
3141486Smckusick #include "vnode.h"
3241486Smckusick #include "ioctl.h"
3341486Smckusick #include "uio.h"
3441486Smckusick #include "ptrace.h"
3541486Smckusick #include "stat.h"
3641486Smckusick #include "syslog.h"
3741486Smckusick #include "malloc.h"
3841486Smckusick #include "mount.h"
3941486Smckusick #include "ipc.h"
4041486Smckusick 
4141486Smckusick #include "machine/cpu.h"
4241486Smckusick #include "machine/reg.h"
4341486Smckusick #include "machine/psl.h"
4441486Smckusick #include "machine/vmparam.h"
4541486Smckusick #include "hpux.h"
4641486Smckusick #include "hpux_termio.h"
4741486Smckusick 
4841486Smckusick #ifdef DEBUG
4941486Smckusick int unimpresponse = 0;
5041486Smckusick #endif
5141486Smckusick 
5241486Smckusick /* "tick" value for HZ==50 */
5341486Smckusick int hpuxtick = 1000000 / 50;
5441486Smckusick 
5541486Smckusick /* SYS5 style UTSNAME info */
5641486Smckusick struct hpuxutsname protoutsname = {
5741486Smckusick 	"4.4bsd", "", "2.0", "B", "9000/3?0", ""
5841486Smckusick };
5941486Smckusick 
6041486Smckusick /* 6.0 and later style context */
6141486Smckusick #ifdef FPCOPROC
6241486Smckusick char hpuxcontext[] =
6341486Smckusick 	"standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default";
6441486Smckusick #else
6541486Smckusick char hpuxcontext[] =
6641486Smckusick 	"standalone HP-MC68020 HP-MC68010 localroot default";
6741486Smckusick #endif
6841486Smckusick 
6941486Smckusick /* YP domainname */
7041486Smckusick char	domainname[MAXHOSTNAMELEN] = "unknown";
7141486Smckusick int	domainnamelen = 7;
7241486Smckusick 
7341486Smckusick #define NERR	79
7441486Smckusick #define BERR	1000
7541486Smckusick 
7641486Smckusick /* indexed by BSD errno */
7741486Smckusick short bsdtohpuxerrnomap[NERR] = {
7841486Smckusick /*00*/	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
7941486Smckusick /*10*/	 10,  45,  12,  13,  14,  15,  16,  17,  18,  19,
8041486Smckusick /*20*/	 20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
8141486Smckusick /*30*/	 30,  31,  32,  33,  34, 246, 245, 244, 216, 217,
8241486Smckusick /*40*/	218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
8341486Smckusick /*50*/	228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
8441486Smckusick /*60*/	238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,
8541486Smckusick /*70*/   70,  71,BERR,BERR,BERR,BERR,BERR,  46,BERR
8641486Smckusick };
8741486Smckusick 
8841486Smckusick notimp(code, nargs)
8941486Smckusick {
9041486Smckusick #ifdef DEBUG
9141486Smckusick 	int *argp = u.u_ap;
9241486Smckusick 	extern char *hpuxsyscallnames[];
9341486Smckusick 
9441486Smckusick 	printf("HPUX %s(", hpuxsyscallnames[code]);
9541486Smckusick 	if (nargs)
9641486Smckusick 		while (nargs--)
9741486Smckusick 			printf("%x%c", *argp++, nargs? ',' : ')');
9841486Smckusick 	else
9941486Smckusick 		printf(")");
10041486Smckusick 	printf("\n");
10141486Smckusick 	switch (unimpresponse) {
10241486Smckusick 	case 0:
10341486Smckusick 		nosys();
10441486Smckusick 		break;
10541486Smckusick 	case 1:
10641486Smckusick 		u.u_error = EINVAL;
10741486Smckusick 		break;
10841486Smckusick 	}
10941486Smckusick #else
11041486Smckusick 	nosys();
11141486Smckusick #endif
11241486Smckusick 	uprintf("HPUX system call %d not implemented\n", code);
11341486Smckusick }
11441486Smckusick 
11541486Smckusick /*
11641486Smckusick  * HPUX versions of wait and wait3 actually pass the parameters
11741486Smckusick  * (status pointer, options, rusage) into the kernel rather than
118*42352Smckusick  * handling it in the C library stub.  We also need to map any
119*42352Smckusick  * termination signal from BSD to HPUX.
12041486Smckusick  */
12141486Smckusick hpuxwait3()
12241486Smckusick {
12341486Smckusick 	struct a {
12441486Smckusick 		int	*status;
12541486Smckusick 		int	options;
12641486Smckusick 		int	rusage;
12741486Smckusick 	} *uap = (struct a *)u.u_ap;
12841486Smckusick 
12941486Smckusick 	/* rusage pointer must be zero */
13041486Smckusick 	if (uap->rusage) {
13141486Smckusick 		u.u_error = EINVAL;
13241486Smckusick 		return;
13341486Smckusick 	}
13441486Smckusick 	u.u_ar0[PS] = PSL_ALLCC;
13541486Smckusick 	u.u_ar0[R0] = uap->options;
13641486Smckusick 	u.u_ar0[R1] = uap->rusage;
13741486Smckusick 	hpuxwait();
13841486Smckusick }
13941486Smckusick 
14041486Smckusick hpuxwait()
14141486Smckusick {
14241486Smckusick 	int sig, *statp;
14341486Smckusick 	struct a {
14441486Smckusick 		int	*status;
14541486Smckusick 	} *uap = (struct a *)u.u_ap;
14641486Smckusick 
14741486Smckusick 	statp = uap->status;	/* owait clobbers first arg */
14841486Smckusick 	owait();
14941486Smckusick 	/*
15041486Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
15141486Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
15241486Smckusick 	 */
15342155Skarels 	if (u.u_error == ERESTART)
15441486Smckusick 		u.u_error = EINTR;
15541486Smckusick 	if (u.u_error)
15641486Smckusick 		return;
15741486Smckusick 	sig = u.u_r.r_val2 & 0xFF;
15841486Smckusick 	if (sig == WSTOPPED) {
15941486Smckusick 		sig = (u.u_r.r_val2 >> 8) & 0xFF;
16041486Smckusick 		u.u_r.r_val2 = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
16141486Smckusick 	} else if (sig)
16241486Smckusick 		u.u_r.r_val2 = (u.u_r.r_val2 & 0xFF00) |
16341486Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
16441486Smckusick 	if (statp)
16541486Smckusick 		if (suword((caddr_t)statp, u.u_r.r_val2))
16641486Smckusick 			u.u_error = EFAULT;
16741486Smckusick }
16841486Smckusick 
169*42352Smckusick hpuxwaitpid()
170*42352Smckusick {
171*42352Smckusick 	int sig, *statp;
172*42352Smckusick 	struct a {
173*42352Smckusick 		int	pid;
174*42352Smckusick 		int	*status;
175*42352Smckusick 		int	options;
176*42352Smckusick 		struct	rusage *rusage;	/* wait4 arg */
177*42352Smckusick 	} *uap = (struct a *)u.u_ap;
178*42352Smckusick 
179*42352Smckusick 	uap->rusage = 0;
180*42352Smckusick 	wait4();
181*42352Smckusick 	/*
182*42352Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
183*42352Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
184*42352Smckusick 	 */
185*42352Smckusick 	if (u.u_error == ERESTART)
186*42352Smckusick 		u.u_error = EINTR;
187*42352Smckusick 	if (u.u_error)
188*42352Smckusick 		return;
189*42352Smckusick 	sig = u.u_r.r_val2 & 0xFF;
190*42352Smckusick 	if (sig == WSTOPPED) {
191*42352Smckusick 		sig = (u.u_r.r_val2 >> 8) & 0xFF;
192*42352Smckusick 		u.u_r.r_val2 = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
193*42352Smckusick 	} else if (sig)
194*42352Smckusick 		u.u_r.r_val2 = (u.u_r.r_val2 & 0xFF00) |
195*42352Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
196*42352Smckusick 	if (statp)
197*42352Smckusick 		if (suword((caddr_t)statp, u.u_r.r_val2))
198*42352Smckusick 			u.u_error = EFAULT;
199*42352Smckusick }
200*42352Smckusick 
20141486Smckusick /*
20241486Smckusick  * Must remap some bits in the mode mask.
20341486Smckusick  * O_CREAT, O_TRUNC, and O_EXCL must be remapped,
20441486Smckusick  * O_SYNCIO (0100000) is removed entirely.
20541486Smckusick  */
20641486Smckusick hpuxopen(scp)
20741486Smckusick 	register struct syscontext *scp;
20841486Smckusick {
20941486Smckusick 	struct a {
21041486Smckusick 		char	*fname;
21141486Smckusick 		int	mode;
21241486Smckusick 		int	crtmode;
21341486Smckusick 	} *uap = (struct a *) scp->sc_ap;
21441486Smckusick 	struct nameidata *ndp = &scp->sc_nd;
21541486Smckusick 	int mode;
21641486Smckusick 
21741486Smckusick 	mode = uap->mode;
21841486Smckusick 	uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT);
21941486Smckusick 	if (mode & HPUXFCREAT) {
22041486Smckusick 		/*
22141486Smckusick 		 * simulate the pre-NFS behavior that opening a
22241486Smckusick 		 * file for READ+CREATE ignores the CREATE (unless
22341486Smckusick 		 * EXCL is set in which case we will return the
22441486Smckusick 		 * proper error).
22541486Smckusick 		 */
22641486Smckusick 		if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE))
22741486Smckusick 			uap->mode |= FCREAT;
22841486Smckusick 	}
22941486Smckusick 	if (mode & HPUXFTRUNC)
23041486Smckusick 		uap->mode |= FTRUNC;
23141486Smckusick 	if (mode & HPUXFEXCL)
23241486Smckusick 		uap->mode |= FEXCL;
23341486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
23441486Smckusick 	ndp->ni_dirp = uap->fname;
23541486Smckusick 	RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp,
23641486Smckusick 		&scp->sc_retval1));
23741486Smckusick }
23841486Smckusick 
23941486Smckusick hpuxfcntl()
24041486Smckusick {
24141486Smckusick 	register struct a {
24241486Smckusick 		int	fdes;
24341486Smckusick 		int	cmd;
24441486Smckusick 		int	arg;
24541486Smckusick 	} *uap = (struct a *)u.u_ap;
24641486Smckusick 	int mode;
24741486Smckusick 
24841486Smckusick 	switch (uap->cmd) {
24941486Smckusick 	case F_SETFL:
25041486Smckusick 		uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE);
25141486Smckusick 		break;
25241486Smckusick 	case F_GETFL:
25341486Smckusick 	case F_DUPFD:
25441486Smckusick 	case F_GETFD:
25541486Smckusick 	case F_SETFD:
25641486Smckusick 		break;
25741486Smckusick 	default:
25841486Smckusick 		u.u_error = EINVAL;
25941486Smckusick 		return;
26041486Smckusick 	}
26141486Smckusick 	fcntl();
26241486Smckusick 	if (u.u_error == 0 && uap->arg == F_GETFL) {
26341486Smckusick 		mode = u.u_r.r_val1;
26441486Smckusick 		u.u_r.r_val1 &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE);
26541486Smckusick 		if (mode & FCREAT)
26641486Smckusick 			u.u_r.r_val1 |= HPUXFCREAT;
26741486Smckusick 		if (mode & FTRUNC)
26841486Smckusick 			u.u_r.r_val1 |= HPUXFTRUNC;
26941486Smckusick 		if (mode & FEXCL)
27041486Smckusick 			u.u_r.r_val1 |= HPUXFEXCL;
27141486Smckusick 	}
27241486Smckusick }
27341486Smckusick 
27441486Smckusick /*
27541486Smckusick  * Read and write should return a 0 count when an operation
27641486Smckusick  * on a VNODE would block, not an error.  Sockets appear to
27741486Smckusick  * return EWOULDBLOCK (at least in 6.2).  This is probably
27841486Smckusick  * not entirely correct, since the behavior is only defined
27941486Smckusick  * for pipes and tty type devices.
28041486Smckusick  */
28141486Smckusick hpuxread()
28241486Smckusick {
28341486Smckusick 	struct a {
28441486Smckusick 		int	fd;
28541486Smckusick 	} *uap = (struct a *)u.u_ap;
28641486Smckusick 
28741486Smckusick 	read();
28841486Smckusick 	if (u.u_error == EWOULDBLOCK &&
28941486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
29041486Smckusick 		u.u_error = 0;
29141486Smckusick 		u.u_r.r_val1 = 0;
29241486Smckusick 	}
29341486Smckusick }
29441486Smckusick 
29541486Smckusick hpuxwrite()
29641486Smckusick {
29741486Smckusick 	struct a {
29841486Smckusick 		int	fd;
29941486Smckusick 	} *uap = (struct a *)u.u_ap;
30041486Smckusick 
30141486Smckusick 	write();
30241486Smckusick 	if (u.u_error == EWOULDBLOCK &&
30341486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
30441486Smckusick 		u.u_error = 0;
30541486Smckusick 		u.u_r.r_val1 = 0;
30641486Smckusick 	}
30741486Smckusick }
30841486Smckusick 
30941486Smckusick hpuxreadv()
31041486Smckusick {
31141486Smckusick 	struct a {
31241486Smckusick 		int	fd;
31341486Smckusick 	} *uap = (struct a *)u.u_ap;
31441486Smckusick 
31541486Smckusick 	readv();
31641486Smckusick 	if (u.u_error == EWOULDBLOCK &&
31741486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
31841486Smckusick 		u.u_error = 0;
31941486Smckusick 		u.u_r.r_val1 = 0;
32041486Smckusick 	}
32141486Smckusick }
32241486Smckusick 
32341486Smckusick hpuxwritev()
32441486Smckusick {
32541486Smckusick 	struct a {
32641486Smckusick 		int	fd;
32741486Smckusick 	} *uap = (struct a *)u.u_ap;
32841486Smckusick 
32941486Smckusick 	writev();
33041486Smckusick 	if (u.u_error == EWOULDBLOCK &&
33141486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
33241486Smckusick 		u.u_error = 0;
33341486Smckusick 		u.u_r.r_val1 = 0;
33441486Smckusick 	}
33541486Smckusick }
33641486Smckusick 
33741486Smckusick /*
33841486Smckusick  * 4.3bsd dup allows dup2 to come in on the same syscall entry
33941486Smckusick  * and hence allows two arguments.  HPUX dup has only one arg.
34041486Smckusick  */
34141486Smckusick hpuxdup()
34241486Smckusick {
34341486Smckusick 	register struct a {
34441486Smckusick 		int	i;
34541486Smckusick 	} *uap = (struct a *)u.u_ap;
34641486Smckusick 	struct file *fp;
34741486Smckusick 	int j;
34841486Smckusick 
34941486Smckusick 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) {
35041486Smckusick 		u.u_error = EBADF;
35141486Smckusick 		return;
35241486Smckusick 	}
35341486Smckusick 	u.u_error = ufalloc(0, &j);
35441486Smckusick 	if (u.u_error)
35541486Smckusick 		return;
35641486Smckusick 	u.u_r.r_val1 = j;
35741486Smckusick 	dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
35841486Smckusick }
35941486Smckusick 
36041486Smckusick hpuxuname()
36141486Smckusick {
36241486Smckusick 	register struct a {
36341486Smckusick 		struct hpuxutsname *uts;
36441486Smckusick 		int dev;
36541486Smckusick 		int request;
36641486Smckusick 	} *uap = (struct a *)u.u_ap;
36741486Smckusick 	register int i;
36841486Smckusick 
36941486Smckusick 	switch (uap->request) {
37041486Smckusick 	/* uname */
37141486Smckusick 	case 0:
37241486Smckusick 		/* fill in machine type */
37341486Smckusick 		switch (machineid) {
37441486Smckusick 		case HP_320:
37541486Smckusick 			protoutsname.machine[6] = '2';
37641486Smckusick 			break;
37741486Smckusick 		/* includes 318 and 319 */
37841486Smckusick 		case HP_330:
37941486Smckusick 			protoutsname.machine[6] = '3';
38041486Smckusick 			break;
38141486Smckusick 		case HP_340:
38241486Smckusick 			protoutsname.machine[6] = '4';
38341486Smckusick 			break;
38441486Smckusick 		case HP_350:
38541486Smckusick 			protoutsname.machine[6] = '5';
38641486Smckusick 			break;
38741486Smckusick 		case HP_360:
38841486Smckusick 			protoutsname.machine[6] = '6';
38941486Smckusick 			break;
39041486Smckusick 		case HP_370:
39141486Smckusick 			protoutsname.machine[6] = '7';
39241486Smckusick 			break;
39341486Smckusick 		}
39441486Smckusick 		/* copy hostname (sans domain) to nodename */
39541486Smckusick 		for (i = 0; i < 9 && hostname[i] != '.'; i++)
39641486Smckusick 			protoutsname.nodename[i] = hostname[i];
39741486Smckusick 		u.u_error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts,
39841486Smckusick 				    sizeof(struct hpuxutsname));
39941486Smckusick 		break;
40041486Smckusick 	/* ustat - who cares? */
40141486Smckusick 	case 2:
40241486Smckusick 	default:
40341486Smckusick 		u.u_error = EINVAL;
40441486Smckusick 		break;
40541486Smckusick 	}
40641486Smckusick }
40741486Smckusick 
40841486Smckusick hpuxstat()
40941486Smckusick {
41041486Smckusick 	struct a {
41141486Smckusick 		char	*fname;
41241486Smckusick 		struct hpuxstat *hsb;
41341486Smckusick 	} *uap = (struct a *)u.u_ap;
41441486Smckusick 
41541486Smckusick 	u.u_error = hpuxstat1(uap->fname, uap->hsb, FOLLOW);
41641486Smckusick }
41741486Smckusick 
41841486Smckusick hpuxlstat()
41941486Smckusick {
42041486Smckusick 	struct a {
42141486Smckusick 		char	*fname;
42241486Smckusick 		struct	hpuxstat *hsb;
42341486Smckusick 	} *uap = (struct a *) u.u_ap;
42441486Smckusick 
42541486Smckusick 	u.u_error = hpuxstat1(uap->fname, uap->hsb, NOFOLLOW);
42641486Smckusick }
42741486Smckusick 
42841486Smckusick hpuxfstat()
42941486Smckusick {
43041486Smckusick 	register struct file *fp;
43141486Smckusick 	register struct a {
43241486Smckusick 		int	fdes;
43341486Smckusick 		struct	hpuxstat *hsb;
43441486Smckusick 	} *uap = (struct a *)u.u_ap;
43541486Smckusick 	struct stat sb;
43641486Smckusick 
43741486Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
43841486Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL) {
43941486Smckusick 		u.u_error = EBADF;
44041486Smckusick 		return;
44141486Smckusick 	}
44241486Smckusick 	switch (fp->f_type) {
44341486Smckusick 
44441486Smckusick 	case DTYPE_VNODE:
44541486Smckusick 		u.u_error = vn_stat((struct vnode *)fp->f_data, &sb);
44641486Smckusick 		break;
44741486Smckusick 
44841486Smckusick 	case DTYPE_SOCKET:
44941486Smckusick 		u.u_error = soo_stat((struct socket *)fp->f_data, &sb);
45041486Smckusick 		break;
45141486Smckusick 
45241486Smckusick 	default:
45341486Smckusick 		panic("fstat");
45441486Smckusick 		/*NOTREACHED*/
45541486Smckusick 	}
45641486Smckusick 	/* is this right for sockets?? */
45741486Smckusick 	if (u.u_error == 0)
45841486Smckusick 		u.u_error = bsdtohpuxstat(&sb, uap->hsb);
45941486Smckusick }
46041486Smckusick 
46141486Smckusick hpuxulimit()
46241486Smckusick {
46341486Smckusick 	struct a {
46441486Smckusick 		int	cmd;
46541486Smckusick 		long	newlimit;
46641486Smckusick 	} *uap = (struct a *)u.u_ap;
46741486Smckusick 	struct rlimit *limp;
46841486Smckusick 
46941486Smckusick 	limp = &u.u_rlimit[RLIMIT_FSIZE];
47041486Smckusick 	switch (uap->cmd) {
47141486Smckusick 	case 2:
47241486Smckusick 		uap->newlimit *= 512;
47341486Smckusick 		if (uap->newlimit > limp->rlim_max &&
47441486Smckusick 		    (u.u_error = suser(u.u_cred, &u.u_acflag)))
47541486Smckusick 			break;
47641486Smckusick 		limp->rlim_cur = limp->rlim_max = uap->newlimit;
47741486Smckusick 		/* else fall into... */
47841486Smckusick 
47941486Smckusick 	case 1:
48041486Smckusick 		u.u_r.r_off = limp->rlim_max / 512;
48141486Smckusick 		break;
48241486Smckusick 
48341486Smckusick 	case 3:
48441486Smckusick 		limp = &u.u_rlimit[RLIMIT_DATA];
48541486Smckusick 		u.u_r.r_off = ctob(u.u_tsize) + limp->rlim_max;
48641486Smckusick 		break;
48741486Smckusick 
48841486Smckusick 	default:
48941486Smckusick 		u.u_error = EINVAL;
49041486Smckusick 		break;
49141486Smckusick 	}
49241486Smckusick }
49341486Smckusick 
49441486Smckusick /*
49541486Smckusick  * Map "real time" priorities 0 (high) thru 127 (low) into nice
49641486Smckusick  * values -16 (high) thru -1 (low).
49741486Smckusick  */
49841486Smckusick hpuxrtprio()
49941486Smckusick {
50041486Smckusick 	register struct a {
50141486Smckusick 		int pid;
50241486Smckusick 		int prio;
50341486Smckusick 	} *uap = (struct a *)u.u_ap;
50441486Smckusick 	struct proc *p;
50541486Smckusick 	int nice;
50641486Smckusick 
50741486Smckusick 	if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX &&
50841486Smckusick 	    uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) {
50941486Smckusick 		u.u_error = EINVAL;
51041486Smckusick 		return;
51141486Smckusick 	}
51241486Smckusick 	if (uap->pid == 0)
51341486Smckusick 		p = u.u_procp;
51441486Smckusick 	else if ((p = pfind(uap->pid)) == 0) {
51541486Smckusick 		u.u_error = ESRCH;
51641486Smckusick 		return;
51741486Smckusick 	}
51841486Smckusick 	nice = p->p_nice;
51941486Smckusick 	if (nice < NZERO)
52041486Smckusick 		u.u_r.r_val1 = (nice + 16) << 3;
52141486Smckusick 	else
52241486Smckusick 		u.u_r.r_val1 = RTPRIO_RTOFF;
52341486Smckusick 	switch (uap->prio) {
52441486Smckusick 
52541486Smckusick 	case RTPRIO_NOCHG:
52641486Smckusick 		return;
52741486Smckusick 
52841486Smckusick 	case RTPRIO_RTOFF:
52941486Smckusick 		if (nice >= NZERO)
53041486Smckusick 			return;
53141486Smckusick 		nice = NZERO;
53241486Smckusick 		break;
53341486Smckusick 
53441486Smckusick 	default:
53541486Smckusick 		nice = (uap->prio >> 3) - 16;
53641486Smckusick 		break;
53741486Smckusick 	}
53841486Smckusick 	donice(p, nice);
53941486Smckusick 	if (u.u_error == EACCES)
54041486Smckusick 		u.u_error = EPERM;
54141486Smckusick }
54241486Smckusick 
54341486Smckusick /*
54441486Smckusick  * Kudos to HP folks for using such mnemonic names so I could figure
54541486Smckusick  * out what this guy does.
54641486Smckusick  */
54741486Smckusick hpuxadvise()
54841486Smckusick {
54941486Smckusick 	struct a {
55041486Smckusick 		int	arg;
55141486Smckusick 	} *uap = (struct a *) u.u_ap;
55241486Smckusick 
55341486Smckusick 	switch (uap->arg) {
55441486Smckusick 	case 0:
55541486Smckusick 		u.u_pcb.pcb_flags |= PCB_HPUXMMAP;
55641486Smckusick 		break;
55741486Smckusick 	case 1:
55841486Smckusick 		ICIA();
55941486Smckusick 		break;
56041486Smckusick 	case 2:
56141486Smckusick 		DCIA();
56241486Smckusick 		break;
56341486Smckusick 	default:
56441486Smckusick 		u.u_error = EINVAL;
56541486Smckusick 		break;
56641486Smckusick 	}
56741486Smckusick }
56841486Smckusick 
56941486Smckusick hpuxptrace()
57041486Smckusick {
57141486Smckusick 	struct a {
57241486Smckusick 		int	req;
57341486Smckusick 		int	pid;
57441486Smckusick 		int	*addr;
57541486Smckusick 		int	data;
57641486Smckusick 	} *uap = (struct a *)u.u_ap;
57741486Smckusick 
57841486Smckusick 	if (uap->req == PT_STEP || uap->req == PT_CONTINUE) {
57941486Smckusick 		if (uap->data) {
58041486Smckusick 			uap->data = hpuxtobsdsig(uap->data);
58141486Smckusick 			if (uap->data == 0)
58241486Smckusick 				uap->data = NSIG;
58341486Smckusick 		}
58441486Smckusick 	}
58541486Smckusick 	ptrace();
58641486Smckusick }
58741486Smckusick 
58841486Smckusick hpuxgetdomainname()
58941486Smckusick {
59041486Smckusick 	register struct a {
59141486Smckusick 		char	*domainname;
59241486Smckusick 		u_int	len;
59341486Smckusick 	} *uap = (struct a *)u.u_ap;
59441486Smckusick 
59541486Smckusick 	if (uap->len > domainnamelen + 1)
59641486Smckusick 		uap->len = domainnamelen + 1;
59741486Smckusick 	u.u_error = copyout(domainname, uap->domainname, uap->len);
59841486Smckusick }
59941486Smckusick 
60041486Smckusick hpuxsetdomainname()
60141486Smckusick {
60241486Smckusick 	register struct a {
60341486Smckusick 		char	*domainname;
60441486Smckusick 		u_int	len;
60541486Smckusick 	} *uap = (struct a *)u.u_ap;
60641486Smckusick 
60741486Smckusick 	if (u.u_error = suser(u.u_cred, &u.u_acflag))
60841486Smckusick 		return;
60941486Smckusick 	if (uap->len > sizeof (domainname) - 1) {
61041486Smckusick 		u.u_error = EINVAL;
61141486Smckusick 		return;
61241486Smckusick 	}
61341486Smckusick 	domainnamelen = uap->len;
61441486Smckusick 	u.u_error = copyin(uap->domainname, domainname, uap->len);
61541486Smckusick 	domainname[domainnamelen] = 0;
61641486Smckusick }
61741486Smckusick 
61841486Smckusick #ifdef SYSVSHM
61941486Smckusick hpuxshmat()
62041486Smckusick {
62141486Smckusick 	shmat(u.u_ap);
62241486Smckusick }
62341486Smckusick 
62441486Smckusick hpuxshmctl()
62541486Smckusick {
62641486Smckusick 	shmctl(u.u_ap);
62741486Smckusick }
62841486Smckusick 
62941486Smckusick hpuxshmdt()
63041486Smckusick {
63141486Smckusick 	shmdt(u.u_ap);
63241486Smckusick }
63341486Smckusick 
63441486Smckusick hpuxshmget()
63541486Smckusick {
63641486Smckusick 	shmget(u.u_ap);
63741486Smckusick }
63841486Smckusick #endif
63941486Smckusick 
64041486Smckusick /*
64141486Smckusick  * Fake semaphore routines, just don't return an error.
64241486Smckusick  * Should be adequate for starbase to run.
64341486Smckusick  */
64441486Smckusick hpuxsemctl()
64541486Smckusick {
64641486Smckusick 	struct a {
64741486Smckusick 		int semid;
64841486Smckusick 		u_int semnum;
64941486Smckusick 		int cmd;
65041486Smckusick 		int arg;
65141486Smckusick 	} *uap = (struct a *)u.u_ap;
65241486Smckusick 
65341486Smckusick 	/* XXX: should do something here */
65441486Smckusick }
65541486Smckusick 
65641486Smckusick hpuxsemget()
65741486Smckusick {
65841486Smckusick 	struct a {
65941486Smckusick 		key_t key;
66041486Smckusick 		int nsems;
66141486Smckusick 		int semflg;
66241486Smckusick 	} *uap = (struct a *)u.u_ap;
66341486Smckusick 
66441486Smckusick 	/* XXX: should do something here */
66541486Smckusick }
66641486Smckusick 
66741486Smckusick hpuxsemop()
66841486Smckusick {
66941486Smckusick 	struct a {
67041486Smckusick 		int semid;
67141486Smckusick 		struct sembuf *sops;
67241486Smckusick 		u_int nsops;
67341486Smckusick 	} *uap = (struct a *)u.u_ap;
67441486Smckusick 
67541486Smckusick 	/* XXX: should do something here */
67641486Smckusick }
67741486Smckusick 
67841486Smckusick /* convert from BSD to HPUX errno */
67941486Smckusick bsdtohpuxerrno(err)
68041486Smckusick 	int err;
68141486Smckusick {
68241486Smckusick 	if (err < 0 || err >= NERR)
68341486Smckusick 		return(BERR);
68441486Smckusick 	return((int)bsdtohpuxerrnomap[err]);
68541486Smckusick }
68641486Smckusick 
68741486Smckusick hpuxstat1(fname, hsb, follow)
68841486Smckusick 	char *fname;
68941486Smckusick 	struct hpuxstat *hsb;
69041486Smckusick 	int follow;
69141486Smckusick {
69241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
69341486Smckusick 	struct stat sb;
69441486Smckusick 	int error;
69541486Smckusick 
69641486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
69741486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
69841486Smckusick 	ndp->ni_dirp = fname;
69941486Smckusick 	if (error = namei(ndp))
70041486Smckusick 		return (error);
70141486Smckusick 	error = vn_stat(ndp->ni_vp, &sb);
70241486Smckusick 	vput(ndp->ni_vp);
70341486Smckusick 	if (error == 0)
70441486Smckusick 		error = bsdtohpuxstat(&sb, hsb);
70541486Smckusick 	return (error);
70641486Smckusick }
70741486Smckusick 
70841486Smckusick #include "grf.h"
70941486Smckusick 
71041486Smckusick bsdtohpuxstat(sb, hsb)
71141486Smckusick 	struct stat *sb;
71241486Smckusick 	struct hpuxstat *hsb;
71341486Smckusick {
71441486Smckusick 	struct hpuxstat ds;
71541486Smckusick 
71641486Smckusick 	bzero((caddr_t)&ds, sizeof(ds));
71741486Smckusick 	ds.hst_dev = sb->st_dev;
71841486Smckusick 	ds.hst_ino = (u_long)sb->st_ino;
71941486Smckusick 	ds.hst_mode = sb->st_mode;
72041486Smckusick 	ds.hst_nlink = sb->st_nlink;
72141486Smckusick 	ds.hst_uid = (u_short)sb->st_uid;
72241486Smckusick 	ds.hst_gid = (u_short)sb->st_gid;
72341486Smckusick #if NGRF > 0
72441486Smckusick 	/* XXX: I don't want to talk about it... */
72541486Smckusick 	if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10)
72641486Smckusick 		ds.hst_rdev = grfdevno(sb->st_rdev);
72741486Smckusick 	else
72841486Smckusick #endif
72941486Smckusick 		ds.hst_rdev = bsdtohpuxdev(sb->st_rdev);
73041486Smckusick 	ds.hst_size = sb->st_size;
73141486Smckusick 	ds.hst_atime = sb->st_atime;
73241486Smckusick 	ds.hst_mtime = sb->st_mtime;
73341486Smckusick 	ds.hst_ctime = sb->st_ctime;
73441486Smckusick 	ds.hst_blksize = sb->st_blksize;
73541486Smckusick 	ds.hst_blocks = sb->st_blocks;
73641486Smckusick 	return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds)));
73741486Smckusick }
73841486Smckusick 
73941486Smckusick hpuxtobsdioctl(com)
74041486Smckusick 	int com;
74141486Smckusick {
74241486Smckusick 	switch (com) {
74341486Smckusick 	case HPUXTIOCSLTC:
74441486Smckusick 		com = TIOCSLTC; break;
74541486Smckusick 	case HPUXTIOCGLTC:
74641486Smckusick 		com = TIOCGLTC; break;
74741486Smckusick 	case HPUXTIOCSPGRP:
74841486Smckusick 		com = TIOCSPGRP; break;
74941486Smckusick 	case HPUXTIOCGPGRP:
75041486Smckusick 		com = TIOCGPGRP; break;
75141486Smckusick 	case HPUXTIOCLBIS:
75241486Smckusick 		com = TIOCLBIS; break;
75341486Smckusick 	case HPUXTIOCLBIC:
75441486Smckusick 		com = TIOCLBIC; break;
75541486Smckusick 	case HPUXTIOCLSET:
75641486Smckusick 		com = TIOCLSET; break;
75741486Smckusick 	case HPUXTIOCLGET:
75841486Smckusick 		com = TIOCLGET; break;
75941486Smckusick 	}
76041486Smckusick 	return(com);
76141486Smckusick }
76241486Smckusick 
76341486Smckusick /*
76441486Smckusick  * HPUX ioctl system call.  The differences here are:
76541486Smckusick  *	IOC_IN also means IOC_VOID if the size portion is zero.
76641486Smckusick  *	no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN
76741486Smckusick  *	the sgttyb struct is 2 bytes longer
76841486Smckusick  */
76941486Smckusick hpuxioctl()
77041486Smckusick {
77141486Smckusick 	register struct file *fp;
77241486Smckusick 	struct a {
77341486Smckusick 		int	fdes;
77441486Smckusick 		int	cmd;
77541486Smckusick 		caddr_t	cmarg;
77641486Smckusick 	} *uap = (struct a *)u.u_ap;
77741486Smckusick 	register int com;
77841486Smckusick 	register u_int size;
77941486Smckusick 	caddr_t memp = 0;
78041486Smckusick #define STK_PARAMS	128
78141486Smckusick 	char stkbuf[STK_PARAMS];
78241486Smckusick 	caddr_t data = stkbuf;
78341486Smckusick 
78441486Smckusick 	com = uap->cmd;
78541486Smckusick 
78641486Smckusick 	/* XXX */
78741486Smckusick 	if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) {
78841486Smckusick 		getsettty(uap->fdes, com, uap->cmarg);
78941486Smckusick 		return;
79041486Smckusick 	}
79141486Smckusick 
79241486Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
79341486Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL) {
79441486Smckusick 		u.u_error = EBADF;
79541486Smckusick 		return;
79641486Smckusick 	}
79741486Smckusick 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
79841486Smckusick 		u.u_error = EBADF;
79941486Smckusick 		return;
80041486Smckusick 	}
80141486Smckusick 
80241486Smckusick 	/*
80341486Smckusick 	 * Interpret high order word to find
80441486Smckusick 	 * amount of data to be copied to/from the
80541486Smckusick 	 * user's address space.
80641486Smckusick 	 */
80741486Smckusick 	size = IOCPARM_LEN(com);
80841486Smckusick 	if (size > IOCPARM_MAX) {
80941486Smckusick 		u.u_error = EFAULT;
81041486Smckusick 		return;
81141486Smckusick 	}
81241486Smckusick 	if (size > sizeof (stkbuf)) {
81341486Smckusick 		memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS,
81441486Smckusick 		    M_WAITOK);
81541486Smckusick 		data = memp;
81641486Smckusick 	}
81741486Smckusick 	if (com&IOC_IN) {
81841486Smckusick 		if (size) {
81941486Smckusick 			u.u_error = copyin(uap->cmarg, data, (u_int)size);
82041486Smckusick 			if (u.u_error) {
82141486Smckusick 				if (memp)
82241486Smckusick 					free(memp, M_IOCTLOPS);
82341486Smckusick 				return;
82441486Smckusick 			}
82541486Smckusick 		} else
82641486Smckusick 			*(caddr_t *)data = uap->cmarg;
82741486Smckusick 	} else if ((com&IOC_OUT) && size)
82841486Smckusick 		/*
82941486Smckusick 		 * Zero the buffer on the stack so the user
83041486Smckusick 		 * always gets back something deterministic.
83141486Smckusick 		 */
83241486Smckusick 		bzero(data, size);
83341486Smckusick 	else if (com&IOC_VOID)
83441486Smckusick 		*(caddr_t *)data = uap->cmarg;
83541486Smckusick 
83641486Smckusick 	switch (com) {
83741486Smckusick 
83841486Smckusick 	case HPUXTIOCCONS:
83941486Smckusick 		*(int *)data = 1;
84041486Smckusick 		u.u_error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data);
84141486Smckusick 		break;
84241486Smckusick 
84341486Smckusick 	/* BSD-style job control ioctls */
84441486Smckusick 	case HPUXTIOCLBIS:
84541486Smckusick 	case HPUXTIOCLBIC:
84641486Smckusick 	case HPUXTIOCLSET:
84741486Smckusick 		*(int *)data &= HPUXLTOSTOP;
84841486Smckusick 		if (*(int *)data & HPUXLTOSTOP)
84941486Smckusick 			*(int *)data = LTOSTOP;
85041486Smckusick 		/* fall into */
85141486Smckusick 	case HPUXTIOCLGET:
85241486Smckusick 	case HPUXTIOCSLTC:
85341486Smckusick 	case HPUXTIOCGLTC:
85441486Smckusick 	case HPUXTIOCSPGRP:
85541486Smckusick 	case HPUXTIOCGPGRP:
85641486Smckusick 		u.u_error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data);
85741486Smckusick 		if (u.u_error == 0 && com == HPUXTIOCLGET) {
85841486Smckusick 			*(int *)data &= LTOSTOP;
85941486Smckusick 			if (*(int *)data & LTOSTOP)
86041486Smckusick 				*(int *)data = HPUXLTOSTOP;
86141486Smckusick 		}
86241486Smckusick 		break;
86341486Smckusick 
86441486Smckusick 	/* SYS 5 termio */
86541486Smckusick 	case HPUXTCGETA:
86641486Smckusick 	case HPUXTCSETA:
86741486Smckusick 	case HPUXTCSETAW:
86841486Smckusick 	case HPUXTCSETAF:
86941486Smckusick 		u.u_error = hpuxtermio(fp, com, data);
87041486Smckusick 		break;
87141486Smckusick 
87241486Smckusick 	default:
87341486Smckusick 		u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
87441486Smckusick 		break;
87541486Smckusick 	}
87641486Smckusick 	/*
87741486Smckusick 	 * Copy any data to user, size was
87841486Smckusick 	 * already set and checked above.
87941486Smckusick 	 */
88041486Smckusick 	if (u.u_error == 0 && (com&IOC_OUT) && size)
88141486Smckusick 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
88241486Smckusick 	if (memp)
88341486Smckusick 		free(memp, M_IOCTLOPS);
88441486Smckusick }
88541486Smckusick 
88641486Smckusick /*
88741486Smckusick  * Man page lies, behaviour here is based on observed behaviour.
88841486Smckusick  */
88941486Smckusick hpuxgetcontext()
89041486Smckusick {
89141486Smckusick 	struct a {
89241486Smckusick 		char *buf;
89341486Smckusick 		int len;
89441486Smckusick 	} *uap = (struct a *)u.u_ap;
89541486Smckusick 	int error = 0;
89641486Smckusick 	register int len;
89741486Smckusick 
89841486Smckusick 	len = MIN(uap->len, sizeof(hpuxcontext));
89941486Smckusick 	if (len)
90041486Smckusick 		error = copyout(hpuxcontext, uap->buf, (u_int)len);
90141486Smckusick 	if (!error)
90241486Smckusick 		u.u_r.r_val1 = sizeof(hpuxcontext);
90341486Smckusick 	return(error);
90441486Smckusick }
90541486Smckusick 
90641486Smckusick /*
90741486Smckusick  * XXX: simple recognition hack to see if we can make grmd work.
90841486Smckusick  */
90941486Smckusick hpuxlockf()
91041486Smckusick {
91141486Smckusick 	struct a {
91241486Smckusick 		int fd;
91341486Smckusick 		int func;
91441486Smckusick 		long size;
91541486Smckusick 	} *uap = (struct a *)u.u_ap;
91641486Smckusick #ifdef DEBUG
91741486Smckusick 	log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n",
91841486Smckusick 	    u.u_procp->p_pid, uap->fd, uap->func, uap->size);
91941486Smckusick #endif
92041486Smckusick 	return(0);
92141486Smckusick }
92241486Smckusick 
92341486Smckusick /*
92441486Smckusick  * This is the equivalent of BSD getpgrp but with more restrictions.
92541486Smckusick  * Note we do not check the real uid or "saved" uid.
92641486Smckusick  */
92741486Smckusick hpuxgetpgrp2()
92841486Smckusick {
92941486Smckusick 	register struct proc *p;
93041486Smckusick 	register struct a {
93141486Smckusick 		int pid;
93241486Smckusick 	} *uap = (struct a *)u.u_ap;
93341486Smckusick 
93441486Smckusick 	if (uap->pid == 0)
93541486Smckusick 		uap->pid = u.u_procp->p_pid;
93641486Smckusick 	p = pfind(uap->pid);
93741486Smckusick 	if (p == 0) {
93841486Smckusick 		u.u_error = ESRCH;
93941486Smckusick 		return;
94041486Smckusick 	}
94141486Smckusick 	if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) {
94241486Smckusick 		u.u_error = EPERM;
94341486Smckusick 		return;
94441486Smckusick 	}
94541486Smckusick 	u.u_r.r_val1 = p->p_pgid;
94641486Smckusick }
94741486Smckusick 
94841486Smckusick /*
94941486Smckusick  * This is the equivalent of BSD setpgrp but with more restrictions.
95041486Smckusick  * Note we do not check the real uid or "saved" uid or pgrp.
95141486Smckusick  */
95241486Smckusick hpuxsetpgrp2()
95341486Smckusick {
95441486Smckusick 	struct a {
95541486Smckusick 		int	pid;
95641486Smckusick 		int	pgrp;
95741486Smckusick 	} *uap = (struct a *)u.u_ap;
95841486Smckusick 
95941486Smckusick 	/* empirically determined */
96041486Smckusick 	if (uap->pgrp < 0 || uap->pgrp >= 30000) {
96141486Smckusick 		u.u_error = EINVAL;
96241486Smckusick 		return;
96341486Smckusick 	}
96441486Smckusick 	setpgrp();
96541486Smckusick }
96641486Smckusick 
96741486Smckusick /*
96841486Smckusick  * Brutal hack!  Map HPUX u-area offsets into BSD u offsets.
96941486Smckusick  * No apologies offered, if you don't like it, rewrite it!
97041486Smckusick  */
97141486Smckusick 
97241486Smckusick #define UOFF(f)		((int)&((struct user *)0)->f)
97341486Smckusick #define HPUOFF(f)	((int)&((struct hpuxuser *)0)->f)
97441486Smckusick 
97541486Smckusick /* simplified FP structure */
97641486Smckusick struct bsdfp {
97741486Smckusick 	int save[54];
97841486Smckusick 	int reg[24];
97941486Smckusick 	int ctrl[3];
98041486Smckusick };
98141486Smckusick 
98241486Smckusick hpuxtobsduoff(off)
98341486Smckusick 	int *off;
98441486Smckusick {
98541486Smckusick 	struct hpuxfp *hp;
98641486Smckusick 	struct bsdfp *bp;
98741486Smckusick 	register u_int raddr;
98841486Smckusick 
98941486Smckusick 	/* u_ar0 field */
99041486Smckusick 	if ((int)off == HPUOFF(hpuxu_ar0))
99141486Smckusick 		return(UOFF(u_ar0));
99241486Smckusick 
99341486Smckusick #ifdef FPCOPROC
99441486Smckusick 	/* 68881 registers from PCB */
99541486Smckusick 	hp = (struct hpuxfp *)HPUOFF(hpuxu_fp);
99641486Smckusick 	bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
99741486Smckusick 	if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
99841486Smckusick 		return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
99941486Smckusick 	if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
100041486Smckusick 		return((int)&bp->reg[off - hp->hpfp_reg]);
100141486Smckusick #endif
100241486Smckusick 
100341486Smckusick 	/*
100441486Smckusick 	 * Everything else we recognize comes from the kernel stack,
100541486Smckusick 	 * so we convert off to an absolute address (if not already)
100641486Smckusick 	 * for simplicity.
100741486Smckusick 	 */
100841486Smckusick 	if (off < (int *)ctob(UPAGES))
100941486Smckusick 		off = (int *)((u_int)off + (u_int)&u);
101041486Smckusick 
101141486Smckusick 	/*
101241486Smckusick 	 * 68020 registers.
101341486Smckusick 	 * We know that the HPUX registers are in the same order as ours.
101441486Smckusick 	 * The only difference is that their PS is 2 bytes instead of a
101541486Smckusick 	 * padded 4 like ours throwing the alignment off.
101641486Smckusick 	 */
101741486Smckusick 	if (off >= u.u_ar0 && off < &u.u_ar0[18]) {
101841486Smckusick 		/*
101941486Smckusick 		 * PS: return low word and high word of PC as HP-UX would
102041486Smckusick 		 * (e.g. &u.u_ar0[16.5]).
102141486Smckusick 		 */
102241486Smckusick 		if (off == &u.u_ar0[PS])
102341486Smckusick 			raddr = (u_int) &((short *)u.u_ar0)[PS*2+1];
102441486Smckusick 		/*
102541486Smckusick 		 * PC: off will be &u.u_ar0[16.5]
102641486Smckusick 		 */
102741486Smckusick 		else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1]))
102841486Smckusick 			raddr = (u_int) &u.u_ar0[PC];
102941486Smckusick 		/*
103041486Smckusick 		 * D0-D7, A0-A7: easy
103141486Smckusick 		 */
103241486Smckusick 		else
103341486Smckusick 			raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)];
103441486Smckusick 		return((int)(raddr - (u_int)&u));
103541486Smckusick 	}
103641486Smckusick 
103741486Smckusick 	/* everything else */
103841486Smckusick 	return(-1);
103941486Smckusick }
104041486Smckusick 
104141486Smckusick /*
104241486Smckusick  * Kludge up a uarea dump so that HPUX debuggers can find out
104341486Smckusick  * what they need.  IMPORTANT NOTE: we do not EVEN attempt to
104441486Smckusick  * convert the entire user struct.
104541486Smckusick  */
104641486Smckusick hpuxdumpu(vp, cred)
104741486Smckusick 	struct vnode *vp;
104841486Smckusick 	struct ucred *cred;
104941486Smckusick {
105041486Smckusick 	int error;
105141486Smckusick 	struct hpuxuser *faku;
105241486Smckusick 	struct bsdfp *bp;
105341486Smckusick 	short *foop;
105441486Smckusick 
105541486Smckusick 	faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK);
105641486Smckusick 	/*
105741486Smckusick 	 * Make sure there is no mistake about this
105841486Smckusick 	 * being a real user structure.
105941486Smckusick 	 */
106041486Smckusick 	bzero((caddr_t)faku, ctob(1));
106141486Smckusick 	/*
106241486Smckusick 	 * Fill in the process sizes.
106341486Smckusick 	 */
106441486Smckusick 	faku->hpuxu_tsize = u.u_tsize;
106541486Smckusick 	faku->hpuxu_dsize = u.u_dsize;
106641486Smckusick 	faku->hpuxu_ssize = u.u_ssize;
106741486Smckusick 	/*
106841486Smckusick 	 * Fill in the exec header for CDB.
106941486Smckusick 	 * This was saved back in exec().  As far as I can tell CDB
107041486Smckusick 	 * only uses this information to verify that a particular
107141486Smckusick 	 * core file goes with a particular binary.
107241486Smckusick 	 */
107341486Smckusick 	bcopy((caddr_t)u.u_pcb.pcb_exec,
107441486Smckusick 	      (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec));
107541486Smckusick 	/*
107641486Smckusick 	 * Adjust user's saved registers (on kernel stack) to reflect
107741486Smckusick 	 * HPUX order.  Note that HPUX saves the SR as 2 bytes not 4
107841486Smckusick 	 * so we have to move it up.
107941486Smckusick 	 */
108041486Smckusick 	faku->hpuxu_ar0 = u.u_ar0;
108141486Smckusick 	foop = (short *) u.u_ar0;
108241486Smckusick 	foop[32] = foop[33];
108341486Smckusick 	foop[33] = foop[34];
108441486Smckusick 	foop[34] = foop[35];
108541486Smckusick #ifdef FPCOPROC
108641486Smckusick 	/*
108741486Smckusick 	 * Copy 68881 registers from our PCB format to HPUX format
108841486Smckusick 	 */
108941486Smckusick 	bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs;
109041486Smckusick 	bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save,
109141486Smckusick 	      sizeof(bp->save));
109241486Smckusick 	bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl,
109341486Smckusick 	      sizeof(bp->ctrl));
109441486Smckusick 	bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg,
109541486Smckusick 	      sizeof(bp->reg));
109641486Smckusick #endif
109741486Smckusick 	/*
109841486Smckusick 	 * Slay the dragon
109941486Smckusick 	 */
110041486Smckusick 	faku->hpuxu_dragon = -1;
110141486Smckusick 	/*
110241486Smckusick 	 * Dump this artfully constructed page in place of the
110341486Smckusick 	 * user struct page.
110441486Smckusick 	 */
110541486Smckusick 	error = vn_rdwr(UIO_WRITE, vp,
110641486Smckusick 			(caddr_t)faku, ctob(1), (off_t)0,
110741486Smckusick 			UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0);
110841486Smckusick 	/*
110941486Smckusick 	 * Dump the remaining UPAGES-1 pages normally
111041486Smckusick 	 */
111141486Smckusick 	if (!error)
111241486Smckusick 		error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1),
111341486Smckusick 				ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE,
111441486Smckusick 				IO_NODELOCKED|IO_UNIT, cred, (int *)0);
111541486Smckusick 	free((caddr_t)faku, M_TEMP);
111641486Smckusick 	return(error);
111741486Smckusick }
111841486Smckusick 
111941486Smckusick /*
112041486Smckusick  * The remaining routines are essentially the same as those in kern_xxx.c
112141486Smckusick  * and vfs_xxx.c as defined under "#ifdef COMPAT".  We replicate them here
112241486Smckusick  * to avoid HPUXCOMPAT dependencies in those files and to make sure that
112341486Smckusick  * HP-UX compatibility still works even when COMPAT is not defined.
112441486Smckusick  */
112541486Smckusick /* #ifdef COMPAT */
112641486Smckusick 
112742088Smckusick #include "../sys/times.h"
112841486Smckusick 
112941486Smckusick /* from old timeb.h */
113041486Smckusick struct hpuxtimeb {
113141486Smckusick 	time_t	time;
113241486Smckusick 	u_short	millitm;
113341486Smckusick 	short	timezone;
113441486Smckusick 	short	dstflag;
113541486Smckusick };
113641486Smckusick 
113741486Smckusick /* ye ole stat structure */
113841486Smckusick struct	ohpuxstat {
113941486Smckusick 	dev_t	ohst_dev;
114041486Smckusick 	u_short	ohst_ino;
114141486Smckusick 	u_short ohst_mode;
114241486Smckusick 	short  	ohst_nlink;
114341486Smckusick 	short  	ohst_uid;
114441486Smckusick 	short  	ohst_gid;
114541486Smckusick 	dev_t	ohst_rdev;
114641486Smckusick 	int	ohst_size;
114741486Smckusick 	int	ohst_atime;
114841486Smckusick 	int	ohst_mtime;
114941486Smckusick 	int	ohst_ctime;
115041486Smckusick };
115141486Smckusick 
115241486Smckusick /*
115341486Smckusick  * Right now the following two routines are the same as the 4.3
115441486Smckusick  * osetuid/osetgid calls.  Eventually they need to be changed to
115541486Smckusick  * implement the notion of "saved" ids (whatever that means).
115641486Smckusick  */
115741486Smckusick ohpuxsetuid()
115841486Smckusick {
115941486Smckusick 	register uid;
116041486Smckusick 	register struct a {
116141486Smckusick 		int	uid;
116241486Smckusick 	} *uap = (struct a *)u.u_ap;
116341486Smckusick 
116441486Smckusick 	uid = uap->uid;
116541486Smckusick 	if (uid != u.u_procp->p_ruid && uid != u.u_cred->cr_uid &&
116641486Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
116741486Smckusick 		return;
116841486Smckusick 	if (u.u_cred->cr_ref > 1)
116941486Smckusick 		u.u_cred = crcopy(u.u_cred);
117041486Smckusick 	u.u_cred->cr_uid = uid;
117141486Smckusick 	u.u_procp->p_uid = uid;
117241486Smckusick 	u.u_procp->p_ruid = uid;
117341486Smckusick }
117441486Smckusick 
117541486Smckusick ohpuxsetgid()
117641486Smckusick {
117741486Smckusick 	register gid;
117841486Smckusick 	register struct a {
117941486Smckusick 		int	gid;
118041486Smckusick 	} *uap = (struct a *)u.u_ap;
118141486Smckusick 
118241486Smckusick 	gid = uap->gid;
118341486Smckusick 	if (u.u_procp->p_rgid != gid && u.u_cred->cr_groups[0] != gid &&
118441486Smckusick 	    (u.u_error = suser(u.u_cred, &u.u_acflag)))
118541486Smckusick 		return;
118641486Smckusick 	if (u.u_cred->cr_ref > 1)
118741486Smckusick 		u.u_cred = crcopy(u.u_cred);
118841486Smckusick 	u.u_procp->p_rgid = gid;
118941486Smckusick 	u.u_cred->cr_groups[0] = gid;
119041486Smckusick }
119141486Smckusick 
119241486Smckusick /*
119341486Smckusick  * SYS V style setpgrp()
119441486Smckusick  */
119541486Smckusick ohpuxsetpgrp()
119641486Smckusick {
119741486Smckusick 	register struct proc *p = u.u_procp;
119841486Smckusick 
119941486Smckusick 	if (p->p_pid != p->p_pgid)
120041486Smckusick 		pgmv(p, p->p_pid, 0);
120141486Smckusick 	u.u_r.r_val1 = p->p_pgid;
120241486Smckusick }
120341486Smckusick 
120441486Smckusick ohpuxtime()
120541486Smckusick {
120641486Smckusick 	register struct a {
120741486Smckusick 		long	*tp;
120841486Smckusick 	} *uap = (struct a *)u.u_ap;
120941486Smckusick 
121041486Smckusick 	if (uap->tp)
121141486Smckusick 		u.u_error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp,
121241486Smckusick 				    sizeof (long));
121341486Smckusick 	u.u_r.r_time = time.tv_sec;
121441486Smckusick }
121541486Smckusick 
121641486Smckusick ohpuxstime()
121741486Smckusick {
121841486Smckusick 	register struct a {
121941486Smckusick 		int	time;
122041486Smckusick 	} *uap = (struct a *)u.u_ap;
122141486Smckusick 	struct timeval tv;
122241486Smckusick 	int s;
122341486Smckusick 
122441486Smckusick 	tv.tv_sec = uap->time;
122541486Smckusick 	tv.tv_usec = 0;
122641486Smckusick 	u.u_error = suser(u.u_cred, &u.u_acflag);
122741486Smckusick 	if (u.u_error)
122841486Smckusick 		return;
122941486Smckusick 
123041486Smckusick 	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
123141486Smckusick 	boottime.tv_sec += tv.tv_sec - time.tv_sec;
123241486Smckusick 	s = splhigh(); time = tv; splx(s);
123341486Smckusick 	resettodr();
123441486Smckusick }
123541486Smckusick 
123641486Smckusick ohpuxftime()
123741486Smckusick {
123841486Smckusick 	register struct a {
123941486Smckusick 		struct	hpuxtimeb *tp;
124041486Smckusick 	} *uap;
124141486Smckusick 	struct hpuxtimeb tb;
124241486Smckusick 	int s;
124341486Smckusick 
124441486Smckusick 	uap = (struct a *)u.u_ap;
124541486Smckusick 	s = splhigh();
124641486Smckusick 	tb.time = time.tv_sec;
124741486Smckusick 	tb.millitm = time.tv_usec / 1000;
124841486Smckusick 	splx(s);
124941486Smckusick 	tb.timezone = tz.tz_minuteswest;
125041486Smckusick 	tb.dstflag = tz.tz_dsttime;
125141486Smckusick 	u.u_error = copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb));
125241486Smckusick }
125341486Smckusick 
125441486Smckusick ohpuxalarm()
125541486Smckusick {
125641486Smckusick 	register struct a {
125741486Smckusick 		int	deltat;
125841486Smckusick 	} *uap = (struct a *)u.u_ap;
125941486Smckusick 	register struct proc *p = u.u_procp;
126041486Smckusick 	int s = splhigh();
126141486Smckusick 
126241486Smckusick 	untimeout(realitexpire, (caddr_t)p);
126341486Smckusick 	timerclear(&p->p_realtimer.it_interval);
126441486Smckusick 	u.u_r.r_val1 = 0;
126541486Smckusick 	if (timerisset(&p->p_realtimer.it_value) &&
126641486Smckusick 	    timercmp(&p->p_realtimer.it_value, &time, >))
126741486Smckusick 		u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec;
126841486Smckusick 	if (uap->deltat == 0) {
126941486Smckusick 		timerclear(&p->p_realtimer.it_value);
127041486Smckusick 		splx(s);
127141486Smckusick 		return;
127241486Smckusick 	}
127341486Smckusick 	p->p_realtimer.it_value = time;
127441486Smckusick 	p->p_realtimer.it_value.tv_sec += uap->deltat;
127541486Smckusick 	timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value));
127641486Smckusick 	splx(s);
127741486Smckusick }
127841486Smckusick 
127941486Smckusick ohpuxnice()
128041486Smckusick {
128141486Smckusick 	register struct a {
128241486Smckusick 		int	niceness;
128341486Smckusick 	} *uap = (struct a *)u.u_ap;
128441486Smckusick 	register struct proc *p = u.u_procp;
128541486Smckusick 
128641486Smckusick 	donice(p, (p->p_nice-NZERO)+uap->niceness);
128741486Smckusick 	u.u_r.r_val1 = p->p_nice - NZERO;
128841486Smckusick }
128941486Smckusick 
129041486Smckusick ohpuxtimes()
129141486Smckusick {
129241486Smckusick 	register struct a {
129341486Smckusick 		struct	tms *tmsb;
129441486Smckusick 	} *uap = (struct a *)u.u_ap;
129541486Smckusick 	struct tms atms;
129641486Smckusick 
129741486Smckusick 	atms.tms_utime = scale50(&u.u_ru.ru_utime);
129841486Smckusick 	atms.tms_stime = scale50(&u.u_ru.ru_stime);
129941486Smckusick 	atms.tms_cutime = scale50(&u.u_cru.ru_utime);
130041486Smckusick 	atms.tms_cstime = scale50(&u.u_cru.ru_stime);
130141486Smckusick 	u.u_error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms));
130241486Smckusick 	if (u.u_error == 0)
130341486Smckusick 		u.u_r.r_time = scale50(&time) - scale50(&boottime);
130441486Smckusick }
130541486Smckusick 
130641486Smckusick scale50(tvp)
130741486Smckusick 	register struct timeval *tvp;
130841486Smckusick {
130941486Smckusick 	extern int hpuxtick;
131041486Smckusick 
131141486Smckusick 	/*
131241486Smckusick 	 * Doesn't exactly do what the documentation says.
131341486Smckusick 	 * What we really do is return 50th of a second since that
131441486Smckusick 	 * is what HZ is on all bobcats I know of.
131541486Smckusick 	 */
131641486Smckusick 	return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick));
131741486Smckusick }
131841486Smckusick 
131941486Smckusick /*
132041486Smckusick  * Set IUPD and IACC times on file.
132141486Smckusick  * Can't set ICHG.
132241486Smckusick  */
132341486Smckusick ohpuxutime()
132441486Smckusick {
132541486Smckusick 	register struct a {
132641486Smckusick 		char	*fname;
132741486Smckusick 		time_t	*tptr;
132841486Smckusick 	} *uap = (struct a *)u.u_ap;
132941486Smckusick 	struct vattr vattr;
133041486Smckusick 	time_t tv[2];
133141486Smckusick 	register struct vnode *vp;
133241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
133341486Smckusick 
133441486Smckusick 	if (uap->tptr) {
133541486Smckusick 		u.u_error =
133641486Smckusick 			copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
133741486Smckusick 		if (u.u_error)
133841486Smckusick 			return;
133941486Smckusick 	} else
134041486Smckusick 		tv[0] = tv[1] = time.tv_sec;
134141486Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
134241486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
134341486Smckusick 	ndp->ni_dirp = uap->fname;
134441486Smckusick 	vattr_null(&vattr);
134541486Smckusick 	vattr.va_atime.tv_sec = tv[0];
134641486Smckusick 	vattr.va_atime.tv_usec = 0;
134741486Smckusick 	vattr.va_mtime.tv_sec = tv[1];
134841486Smckusick 	vattr.va_mtime.tv_usec = 0;
134941486Smckusick 	if (u.u_error = namei(ndp))
135041486Smckusick 		return;
135141486Smckusick 	vp = ndp->ni_vp;
135242154Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
135341486Smckusick 		u.u_error = EROFS;
135441486Smckusick 	else
135541486Smckusick 		u.u_error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
135641486Smckusick 	vput(vp);
135741486Smckusick }
135841486Smckusick 
135941486Smckusick ohpuxpause()
136041486Smckusick {
136141486Smckusick 
136242155Skarels 	(void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0);
136342155Skarels 	/* always return EINTR rather than ERESTART... */
136442155Skarels 	RETURN (EINTR);
136541486Smckusick }
136641486Smckusick 
136741486Smckusick /*
136841486Smckusick  * The old fstat system call.
136941486Smckusick  */
137041486Smckusick ohpuxfstat()
137141486Smckusick {
137241486Smckusick 	register struct a {
137341486Smckusick 		int	fd;
137441486Smckusick 		struct ohpuxstat *sb;
137541486Smckusick 	} *uap = (struct a *)u.u_ap;
137641486Smckusick 	struct file *fp;
137741486Smckusick 	extern struct file *getinode();
137841486Smckusick 
137941486Smckusick 	if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) {
138041486Smckusick 		u.u_error = EBADF;
138141486Smckusick 		return;
138241486Smckusick 	}
138341486Smckusick 	if (fp->f_type != DTYPE_VNODE) {
138441486Smckusick 		u.u_error = EINVAL;
138541486Smckusick 		return;
138641486Smckusick 	}
138741486Smckusick 	u.u_error = ohpuxstat1((struct vnode *)fp->f_data, uap->sb);
138841486Smckusick }
138941486Smckusick 
139041486Smckusick /*
139141486Smckusick  * Old stat system call.  This version follows links.
139241486Smckusick  */
139341486Smckusick ohpuxstat()
139441486Smckusick {
139541486Smckusick 	register struct a {
139641486Smckusick 		char	*fname;
139741486Smckusick 		struct ohpuxstat *sb;
139841486Smckusick 	} *uap = (struct a *)u.u_ap;
139941486Smckusick 	register struct nameidata *ndp = &u.u_nd;
140041486Smckusick 
140141486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
140241486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
140341486Smckusick 	ndp->ni_dirp = uap->fname;
140441486Smckusick 	if (u.u_error = namei(ndp))
140541486Smckusick 		return;
140641486Smckusick 	u.u_error = ohpuxstat1(ndp->ni_vp, uap->sb);
140741486Smckusick 	vput(ndp->ni_vp);
140841486Smckusick }
140941486Smckusick 
141041486Smckusick int
141141486Smckusick ohpuxstat1(vp, ub)
141241486Smckusick 	register struct vnode *vp;
141341486Smckusick 	struct ohpuxstat *ub;
141441486Smckusick {
141541486Smckusick 	struct ohpuxstat ds;
141641486Smckusick 	struct vattr vattr;
141741486Smckusick 	register int error;
141841486Smckusick 
141941486Smckusick 	error = VOP_GETATTR(vp, &vattr, u.u_cred);
142041486Smckusick 	if (error)
142141486Smckusick 		return(error);
142241486Smckusick 	/*
142341486Smckusick 	 * Copy from inode table
142441486Smckusick 	 */
142541486Smckusick 	ds.ohst_dev = vattr.va_fsid;
142641486Smckusick 	ds.ohst_ino = (short)vattr.va_fileid;
142741486Smckusick 	ds.ohst_mode = (u_short)vattr.va_mode;
142841486Smckusick 	ds.ohst_nlink = vattr.va_nlink;
142941486Smckusick 	ds.ohst_uid = (short)vattr.va_uid;
143041486Smckusick 	ds.ohst_gid = (short)vattr.va_gid;
143141486Smckusick 	ds.ohst_rdev = (dev_t)vattr.va_rdev;
143241486Smckusick 	ds.ohst_size = (int)vattr.va_size;
143341486Smckusick 	ds.ohst_atime = (int)vattr.va_atime.tv_sec;
143441486Smckusick 	ds.ohst_mtime = (int)vattr.va_mtime.tv_sec;
143541486Smckusick 	ds.ohst_ctime = (int)vattr.va_ctime.tv_sec;
143641486Smckusick 	return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)));
143741486Smckusick }
143841486Smckusick /* #endif */
143941486Smckusick 
144041486Smckusick #endif
1441