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