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