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