xref: /original-bsd/sys/hp/hpux/hpux_compat.c (revision 9b5efc43)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: hpux_compat.c 1.3 90/09/17$
13  *
14  *	@(#)hpux_compat.c	7.12 (Berkeley) 01/11/91
15  */
16 
17 /*
18  * Various HPUX compatibility routines
19  */
20 
21 #ifdef HPUXCOMPAT
22 
23 #include "sys/param.h"
24 #include "sys/systm.h"
25 #include "sys/user.h"
26 #include "sys/kernel.h"
27 #include "sys/filedesc.h"
28 #include "sys/proc.h"
29 #include "sys/buf.h"
30 #include "sys/wait.h"
31 #include "sys/file.h"
32 #include "sys/vnode.h"
33 #include "sys/ioctl.h"
34 #include "sys/uio.h"
35 #include "sys/ptrace.h"
36 #include "sys/stat.h"
37 #include "sys/syslog.h"
38 #include "sys/malloc.h"
39 #include "sys/mount.h"
40 #include "sys/ipc.h"
41 
42 #include "../include/cpu.h"
43 #include "../include/reg.h"
44 #include "../include/psl.h"
45 #include "../include/vmparam.h"
46 #include "hpux.h"
47 #include "hpux_termio.h"
48 
49 #ifdef DEBUG
50 int unimpresponse = 0;
51 #endif
52 
53 /* SYS5 style UTSNAME info */
54 struct hpuxutsname protoutsname = {
55 	"4.4bsd", "", "2.0", "B", "9000/3?0", ""
56 };
57 
58 /* 6.0 and later style context */
59 #ifdef FPCOPROC
60 char hpuxcontext[] =
61 	"standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default";
62 #else
63 char hpuxcontext[] =
64 	"standalone HP-MC68020 HP-MC68010 localroot default";
65 #endif
66 
67 /* YP domainname */
68 char	domainname[MAXHOSTNAMELEN] = "unknown";
69 int	domainnamelen = 7;
70 
71 #define NERR	79
72 #define BERR	1000
73 
74 /* indexed by BSD errno */
75 short bsdtohpuxerrnomap[NERR] = {
76 /*00*/	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
77 /*10*/	 10,  45,  12,  13,  14,  15,  16,  17,  18,  19,
78 /*20*/	 20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
79 /*30*/	 30,  31,  32,  33,  34, 246, 245, 244, 216, 217,
80 /*40*/	218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
81 /*50*/	228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
82 /*60*/	238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,
83 /*70*/   70,  71,BERR,BERR,BERR,BERR,BERR,  46,BERR
84 };
85 
86 notimp(p, uap, retval, code, nargs)
87 	struct proc *p;
88 	int *uap, *retval;
89 	int code, nargs;
90 {
91 	int error = 0;
92 #ifdef DEBUG
93 	register int *argp = uap;
94 	extern char *hpuxsyscallnames[];
95 
96 	printf("HPUX %s(", hpuxsyscallnames[code]);
97 	if (nargs)
98 		while (nargs--)
99 			printf("%x%c", *argp++, nargs? ',' : ')');
100 	else
101 		printf(")");
102 	printf("\n");
103 	switch (unimpresponse) {
104 	case 0:
105 		error = nosys(p, uap, retval);
106 		break;
107 	case 1:
108 		error = EINVAL;
109 		break;
110 	}
111 #else
112 	error = nosys(p, uap, retval);
113 #endif
114 	uprintf("HP-UX system call %d not implemented\n", code);
115 	return (error);
116 }
117 
118 /*
119  * HPUX versions of wait and wait3 actually pass the parameters
120  * (status pointer, options, rusage) into the kernel rather than
121  * handling it in the C library stub.  We also need to map any
122  * termination signal from BSD to HPUX.
123  */
124 hpuxwait3(p, uap, retval)
125 	struct proc *p;
126 	struct args {
127 		int	*status;
128 		int	options;
129 		int	rusage;
130 	} *uap;
131 	int *retval;
132 {
133 	/* rusage pointer must be zero */
134 	if (uap->rusage)
135 		return (EINVAL);
136 	u.u_ar0[PS] = PSL_ALLCC;
137 	u.u_ar0[R0] = uap->options;
138 	u.u_ar0[R1] = uap->rusage;
139 	return (hpuxwait(p, uap, retval));
140 }
141 
142 hpuxwait(p, uap, retval)
143 	struct proc *p;
144 	struct args {
145 		int	*status;
146 	} *uap;
147 	int *retval;
148 {
149 	int sig, *statp, error;
150 
151 	statp = uap->status;	/* owait clobbers first arg */
152 	error = owait(p, uap, retval);
153 	/*
154 	 * HP-UX wait always returns EINTR when interrupted by a signal
155 	 * (well, unless its emulating a BSD process, but we don't bother...)
156 	 */
157 	if (error == ERESTART)
158 		error = EINTR;
159 	if (error)
160 		return (error);
161 	sig = retval[1] & 0xFF;
162 	if (sig == WSTOPPED) {
163 		sig = (retval[1] >> 8) & 0xFF;
164 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
165 	} else if (sig)
166 		retval[1] = (retval[1] & 0xFF00) |
167 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
168 	if (statp)
169 		if (suword((caddr_t)statp, retval[1]))
170 			error = EFAULT;
171 	return (error);
172 }
173 
174 hpuxwaitpid(p, uap, retval)
175 	struct proc *p;
176 	struct args {
177 		int	pid;
178 		int	*status;
179 		int	options;
180 		struct	rusage *rusage;	/* wait4 arg */
181 	} *uap;
182 	int *retval;
183 {
184 	int sig, *statp, error;
185 
186 	uap->rusage = 0;
187 	error = wait4(p, uap, retval);
188 	/*
189 	 * HP-UX wait always returns EINTR when interrupted by a signal
190 	 * (well, unless its emulating a BSD process, but we don't bother...)
191 	 */
192 	if (error == ERESTART)
193 		error = EINTR;
194 	if (error)
195 		return (error);
196 	sig = retval[1] & 0xFF;
197 	if (sig == WSTOPPED) {
198 		sig = (retval[1] >> 8) & 0xFF;
199 		retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
200 	} else if (sig)
201 		retval[1] = (retval[1] & 0xFF00) |
202 			bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
203 	if (statp)
204 		if (suword((caddr_t)statp, retval[1]))
205 			error = EFAULT;
206 	return (error);
207 }
208 
209 /*
210  * Must remap some bits in the mode mask.
211  * O_CREAT, O_TRUNC, and O_EXCL must be remapped,
212  * O_SYNCIO (0100000) is removed entirely.
213  */
214 hpuxopen(p, uap, retval)
215 	struct proc *p;
216 	register struct args {
217 		char	*fname;
218 		int	mode;
219 		int	crtmode;
220 	} *uap;
221 	int *retval;
222 {
223 	int mode;
224 
225 	mode = uap->mode;
226 	uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT);
227 	if (mode & HPUXFCREAT) {
228 		/*
229 		 * simulate the pre-NFS behavior that opening a
230 		 * file for READ+CREATE ignores the CREATE (unless
231 		 * EXCL is set in which case we will return the
232 		 * proper error).
233 		 */
234 		if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE))
235 			uap->mode |= FCREAT;
236 	}
237 	if (mode & HPUXFTRUNC)
238 		uap->mode |= FTRUNC;
239 	if (mode & HPUXFEXCL)
240 		uap->mode |= FEXCL;
241 	return (open(p, uap, retval));
242 }
243 
244 hpuxfcntl(p, uap, retval)
245 	struct proc *p;
246 	register struct args {
247 		int	fdes;
248 		int	cmd;
249 		int	arg;
250 	} *uap;
251 	int *retval;
252 {
253 	int mode, error;
254 
255 	switch (uap->cmd) {
256 	case F_SETFL:
257 		uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE);
258 		break;
259 	case F_GETFL:
260 	case F_DUPFD:
261 	case F_GETFD:
262 	case F_SETFD:
263 		break;
264 	default:
265 		return (EINVAL);
266 	}
267 	error = fcntl(p, uap, retval);
268 	if (error == 0 && uap->arg == F_GETFL) {
269 		mode = *retval;
270 		*retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE);
271 		if (mode & FCREAT)
272 			*retval |= HPUXFCREAT;
273 		if (mode & FTRUNC)
274 			*retval |= HPUXFTRUNC;
275 		if (mode & FEXCL)
276 			*retval |= HPUXFEXCL;
277 	}
278 	return (error);
279 }
280 
281 /*
282  * Read and write should return a 0 count when an operation
283  * on a VNODE would block, not an error.  Sockets appear to
284  * return EWOULDBLOCK (at least in 6.2).  This is probably
285  * not entirely correct, since the behavior is only defined
286  * for pipes and tty type devices.
287  */
288 hpuxread(p, uap, retval)
289 	struct proc *p;
290 	struct args {
291 		int	fd;
292 	} *uap;
293 	int *retval;
294 {
295 	int error;
296 
297 	error = read(p, uap, retval);
298 	if (error == EWOULDBLOCK &&
299 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
300 		error = 0;
301 		*retval = 0;
302 	}
303 	return (error);
304 }
305 
306 hpuxwrite(p, uap, retval)
307 	struct proc *p;
308 	struct args {
309 		int	fd;
310 	} *uap;
311 	int *retval;
312 {
313 	int error;
314 
315 	error = write(p, uap, retval);
316 	if (error == EWOULDBLOCK &&
317 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
318 		error = 0;
319 		*retval = 0;
320 	}
321 	return (error);
322 }
323 
324 hpuxreadv(p, uap, retval)
325 	struct proc *p;
326 	struct args {
327 		int	fd;
328 	} *uap;
329 	int *retval;
330 {
331 	int error;
332 
333 	error = readv(p, uap, retval);
334 	if (error == EWOULDBLOCK &&
335 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
336 		error = 0;
337 		*retval = 0;
338 	}
339 	return (error);
340 }
341 
342 hpuxwritev(p, uap, retval)
343 	struct proc *p;
344 	struct args {
345 		int	fd;
346 	} *uap;
347 	int *retval;
348 {
349 	int error;
350 
351 	error = writev(p, uap, retval);
352 	if (error == EWOULDBLOCK &&
353 	    (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) {
354 		error = 0;
355 		*retval = 0;
356 	}
357 	return (error);
358 }
359 
360 /*
361  * 4.3bsd dup allows dup2 to come in on the same syscall entry
362  * and hence allows two arguments.  HPUX dup has only one arg.
363  */
364 hpuxdup(p, uap, retval)
365 	struct proc *p;
366 	register struct args {
367 		int	i;
368 	} *uap;
369 	int *retval;
370 {
371 	register struct filedesc *fdp = p->p_fd;
372 	struct file *fp;
373 	int fd, error;
374 
375 	if (((unsigned)uap->i) >= fdp->fd_maxfiles ||
376 	    (fp = OFILE(fdp, uap->i)) == NULL)
377 		return (EBADF);
378 	if (error = ufalloc(fdp, 0, &fd))
379 		return (error);
380 	OFILE(fdp, fd) = fp;
381 	OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE;
382 	fp->f_count++;
383 	if (fd > fdp->fd_lastfile)
384 		fdp->fd_lastfile = fd;
385 	*retval = fd;
386 	return (0);
387 }
388 
389 hpuxutssys(p, uap, retval)
390 	struct proc *p;
391 	register struct args {
392 		struct hpuxutsname *uts;
393 		int dev;
394 		int request;
395 	} *uap;
396 	int *retval;
397 {
398 	register int i;
399 	int error;
400 
401 	switch (uap->request) {
402 	/* uname */
403 	case 0:
404 		/* fill in machine type */
405 		switch (machineid) {
406 		case HP_320:
407 			protoutsname.machine[6] = '2';
408 			break;
409 		/* includes 318 and 319 */
410 		case HP_330:
411 			protoutsname.machine[6] = '3';
412 			break;
413 		case HP_340:
414 			protoutsname.machine[6] = '4';
415 			break;
416 		case HP_350:
417 			protoutsname.machine[6] = '5';
418 			break;
419 		case HP_360:
420 			protoutsname.machine[6] = '6';
421 			break;
422 		case HP_370:
423 			protoutsname.machine[6] = '7';
424 			break;
425 		/* includes 345 */
426 		case HP_375:
427 			protoutsname.machine[6] = '7';
428 			protoutsname.machine[7] = '5';
429 			break;
430 		}
431 		/* copy hostname (sans domain) to nodename */
432 		for (i = 0; i < 9 && hostname[i] != '.'; i++)
433 			protoutsname.nodename[i] = hostname[i];
434 		error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts,
435 				sizeof(struct hpuxutsname));
436 		break;
437 
438 	/* gethostname */
439 	case 5:
440 		/* uap->dev is length */
441 		if (uap->dev > hostnamelen + 1)
442 			uap->dev = hostnamelen + 1;
443 		error = copyout((caddr_t)hostname, (caddr_t)uap->uts,
444 				uap->dev);
445 		break;
446 
447 	case 1:	/* ?? */
448 	case 2:	/* ustat */
449 	case 3:	/* ?? */
450 	case 4:	/* sethostname */
451 	default:
452 		error = EINVAL;
453 		break;
454 	}
455 	return (error);
456 }
457 
458 hpuxstat(p, uap, retval)
459 	struct proc *p;
460 	struct args {
461 		char	*fname;
462 		struct hpuxstat *hsb;
463 	} *uap;
464 	int *retval;
465 {
466 	return (hpuxstat1(uap->fname, uap->hsb, FOLLOW));
467 }
468 
469 hpuxlstat(p, uap, retval)
470 	struct proc *p;
471 	struct args {
472 		char	*fname;
473 		struct hpuxstat *hsb;
474 	} *uap;
475 	int *retval;
476 {
477 	return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW));
478 }
479 
480 hpuxfstat(p, uap, retval)
481 	struct proc *p;
482 	register struct args {
483 		int	fdes;
484 		struct	hpuxstat *hsb;
485 	} *uap;
486 	int *retval;
487 {
488 	register struct filedesc *fdp = p->p_fd;
489 	register struct file *fp;
490 	struct stat sb;
491 	int error;
492 
493 	if (((unsigned)uap->fdes) >= fdp->fd_maxfiles ||
494 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
495 		return (EBADF);
496 
497 	switch (fp->f_type) {
498 
499 	case DTYPE_VNODE:
500 		error = vn_stat((struct vnode *)fp->f_data, &sb);
501 		break;
502 
503 	case DTYPE_SOCKET:
504 		error = soo_stat((struct socket *)fp->f_data, &sb);
505 		break;
506 
507 	default:
508 		panic("fstat");
509 		/*NOTREACHED*/
510 	}
511 	/* is this right for sockets?? */
512 	if (error == 0)
513 		error = bsdtohpuxstat(&sb, uap->hsb);
514 	return (error);
515 }
516 
517 hpuxulimit(p, uap, retval)
518 	struct proc *p;
519 	register struct args {
520 		int	cmd;
521 		long	newlimit;
522 	} *uap;
523 	off_t *retval;
524 {
525 	struct rlimit *limp;
526 	int error = 0;
527 
528 	limp = &u.u_rlimit[RLIMIT_FSIZE];
529 	switch (uap->cmd) {
530 	case 2:
531 		uap->newlimit *= 512;
532 		if (uap->newlimit > limp->rlim_max &&
533 		    (error = suser(u.u_cred, &u.u_acflag)))
534 			break;
535 		limp->rlim_cur = limp->rlim_max = uap->newlimit;
536 		/* else fall into... */
537 
538 	case 1:
539 		*retval = limp->rlim_max / 512;
540 		break;
541 
542 	case 3:
543 		limp = &u.u_rlimit[RLIMIT_DATA];
544 		*retval = ctob(u.u_tsize) + limp->rlim_max;
545 		break;
546 
547 	default:
548 		error = EINVAL;
549 		break;
550 	}
551 	return (error);
552 }
553 
554 /*
555  * Map "real time" priorities 0 (high) thru 127 (low) into nice
556  * values -16 (high) thru -1 (low).
557  */
558 hpuxrtprio(cp, uap, retval)
559 	struct proc *cp;
560 	register struct args {
561 		int pid;
562 		int prio;
563 	} *uap;
564 	int *retval;
565 {
566 	struct proc *p;
567 	int nice, error;
568 
569 	if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX &&
570 	    uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF)
571 		return (EINVAL);
572 	if (uap->pid == 0)
573 		p = cp;
574 	else if ((p = pfind(uap->pid)) == 0)
575 		return (ESRCH);
576 	nice = p->p_nice;
577 	if (nice < NZERO)
578 		*retval = (nice + 16) << 3;
579 	else
580 		*retval = RTPRIO_RTOFF;
581 	switch (uap->prio) {
582 
583 	case RTPRIO_NOCHG:
584 		return (0);
585 
586 	case RTPRIO_RTOFF:
587 		if (nice >= NZERO)
588 			return (0);
589 		nice = NZERO;
590 		break;
591 
592 	default:
593 		nice = (uap->prio >> 3) - 16;
594 		break;
595 	}
596 	error = donice(cp, p, nice);
597 	if (error == EACCES)
598 		error = EPERM;
599 	return (error);
600 }
601 
602 hpuxadvise(p, uap, retval)
603 	struct proc *p;
604 	struct args {
605 		int	arg;
606 	} *uap;
607 	int *retval;
608 {
609 	int error = 0;
610 
611 	switch (uap->arg) {
612 	case 0:
613 		u.u_pcb.pcb_flags |= PCB_HPUXMMAP;
614 		break;
615 	case 1:
616 		ICIA();
617 		break;
618 	case 2:
619 		DCIA();
620 		break;
621 	default:
622 		error = EINVAL;
623 		break;
624 	}
625 	return (error);
626 }
627 
628 hpuxptrace(p, uap, retval)
629 	struct proc *p;
630 	struct args {
631 		int	req;
632 		int	pid;
633 		int	*addr;
634 		int	data;
635 	} *uap;
636 	int *retval;
637 {
638 	int error;
639 
640 	if (uap->req == PT_STEP || uap->req == PT_CONTINUE) {
641 		if (uap->data) {
642 			uap->data = hpuxtobsdsig(uap->data);
643 			if (uap->data == 0)
644 				uap->data = NSIG;
645 		}
646 	}
647 	error = ptrace(p, uap, retval);
648 	return (error);
649 }
650 
651 hpuxgetdomainname(p, uap, retval)
652 	struct proc *p;
653 	register struct args {
654 		char	*domainname;
655 		u_int	len;
656 	} *uap;
657 	int *retval;
658 {
659 	if (uap->len > domainnamelen + 1)
660 		uap->len = domainnamelen + 1;
661 	return (copyout(domainname, uap->domainname, uap->len));
662 }
663 
664 hpuxsetdomainname(p, uap, retval)
665 	struct proc *p;
666 	register struct args {
667 		char	*domainname;
668 		u_int	len;
669 	} *uap;
670 	int *retval;
671 {
672 	int error;
673 
674 	if (error = suser(u.u_cred, &u.u_acflag))
675 		return (error);
676 	if (uap->len > sizeof (domainname) - 1)
677 		return (EINVAL);
678 	domainnamelen = uap->len;
679 	error = copyin(uap->domainname, domainname, uap->len);
680 	domainname[domainnamelen] = 0;
681 	return (error);
682 }
683 
684 #ifdef SYSVSHM
685 hpuxshmat(p, uap, retval)
686 	struct proc *p;
687 	int *uap, *retval;
688 {
689 	return (shmat(p, uap, retval));
690 }
691 
692 hpuxshmctl(p, uap, retval)
693 	struct proc *p;
694 	int *uap, *retval;
695 {
696 	return (shmctl(p, uap, retval));
697 }
698 
699 hpuxshmdt(p, uap, retval)
700 	struct proc *p;
701 	int *uap, *retval;
702 {
703 	return (shmdt(p, uap, retval));
704 }
705 
706 hpuxshmget(p, uap, retval)
707 	struct proc *p;
708 	int *uap, *retval;
709 {
710 	return (shmget(p, uap, retval));
711 }
712 #endif
713 
714 /*
715  * Fake semaphore routines, just don't return an error.
716  * Should be adequate for starbase to run.
717  */
718 hpuxsemctl(p, uap, retval)
719 	struct proc *p;
720 	struct args {
721 		int semid;
722 		u_int semnum;
723 		int cmd;
724 		int arg;
725 	} *uap;
726 	int *retval;
727 {
728 	/* XXX: should do something here */
729 	return (0);
730 }
731 
732 hpuxsemget(p, uap, retval)
733 	struct proc *p;
734 	struct args {
735 		key_t key;
736 		int nsems;
737 		int semflg;
738 	} *uap;
739 	int *retval;
740 {
741 	/* XXX: should do something here */
742 	return (0);
743 }
744 
745 hpuxsemop(p, uap, retval)
746 	struct proc *p;
747 	struct args {
748 		int semid;
749 		struct sembuf *sops;
750 		u_int nsops;
751 	} *uap;
752 	int *retval;
753 {
754 	/* XXX: should do something here */
755 	return (0);
756 }
757 
758 /* convert from BSD to HPUX errno */
759 bsdtohpuxerrno(err)
760 	int err;
761 {
762 	if (err < 0 || err >= NERR)
763 		return(BERR);
764 	return((int)bsdtohpuxerrnomap[err]);
765 }
766 
767 hpuxstat1(fname, hsb, follow)
768 	char *fname;
769 	struct hpuxstat *hsb;
770 	int follow;
771 {
772 	register struct nameidata *ndp = &u.u_nd;
773 	struct stat sb;
774 	int error;
775 
776 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
777 	ndp->ni_segflg = UIO_USERSPACE;
778 	ndp->ni_dirp = fname;
779 	if (error = namei(ndp))
780 		return (error);
781 	error = vn_stat(ndp->ni_vp, &sb);
782 	vput(ndp->ni_vp);
783 	if (error == 0)
784 		error = bsdtohpuxstat(&sb, hsb);
785 	return (error);
786 }
787 
788 #include "grf.h"
789 
790 bsdtohpuxstat(sb, hsb)
791 	struct stat *sb;
792 	struct hpuxstat *hsb;
793 {
794 	struct hpuxstat ds;
795 
796 	bzero((caddr_t)&ds, sizeof(ds));
797 	ds.hst_dev = sb->st_dev;
798 	ds.hst_ino = (u_long)sb->st_ino;
799 	ds.hst_mode = sb->st_mode;
800 	ds.hst_nlink = sb->st_nlink;
801 	ds.hst_uid = (u_short)sb->st_uid;
802 	ds.hst_gid = (u_short)sb->st_gid;
803 #if NGRF > 0
804 	/* XXX: I don't want to talk about it... */
805 	if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10)
806 		ds.hst_rdev = grfdevno(sb->st_rdev);
807 	else
808 #endif
809 		ds.hst_rdev = bsdtohpuxdev(sb->st_rdev);
810 	ds.hst_size = sb->st_size;
811 	ds.hst_atime = sb->st_atime;
812 	ds.hst_mtime = sb->st_mtime;
813 	ds.hst_ctime = sb->st_ctime;
814 	ds.hst_blksize = sb->st_blksize;
815 	ds.hst_blocks = sb->st_blocks;
816 	return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds)));
817 }
818 
819 hpuxtobsdioctl(com)
820 	int com;
821 {
822 	switch (com) {
823 	case HPUXTIOCSLTC:
824 		com = TIOCSLTC; break;
825 	case HPUXTIOCGLTC:
826 		com = TIOCGLTC; break;
827 	case HPUXTIOCSPGRP:
828 		com = TIOCSPGRP; break;
829 	case HPUXTIOCGPGRP:
830 		com = TIOCGPGRP; break;
831 	case HPUXTIOCLBIS:
832 		com = TIOCLBIS; break;
833 	case HPUXTIOCLBIC:
834 		com = TIOCLBIC; break;
835 	case HPUXTIOCLSET:
836 		com = TIOCLSET; break;
837 	case HPUXTIOCLGET:
838 		com = TIOCLGET; break;
839 	}
840 	return(com);
841 }
842 
843 /*
844  * HPUX ioctl system call.  The differences here are:
845  *	IOC_IN also means IOC_VOID if the size portion is zero.
846  *	no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN
847  *	the sgttyb struct is 2 bytes longer
848  */
849 hpuxioctl(p, uap, retval)
850 	struct proc *p;
851 	register struct args {
852 		int	fdes;
853 		int	cmd;
854 		caddr_t	cmarg;
855 	} *uap;
856 	int *retval;
857 {
858 	register struct filedesc *fdp = p->p_fd;
859 	register struct file *fp;
860 	register int com, error;
861 	register u_int size;
862 	caddr_t memp = 0;
863 #define STK_PARAMS	128
864 	char stkbuf[STK_PARAMS];
865 	caddr_t data = stkbuf;
866 
867 	com = uap->cmd;
868 
869 	/* XXX */
870 	if (com == HPUXTIOCGETP || com == HPUXTIOCSETP)
871 		return (getsettty(p, uap->fdes, com, uap->cmarg));
872 
873 	if (((unsigned)uap->fdes) >= fdp->fd_maxfiles ||
874 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
875 		return (EBADF);
876 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
877 		return (EBADF);
878 
879 	/*
880 	 * Interpret high order word to find
881 	 * amount of data to be copied to/from the
882 	 * user's address space.
883 	 */
884 	size = IOCPARM_LEN(com);
885 	if (size > IOCPARM_MAX)
886 		return (ENOTTY);
887 	if (size > sizeof (stkbuf)) {
888 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
889 		data = memp;
890 	}
891 	if (com&IOC_IN) {
892 		if (size) {
893 			error = copyin(uap->cmarg, data, (u_int)size);
894 			if (error) {
895 				if (memp)
896 					free(memp, M_IOCTLOPS);
897 				return (error);
898 			}
899 		} else
900 			*(caddr_t *)data = uap->cmarg;
901 	} else if ((com&IOC_OUT) && size)
902 		/*
903 		 * Zero the buffer so the user always
904 		 * gets back something deterministic.
905 		 */
906 		bzero(data, size);
907 	else if (com&IOC_VOID)
908 		*(caddr_t *)data = uap->cmarg;
909 
910 	switch (com) {
911 
912 	case HPUXTIOCCONS:
913 		*(int *)data = 1;
914 		error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data);
915 		break;
916 
917 	/* BSD-style job control ioctls */
918 	case HPUXTIOCLBIS:
919 	case HPUXTIOCLBIC:
920 	case HPUXTIOCLSET:
921 		*(int *)data &= HPUXLTOSTOP;
922 		if (*(int *)data & HPUXLTOSTOP)
923 			*(int *)data = LTOSTOP;
924 		/* fall into */
925 	case HPUXTIOCLGET:
926 	case HPUXTIOCSLTC:
927 	case HPUXTIOCGLTC:
928 	case HPUXTIOCSPGRP:
929 	case HPUXTIOCGPGRP:
930 		error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data);
931 		if (error == 0 && com == HPUXTIOCLGET) {
932 			*(int *)data &= LTOSTOP;
933 			if (*(int *)data & LTOSTOP)
934 				*(int *)data = HPUXLTOSTOP;
935 		}
936 		break;
937 
938 	/* SYS 5 termio */
939 	case HPUXTCGETA:
940 	case HPUXTCSETA:
941 	case HPUXTCSETAW:
942 	case HPUXTCSETAF:
943 		error = hpuxtermio(fp, com, data);
944 		break;
945 
946 	default:
947 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
948 		break;
949 	}
950 	/*
951 	 * Copy any data to user, size was
952 	 * already set and checked above.
953 	 */
954 	if (error == 0 && (com&IOC_OUT) && size)
955 		error = copyout(data, uap->cmarg, (u_int)size);
956 	if (memp)
957 		free(memp, M_IOCTLOPS);
958 	return (error);
959 }
960 
961 /*
962  * Man page lies, behaviour here is based on observed behaviour.
963  */
964 hpuxgetcontext(p, uap, retval)
965 	struct proc *p;
966 	struct args {
967 		char *buf;
968 		int len;
969 	} *uap;
970 	int *retval;
971 {
972 	int error = 0;
973 	register int len;
974 
975 	len = MIN(uap->len, sizeof(hpuxcontext));
976 	if (len)
977 		error = copyout(hpuxcontext, uap->buf, (u_int)len);
978 	if (error == 0)
979 		*retval = sizeof(hpuxcontext);
980 	return (error);
981 }
982 
983 /*
984  * This is the equivalent of BSD getpgrp but with more restrictions.
985  * Note we do not check the real uid or "saved" uid.
986  */
987 hpuxgetpgrp2(cp, uap, retval)
988 	struct proc *cp;
989 	register struct args {
990 		int pid;
991 	} *uap;
992 	int *retval;
993 {
994 	register struct proc *p;
995 
996 	if (uap->pid == 0)
997 		uap->pid = cp->p_pid;
998 	p = pfind(uap->pid);
999 	if (p == 0)
1000 		return (ESRCH);
1001 	if (u.u_uid && p->p_uid != u.u_uid && !inferior(p))
1002 		return (EPERM);
1003 	*retval = p->p_pgid;
1004 	return (0);
1005 }
1006 
1007 /*
1008  * This is the equivalent of BSD setpgrp but with more restrictions.
1009  * Note we do not check the real uid or "saved" uid or pgrp.
1010  */
1011 hpuxsetpgrp2(p, uap, retval)
1012 	struct proc *p;
1013 	struct args {
1014 		int	pid;
1015 		int	pgrp;
1016 	} *uap;
1017 	int *retval;
1018 {
1019 	/* empirically determined */
1020 	if (uap->pgrp < 0 || uap->pgrp >= 30000)
1021 		return (EINVAL);
1022 	return (setpgrp(p, uap, retval));
1023 }
1024 
1025 /*
1026  * XXX Same as BSD setre[ug]id right now.  Need to consider saved ids.
1027  */
1028 hpuxsetresuid(p, uap, retval)
1029 	struct proc *p;
1030 	struct args {
1031 		int	ruid;
1032 		int	euid;
1033 		int	suid;
1034 	} *uap;
1035 	int *retval;
1036 {
1037 	return (osetreuid(p, uap, retval));
1038 }
1039 
1040 hpuxsetresgid(p, uap, retval)
1041 	struct proc *p;
1042 	struct args {
1043 		int	rgid;
1044 		int	egid;
1045 		int	sgid;
1046 	} *uap;
1047 	int *retval;
1048 {
1049 	return (osetregid(p, uap, retval));
1050 }
1051 
1052 /*
1053  * XXX: simple recognition hack to see if we can make grmd work.
1054  */
1055 hpuxlockf(p, uap, retval)
1056 	struct proc *p;
1057 	struct args {
1058 		int fd;
1059 		int func;
1060 		long size;
1061 	} *uap;
1062 	int *retval;
1063 {
1064 #ifdef DEBUG
1065 	log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n",
1066 	    p->p_pid, uap->fd, uap->func, uap->size);
1067 #endif
1068 	return (0);
1069 }
1070 
1071 hpuxgetaccess(p, uap, retval)
1072 	register struct proc *p;
1073 	register struct args {
1074 		char	*path;
1075 		int	uid;
1076 		int	ngroups;
1077 		int	*gidset;
1078 		void	*label;
1079 		void	*privs;
1080 	} *uap;
1081 	int *retval;
1082 {
1083 	struct nameidata *ndp = &u.u_nd;
1084 	int lgroups[NGROUPS];
1085 	int error = 0;
1086 	register struct ucred *cred;
1087 	register struct vnode *vp;
1088 
1089 	/*
1090 	 * Build an appropriate credential structure
1091 	 */
1092 	cred = crdup(ndp->ni_cred);
1093 	switch (uap->uid) {
1094 	case 65502:	/* UID_EUID */
1095 		break;
1096 	case 65503:	/* UID_RUID */
1097 		cred->cr_uid = p->p_ruid;
1098 		break;
1099 	case 65504:	/* UID_SUID */
1100 		error = EINVAL;
1101 		break;
1102 	default:
1103 		if (uap->uid > 65504)
1104 			error = EINVAL;
1105 		cred->cr_uid = uap->uid;
1106 		break;
1107 	}
1108 	switch (uap->ngroups) {
1109 	case -1:	/* NGROUPS_EGID */
1110 		cred->cr_ngroups = 1;
1111 		break;
1112 	case -5:	/* NGROUPS_EGID_SUPP */
1113 		break;
1114 	case -2:	/* NGROUPS_RGID */
1115 		cred->cr_ngroups = 1;
1116 		cred->cr_gid = p->p_rgid;
1117 		break;
1118 	case -6:	/* NGROUPS_RGID_SUPP */
1119 		cred->cr_gid = p->p_rgid;
1120 		break;
1121 	case -3:	/* NGROUPS_SGID */
1122 	case -7:	/* NGROUPS_SGID_SUPP */
1123 		error = EINVAL;
1124 		break;
1125 	case -4:	/* NGROUPS_SUPP */
1126 		if (cred->cr_ngroups > 1)
1127 			cred->cr_gid = cred->cr_groups[1];
1128 		else
1129 			error = EINVAL;
1130 		break;
1131 	default:
1132 		if (uap->ngroups > 0 && uap->ngroups <= NGROUPS)
1133 			error = copyin((caddr_t)uap->gidset,
1134 				       (caddr_t)&lgroups[0],
1135 				       uap->ngroups * sizeof(lgroups[0]));
1136 		else
1137 			error = EINVAL;
1138 		if (error == 0) {
1139 			int gid;
1140 
1141 			for (gid = 0; gid < uap->ngroups; gid++)
1142 				cred->cr_groups[gid] = lgroups[gid];
1143 			cred->cr_ngroups = uap->ngroups;
1144 		}
1145 		break;
1146 	}
1147 	/*
1148 	 * Lookup file using caller's effective IDs.
1149 	 */
1150 	if (error == 0) {
1151 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1152 		ndp->ni_segflg = UIO_USERSPACE;
1153 		ndp->ni_dirp = uap->path;
1154 		error = namei(ndp);
1155 	}
1156 	if (error) {
1157 		crfree(cred);
1158 		return (error);
1159 	}
1160 	/*
1161 	 * Use the constructed credentials for access checks.
1162 	 */
1163 	vp = ndp->ni_vp;
1164 	*retval = 0;
1165 	if (VOP_ACCESS(vp, VREAD, cred) == 0)
1166 		*retval |= R_OK;
1167 	if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred) == 0)
1168 		*retval |= W_OK;
1169 	/* XXX we return X_OK for root on VREG even if not */
1170 	if (VOP_ACCESS(vp, VEXEC, cred) == 0)
1171 		*retval |= X_OK;
1172 	vput(vp);
1173 	crfree(cred);
1174 	return (error);
1175 }
1176 
1177 /*
1178  * Brutal hack!  Map HPUX u-area offsets into BSD u offsets.
1179  * No apologies offered, if you don't like it, rewrite it!
1180  */
1181 
1182 #define UOFF(f)		((int)&((struct user *)0)->f)
1183 #define HPUOFF(f)	((int)&((struct hpuxuser *)0)->f)
1184 
1185 /* simplified FP structure */
1186 struct bsdfp {
1187 	int save[54];
1188 	int reg[24];
1189 	int ctrl[3];
1190 };
1191 
1192 hpuxtobsduoff(off)
1193 	int *off;
1194 {
1195 	struct hpuxfp *hp;
1196 	struct bsdfp *bp;
1197 	register u_int raddr;
1198 
1199 	/* u_ar0 field */
1200 	if ((int)off == HPUOFF(hpuxu_ar0))
1201 		return(UOFF(u_ar0));
1202 
1203 #ifdef FPCOPROC
1204 	/* 68881 registers from PCB */
1205 	hp = (struct hpuxfp *)HPUOFF(hpuxu_fp);
1206 	bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
1207 	if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
1208 		return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
1209 	if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
1210 		return((int)&bp->reg[off - hp->hpfp_reg]);
1211 #endif
1212 
1213 	/*
1214 	 * Everything else we recognize comes from the kernel stack,
1215 	 * so we convert off to an absolute address (if not already)
1216 	 * for simplicity.
1217 	 */
1218 	if (off < (int *)ctob(UPAGES))
1219 		off = (int *)((u_int)off + (u_int)&u);
1220 
1221 	/*
1222 	 * 68020 registers.
1223 	 * We know that the HPUX registers are in the same order as ours.
1224 	 * The only difference is that their PS is 2 bytes instead of a
1225 	 * padded 4 like ours throwing the alignment off.
1226 	 */
1227 	if (off >= u.u_ar0 && off < &u.u_ar0[18]) {
1228 		/*
1229 		 * PS: return low word and high word of PC as HP-UX would
1230 		 * (e.g. &u.u_ar0[16.5]).
1231 		 */
1232 		if (off == &u.u_ar0[PS])
1233 			raddr = (u_int) &((short *)u.u_ar0)[PS*2+1];
1234 		/*
1235 		 * PC: off will be &u.u_ar0[16.5]
1236 		 */
1237 		else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1]))
1238 			raddr = (u_int) &u.u_ar0[PC];
1239 		/*
1240 		 * D0-D7, A0-A7: easy
1241 		 */
1242 		else
1243 			raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)];
1244 		return((int)(raddr - (u_int)&u));
1245 	}
1246 
1247 	/* everything else */
1248 	return(-1);
1249 }
1250 
1251 /*
1252  * Kludge up a uarea dump so that HPUX debuggers can find out
1253  * what they need.  IMPORTANT NOTE: we do not EVEN attempt to
1254  * convert the entire user struct.
1255  */
1256 hpuxdumpu(vp, cred)
1257 	struct vnode *vp;
1258 	struct ucred *cred;
1259 {
1260 	int error;
1261 	struct hpuxuser *faku;
1262 	struct bsdfp *bp;
1263 	short *foop;
1264 
1265 	faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK);
1266 	/*
1267 	 * Make sure there is no mistake about this
1268 	 * being a real user structure.
1269 	 */
1270 	bzero((caddr_t)faku, ctob(1));
1271 	/*
1272 	 * Fill in the process sizes.
1273 	 */
1274 	faku->hpuxu_tsize = u.u_tsize;
1275 	faku->hpuxu_dsize = u.u_dsize;
1276 	faku->hpuxu_ssize = u.u_ssize;
1277 	/*
1278 	 * Fill in the exec header for CDB.
1279 	 * This was saved back in exec().  As far as I can tell CDB
1280 	 * only uses this information to verify that a particular
1281 	 * core file goes with a particular binary.
1282 	 */
1283 	bcopy((caddr_t)u.u_pcb.pcb_exec,
1284 	      (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec));
1285 	/*
1286 	 * Adjust user's saved registers (on kernel stack) to reflect
1287 	 * HPUX order.  Note that HPUX saves the SR as 2 bytes not 4
1288 	 * so we have to move it up.
1289 	 */
1290 	faku->hpuxu_ar0 = u.u_ar0;
1291 	foop = (short *) u.u_ar0;
1292 	foop[32] = foop[33];
1293 	foop[33] = foop[34];
1294 	foop[34] = foop[35];
1295 #ifdef FPCOPROC
1296 	/*
1297 	 * Copy 68881 registers from our PCB format to HPUX format
1298 	 */
1299 	bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs;
1300 	bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save,
1301 	      sizeof(bp->save));
1302 	bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl,
1303 	      sizeof(bp->ctrl));
1304 	bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg,
1305 	      sizeof(bp->reg));
1306 #endif
1307 	/*
1308 	 * Slay the dragon
1309 	 */
1310 	faku->hpuxu_dragon = -1;
1311 	/*
1312 	 * Dump this artfully constructed page in place of the
1313 	 * user struct page.
1314 	 */
1315 	error = vn_rdwr(UIO_WRITE, vp,
1316 			(caddr_t)faku, ctob(1), (off_t)0,
1317 			UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0);
1318 	/*
1319 	 * Dump the remaining UPAGES-1 pages normally
1320 	 */
1321 	if (!error)
1322 		error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1),
1323 				ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE,
1324 				IO_NODELOCKED|IO_UNIT, cred, (int *)0);
1325 	free((caddr_t)faku, M_TEMP);
1326 	return(error);
1327 }
1328 
1329 /*
1330  * The remaining routines are essentially the same as those in kern_xxx.c
1331  * and vfs_xxx.c as defined under "#ifdef COMPAT".  We replicate them here
1332  * to avoid HPUXCOMPAT dependencies in those files and to make sure that
1333  * HP-UX compatibility still works even when COMPAT is not defined.
1334  */
1335 /* #ifdef COMPAT */
1336 
1337 #define HPUX_HZ	50
1338 
1339 #include "sys/times.h"
1340 
1341 /* from old timeb.h */
1342 struct hpuxtimeb {
1343 	time_t	time;
1344 	u_short	millitm;
1345 	short	timezone;
1346 	short	dstflag;
1347 };
1348 
1349 /* ye ole stat structure */
1350 struct	ohpuxstat {
1351 	dev_t	ohst_dev;
1352 	u_short	ohst_ino;
1353 	u_short ohst_mode;
1354 	short  	ohst_nlink;
1355 	short  	ohst_uid;
1356 	short  	ohst_gid;
1357 	dev_t	ohst_rdev;
1358 	int	ohst_size;
1359 	int	ohst_atime;
1360 	int	ohst_mtime;
1361 	int	ohst_ctime;
1362 };
1363 
1364 /*
1365  * SYS V style setpgrp()
1366  */
1367 ohpuxsetpgrp(p, uap, retval)
1368 	register struct proc *p;
1369 	int *uap, *retval;
1370 {
1371 	if (p->p_pid != p->p_pgid)
1372 		pgmv(p, p->p_pid, 0);
1373 	*retval = p->p_pgid;
1374 	return (0);
1375 }
1376 
1377 ohpuxtime(p, uap, retval)
1378 	struct proc *p;
1379 	register struct args {
1380 		long	*tp;
1381 	} *uap;
1382 	time_t *retval;
1383 {
1384 	int error = 0;
1385 
1386 	if (uap->tp)
1387 		error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp,
1388 				sizeof (long));
1389 	*retval = time.tv_sec;
1390 	return (error);
1391 }
1392 
1393 ohpuxstime(p, uap, retval)
1394 	struct proc *p;
1395 	register struct args {
1396 		int	time;
1397 	} *uap;
1398 	int *retval;
1399 {
1400 	struct timeval tv;
1401 	int s, error;
1402 
1403 	tv.tv_sec = uap->time;
1404 	tv.tv_usec = 0;
1405 	if (error = suser(u.u_cred, &u.u_acflag))
1406 		return (error);
1407 
1408 	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
1409 	boottime.tv_sec += tv.tv_sec - time.tv_sec;
1410 	s = splhigh(); time = tv; splx(s);
1411 	resettodr();
1412 	return (0);
1413 }
1414 
1415 ohpuxftime(p, uap, retval)
1416 	struct proc *p;
1417 	register struct args {
1418 		struct	hpuxtimeb *tp;
1419 	} *uap;
1420 	int *retval;
1421 {
1422 	struct hpuxtimeb tb;
1423 	int s;
1424 
1425 	s = splhigh();
1426 	tb.time = time.tv_sec;
1427 	tb.millitm = time.tv_usec / 1000;
1428 	splx(s);
1429 	tb.timezone = tz.tz_minuteswest;
1430 	tb.dstflag = tz.tz_dsttime;
1431 	return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)));
1432 }
1433 
1434 ohpuxalarm(p, uap, retval)
1435 	register struct proc *p;
1436 	register struct args {
1437 		int	deltat;
1438 	} *uap;
1439 	int *retval;
1440 {
1441 	int s = splhigh();
1442 
1443 	untimeout(realitexpire, (caddr_t)p);
1444 	timerclear(&p->p_realtimer.it_interval);
1445 	*retval = 0;
1446 	if (timerisset(&p->p_realtimer.it_value) &&
1447 	    timercmp(&p->p_realtimer.it_value, &time, >))
1448 		*retval = p->p_realtimer.it_value.tv_sec - time.tv_sec;
1449 	if (uap->deltat == 0) {
1450 		timerclear(&p->p_realtimer.it_value);
1451 		splx(s);
1452 		return (0);
1453 	}
1454 	p->p_realtimer.it_value = time;
1455 	p->p_realtimer.it_value.tv_sec += uap->deltat;
1456 	timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value));
1457 	splx(s);
1458 	return (0);
1459 }
1460 
1461 ohpuxnice(p, uap, retval)
1462 	register struct proc *p;
1463 	register struct args {
1464 		int	niceness;
1465 	} *uap;
1466 	int *retval;
1467 {
1468 	int error;
1469 
1470 	error = donice(p, p, (p->p_nice-NZERO)+uap->niceness);
1471 	if (error == 0)
1472 		*retval = p->p_nice - NZERO;
1473 	return (error);
1474 }
1475 
1476 ohpuxtimes(p, uap, retval)
1477 	struct proc *p;
1478 	register struct args {
1479 		struct	tms *tmsb;
1480 	} *uap;
1481 	time_t *retval;
1482 {
1483 	struct tms atms;
1484 	int error;
1485 
1486 	atms.tms_utime = hpuxscale(&u.u_ru.ru_utime);
1487 	atms.tms_stime = hpuxscale(&u.u_ru.ru_stime);
1488 	atms.tms_cutime = hpuxscale(&u.u_cru.ru_utime);
1489 	atms.tms_cstime = hpuxscale(&u.u_cru.ru_stime);
1490 	error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms));
1491 	if (error == 0)
1492 		*retval = hpuxscale(&time) - hpuxscale(&boottime);
1493 	return (error);
1494 }
1495 
1496 /*
1497  * Doesn't exactly do what the documentation says.
1498  * What we really do is return 1/HPUX_HZ-th of a second since that
1499  * is what HP-UX returns.
1500  */
1501 hpuxscale(tvp)
1502 	register struct timeval *tvp;
1503 {
1504 	return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000);
1505 }
1506 
1507 /*
1508  * Set IUPD and IACC times on file.
1509  * Can't set ICHG.
1510  */
1511 ohpuxutime(p, uap, retval)
1512 	struct proc *p;
1513 	register struct a {
1514 		char	*fname;
1515 		time_t	*tptr;
1516 	} *uap;
1517 	int *retval;
1518 {
1519 	struct vattr vattr;
1520 	time_t tv[2];
1521 	register struct vnode *vp;
1522 	register struct nameidata *ndp = &u.u_nd;
1523 	int error;
1524 
1525 	if (uap->tptr) {
1526 		error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
1527 		if (error)
1528 			return (error);
1529 	} else
1530 		tv[0] = tv[1] = time.tv_sec;
1531 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1532 	ndp->ni_segflg = UIO_USERSPACE;
1533 	ndp->ni_dirp = uap->fname;
1534 	vattr_null(&vattr);
1535 	vattr.va_atime.tv_sec = tv[0];
1536 	vattr.va_atime.tv_usec = 0;
1537 	vattr.va_mtime.tv_sec = tv[1];
1538 	vattr.va_mtime.tv_usec = 0;
1539 	if (error = namei(ndp))
1540 		return (error);
1541 	vp = ndp->ni_vp;
1542 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1543 		error = EROFS;
1544 	else
1545 		error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1546 	vput(vp);
1547 	return (error);
1548 }
1549 
1550 ohpuxpause(p, uap, retval)
1551 	struct proc *p;
1552 	int *uap, *retval;
1553 {
1554 	(void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0);
1555 	/* always return EINTR rather than ERESTART... */
1556 	return (EINTR);
1557 }
1558 
1559 /*
1560  * The old fstat system call.
1561  */
1562 ohpuxfstat(p, uap, retval)
1563 	struct proc *p;
1564 	register struct args {
1565 		int	fd;
1566 		struct ohpuxstat *sb;
1567 	} *uap;
1568 	int *retval;
1569 {
1570 	register struct filedesc *fdp = p->p_fd;
1571 	struct file *fp;
1572 
1573 	if (((unsigned)uap->fd) >= fdp->fd_maxfiles ||
1574 	    (fp = OFILE(fdp, uap->fd)) == NULL)
1575 		return (EBADF);
1576 	if (fp->f_type != DTYPE_VNODE)
1577 		return (EINVAL);
1578 	return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb));
1579 }
1580 
1581 /*
1582  * Old stat system call.  This version follows links.
1583  */
1584 ohpuxstat(p, uap, retval)
1585 	struct proc *p;
1586 	register struct args {
1587 		char	*fname;
1588 		struct ohpuxstat *sb;
1589 	} *uap;
1590 	int *retval;
1591 {
1592 	register struct nameidata *ndp = &u.u_nd;
1593 	int error;
1594 
1595 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
1596 	ndp->ni_segflg = UIO_USERSPACE;
1597 	ndp->ni_dirp = uap->fname;
1598 	if (error = namei(ndp))
1599 		return (error);
1600 	error = ohpuxstat1(ndp->ni_vp, uap->sb);
1601 	vput(ndp->ni_vp);
1602 	return (error);
1603 }
1604 
1605 int
1606 ohpuxstat1(vp, ub)
1607 	register struct vnode *vp;
1608 	struct ohpuxstat *ub;
1609 {
1610 	struct ohpuxstat ds;
1611 	struct vattr vattr;
1612 	register int error;
1613 
1614 	error = VOP_GETATTR(vp, &vattr, u.u_cred);
1615 	if (error)
1616 		return(error);
1617 	/*
1618 	 * Copy from inode table
1619 	 */
1620 	ds.ohst_dev = vattr.va_fsid;
1621 	ds.ohst_ino = (short)vattr.va_fileid;
1622 	ds.ohst_mode = (u_short)vattr.va_mode;
1623 	ds.ohst_nlink = vattr.va_nlink;
1624 	ds.ohst_uid = (short)vattr.va_uid;
1625 	ds.ohst_gid = (short)vattr.va_gid;
1626 	ds.ohst_rdev = (dev_t)vattr.va_rdev;
1627 	ds.ohst_size = (int)vattr.va_size;
1628 	ds.ohst_atime = (int)vattr.va_atime.tv_sec;
1629 	ds.ohst_mtime = (int)vattr.va_mtime.tv_sec;
1630 	ds.ohst_ctime = (int)vattr.va_ctime.tv_sec;
1631 	return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)));
1632 }
1633 /* #endif */
1634 
1635 #endif
1636