xref: /csrg-svn/sys/hp/hpux/hpux_compat.c (revision 44421)
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*44421Skarels  *	@(#)hpux_compat.c	7.9 (Berkeley) 06/28/90
1541486Smckusick  */
1641486Smckusick 
1741486Smckusick /*
1841486Smckusick  * Various HPUX compatibility routines
1941486Smckusick  */
2041486Smckusick 
2141486Smckusick #ifdef HPUXCOMPAT
2241486Smckusick 
2341486Smckusick #include "param.h"
2441486Smckusick #include "systm.h"
25*44421Skarels #include "user.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 
8843452Shibler notimp(p, uap, retval, code, nargs)
8943452Shibler 	struct proc *p;
9043452Shibler 	int *uap, *retval;
9143452Shibler 	int code, nargs;
9241486Smckusick {
9343452Shibler 	int error = 0;
9441486Smckusick #ifdef DEBUG
9543452Shibler 	register int *argp = uap;
9641486Smckusick 	extern char *hpuxsyscallnames[];
9741486Smckusick 
9841486Smckusick 	printf("HPUX %s(", hpuxsyscallnames[code]);
9941486Smckusick 	if (nargs)
10041486Smckusick 		while (nargs--)
10141486Smckusick 			printf("%x%c", *argp++, nargs? ',' : ')');
10241486Smckusick 	else
10341486Smckusick 		printf(")");
10441486Smckusick 	printf("\n");
10541486Smckusick 	switch (unimpresponse) {
10641486Smckusick 	case 0:
10743452Shibler 		error = nosys(p, uap, retval);
10841486Smckusick 		break;
10941486Smckusick 	case 1:
11043452Shibler 		error = EINVAL;
11141486Smckusick 		break;
11241486Smckusick 	}
11341486Smckusick #else
11443452Shibler 	error = nosys(p, uap, retval);
11541486Smckusick #endif
11643452Shibler 	uprintf("HP-UX system call %d not implemented\n", code);
117*44421Skarels 	return (error);
11841486Smckusick }
11941486Smckusick 
12041486Smckusick /*
12141486Smckusick  * HPUX versions of wait and wait3 actually pass the parameters
12241486Smckusick  * (status pointer, options, rusage) into the kernel rather than
12342352Smckusick  * handling it in the C library stub.  We also need to map any
12442352Smckusick  * termination signal from BSD to HPUX.
12541486Smckusick  */
12643452Shibler hpuxwait3(p, uap, retval)
12743452Shibler 	struct proc *p;
12843452Shibler 	struct args {
12941486Smckusick 		int	*status;
13041486Smckusick 		int	options;
13141486Smckusick 		int	rusage;
13243452Shibler 	} *uap;
13343452Shibler 	int *retval;
13443452Shibler {
13541486Smckusick 	/* rusage pointer must be zero */
13643452Shibler 	if (uap->rusage)
137*44421Skarels 		return (EINVAL);
13841486Smckusick 	u.u_ar0[PS] = PSL_ALLCC;
13941486Smckusick 	u.u_ar0[R0] = uap->options;
14041486Smckusick 	u.u_ar0[R1] = uap->rusage;
141*44421Skarels 	return (hpuxwait(p, uap, retval));
14241486Smckusick }
14341486Smckusick 
14443452Shibler hpuxwait(p, uap, retval)
14543452Shibler 	struct proc *p;
14643452Shibler 	struct args {
14743452Shibler 		int	*status;
14843452Shibler 	} *uap;
14943452Shibler 	int *retval;
15041486Smckusick {
15143452Shibler 	int sig, *statp, error;
15241486Smckusick 
15341486Smckusick 	statp = uap->status;	/* owait clobbers first arg */
15443452Shibler 	error = owait(p, uap, retval);
15541486Smckusick 	/*
15641486Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
15741486Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
15841486Smckusick 	 */
15943452Shibler 	if (error == ERESTART)
16043452Shibler 		error = EINTR;
16143452Shibler 	if (error)
162*44421Skarels 		return (error);
16343452Shibler 	sig = retval[1] & 0xFF;
16441486Smckusick 	if (sig == WSTOPPED) {
16543452Shibler 		sig = (retval[1] >> 8) & 0xFF;
16643452Shibler 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
16741486Smckusick 	} else if (sig)
16843452Shibler 		retval[1] = (retval[1] & 0xFF00) |
16941486Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
17041486Smckusick 	if (statp)
17143452Shibler 		if (suword((caddr_t)statp, retval[1]))
17243452Shibler 			error = EFAULT;
173*44421Skarels 	return (error);
17441486Smckusick }
17541486Smckusick 
17643452Shibler hpuxwaitpid(p, uap, retval)
17743452Shibler 	struct proc *p;
17843452Shibler 	struct args {
17942352Smckusick 		int	pid;
18042352Smckusick 		int	*status;
18142352Smckusick 		int	options;
18242352Smckusick 		struct	rusage *rusage;	/* wait4 arg */
18343452Shibler 	} *uap;
18443452Shibler 	int *retval;
18543452Shibler {
18643452Shibler 	int sig, *statp, error;
18742352Smckusick 
18842352Smckusick 	uap->rusage = 0;
18943452Shibler 	error = wait4(p, uap, retval);
19042352Smckusick 	/*
19142352Smckusick 	 * HP-UX wait always returns EINTR when interrupted by a signal
19242352Smckusick 	 * (well, unless its emulating a BSD process, but we don't bother...)
19342352Smckusick 	 */
19443452Shibler 	if (error == ERESTART)
19543452Shibler 		error = EINTR;
19643452Shibler 	if (error)
197*44421Skarels 		return (error);
19843452Shibler 	sig = retval[1] & 0xFF;
19942352Smckusick 	if (sig == WSTOPPED) {
20043452Shibler 		sig = (retval[1] >> 8) & 0xFF;
20143452Shibler 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
20242352Smckusick 	} else if (sig)
20343452Shibler 		retval[1] = (retval[1] & 0xFF00) |
20442352Smckusick 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
20542352Smckusick 	if (statp)
20643452Shibler 		if (suword((caddr_t)statp, retval[1]))
20743452Shibler 			error = EFAULT;
208*44421Skarels 	return (error);
20942352Smckusick }
21042352Smckusick 
21141486Smckusick /*
21241486Smckusick  * Must remap some bits in the mode mask.
21341486Smckusick  * O_CREAT, O_TRUNC, and O_EXCL must be remapped,
21441486Smckusick  * O_SYNCIO (0100000) is removed entirely.
21541486Smckusick  */
21643067Skarels hpuxopen(p, uap, retval)
21743067Skarels 	struct proc *p;
21843452Shibler 	register struct args {
21941486Smckusick 		char	*fname;
22041486Smckusick 		int	mode;
22141486Smckusick 		int	crtmode;
22243067Skarels 	} *uap;
22343067Skarels 	int *retval;
22443067Skarels {
22541486Smckusick 	int mode;
22641486Smckusick 
22741486Smckusick 	mode = uap->mode;
22841486Smckusick 	uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT);
22941486Smckusick 	if (mode & HPUXFCREAT) {
23041486Smckusick 		/*
23141486Smckusick 		 * simulate the pre-NFS behavior that opening a
23241486Smckusick 		 * file for READ+CREATE ignores the CREATE (unless
23341486Smckusick 		 * EXCL is set in which case we will return the
23441486Smckusick 		 * proper error).
23541486Smckusick 		 */
23641486Smckusick 		if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE))
23741486Smckusick 			uap->mode |= FCREAT;
23841486Smckusick 	}
23941486Smckusick 	if (mode & HPUXFTRUNC)
24041486Smckusick 		uap->mode |= FTRUNC;
24141486Smckusick 	if (mode & HPUXFEXCL)
24241486Smckusick 		uap->mode |= FEXCL;
243*44421Skarels 	return (open(p, uap, retval));
24441486Smckusick }
24541486Smckusick 
24643452Shibler hpuxfcntl(p, uap, retval)
24743452Shibler 	struct proc *p;
24843452Shibler 	register struct args {
24941486Smckusick 		int	fdes;
25041486Smckusick 		int	cmd;
25141486Smckusick 		int	arg;
25243452Shibler 	} *uap;
25343452Shibler 	int *retval;
25443452Shibler {
25543452Shibler 	int mode, error;
25641486Smckusick 
25741486Smckusick 	switch (uap->cmd) {
25841486Smckusick 	case F_SETFL:
25941486Smckusick 		uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE);
26041486Smckusick 		break;
26141486Smckusick 	case F_GETFL:
26241486Smckusick 	case F_DUPFD:
26341486Smckusick 	case F_GETFD:
26441486Smckusick 	case F_SETFD:
26541486Smckusick 		break;
26641486Smckusick 	default:
267*44421Skarels 		return (EINVAL);
26841486Smckusick 	}
26943452Shibler 	error = fcntl(p, uap, retval);
27043452Shibler 	if (error == 0 && uap->arg == F_GETFL) {
27143452Shibler 		mode = *retval;
27243452Shibler 		*retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE);
27341486Smckusick 		if (mode & FCREAT)
27443452Shibler 			*retval |= HPUXFCREAT;
27541486Smckusick 		if (mode & FTRUNC)
27643452Shibler 			*retval |= HPUXFTRUNC;
27741486Smckusick 		if (mode & FEXCL)
27843452Shibler 			*retval |= HPUXFEXCL;
27941486Smckusick 	}
280*44421Skarels 	return (error);
28141486Smckusick }
28241486Smckusick 
28341486Smckusick /*
28441486Smckusick  * Read and write should return a 0 count when an operation
28541486Smckusick  * on a VNODE would block, not an error.  Sockets appear to
28641486Smckusick  * return EWOULDBLOCK (at least in 6.2).  This is probably
28741486Smckusick  * not entirely correct, since the behavior is only defined
28841486Smckusick  * for pipes and tty type devices.
28941486Smckusick  */
29043452Shibler hpuxread(p, uap, retval)
29143452Shibler 	struct proc *p;
29243452Shibler 	struct args {
29343452Shibler 		int	fd;
29443452Shibler 	} *uap;
29543452Shibler 	int *retval;
29641486Smckusick {
29743452Shibler 	int error;
29841486Smckusick 
29943452Shibler 	error = read(p, uap, retval);
30043452Shibler 	if (error == EWOULDBLOCK &&
30141486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
30243452Shibler 		error = 0;
30343452Shibler 		*retval = 0;
30441486Smckusick 	}
305*44421Skarels 	return (error);
30641486Smckusick }
30741486Smckusick 
30843452Shibler hpuxwrite(p, uap, retval)
30943452Shibler 	struct proc *p;
31043452Shibler 	struct args {
31143452Shibler 		int	fd;
31243452Shibler 	} *uap;
31343452Shibler 	int *retval;
31441486Smckusick {
31543452Shibler 	int error;
31641486Smckusick 
31743452Shibler 	error = write(p, uap, retval);
31843452Shibler 	if (error == EWOULDBLOCK &&
31941486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
32043452Shibler 		error = 0;
32143452Shibler 		*retval = 0;
32241486Smckusick 	}
323*44421Skarels 	return (error);
32441486Smckusick }
32541486Smckusick 
32643452Shibler hpuxreadv(p, uap, retval)
32743452Shibler 	struct proc *p;
32843452Shibler 	struct args {
32943452Shibler 		int	fd;
33043452Shibler 	} *uap;
33143452Shibler 	int *retval;
33241486Smckusick {
33343452Shibler 	int error;
33441486Smckusick 
33543452Shibler 	error = readv(p, uap, retval);
33643452Shibler 	if (error == EWOULDBLOCK &&
33741486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
33843452Shibler 		error = 0;
33943452Shibler 		*retval = 0;
34041486Smckusick 	}
341*44421Skarels 	return (error);
34241486Smckusick }
34341486Smckusick 
34443452Shibler hpuxwritev(p, uap, retval)
34543452Shibler 	struct proc *p;
34643452Shibler 	struct args {
34743452Shibler 		int	fd;
34843452Shibler 	} *uap;
34943452Shibler 	int *retval;
35041486Smckusick {
35143452Shibler 	int error;
35241486Smckusick 
35343452Shibler 	error = writev(p, uap, retval);
35443452Shibler 	if (error == EWOULDBLOCK &&
35541486Smckusick 	    u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) {
35643452Shibler 		error = 0;
35743452Shibler 		*retval = 0;
35841486Smckusick 	}
359*44421Skarels 	return (error);
36041486Smckusick }
36141486Smckusick 
36241486Smckusick /*
36341486Smckusick  * 4.3bsd dup allows dup2 to come in on the same syscall entry
36441486Smckusick  * and hence allows two arguments.  HPUX dup has only one arg.
36541486Smckusick  */
36643452Shibler hpuxdup(p, uap, retval)
36743452Shibler 	struct proc *p;
36843452Shibler 	register struct args {
36943452Shibler 		int	i;
37043452Shibler 	} *uap;
37143452Shibler 	int *retval;
37241486Smckusick {
37341486Smckusick 	struct file *fp;
37443452Shibler 	int fd, error;
37541486Smckusick 
37643452Shibler 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
377*44421Skarels 		return (EBADF);
37843452Shibler 	if (error = ufalloc(0, &fd))
379*44421Skarels 		return (error);
38043452Shibler 	*retval = fd;
38143452Shibler 	u.u_ofile[fd] = fp;
38243452Shibler 	u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE;
38343067Skarels 	fp->f_count++;
38443452Shibler 	if (fd > u.u_lastfile)
38543452Shibler 		u.u_lastfile = fd;
386*44421Skarels 	return (0);
38741486Smckusick }
38841486Smckusick 
38943452Shibler hpuxuname(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;
43741486Smckusick 	/* ustat - who cares? */
43841486Smckusick 	case 2:
43941486Smckusick 	default:
44043452Shibler 		error = EINVAL;
44141486Smckusick 		break;
44241486Smckusick 	}
443*44421Skarels 	return (error);
44441486Smckusick }
44541486Smckusick 
44643452Shibler hpuxstat(p, uap, retval)
44743452Shibler 	struct proc *p;
44843452Shibler 	struct args {
44941486Smckusick 		char	*fname;
45041486Smckusick 		struct hpuxstat *hsb;
45143452Shibler 	} *uap;
45243452Shibler 	int *retval;
45343452Shibler {
454*44421Skarels 	return (hpuxstat1(uap->fname, uap->hsb, FOLLOW));
45541486Smckusick }
45641486Smckusick 
45743452Shibler hpuxlstat(p, uap, retval)
45843452Shibler 	struct proc *p;
45943452Shibler 	struct args {
46043452Shibler 		char	*fname;
46143452Shibler 		struct hpuxstat *hsb;
46243452Shibler 	} *uap;
46343452Shibler 	int *retval;
46441486Smckusick {
465*44421Skarels 	return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW));
46641486Smckusick }
46741486Smckusick 
46843452Shibler hpuxfstat(p, uap, retval)
46943452Shibler 	struct proc *p;
47043452Shibler 	register struct args {
47143452Shibler 		int	fdes;
47243452Shibler 		struct	hpuxstat *hsb;
47343452Shibler 	} *uap;
47443452Shibler 	int *retval;
47541486Smckusick {
47641486Smckusick 	register struct file *fp;
47741486Smckusick 	struct stat sb;
47843452Shibler 	int error;
47941486Smckusick 
48041486Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
48143452Shibler 	    (fp = u.u_ofile[uap->fdes]) == NULL)
482*44421Skarels 		return (EBADF);
48343452Shibler 
48441486Smckusick 	switch (fp->f_type) {
48541486Smckusick 
48641486Smckusick 	case DTYPE_VNODE:
48743452Shibler 		error = vn_stat((struct vnode *)fp->f_data, &sb);
48841486Smckusick 		break;
48941486Smckusick 
49041486Smckusick 	case DTYPE_SOCKET:
49143452Shibler 		error = soo_stat((struct socket *)fp->f_data, &sb);
49241486Smckusick 		break;
49341486Smckusick 
49441486Smckusick 	default:
49541486Smckusick 		panic("fstat");
49641486Smckusick 		/*NOTREACHED*/
49741486Smckusick 	}
49841486Smckusick 	/* is this right for sockets?? */
49943452Shibler 	if (error == 0)
50043452Shibler 		error = bsdtohpuxstat(&sb, uap->hsb);
501*44421Skarels 	return (error);
50241486Smckusick }
50341486Smckusick 
50443452Shibler hpuxulimit(p, uap, retval)
50543452Shibler 	struct proc *p;
50643452Shibler 	register struct args {
50741486Smckusick 		int	cmd;
50841486Smckusick 		long	newlimit;
50943452Shibler 	} *uap;
51043713Smckusick 	off_t *retval;
51143452Shibler {
51241486Smckusick 	struct rlimit *limp;
51343452Shibler 	int error = 0;
51441486Smckusick 
51541486Smckusick 	limp = &u.u_rlimit[RLIMIT_FSIZE];
51641486Smckusick 	switch (uap->cmd) {
51741486Smckusick 	case 2:
51841486Smckusick 		uap->newlimit *= 512;
51941486Smckusick 		if (uap->newlimit > limp->rlim_max &&
52043452Shibler 		    (error = suser(u.u_cred, &u.u_acflag)))
52141486Smckusick 			break;
52241486Smckusick 		limp->rlim_cur = limp->rlim_max = uap->newlimit;
52341486Smckusick 		/* else fall into... */
52441486Smckusick 
52541486Smckusick 	case 1:
52643713Smckusick 		*retval = limp->rlim_max / 512;		/* XXX */
52741486Smckusick 		break;
52841486Smckusick 
52941486Smckusick 	case 3:
53041486Smckusick 		limp = &u.u_rlimit[RLIMIT_DATA];
53143713Smckusick 		*retval = ctob(u.u_tsize) + limp->rlim_max;	/* XXX */
53241486Smckusick 		break;
53341486Smckusick 
53441486Smckusick 	default:
53543452Shibler 		error = EINVAL;
53641486Smckusick 		break;
53741486Smckusick 	}
538*44421Skarels 	return (error);
53941486Smckusick }
54041486Smckusick 
54141486Smckusick /*
54241486Smckusick  * Map "real time" priorities 0 (high) thru 127 (low) into nice
54341486Smckusick  * values -16 (high) thru -1 (low).
54441486Smckusick  */
54543452Shibler hpuxrtprio(cp, uap, retval)
54643452Shibler 	struct proc *cp;
54743452Shibler 	register struct args {
54841486Smckusick 		int pid;
54941486Smckusick 		int prio;
55043452Shibler 	} *uap;
55143452Shibler 	int *retval;
55243452Shibler {
55341486Smckusick 	struct proc *p;
55443452Shibler 	int nice, error;
55541486Smckusick 
55641486Smckusick 	if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX &&
55743452Shibler 	    uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF)
558*44421Skarels 		return (EINVAL);
55941486Smckusick 	if (uap->pid == 0)
56043452Shibler 		p = cp;
56143452Shibler 	else if ((p = pfind(uap->pid)) == 0)
562*44421Skarels 		return (ESRCH);
56341486Smckusick 	nice = p->p_nice;
56441486Smckusick 	if (nice < NZERO)
56543452Shibler 		*retval = (nice + 16) << 3;
56641486Smckusick 	else
56743452Shibler 		*retval = RTPRIO_RTOFF;
56841486Smckusick 	switch (uap->prio) {
56941486Smckusick 
57041486Smckusick 	case RTPRIO_NOCHG:
571*44421Skarels 		return (0);
57241486Smckusick 
57341486Smckusick 	case RTPRIO_RTOFF:
57441486Smckusick 		if (nice >= NZERO)
575*44421Skarels 			return (0);
57641486Smckusick 		nice = NZERO;
57741486Smckusick 		break;
57841486Smckusick 
57941486Smckusick 	default:
58041486Smckusick 		nice = (uap->prio >> 3) - 16;
58141486Smckusick 		break;
58241486Smckusick 	}
58343452Shibler 	error = donice(cp, p, nice);
58443452Shibler 	if (error == EACCES)
58543452Shibler 		error = EPERM;
586*44421Skarels 	return (error);
58741486Smckusick }
58841486Smckusick 
58943452Shibler hpuxadvise(p, uap, retval)
59043452Shibler 	struct proc *p;
59143452Shibler 	struct args {
59243452Shibler 		int	arg;
59343452Shibler 	} *uap;
59443452Shibler 	int *retval;
59541486Smckusick {
59643452Shibler 	int error = 0;
59741486Smckusick 
59841486Smckusick 	switch (uap->arg) {
59941486Smckusick 	case 0:
60041486Smckusick 		u.u_pcb.pcb_flags |= PCB_HPUXMMAP;
60141486Smckusick 		break;
60241486Smckusick 	case 1:
60341486Smckusick 		ICIA();
60441486Smckusick 		break;
60541486Smckusick 	case 2:
60641486Smckusick 		DCIA();
60741486Smckusick 		break;
60841486Smckusick 	default:
60943452Shibler 		error = EINVAL;
61041486Smckusick 		break;
61141486Smckusick 	}
612*44421Skarels 	return (error);
61341486Smckusick }
61441486Smckusick 
61543452Shibler hpuxptrace(p, uap, retval)
61643452Shibler 	struct proc *p;
61743452Shibler 	struct args {
61841486Smckusick 		int	req;
61941486Smckusick 		int	pid;
62041486Smckusick 		int	*addr;
62141486Smckusick 		int	data;
62243452Shibler 	} *uap;
62343452Shibler 	int *retval;
62443452Shibler {
62543452Shibler 	int error;
62641486Smckusick 
62741486Smckusick 	if (uap->req == PT_STEP || uap->req == PT_CONTINUE) {
62841486Smckusick 		if (uap->data) {
62941486Smckusick 			uap->data = hpuxtobsdsig(uap->data);
63041486Smckusick 			if (uap->data == 0)
63141486Smckusick 				uap->data = NSIG;
63241486Smckusick 		}
63341486Smckusick 	}
63443452Shibler 	error = ptrace(p, uap, retval);
635*44421Skarels 	return (error);
63641486Smckusick }
63741486Smckusick 
63843452Shibler hpuxgetdomainname(p, uap, retval)
63943452Shibler 	struct proc *p;
64043452Shibler 	register struct args {
64141486Smckusick 		char	*domainname;
64241486Smckusick 		u_int	len;
64343452Shibler 	} *uap;
64443452Shibler 	int *retval;
64543452Shibler {
64641486Smckusick 	if (uap->len > domainnamelen + 1)
64741486Smckusick 		uap->len = domainnamelen + 1;
648*44421Skarels 	return (copyout(domainname, uap->domainname, uap->len));
64941486Smckusick }
65041486Smckusick 
65143452Shibler hpuxsetdomainname(p, uap, retval)
65243452Shibler 	struct proc *p;
65343452Shibler 	register struct args {
65441486Smckusick 		char	*domainname;
65541486Smckusick 		u_int	len;
65643452Shibler 	} *uap;
65743452Shibler 	int *retval;
65843452Shibler {
65943452Shibler 	int error;
66041486Smckusick 
66143452Shibler 	if (error = suser(u.u_cred, &u.u_acflag))
662*44421Skarels 		return (error);
66343452Shibler 	if (uap->len > sizeof (domainname) - 1)
664*44421Skarels 		return (EINVAL);
66541486Smckusick 	domainnamelen = uap->len;
66643452Shibler 	error = copyin(uap->domainname, domainname, uap->len);
66741486Smckusick 	domainname[domainnamelen] = 0;
668*44421Skarels 	return (error);
66941486Smckusick }
67041486Smckusick 
67141486Smckusick #ifdef SYSVSHM
67243452Shibler hpuxshmat(p, uap, retval)
67343452Shibler 	struct proc *p;
67443452Shibler 	int *uap, *retval;
67541486Smckusick {
676*44421Skarels 	return (shmat(p, uap, retval));
67741486Smckusick }
67841486Smckusick 
67943452Shibler hpuxshmctl(p, uap, retval)
68043452Shibler 	struct proc *p;
68143452Shibler 	int *uap, *retval;
68241486Smckusick {
683*44421Skarels 	return (shmctl(p, uap, retval));
68441486Smckusick }
68541486Smckusick 
68643452Shibler hpuxshmdt(p, uap, retval)
68743452Shibler 	struct proc *p;
68843452Shibler 	int *uap, *retval;
68941486Smckusick {
690*44421Skarels 	return (shmdt(p, uap, retval));
69141486Smckusick }
69241486Smckusick 
69343452Shibler hpuxshmget(p, uap, retval)
69443452Shibler 	struct proc *p;
69543452Shibler 	int *uap, *retval;
69641486Smckusick {
697*44421Skarels 	return (shmget(p, uap, retval));
69841486Smckusick }
69941486Smckusick #endif
70041486Smckusick 
70141486Smckusick /*
70241486Smckusick  * Fake semaphore routines, just don't return an error.
70341486Smckusick  * Should be adequate for starbase to run.
70441486Smckusick  */
70543452Shibler hpuxsemctl(p, uap, retval)
70643452Shibler 	struct proc *p;
70743452Shibler 	struct args {
70841486Smckusick 		int semid;
70941486Smckusick 		u_int semnum;
71041486Smckusick 		int cmd;
71141486Smckusick 		int arg;
71243452Shibler 	} *uap;
71343452Shibler 	int *retval;
71443452Shibler {
71541486Smckusick 	/* XXX: should do something here */
716*44421Skarels 	return (0);
71741486Smckusick }
71841486Smckusick 
71943452Shibler hpuxsemget(p, uap, retval)
72043452Shibler 	struct proc *p;
72143452Shibler 	struct args {
72241486Smckusick 		key_t key;
72341486Smckusick 		int nsems;
72441486Smckusick 		int semflg;
72543452Shibler 	} *uap;
72643452Shibler 	int *retval;
72743452Shibler {
72841486Smckusick 	/* XXX: should do something here */
729*44421Skarels 	return (0);
73041486Smckusick }
73141486Smckusick 
73243452Shibler hpuxsemop(p, uap, retval)
73343452Shibler 	struct proc *p;
73443452Shibler 	struct args {
73541486Smckusick 		int semid;
73641486Smckusick 		struct sembuf *sops;
73741486Smckusick 		u_int nsops;
73843452Shibler 	} *uap;
73943452Shibler 	int *retval;
74043452Shibler {
74141486Smckusick 	/* XXX: should do something here */
742*44421Skarels 	return (0);
74341486Smckusick }
74441486Smckusick 
74541486Smckusick /* convert from BSD to HPUX errno */
74641486Smckusick bsdtohpuxerrno(err)
74741486Smckusick 	int err;
74841486Smckusick {
74941486Smckusick 	if (err < 0 || err >= NERR)
75041486Smckusick 		return(BERR);
75141486Smckusick 	return((int)bsdtohpuxerrnomap[err]);
75241486Smckusick }
75341486Smckusick 
75441486Smckusick hpuxstat1(fname, hsb, follow)
75541486Smckusick 	char *fname;
75641486Smckusick 	struct hpuxstat *hsb;
75741486Smckusick 	int follow;
75841486Smckusick {
75941486Smckusick 	register struct nameidata *ndp = &u.u_nd;
76041486Smckusick 	struct stat sb;
76141486Smckusick 	int error;
76241486Smckusick 
76341486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
76441486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
76541486Smckusick 	ndp->ni_dirp = fname;
76641486Smckusick 	if (error = namei(ndp))
76741486Smckusick 		return (error);
76841486Smckusick 	error = vn_stat(ndp->ni_vp, &sb);
76941486Smckusick 	vput(ndp->ni_vp);
77041486Smckusick 	if (error == 0)
77141486Smckusick 		error = bsdtohpuxstat(&sb, hsb);
77241486Smckusick 	return (error);
77341486Smckusick }
77441486Smckusick 
77541486Smckusick #include "grf.h"
77641486Smckusick 
77741486Smckusick bsdtohpuxstat(sb, hsb)
77841486Smckusick 	struct stat *sb;
77941486Smckusick 	struct hpuxstat *hsb;
78041486Smckusick {
78141486Smckusick 	struct hpuxstat ds;
78241486Smckusick 
78341486Smckusick 	bzero((caddr_t)&ds, sizeof(ds));
78441486Smckusick 	ds.hst_dev = sb->st_dev;
78541486Smckusick 	ds.hst_ino = (u_long)sb->st_ino;
78641486Smckusick 	ds.hst_mode = sb->st_mode;
78741486Smckusick 	ds.hst_nlink = sb->st_nlink;
78841486Smckusick 	ds.hst_uid = (u_short)sb->st_uid;
78941486Smckusick 	ds.hst_gid = (u_short)sb->st_gid;
79041486Smckusick #if NGRF > 0
79141486Smckusick 	/* XXX: I don't want to talk about it... */
79241486Smckusick 	if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10)
79341486Smckusick 		ds.hst_rdev = grfdevno(sb->st_rdev);
79441486Smckusick 	else
79541486Smckusick #endif
79641486Smckusick 		ds.hst_rdev = bsdtohpuxdev(sb->st_rdev);
79741486Smckusick 	ds.hst_size = sb->st_size;
79841486Smckusick 	ds.hst_atime = sb->st_atime;
79941486Smckusick 	ds.hst_mtime = sb->st_mtime;
80041486Smckusick 	ds.hst_ctime = sb->st_ctime;
80141486Smckusick 	ds.hst_blksize = sb->st_blksize;
80241486Smckusick 	ds.hst_blocks = sb->st_blocks;
80341486Smckusick 	return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds)));
80441486Smckusick }
80541486Smckusick 
80641486Smckusick hpuxtobsdioctl(com)
80741486Smckusick 	int com;
80841486Smckusick {
80941486Smckusick 	switch (com) {
81041486Smckusick 	case HPUXTIOCSLTC:
81141486Smckusick 		com = TIOCSLTC; break;
81241486Smckusick 	case HPUXTIOCGLTC:
81341486Smckusick 		com = TIOCGLTC; break;
81441486Smckusick 	case HPUXTIOCSPGRP:
81541486Smckusick 		com = TIOCSPGRP; break;
81641486Smckusick 	case HPUXTIOCGPGRP:
81741486Smckusick 		com = TIOCGPGRP; break;
81841486Smckusick 	case HPUXTIOCLBIS:
81941486Smckusick 		com = TIOCLBIS; break;
82041486Smckusick 	case HPUXTIOCLBIC:
82141486Smckusick 		com = TIOCLBIC; break;
82241486Smckusick 	case HPUXTIOCLSET:
82341486Smckusick 		com = TIOCLSET; break;
82441486Smckusick 	case HPUXTIOCLGET:
82541486Smckusick 		com = TIOCLGET; break;
82641486Smckusick 	}
82741486Smckusick 	return(com);
82841486Smckusick }
82941486Smckusick 
83041486Smckusick /*
83141486Smckusick  * HPUX ioctl system call.  The differences here are:
83241486Smckusick  *	IOC_IN also means IOC_VOID if the size portion is zero.
83341486Smckusick  *	no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN
83441486Smckusick  *	the sgttyb struct is 2 bytes longer
83541486Smckusick  */
83643452Shibler hpuxioctl(p, uap, retval)
83743452Shibler 	struct proc *p;
83843452Shibler 	register struct args {
83941486Smckusick 		int	fdes;
84041486Smckusick 		int	cmd;
84141486Smckusick 		caddr_t	cmarg;
84243452Shibler 	} *uap;
84343452Shibler 	int *retval;
84443452Shibler {
84543452Shibler 	register struct file *fp;
84643452Shibler 	register int com, error;
84741486Smckusick 	register u_int size;
84841486Smckusick 	caddr_t memp = 0;
84941486Smckusick #define STK_PARAMS	128
85041486Smckusick 	char stkbuf[STK_PARAMS];
85141486Smckusick 	caddr_t data = stkbuf;
85241486Smckusick 
85341486Smckusick 	com = uap->cmd;
85441486Smckusick 
85541486Smckusick 	/* XXX */
85643452Shibler 	if (com == HPUXTIOCGETP || com == HPUXTIOCSETP)
857*44421Skarels 		return (getsettty(uap->fdes, com, uap->cmarg));
85841486Smckusick 
85941486Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
86043452Shibler 	    (fp = u.u_ofile[uap->fdes]) == NULL)
861*44421Skarels 		return (EBADF);
86243452Shibler 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
863*44421Skarels 		return (EBADF);
86441486Smckusick 
86541486Smckusick 	/*
86641486Smckusick 	 * Interpret high order word to find
86741486Smckusick 	 * amount of data to be copied to/from the
86841486Smckusick 	 * user's address space.
86941486Smckusick 	 */
87041486Smckusick 	size = IOCPARM_LEN(com);
87143452Shibler 	if (size > IOCPARM_MAX)
872*44421Skarels 		return (ENOTTY);
87341486Smckusick 	if (size > sizeof (stkbuf)) {
87443452Shibler 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
87541486Smckusick 		data = memp;
87641486Smckusick 	}
87741486Smckusick 	if (com&IOC_IN) {
87841486Smckusick 		if (size) {
87943452Shibler 			error = copyin(uap->cmarg, data, (u_int)size);
88043452Shibler 			if (error) {
88141486Smckusick 				if (memp)
88241486Smckusick 					free(memp, M_IOCTLOPS);
883*44421Skarels 				return (error);
88441486Smckusick 			}
88541486Smckusick 		} else
88641486Smckusick 			*(caddr_t *)data = uap->cmarg;
88741486Smckusick 	} else if ((com&IOC_OUT) && size)
88841486Smckusick 		/*
88943452Shibler 		 * Zero the buffer so the user always
89043452Shibler 		 * gets back something deterministic.
89141486Smckusick 		 */
89241486Smckusick 		bzero(data, size);
89341486Smckusick 	else if (com&IOC_VOID)
89441486Smckusick 		*(caddr_t *)data = uap->cmarg;
89541486Smckusick 
89641486Smckusick 	switch (com) {
89741486Smckusick 
89841486Smckusick 	case HPUXTIOCCONS:
89941486Smckusick 		*(int *)data = 1;
90043452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data);
90141486Smckusick 		break;
90241486Smckusick 
90341486Smckusick 	/* BSD-style job control ioctls */
90441486Smckusick 	case HPUXTIOCLBIS:
90541486Smckusick 	case HPUXTIOCLBIC:
90641486Smckusick 	case HPUXTIOCLSET:
90741486Smckusick 		*(int *)data &= HPUXLTOSTOP;
90841486Smckusick 		if (*(int *)data & HPUXLTOSTOP)
90941486Smckusick 			*(int *)data = LTOSTOP;
91041486Smckusick 		/* fall into */
91141486Smckusick 	case HPUXTIOCLGET:
91241486Smckusick 	case HPUXTIOCSLTC:
91341486Smckusick 	case HPUXTIOCGLTC:
91441486Smckusick 	case HPUXTIOCSPGRP:
91541486Smckusick 	case HPUXTIOCGPGRP:
91643452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data);
91743452Shibler 		if (error == 0 && com == HPUXTIOCLGET) {
91841486Smckusick 			*(int *)data &= LTOSTOP;
91941486Smckusick 			if (*(int *)data & LTOSTOP)
92041486Smckusick 				*(int *)data = HPUXLTOSTOP;
92141486Smckusick 		}
92241486Smckusick 		break;
92341486Smckusick 
92441486Smckusick 	/* SYS 5 termio */
92541486Smckusick 	case HPUXTCGETA:
92641486Smckusick 	case HPUXTCSETA:
92741486Smckusick 	case HPUXTCSETAW:
92841486Smckusick 	case HPUXTCSETAF:
92943452Shibler 		error = hpuxtermio(fp, com, data);
93041486Smckusick 		break;
93141486Smckusick 
93241486Smckusick 	default:
93343452Shibler 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
93441486Smckusick 		break;
93541486Smckusick 	}
93641486Smckusick 	/*
93741486Smckusick 	 * Copy any data to user, size was
93841486Smckusick 	 * already set and checked above.
93941486Smckusick 	 */
94043452Shibler 	if (error == 0 && (com&IOC_OUT) && size)
94143452Shibler 		error = copyout(data, uap->cmarg, (u_int)size);
94241486Smckusick 	if (memp)
94341486Smckusick 		free(memp, M_IOCTLOPS);
944*44421Skarels 	return (error);
94541486Smckusick }
94641486Smckusick 
94741486Smckusick /*
94841486Smckusick  * Man page lies, behaviour here is based on observed behaviour.
94941486Smckusick  */
95043452Shibler hpuxgetcontext(p, uap, retval)
95143452Shibler 	struct proc *p;
95243452Shibler 	struct args {
95341486Smckusick 		char *buf;
95441486Smckusick 		int len;
95543452Shibler 	} *uap;
95643452Shibler 	int *retval;
95743452Shibler {
95841486Smckusick 	int error = 0;
95941486Smckusick 	register int len;
96041486Smckusick 
96141486Smckusick 	len = MIN(uap->len, sizeof(hpuxcontext));
96241486Smckusick 	if (len)
96341486Smckusick 		error = copyout(hpuxcontext, uap->buf, (u_int)len);
96443452Shibler 	if (error == 0)
96543452Shibler 		*retval = sizeof(hpuxcontext);
966*44421Skarels 	return (error);
96741486Smckusick }
96841486Smckusick 
96941486Smckusick /*
97041486Smckusick  * XXX: simple recognition hack to see if we can make grmd work.
97141486Smckusick  */
97243452Shibler hpuxlockf(p, uap, retval)
97343452Shibler 	struct proc *p;
97443452Shibler 	struct args {
97541486Smckusick 		int fd;
97641486Smckusick 		int func;
97741486Smckusick 		long size;
97843452Shibler 	} *uap;
97943452Shibler 	int *retval;
98043452Shibler {
98141486Smckusick #ifdef DEBUG
98241486Smckusick 	log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n",
98343452Shibler 	    p->p_pid, uap->fd, uap->func, uap->size);
98441486Smckusick #endif
985*44421Skarels 	return (0);
98641486Smckusick }
98741486Smckusick 
98841486Smckusick /*
98941486Smckusick  * This is the equivalent of BSD getpgrp but with more restrictions.
99041486Smckusick  * Note we do not check the real uid or "saved" uid.
99141486Smckusick  */
99243452Shibler hpuxgetpgrp2(cp, uap, retval)
99343452Shibler 	struct proc *cp;
99443452Shibler 	register struct args {
99543452Shibler 		int pid;
99643452Shibler 	} *uap;
99743452Shibler 	int *retval;
99841486Smckusick {
99941486Smckusick 	register struct proc *p;
100041486Smckusick 
100141486Smckusick 	if (uap->pid == 0)
100243452Shibler 		uap->pid = cp->p_pid;
100341486Smckusick 	p = pfind(uap->pid);
100443452Shibler 	if (p == 0)
1005*44421Skarels 		return (ESRCH);
100643452Shibler 	if (u.u_uid && p->p_uid != u.u_uid && !inferior(p))
1007*44421Skarels 		return (EPERM);
100843452Shibler 	*retval = p->p_pgid;
1009*44421Skarels 	return (0);
101041486Smckusick }
101141486Smckusick 
101241486Smckusick /*
101341486Smckusick  * This is the equivalent of BSD setpgrp but with more restrictions.
101441486Smckusick  * Note we do not check the real uid or "saved" uid or pgrp.
101541486Smckusick  */
101643452Shibler hpuxsetpgrp2(p, uap, retval)
101743452Shibler 	struct proc *p;
101843452Shibler 	struct args {
101941486Smckusick 		int	pid;
102041486Smckusick 		int	pgrp;
102143452Shibler 	} *uap;
102243452Shibler 	int *retval;
102343452Shibler {
102441486Smckusick 	/* empirically determined */
102543452Shibler 	if (uap->pgrp < 0 || uap->pgrp >= 30000)
1026*44421Skarels 		return (EINVAL);
1027*44421Skarels 	return (setpgrp(p, uap, retval));
102841486Smckusick }
102941486Smckusick 
103041486Smckusick /*
103141486Smckusick  * Brutal hack!  Map HPUX u-area offsets into BSD u offsets.
103241486Smckusick  * No apologies offered, if you don't like it, rewrite it!
103341486Smckusick  */
103441486Smckusick 
103541486Smckusick #define UOFF(f)		((int)&((struct user *)0)->f)
103641486Smckusick #define HPUOFF(f)	((int)&((struct hpuxuser *)0)->f)
103741486Smckusick 
103841486Smckusick /* simplified FP structure */
103941486Smckusick struct bsdfp {
104041486Smckusick 	int save[54];
104141486Smckusick 	int reg[24];
104241486Smckusick 	int ctrl[3];
104341486Smckusick };
104441486Smckusick 
104541486Smckusick hpuxtobsduoff(off)
104641486Smckusick 	int *off;
104741486Smckusick {
104841486Smckusick 	struct hpuxfp *hp;
104941486Smckusick 	struct bsdfp *bp;
105041486Smckusick 	register u_int raddr;
105141486Smckusick 
105241486Smckusick 	/* u_ar0 field */
105341486Smckusick 	if ((int)off == HPUOFF(hpuxu_ar0))
105441486Smckusick 		return(UOFF(u_ar0));
105541486Smckusick 
105641486Smckusick #ifdef FPCOPROC
105741486Smckusick 	/* 68881 registers from PCB */
105841486Smckusick 	hp = (struct hpuxfp *)HPUOFF(hpuxu_fp);
105941486Smckusick 	bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
106041486Smckusick 	if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
106141486Smckusick 		return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
106241486Smckusick 	if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
106341486Smckusick 		return((int)&bp->reg[off - hp->hpfp_reg]);
106441486Smckusick #endif
106541486Smckusick 
106641486Smckusick 	/*
106741486Smckusick 	 * Everything else we recognize comes from the kernel stack,
106841486Smckusick 	 * so we convert off to an absolute address (if not already)
106941486Smckusick 	 * for simplicity.
107041486Smckusick 	 */
107141486Smckusick 	if (off < (int *)ctob(UPAGES))
107241486Smckusick 		off = (int *)((u_int)off + (u_int)&u);
107341486Smckusick 
107441486Smckusick 	/*
107541486Smckusick 	 * 68020 registers.
107641486Smckusick 	 * We know that the HPUX registers are in the same order as ours.
107741486Smckusick 	 * The only difference is that their PS is 2 bytes instead of a
107841486Smckusick 	 * padded 4 like ours throwing the alignment off.
107941486Smckusick 	 */
108041486Smckusick 	if (off >= u.u_ar0 && off < &u.u_ar0[18]) {
108141486Smckusick 		/*
108241486Smckusick 		 * PS: return low word and high word of PC as HP-UX would
108341486Smckusick 		 * (e.g. &u.u_ar0[16.5]).
108441486Smckusick 		 */
108541486Smckusick 		if (off == &u.u_ar0[PS])
108641486Smckusick 			raddr = (u_int) &((short *)u.u_ar0)[PS*2+1];
108741486Smckusick 		/*
108841486Smckusick 		 * PC: off will be &u.u_ar0[16.5]
108941486Smckusick 		 */
109041486Smckusick 		else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1]))
109141486Smckusick 			raddr = (u_int) &u.u_ar0[PC];
109241486Smckusick 		/*
109341486Smckusick 		 * D0-D7, A0-A7: easy
109441486Smckusick 		 */
109541486Smckusick 		else
109641486Smckusick 			raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)];
109741486Smckusick 		return((int)(raddr - (u_int)&u));
109841486Smckusick 	}
109941486Smckusick 
110041486Smckusick 	/* everything else */
110141486Smckusick 	return(-1);
110241486Smckusick }
110341486Smckusick 
110441486Smckusick /*
110541486Smckusick  * Kludge up a uarea dump so that HPUX debuggers can find out
110641486Smckusick  * what they need.  IMPORTANT NOTE: we do not EVEN attempt to
110741486Smckusick  * convert the entire user struct.
110841486Smckusick  */
110941486Smckusick hpuxdumpu(vp, cred)
111041486Smckusick 	struct vnode *vp;
111141486Smckusick 	struct ucred *cred;
111241486Smckusick {
111341486Smckusick 	int error;
111441486Smckusick 	struct hpuxuser *faku;
111541486Smckusick 	struct bsdfp *bp;
111641486Smckusick 	short *foop;
111741486Smckusick 
111841486Smckusick 	faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK);
111941486Smckusick 	/*
112041486Smckusick 	 * Make sure there is no mistake about this
112141486Smckusick 	 * being a real user structure.
112241486Smckusick 	 */
112341486Smckusick 	bzero((caddr_t)faku, ctob(1));
112441486Smckusick 	/*
112541486Smckusick 	 * Fill in the process sizes.
112641486Smckusick 	 */
112741486Smckusick 	faku->hpuxu_tsize = u.u_tsize;
112841486Smckusick 	faku->hpuxu_dsize = u.u_dsize;
112941486Smckusick 	faku->hpuxu_ssize = u.u_ssize;
113041486Smckusick 	/*
113141486Smckusick 	 * Fill in the exec header for CDB.
113241486Smckusick 	 * This was saved back in exec().  As far as I can tell CDB
113341486Smckusick 	 * only uses this information to verify that a particular
113441486Smckusick 	 * core file goes with a particular binary.
113541486Smckusick 	 */
113641486Smckusick 	bcopy((caddr_t)u.u_pcb.pcb_exec,
113741486Smckusick 	      (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec));
113841486Smckusick 	/*
113941486Smckusick 	 * Adjust user's saved registers (on kernel stack) to reflect
114041486Smckusick 	 * HPUX order.  Note that HPUX saves the SR as 2 bytes not 4
114141486Smckusick 	 * so we have to move it up.
114241486Smckusick 	 */
114341486Smckusick 	faku->hpuxu_ar0 = u.u_ar0;
114441486Smckusick 	foop = (short *) u.u_ar0;
114541486Smckusick 	foop[32] = foop[33];
114641486Smckusick 	foop[33] = foop[34];
114741486Smckusick 	foop[34] = foop[35];
114841486Smckusick #ifdef FPCOPROC
114941486Smckusick 	/*
115041486Smckusick 	 * Copy 68881 registers from our PCB format to HPUX format
115141486Smckusick 	 */
115241486Smckusick 	bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs;
115341486Smckusick 	bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save,
115441486Smckusick 	      sizeof(bp->save));
115541486Smckusick 	bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl,
115641486Smckusick 	      sizeof(bp->ctrl));
115741486Smckusick 	bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg,
115841486Smckusick 	      sizeof(bp->reg));
115941486Smckusick #endif
116041486Smckusick 	/*
116141486Smckusick 	 * Slay the dragon
116241486Smckusick 	 */
116341486Smckusick 	faku->hpuxu_dragon = -1;
116441486Smckusick 	/*
116541486Smckusick 	 * Dump this artfully constructed page in place of the
116641486Smckusick 	 * user struct page.
116741486Smckusick 	 */
116841486Smckusick 	error = vn_rdwr(UIO_WRITE, vp,
116941486Smckusick 			(caddr_t)faku, ctob(1), (off_t)0,
117041486Smckusick 			UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0);
117141486Smckusick 	/*
117241486Smckusick 	 * Dump the remaining UPAGES-1 pages normally
117341486Smckusick 	 */
117441486Smckusick 	if (!error)
117541486Smckusick 		error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1),
117641486Smckusick 				ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE,
117741486Smckusick 				IO_NODELOCKED|IO_UNIT, cred, (int *)0);
117841486Smckusick 	free((caddr_t)faku, M_TEMP);
117941486Smckusick 	return(error);
118041486Smckusick }
118141486Smckusick 
118241486Smckusick /*
118341486Smckusick  * The remaining routines are essentially the same as those in kern_xxx.c
118441486Smckusick  * and vfs_xxx.c as defined under "#ifdef COMPAT".  We replicate them here
118541486Smckusick  * to avoid HPUXCOMPAT dependencies in those files and to make sure that
118641486Smckusick  * HP-UX compatibility still works even when COMPAT is not defined.
118741486Smckusick  */
118841486Smckusick /* #ifdef COMPAT */
118941486Smckusick 
119042088Smckusick #include "../sys/times.h"
119141486Smckusick 
119241486Smckusick /* from old timeb.h */
119341486Smckusick struct hpuxtimeb {
119441486Smckusick 	time_t	time;
119541486Smckusick 	u_short	millitm;
119641486Smckusick 	short	timezone;
119741486Smckusick 	short	dstflag;
119841486Smckusick };
119941486Smckusick 
120041486Smckusick /* ye ole stat structure */
120141486Smckusick struct	ohpuxstat {
120241486Smckusick 	dev_t	ohst_dev;
120341486Smckusick 	u_short	ohst_ino;
120441486Smckusick 	u_short ohst_mode;
120541486Smckusick 	short  	ohst_nlink;
120641486Smckusick 	short  	ohst_uid;
120741486Smckusick 	short  	ohst_gid;
120841486Smckusick 	dev_t	ohst_rdev;
120941486Smckusick 	int	ohst_size;
121041486Smckusick 	int	ohst_atime;
121141486Smckusick 	int	ohst_mtime;
121241486Smckusick 	int	ohst_ctime;
121341486Smckusick };
121441486Smckusick 
121541486Smckusick /*
121641486Smckusick  * SYS V style setpgrp()
121741486Smckusick  */
121843452Shibler ohpuxsetpgrp(p, uap, retval)
121943452Shibler 	register struct proc *p;
122043452Shibler 	int *uap, *retval;
122141486Smckusick {
122241486Smckusick 	if (p->p_pid != p->p_pgid)
122341486Smckusick 		pgmv(p, p->p_pid, 0);
122443452Shibler 	*retval = p->p_pgid;
122541486Smckusick }
122641486Smckusick 
122743452Shibler ohpuxtime(p, uap, retval)
122843452Shibler 	struct proc *p;
122943452Shibler 	register struct args {
123043452Shibler 		long	*tp;
123143452Shibler 	} *uap;
123243713Smckusick 	time_t *retval;
123341486Smckusick {
123443452Shibler 	int error;
123541486Smckusick 
123641486Smckusick 	if (uap->tp)
123743452Shibler 		error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp,
123843452Shibler 				sizeof (long));
123943713Smckusick 	*retval = time.tv_sec;		/* XXX */
1240*44421Skarels 	return (error);
124141486Smckusick }
124241486Smckusick 
124343452Shibler ohpuxstime(p, uap, retval)
124443452Shibler 	struct proc *p;
124543452Shibler 	register struct args {
124643452Shibler 		int	time;
124743452Shibler 	} *uap;
124843452Shibler 	int *retval;
124941486Smckusick {
125041486Smckusick 	struct timeval tv;
125143452Shibler 	int s, error;
125241486Smckusick 
125341486Smckusick 	tv.tv_sec = uap->time;
125441486Smckusick 	tv.tv_usec = 0;
125543452Shibler 	if (error = suser(u.u_cred, &u.u_acflag))
1256*44421Skarels 		return (error);
125741486Smckusick 
125841486Smckusick 	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
125941486Smckusick 	boottime.tv_sec += tv.tv_sec - time.tv_sec;
126041486Smckusick 	s = splhigh(); time = tv; splx(s);
126141486Smckusick 	resettodr();
1262*44421Skarels 	return (0);
126341486Smckusick }
126441486Smckusick 
126543452Shibler ohpuxftime(p, uap, retval)
126643452Shibler 	struct proc *p;
126743452Shibler 	register struct args {
126841486Smckusick 		struct	hpuxtimeb *tp;
126941486Smckusick 	} *uap;
127043452Shibler 	int *retval;
127143452Shibler {
127241486Smckusick 	struct hpuxtimeb tb;
127341486Smckusick 	int s;
127441486Smckusick 
127541486Smckusick 	s = splhigh();
127641486Smckusick 	tb.time = time.tv_sec;
127741486Smckusick 	tb.millitm = time.tv_usec / 1000;
127841486Smckusick 	splx(s);
127941486Smckusick 	tb.timezone = tz.tz_minuteswest;
128041486Smckusick 	tb.dstflag = tz.tz_dsttime;
1281*44421Skarels 	return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)));
128241486Smckusick }
128341486Smckusick 
128443452Shibler ohpuxalarm(p, uap, retval)
128543452Shibler 	register struct proc *p;
128643452Shibler 	register struct args {
128743452Shibler 		int	deltat;
128843452Shibler 	} *uap;
128943452Shibler 	int *retval;
129041486Smckusick {
129141486Smckusick 	int s = splhigh();
129241486Smckusick 
129341486Smckusick 	untimeout(realitexpire, (caddr_t)p);
129441486Smckusick 	timerclear(&p->p_realtimer.it_interval);
129543452Shibler 	*retval = 0;
129641486Smckusick 	if (timerisset(&p->p_realtimer.it_value) &&
129741486Smckusick 	    timercmp(&p->p_realtimer.it_value, &time, >))
129843452Shibler 		*retval = p->p_realtimer.it_value.tv_sec - time.tv_sec;
129941486Smckusick 	if (uap->deltat == 0) {
130041486Smckusick 		timerclear(&p->p_realtimer.it_value);
130141486Smckusick 		splx(s);
1302*44421Skarels 		return (0);
130341486Smckusick 	}
130441486Smckusick 	p->p_realtimer.it_value = time;
130541486Smckusick 	p->p_realtimer.it_value.tv_sec += uap->deltat;
130641486Smckusick 	timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value));
130741486Smckusick 	splx(s);
1308*44421Skarels 	return (0);
130941486Smckusick }
131041486Smckusick 
131143452Shibler ohpuxnice(p, uap, retval)
131243452Shibler 	register struct proc *p;
131343452Shibler 	register struct args {
131443452Shibler 		int	niceness;
131543452Shibler 	} *uap;
131643452Shibler 	int *retval;
131741486Smckusick {
131843452Shibler 	int error;
131941486Smckusick 
132043452Shibler 	error = donice(p, p, (p->p_nice-NZERO)+uap->niceness);
132143452Shibler 	if (error == 0)
132243452Shibler 		*retval = p->p_nice - NZERO;
1323*44421Skarels 	return (error);
132441486Smckusick }
132541486Smckusick 
132643452Shibler ohpuxtimes(p, uap, retval)
132743452Shibler 	struct proc *p;
132843452Shibler 	register struct args {
132943452Shibler 		struct	tms *tmsb;
133043452Shibler 	} *uap;
133143713Smckusick 	time_t *retval;
133241486Smckusick {
133341486Smckusick 	struct tms atms;
133443452Shibler 	int error;
133541486Smckusick 
133641486Smckusick 	atms.tms_utime = scale50(&u.u_ru.ru_utime);
133741486Smckusick 	atms.tms_stime = scale50(&u.u_ru.ru_stime);
133841486Smckusick 	atms.tms_cutime = scale50(&u.u_cru.ru_utime);
133941486Smckusick 	atms.tms_cstime = scale50(&u.u_cru.ru_stime);
134043452Shibler 	error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms));
134143452Shibler 	if (error == 0)
134243713Smckusick 		*retval = scale50(&time) - scale50(&boottime); /* XXX */
1343*44421Skarels 	return (error);
134441486Smckusick }
134541486Smckusick 
134641486Smckusick scale50(tvp)
134741486Smckusick 	register struct timeval *tvp;
134841486Smckusick {
134941486Smckusick 	extern int hpuxtick;
135041486Smckusick 
135141486Smckusick 	/*
135241486Smckusick 	 * Doesn't exactly do what the documentation says.
135341486Smckusick 	 * What we really do is return 50th of a second since that
135441486Smckusick 	 * is what HZ is on all bobcats I know of.
135541486Smckusick 	 */
135641486Smckusick 	return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick));
135741486Smckusick }
135841486Smckusick 
135941486Smckusick /*
136041486Smckusick  * Set IUPD and IACC times on file.
136141486Smckusick  * Can't set ICHG.
136241486Smckusick  */
136343452Shibler ohpuxutime(p, uap, retval)
136443452Shibler 	struct proc *p;
136541486Smckusick 	register struct a {
136641486Smckusick 		char	*fname;
136741486Smckusick 		time_t	*tptr;
136843452Shibler 	} *uap;
136943452Shibler 	int *retval;
137043452Shibler {
137141486Smckusick 	struct vattr vattr;
137241486Smckusick 	time_t tv[2];
137341486Smckusick 	register struct vnode *vp;
137441486Smckusick 	register struct nameidata *ndp = &u.u_nd;
137543452Shibler 	int error;
137641486Smckusick 
137741486Smckusick 	if (uap->tptr) {
137843452Shibler 		error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
137943452Shibler 		if (error)
1380*44421Skarels 			return (error);
138141486Smckusick 	} else
138241486Smckusick 		tv[0] = tv[1] = time.tv_sec;
138341486Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
138441486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
138541486Smckusick 	ndp->ni_dirp = uap->fname;
138641486Smckusick 	vattr_null(&vattr);
138741486Smckusick 	vattr.va_atime.tv_sec = tv[0];
138841486Smckusick 	vattr.va_atime.tv_usec = 0;
138941486Smckusick 	vattr.va_mtime.tv_sec = tv[1];
139041486Smckusick 	vattr.va_mtime.tv_usec = 0;
139143452Shibler 	if (error = namei(ndp))
1392*44421Skarels 		return (error);
139341486Smckusick 	vp = ndp->ni_vp;
139442154Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
139543452Shibler 		error = EROFS;
139641486Smckusick 	else
139743452Shibler 		error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
139841486Smckusick 	vput(vp);
1399*44421Skarels 	return (error);
140041486Smckusick }
140141486Smckusick 
140243452Shibler ohpuxpause(p, uap, retval)
140343452Shibler 	struct proc *p;
140443452Shibler 	int *uap, *retval;
140541486Smckusick {
140642155Skarels 	(void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0);
140742155Skarels 	/* always return EINTR rather than ERESTART... */
1408*44421Skarels 	return (EINTR);
140941486Smckusick }
141041486Smckusick 
141141486Smckusick /*
141241486Smckusick  * The old fstat system call.
141341486Smckusick  */
141443452Shibler ohpuxfstat(p, uap, retval)
141543452Shibler 	struct proc *p;
141643452Shibler 	register struct args {
141741486Smckusick 		int	fd;
141841486Smckusick 		struct ohpuxstat *sb;
141943452Shibler 	} *uap;
142043452Shibler 	int *retval;
142143452Shibler {
142241486Smckusick 	struct file *fp;
142341486Smckusick 
142443452Shibler 	if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL)
1425*44421Skarels 		return (EBADF);
142643452Shibler 	if (fp->f_type != DTYPE_VNODE)
1427*44421Skarels 		return (EINVAL);
1428*44421Skarels 	return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb));
142941486Smckusick }
143041486Smckusick 
143141486Smckusick /*
143241486Smckusick  * Old stat system call.  This version follows links.
143341486Smckusick  */
143443452Shibler ohpuxstat(p, uap, retval)
143543452Shibler 	struct proc *p;
143643452Shibler 	register struct args {
143741486Smckusick 		char	*fname;
143841486Smckusick 		struct ohpuxstat *sb;
143943452Shibler 	} *uap;
144043452Shibler 	int *retval;
144143452Shibler {
144241486Smckusick 	register struct nameidata *ndp = &u.u_nd;
144343452Shibler 	int error;
144441486Smckusick 
144541486Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
144641486Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
144741486Smckusick 	ndp->ni_dirp = uap->fname;
144843452Shibler 	if (error = namei(ndp))
1449*44421Skarels 		return (error);
145043452Shibler 	error = ohpuxstat1(ndp->ni_vp, uap->sb);
145141486Smckusick 	vput(ndp->ni_vp);
1452*44421Skarels 	return (error);
145341486Smckusick }
145441486Smckusick 
145541486Smckusick int
145641486Smckusick ohpuxstat1(vp, ub)
145741486Smckusick 	register struct vnode *vp;
145841486Smckusick 	struct ohpuxstat *ub;
145941486Smckusick {
146041486Smckusick 	struct ohpuxstat ds;
146141486Smckusick 	struct vattr vattr;
146241486Smckusick 	register int error;
146341486Smckusick 
146441486Smckusick 	error = VOP_GETATTR(vp, &vattr, u.u_cred);
146541486Smckusick 	if (error)
146641486Smckusick 		return(error);
146741486Smckusick 	/*
146841486Smckusick 	 * Copy from inode table
146941486Smckusick 	 */
147041486Smckusick 	ds.ohst_dev = vattr.va_fsid;
147141486Smckusick 	ds.ohst_ino = (short)vattr.va_fileid;
147241486Smckusick 	ds.ohst_mode = (u_short)vattr.va_mode;
147341486Smckusick 	ds.ohst_nlink = vattr.va_nlink;
147441486Smckusick 	ds.ohst_uid = (short)vattr.va_uid;
147541486Smckusick 	ds.ohst_gid = (short)vattr.va_gid;
147641486Smckusick 	ds.ohst_rdev = (dev_t)vattr.va_rdev;
147741486Smckusick 	ds.ohst_size = (int)vattr.va_size;
147841486Smckusick 	ds.ohst_atime = (int)vattr.va_atime.tv_sec;
147941486Smckusick 	ds.ohst_mtime = (int)vattr.va_mtime.tv_sec;
148041486Smckusick 	ds.ohst_ctime = (int)vattr.va_ctime.tv_sec;
148141486Smckusick 	return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)));
148241486Smckusick }
148341486Smckusick /* #endif */
148441486Smckusick 
148541486Smckusick #endif
1486