Annotation of sys/compat/hpux/hpux_compat.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hpux_compat.c,v 1.28 2004/07/09 21:33:44 mickey Exp $ */
2: /* $NetBSD: hpux_compat.c,v 1.35 1997/05/08 16:19:48 mycroft Exp $ */
3:
4: /*
5: * Copyright (c) 1988 University of Utah.
6: * Copyright (c) 1990, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * the Systems Programming Group of the University of Utah Computer
11: * Science Department.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * from: Utah $Hdr: hpux_compat.c 1.64 93/08/05$
38: *
39: * @(#)hpux_compat.c 8.4 (Berkeley) 2/13/94
40: */
41:
42: /*
43: * Various HP-UX compatibility routines
44: */
45:
46: #ifndef COMPAT_43
47: #define COMPAT_43
48: #endif
49:
50: #include <sys/param.h>
51: #include <sys/systm.h>
52: #include <sys/signalvar.h>
53: #include <sys/kernel.h>
54: #include <sys/filedesc.h>
55: #include <sys/proc.h>
56: #include <sys/buf.h>
57: #include <sys/wait.h>
58: #include <sys/file.h>
59: #include <sys/namei.h>
60: #include <sys/vnode.h>
61: #include <sys/ioctl.h>
62: #include <sys/ptrace.h>
63: #include <sys/stat.h>
64: #include <sys/syslog.h>
65: #include <sys/malloc.h>
66: #include <sys/mount.h>
67: #include <sys/ipc.h>
68: #include <sys/user.h>
69: #include <sys/mman.h>
70:
71: #include <machine/cpu.h>
72: #include <machine/reg.h>
73: #include <machine/psl.h>
74: #include <machine/vmparam.h>
75:
76: #include <sys/syscallargs.h>
77:
78: #include <compat/hpux/hpux.h>
79: #include <compat/hpux/hpux_sig.h>
80: #include <compat/hpux/hpux_util.h>
81: #include <compat/hpux/hpux_termio.h>
82: #include <compat/hpux/hpux_syscall.h>
83: #include <compat/hpux/hpux_syscallargs.h>
84:
85: #include <machine/hpux_machdep.h>
86:
87: #ifdef DEBUG
88: int unimpresponse = 0;
89: #endif
90:
91: #define NERR 83
92: #define BERR 1000
93:
94: /* indexed by BSD errno */
95: int bsdtohpuxerrnomap[NERR] = {
96: /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
97: /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19,
98: /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
99: /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217,
100: /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
101: /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
102: /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,
103: /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46, 251,BERR,
104: /*80*/ BERR,BERR, 11
105: };
106:
107: extern char sigcode[], esigcode[];
108: extern struct sysent hpux_sysent[];
109: extern char *hpux_syscallnames[];
110:
111: int hpux_shmctl1(struct proc *, struct hpux_sys_shmctl_args *,
112: register_t *, int);
113: int hpuxtobsdioctl(u_long);
114:
115: static int hpux_scale(struct timeval *);
116:
117: /*
118: * HP-UX fork and vfork need to map the EAGAIN return value appropriately.
119: */
120: int
121: hpux_sys_fork(p, v, retval)
122: struct proc *p;
123: void *v;
124: register_t *retval;
125: {
126: /* struct hpux_sys_fork_args *uap = v; */
127: int error;
128:
129: error = sys_fork(p, v, retval);
130: if (error == EAGAIN)
131: error = OEAGAIN;
132: return (error);
133: }
134:
135: int
136: hpux_sys_vfork(p, v, retval)
137: struct proc *p;
138: void *v;
139: register_t *retval;
140: {
141: /* struct hpux_sys_vfork_args *uap = v; */
142: int error;
143:
144: error = sys_vfork(p, v, retval);
145: if (error == EAGAIN)
146: error = OEAGAIN;
147: return (error);
148: }
149:
150: /*
151: * HP-UX versions of wait and wait3 actually pass the parameters
152: * (status pointer, options, rusage) into the kernel rather than
153: * handling it in the C library stub. We also need to map any
154: * termination signal from BSD to HP-UX.
155: */
156: int
157: hpux_sys_wait3(p, v, retval)
158: struct proc *p;
159: void *v;
160: register_t *retval;
161: {
162: struct hpux_sys_wait3_args *uap = v;
163:
164: /* rusage pointer must be zero */
165: if (SCARG(uap, rusage))
166: return (EINVAL);
167: #ifdef m68k
168: p->p_md.md_regs[PS] = PSL_ALLCC;
169: p->p_md.md_regs[R0] = SCARG(uap, options);
170: p->p_md.md_regs[R1] = SCARG(uap, rusage);
171: #endif
172:
173: return (hpux_sys_wait(p, uap, retval));
174: }
175:
176: int
177: hpux_sys_wait(p, v, retval)
178: struct proc *p;
179: void *v;
180: register_t *retval;
181: {
182: struct hpux_sys_wait_args *uap = v;
183: struct sys_wait4_args w4;
184: int error;
185: int sig;
186: size_t sz = sizeof(*SCARG(&w4, status));
187: int status;
188:
189: SCARG(&w4, rusage) = NULL;
190: SCARG(&w4, options) = 0;
191:
192: if (SCARG(uap, status) == NULL) {
193: caddr_t sg = stackgap_init(p->p_emul);
194: SCARG(&w4, status) = stackgap_alloc(&sg, sz);
195: }
196: else
197: SCARG(&w4, status) = SCARG(uap, status);
198:
199: SCARG(&w4, pid) = WAIT_ANY;
200:
201: error = sys_wait4(p, &w4, retval);
202: /*
203: * HP-UX wait always returns EINTR when interrupted by a signal
204: * (well, unless its emulating a BSD process, but we don't bother...)
205: */
206: if (error == ERESTART)
207: error = EINTR;
208: if (error)
209: return error;
210:
211: if ((error = copyin(SCARG(&w4, status), &status, sizeof(status))) != 0)
212: return error;
213:
214: sig = status & 0xFF;
215: if (sig == WSTOPPED) {
216: sig = (status >> 8) & 0xFF;
217: retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
218: } else if (sig)
219: retval[1] = (status & 0xFF00) |
220: bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
221:
222: if (SCARG(uap, status) == NULL)
223: return error;
224: else
225: return copyout(&retval[1],
226: SCARG(uap, status), sizeof(retval[1]));
227: }
228:
229: int
230: hpux_sys_waitpid(p, v, retval)
231: struct proc *p;
232: void *v;
233: register_t *retval;
234: {
235: struct hpux_sys_waitpid_args *uap = v;
236: int rv, sig, xstat, error;
237:
238: SCARG(uap, rusage) = 0;
239: error = sys_wait4(p, uap, retval);
240: /*
241: * HP-UX wait always returns EINTR when interrupted by a signal
242: * (well, unless its emulating a BSD process, but we don't bother...)
243: */
244: if (error == ERESTART)
245: error = EINTR;
246: if (error)
247: return (error);
248:
249: if (SCARG(uap, status)) {
250: /*
251: * Wait4 already wrote the status out to user space,
252: * pull it back, change the signal portion, and write
253: * it back out.
254: */
255: if ((error = copyin((caddr_t)SCARG(uap, status), &rv,
256: sizeof(int))) != 0)
257: return error;
258:
259: if (WIFSTOPPED(rv)) {
260: sig = WSTOPSIG(rv);
261: rv = W_STOPCODE(bsdtohpuxsig(sig));
262: } else if (WIFSIGNALED(rv)) {
263: sig = WTERMSIG(rv);
264: xstat = WEXITSTATUS(rv);
265: rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) |
266: WCOREDUMP(rv);
267: }
268: error = copyout(&rv, (caddr_t)SCARG(uap, status), sizeof(int));
269: }
270: return (error);
271: }
272:
273: /*
274: * Read and write calls. Same as BSD except for non-blocking behavior.
275: * There are three types of non-blocking reads/writes in HP-UX checked
276: * in the following order:
277: *
278: * O_NONBLOCK: return -1 and errno == EAGAIN
279: * O_NDELAY: return 0
280: * FIOSNBIO: return -1 and errno == EWOULDBLOCK
281: */
282: int
283: hpux_sys_read(p, v, retval)
284: struct proc *p;
285: void *v;
286: register_t *retval;
287: {
288: struct hpux_sys_read_args *uap = v;
289: int error;
290:
291: error = sys_read(p, (struct sys_read_args *) uap, retval);
292: if (error == EWOULDBLOCK) {
293: char *fp = &p->p_fd->fd_ofileflags[SCARG(uap, fd)];
294:
295: if (*fp & HPUX_UF_NONBLOCK_ON) {
296: *retval = -1;
297: error = OEAGAIN;
298: } else if (*fp & HPUX_UF_FNDELAY_ON) {
299: *retval = 0;
300: error = 0;
301: }
302: }
303: return (error);
304: }
305:
306: int
307: hpux_sys_write(p, v, retval)
308: struct proc *p;
309: void *v;
310: register_t *retval;
311: {
312: struct hpux_sys_write_args *uap = v;
313: int error;
314:
315: error = sys_write(p, (struct sys_write_args *) uap, retval);
316: if (error == EWOULDBLOCK) {
317: char *fp = &p->p_fd->fd_ofileflags[SCARG(uap, fd)];
318:
319: if (*fp & HPUX_UF_NONBLOCK_ON) {
320: *retval = -1;
321: error = OEAGAIN;
322: } else if (*fp & HPUX_UF_FNDELAY_ON) {
323: *retval = 0;
324: error = 0;
325: }
326: }
327: return (error);
328: }
329:
330: int
331: hpux_sys_readv(p, v, retval)
332: struct proc *p;
333: void *v;
334: register_t *retval;
335: {
336: struct hpux_sys_readv_args *uap = v;
337: int error;
338:
339: error = sys_readv(p, (struct sys_readv_args *) uap, retval);
340: if (error == EWOULDBLOCK) {
341: char *fp = &p->p_fd->fd_ofileflags[SCARG(uap, fd)];
342:
343: if (*fp & HPUX_UF_NONBLOCK_ON) {
344: *retval = -1;
345: error = OEAGAIN;
346: } else if (*fp & HPUX_UF_FNDELAY_ON) {
347: *retval = 0;
348: error = 0;
349: }
350: }
351: return (error);
352: }
353:
354: int
355: hpux_sys_writev(p, v, retval)
356: struct proc *p;
357: void *v;
358: register_t *retval;
359: {
360: struct hpux_sys_writev_args *uap = v;
361: int error;
362:
363: error = sys_writev(p, (struct sys_writev_args *) uap, retval);
364: if (error == EWOULDBLOCK) {
365: char *fp = &p->p_fd->fd_ofileflags[SCARG(uap, fd)];
366:
367: if (*fp & HPUX_UF_NONBLOCK_ON) {
368: *retval = -1;
369: error = OEAGAIN;
370: } else if (*fp & HPUX_UF_FNDELAY_ON) {
371: *retval = 0;
372: error = 0;
373: }
374: }
375: return (error);
376: }
377:
378: int
379: hpux_sys_utssys(p, v, retval)
380: struct proc *p;
381: void *v;
382: register_t *retval;
383: {
384: struct hpux_sys_utssys_args *uap = v;
385: int i;
386: int error;
387: struct hpux_utsname ut;
388: extern char hostname[], machine[];
389:
390: switch (SCARG(uap, request)) {
391: /* uname */
392: case 0:
393: bzero(&ut, sizeof(ut));
394:
395: strlcpy(ut.sysname, ostype, sizeof(ut.sysname));
396:
397: /* copy hostname (sans domain) to nodename */
398: for (i = 0; i < 8 && hostname[i] != '.'; i++)
399: ut.nodename[i] = hostname[i];
400: ut.nodename[i] = '\0';
401:
402: strlcpy(ut.release, osrelease, sizeof(ut.release));
403: strlcpy(ut.version, version, sizeof(ut.version));
404: strlcpy(ut.machine, machine, sizeof(ut.machine));
405:
406: error = copyout((caddr_t)&ut,
407: (caddr_t)SCARG(uap, uts), sizeof(ut));
408: break;
409:
410: /* gethostname */
411: case 5:
412: /* SCARG(uap, dev) is length */
413: i = SCARG(uap, dev);
414: if (i < 0) {
415: error = EINVAL;
416: break;
417: }
418: if (i > hostnamelen + 1)
419: i = hostnamelen + 1;
420: error = copyout((caddr_t)hostname, (caddr_t)SCARG(uap, uts), i);
421: break;
422:
423: case 1: /* ?? */
424: case 2: /* ustat */
425: case 3: /* ?? */
426: case 4: /* sethostname */
427: default:
428: error = EINVAL;
429: break;
430: }
431: return (error);
432: }
433:
434: int
435: hpux_sys_sysconf(p, v, retval)
436: struct proc *p;
437: void *v;
438: register_t *retval;
439: {
440: struct hpux_sys_sysconf_args *uap = v;
441: switch (SCARG(uap, name)) {
442:
443: /* clock ticks per second */
444: case HPUX_SYSCONF_CLKTICK:
445: *retval = hz;
446: break;
447:
448: /* open files */
449: case HPUX_SYSCONF_OPENMAX:
450: *retval = NOFILE;
451: break;
452:
453: /* architecture */
454: case HPUX_SYSCONF_CPUTYPE:
455: *retval = hpux_cpu_sysconf_arch();
456: break;
457: default:
458: /* XXX */
459: uprintf("HP-UX sysconf(%d) not implemented\n",
460: SCARG(uap, name));
461: return (EINVAL);
462: }
463: return (0);
464: }
465:
466: int
467: hpux_sys_ulimit(p, v, retval)
468: struct proc *p;
469: void *v;
470: register_t *retval;
471: {
472: struct hpux_sys_ulimit_args *uap = v;
473: struct rlimit *limp;
474: int error = 0;
475:
476: limp = &p->p_rlimit[RLIMIT_FSIZE];
477: switch (SCARG(uap, cmd)) {
478: case 2:
479: SCARG(uap, newlimit) *= 512;
480: if (SCARG(uap, newlimit) > limp->rlim_max &&
481: (error = suser(p, 0)))
482: break;
483: limp->rlim_cur = limp->rlim_max = SCARG(uap, newlimit);
484: /* else fall into... */
485:
486: case 1:
487: *retval = limp->rlim_max / 512;
488: break;
489:
490: case 3:
491: limp = &p->p_rlimit[RLIMIT_DATA];
492: *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max;
493: break;
494:
495: default:
496: error = EINVAL;
497: break;
498: }
499: return (error);
500: }
501:
502: /*
503: * Map "real time" priorities 0 (high) thru 127 (low) into nice
504: * values -16 (high) thru -1 (low).
505: */
506: int
507: hpux_sys_rtprio(cp, v, retval)
508: struct proc *cp;
509: void *v;
510: register_t *retval;
511: {
512: struct hpux_sys_rtprio_args *uap = v;
513: struct proc *p;
514: int nice, error;
515:
516: if (SCARG(uap, prio) < RTPRIO_MIN && SCARG(uap, prio) > RTPRIO_MAX &&
517: SCARG(uap, prio) != RTPRIO_NOCHG &&
518: SCARG(uap, prio) != RTPRIO_RTOFF)
519: return (EINVAL);
520: if (SCARG(uap, pid) == 0)
521: p = cp;
522: else if ((p = pfind(SCARG(uap, pid))) == 0)
523: return (ESRCH);
524: nice = p->p_nice;
525: if (nice < NZERO)
526: *retval = (nice + 16) << 3;
527: else
528: *retval = RTPRIO_RTOFF;
529: switch (SCARG(uap, prio)) {
530:
531: case RTPRIO_NOCHG:
532: return (0);
533:
534: case RTPRIO_RTOFF:
535: if (nice >= NZERO)
536: return (0);
537: nice = NZERO;
538: break;
539:
540: default:
541: nice = (SCARG(uap, prio) >> 3) - 16;
542: break;
543: }
544: error = donice(cp, p, nice);
545: if (error == EACCES)
546: error = EPERM;
547: return (error);
548: }
549:
550: /* hpux_sys_advise() is found in hpux_machdep.c */
551:
552: #ifdef PTRACE
553:
554: int
555: hpux_sys_ptrace(p, v, retval)
556: struct proc *p;
557: void *v;
558: register_t *retval;
559: {
560: struct hpux_sys_ptrace_args *uap = v;
561: int error;
562: #if defined(PT_READ_U) || defined(PT_WRITE_U)
563: int isps = 0;
564: struct proc *cp;
565: #endif
566:
567: switch (SCARG(uap, req)) {
568: /* map signal */
569: #if defined(PT_STEP) || defined(PT_CONTINUE)
570: # ifdef PT_STEP
571: case PT_STEP:
572: # endif
573: # ifdef PT_CONTINUE
574: case PT_CONTINUE:
575: # endif
576: if (SCARG(uap, data)) {
577: SCARG(uap, data) = hpuxtobsdsig(SCARG(uap, data));
578: if (SCARG(uap, data) == 0)
579: SCARG(uap, data) = NSIG;
580: }
581: break;
582: #endif
583: /* map u-area offset */
584: #if defined(PT_READ_U) || defined(PT_WRITE_U)
585: # ifdef PT_READ_U
586: case PT_READ_U:
587: # endif
588: # ifdef PT_WRITE_U
589: case PT_WRITE_U:
590: # endif
591: /*
592: * Big, cheezy hack: hpux_to_bsd_uoff is really intended
593: * to be called in the child context (procxmt) but we
594: * do it here in the parent context to avoid hacks in
595: * the MI sys_process.c file. This works only because
596: * we can access the child's md_regs pointer and it
597: * has the correct value (the child has already trapped
598: * into the kernel).
599: */
600: if ((cp = pfind(SCARG(uap, pid))) == 0)
601: return (ESRCH);
602: SCARG(uap, addr) =
603: (int *)hpux_to_bsd_uoff(SCARG(uap, addr), &isps, cp);
604:
605: /*
606: * Since HP-UX PS is only 16-bits in ar0, requests
607: * to write PS actually contain the PS in the high word
608: * and the high half of the PC (the following register)
609: * in the low word. Move the PS value to where BSD
610: * expects it.
611: */
612: if (isps && SCARG(uap, req) == PT_WRITE_U)
613: SCARG(uap, data) >>= 16;
614: break;
615: #endif
616: }
617:
618: error = sys_ptrace(p, uap, retval);
619: /*
620: * Align PS as HP-UX expects it (see WRITE_U comment above).
621: * Note that we do not return the high part of PC like HP-UX
622: * would, but the HP-UX debuggers don't require it.
623: */
624: #ifdef PT_READ_U
625: if (isps && error == 0 && SCARG(uap, req) == PT_READ_U)
626: *retval <<= 16;
627: #endif
628: return (error);
629: }
630:
631: #endif /* PTRACE */
632:
633: #ifdef SYSVSHM
634: #include <sys/shm.h>
635:
636: int
637: hpux_sys_shmctl(p, v, retval)
638: struct proc *p;
639: void *v;
640: register_t *retval;
641: {
642: struct hpux_sys_shmctl_args *uap = v;
643:
644: return (hpux_shmctl1(p, (struct hpux_sys_shmctl_args *)uap, retval, 0));
645: }
646:
647: int
648: hpux_sys_nshmctl(p, v, retval)
649: struct proc *p;
650: void *v;
651: register_t *retval; /* struct hpux_nshmctl_args * */
652: {
653: struct hpux_sys_nshmctl_args *uap = v;
654:
655: return (hpux_shmctl1(p, (struct hpux_sys_shmctl_args *)uap, retval, 1));
656: }
657:
658: /*
659: * Handle HP-UX specific commands.
660: */
661: int
662: hpux_shmctl1(p, uap, retval, isnew)
663: struct proc *p;
664: struct hpux_sys_shmctl_args *uap;
665: register_t *retval;
666: int isnew;
667: {
668: struct shmid_ds *shp;
669: struct ucred *cred = p->p_ucred;
670: struct hpux_shmid_ds sbuf;
671: int error;
672: extern struct shmid_ds *shm_find_segment_by_shmid(int);
673:
674: if ((shp = shm_find_segment_by_shmid(SCARG(uap, shmid))) == NULL)
675: return EINVAL;
676:
677: switch (SCARG(uap, cmd)) {
678: case SHM_LOCK:
679: case SHM_UNLOCK:
680: /* don't really do anything, but make them think we did */
681: if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid &&
682: cred->cr_uid != shp->shm_perm.cuid)
683: return (EPERM);
684: return (0);
685:
686: case IPC_STAT:
687: if (!isnew)
688: break;
689: error = ipcperm(cred, &shp->shm_perm, IPC_R);
690: if (error == 0) {
691: sbuf.shm_perm.uid = shp->shm_perm.uid;
692: sbuf.shm_perm.gid = shp->shm_perm.gid;
693: sbuf.shm_perm.cuid = shp->shm_perm.cuid;
694: sbuf.shm_perm.cgid = shp->shm_perm.cgid;
695: sbuf.shm_perm.mode = shp->shm_perm.mode;
696: sbuf.shm_perm.seq = shp->shm_perm.seq;
697: sbuf.shm_perm.key = shp->shm_perm.key;
698: sbuf.shm_segsz = shp->shm_segsz;
699: sbuf.shm_ptbl = shp->shm_internal; /* XXX */
700: sbuf.shm_lpid = shp->shm_lpid;
701: sbuf.shm_cpid = shp->shm_cpid;
702: sbuf.shm_nattch = shp->shm_nattch;
703: sbuf.shm_cnattch = shp->shm_nattch; /* XXX */
704: sbuf.shm_atime = shp->shm_atime;
705: sbuf.shm_dtime = shp->shm_dtime;
706: sbuf.shm_ctime = shp->shm_ctime;
707: error = copyout((caddr_t)&sbuf, SCARG(uap, buf),
708: sizeof sbuf);
709: }
710: return (error);
711:
712: case IPC_SET:
713: if (!isnew)
714: break;
715: if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid &&
716: cred->cr_uid != shp->shm_perm.cuid) {
717: return (EPERM);
718: }
719: error = copyin(SCARG(uap, buf), (caddr_t)&sbuf, sizeof sbuf);
720: if (error == 0) {
721: shp->shm_perm.uid = sbuf.shm_perm.uid;
722: shp->shm_perm.gid = sbuf.shm_perm.gid;
723: shp->shm_perm.mode = (shp->shm_perm.mode & ~0777)
724: | (sbuf.shm_perm.mode & 0777);
725: shp->shm_ctime = time_second;
726: }
727: return (error);
728: }
729: return (sys_shmctl(p, uap, retval));
730: }
731: #endif
732:
733: /*
734: * HP-UX mmap() emulation (mainly for shared library support).
735: */
736: int
737: hpux_sys_mmap(p, v, retval)
738: struct proc *p;
739: void *v;
740: register_t *retval;
741: {
742: struct hpux_sys_mmap_args *uap = v;
743: struct sys_mmap_args /* {
744: syscallarg(caddr_t) addr;
745: syscallarg(size_t) len;
746: syscallarg(int) prot;
747: syscallarg(int) flags;
748: syscallarg(int) fd;
749: syscallarg(long) pad;
750: syscallarg(off_t) pos;
751: } */ nargs;
752:
753: SCARG(&nargs, addr) = SCARG(uap, addr);
754: SCARG(&nargs, len) = SCARG(uap, len);
755: SCARG(&nargs, prot) = SCARG(uap, prot);
756: SCARG(&nargs, flags) = SCARG(uap, flags) &
757: ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON);
758: if (SCARG(uap, flags) & HPUXMAP_FIXED)
759: SCARG(&nargs, flags) |= MAP_FIXED;
760: if (SCARG(uap, flags) & HPUXMAP_ANON)
761: SCARG(&nargs, flags) |= MAP_ANON;
762: SCARG(&nargs, fd) = (SCARG(&nargs, flags) & MAP_ANON) ? -1 : SCARG(uap, fd);
763: SCARG(&nargs, pos) = SCARG(uap, pos);
764:
765: return (sys_mmap(p, &nargs, retval));
766: }
767:
768: int
769: hpuxtobsdioctl(com)
770: u_long com;
771: {
772: switch (com) {
773: case HPUXTIOCSLTC:
774: com = TIOCSLTC; break;
775: case HPUXTIOCGLTC:
776: com = TIOCGLTC; break;
777: case HPUXTIOCSPGRP:
778: com = TIOCSPGRP; break;
779: case HPUXTIOCGPGRP:
780: com = TIOCGPGRP; break;
781: case HPUXTIOCLBIS:
782: com = TIOCLBIS; break;
783: case HPUXTIOCLBIC:
784: com = TIOCLBIC; break;
785: case HPUXTIOCLSET:
786: com = TIOCLSET; break;
787: case HPUXTIOCLGET:
788: com = TIOCLGET; break;
789: case HPUXTIOCGWINSZ:
790: com = TIOCGWINSZ; break;
791: case HPUXTIOCSWINSZ:
792: com = TIOCSWINSZ; break;
793: }
794: return(com);
795: }
796:
797: /*
798: * HP-UX ioctl system call. The differences here are:
799: * IOC_IN also means IOC_VOID if the size portion is zero.
800: * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN
801: * the sgttyb struct is 2 bytes longer
802: */
803: int
804: hpux_sys_ioctl(p, v, retval)
805: struct proc *p;
806: void *v;
807: register_t *retval;
808: {
809: struct hpux_sys_ioctl_args /* {
810: syscallarg(int) fd;
811: syscallarg(int) com;
812: syscallarg(caddr_t) data;
813: } */ *uap = v;
814: struct filedesc *fdp = p->p_fd;
815: struct file *fp;
816: int com, error = 0;
817: u_int size;
818: caddr_t memp = 0;
819: #define STK_PARAMS 128
820: char stkbuf[STK_PARAMS];
821: caddr_t dt = stkbuf;
822:
823: com = SCARG(uap, com);
824:
825: /* XXX */
826: if (com == HPUXTIOCGETP || com == HPUXTIOCSETP)
827: return (getsettty(p, SCARG(uap, fd), com, SCARG(uap, data)));
828:
829: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
830: return (EBADF);
831: if ((fp->f_flag & (FREAD|FWRITE)) == 0)
832: return (EBADF);
833:
834: /*
835: * Interpret high order word to find
836: * amount of data to be copied to/from the
837: * user's address space.
838: */
839: size = IOCPARM_LEN(com);
840: if (size > IOCPARM_MAX)
841: return (ENOTTY);
842: FREF(fp);
843: if (size > sizeof (stkbuf)) {
844: memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
845: dt = memp;
846: }
847: if (com&IOC_IN) {
848: if (size) {
849: error = copyin(SCARG(uap, data), dt, (u_int)size);
850: if (error) {
851: goto out;
852: }
853: } else
854: *(caddr_t *)dt = SCARG(uap, data);
855: } else if ((com&IOC_OUT) && size)
856: /*
857: * Zero the buffer so the user always
858: * gets back something deterministic.
859: */
860: bzero(dt, size);
861: else if (com&IOC_VOID)
862: *(caddr_t *)dt = SCARG(uap, data);
863:
864: switch (com) {
865:
866: case HPUXFIOSNBIO:
867: {
868: char *ofp = &fdp->fd_ofileflags[SCARG(uap, fd)];
869: int tmp;
870:
871: if (*(int *)dt)
872: *ofp |= HPUX_UF_FIONBIO_ON;
873: else
874: *ofp &= ~HPUX_UF_FIONBIO_ON;
875: /*
876: * Only set/clear if O_NONBLOCK/FNDELAY not in effect
877: */
878: if ((*ofp & (HPUX_UF_NONBLOCK_ON|HPUX_UF_FNDELAY_ON)) == 0) {
879: tmp = *ofp & HPUX_UF_FIONBIO_ON;
880: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO,
881: (caddr_t)&tmp, p);
882: }
883: break;
884: }
885:
886: case HPUXTIOCCONS:
887: *(int *)dt = 1;
888: error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, dt, p);
889: break;
890:
891: /* BSD-style job control ioctls */
892: case HPUXTIOCLBIS:
893: case HPUXTIOCLBIC:
894: case HPUXTIOCLSET:
895: *(int *)dt &= HPUXLTOSTOP;
896: if (*(int *)dt & HPUXLTOSTOP)
897: *(int *)dt = LTOSTOP;
898: /* fall into */
899:
900: /* simple mapping cases */
901: case HPUXTIOCLGET:
902: case HPUXTIOCSLTC:
903: case HPUXTIOCGLTC:
904: case HPUXTIOCSPGRP:
905: case HPUXTIOCGPGRP:
906: case HPUXTIOCGWINSZ:
907: case HPUXTIOCSWINSZ:
908: error = (*fp->f_ops->fo_ioctl)
909: (fp, hpuxtobsdioctl(com), dt, p);
910: if (error == 0 && com == HPUXTIOCLGET) {
911: *(int *)dt &= LTOSTOP;
912: if (*(int *)dt & LTOSTOP)
913: *(int *)dt = HPUXLTOSTOP;
914: }
915: break;
916:
917: /* SYS 5 termio and POSIX termios */
918: case HPUXTCGETA:
919: case HPUXTCSETA:
920: case HPUXTCSETAW:
921: case HPUXTCSETAF:
922: case HPUXTCGETATTR:
923: case HPUXTCSETATTR:
924: case HPUXTCSETATTRD:
925: case HPUXTCSETATTRF:
926: error = hpux_termio(SCARG(uap, fd), com, dt, p);
927: break;
928:
929: default:
930: error = (*fp->f_ops->fo_ioctl)(fp, com, dt, p);
931: break;
932: }
933: /*
934: * Copy any data to user, size was
935: * already set and checked above.
936: */
937: if (error == 0 && (com&IOC_OUT) && size)
938: error = copyout(dt, SCARG(uap, data), (u_int)size);
939:
940: out:
941: FRELE(fp);
942: if (memp)
943: free(memp, M_IOCTLOPS);
944: return (error);
945: }
946:
947: /* hpux_sys_getcontext() is found in hpux_machdep.c */
948:
949: /*
950: * This is the equivalent of BSD getpgrp but with more restrictions.
951: * Note we do not check the real uid or "saved" uid.
952: */
953: int
954: hpux_sys_getpgrp2(cp, v, retval)
955: struct proc *cp;
956: void *v;
957: register_t *retval;
958: {
959: struct hpux_sys_getpgrp2_args *uap = v;
960: struct proc *p;
961:
962: if (SCARG(uap, pid) == 0)
963: SCARG(uap, pid) = cp->p_pid;
964: p = pfind(SCARG(uap, pid));
965: if (p == 0)
966: return (ESRCH);
967: if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid &&
968: !inferior(p))
969: return (EPERM);
970: *retval = p->p_pgid;
971: return (0);
972: }
973:
974: /*
975: * This is the equivalent of BSD setpgrp but with more restrictions.
976: * Note we do not check the real uid or "saved" uid or pgrp.
977: */
978: int
979: hpux_sys_setpgrp2(p, v, retval)
980: struct proc *p;
981: void *v;
982: register_t *retval;
983: {
984: struct hpux_sys_setpgrp2_args *uap = v;
985:
986: /* empirically determined */
987: if (SCARG(uap, pgid) < 0 || SCARG(uap, pgid) >= 30000)
988: return (EINVAL);
989: return (sys_setpgid(p, uap, retval));
990: }
991:
992: int
993: hpux_sys_getrlimit(p, v, retval)
994: struct proc *p;
995: void *v;
996: register_t *retval;
997: {
998: struct hpux_sys_getrlimit_args *uap = v;
999: struct compat_43_sys_getrlimit_args ap;
1000:
1001: if (SCARG(uap, which) > HPUXRLIMIT_NOFILE)
1002: return (EINVAL);
1003: if (SCARG(uap, which) == HPUXRLIMIT_NOFILE)
1004: SCARG(uap, which) = RLIMIT_NOFILE;
1005:
1006: SCARG(&ap, which) = SCARG(uap, which);
1007: SCARG(&ap, rlp) = SCARG(uap, rlp);
1008:
1009: return (compat_43_sys_getrlimit(p, uap, retval));
1010: }
1011:
1012: int
1013: hpux_sys_setrlimit(p, v, retval)
1014: struct proc *p;
1015: void *v;
1016: register_t *retval;
1017: {
1018: struct hpux_sys_setrlimit_args *uap = v;
1019: struct compat_43_sys_setrlimit_args ap;
1020:
1021: if (SCARG(uap, which) > HPUXRLIMIT_NOFILE)
1022: return (EINVAL);
1023: if (SCARG(uap, which) == HPUXRLIMIT_NOFILE)
1024: SCARG(uap, which) = RLIMIT_NOFILE;
1025:
1026: SCARG(&ap, which) = SCARG(uap, which);
1027: SCARG(&ap, rlp) = SCARG(uap, rlp);
1028:
1029: return (compat_43_sys_setrlimit(p, uap, retval));
1030: }
1031:
1032: /*
1033: * XXX: simple recognition hack to see if we can make grmd work.
1034: */
1035: int
1036: hpux_sys_lockf(p, v, retval)
1037: struct proc *p;
1038: void *v;
1039: register_t *retval;
1040: {
1041: /* struct hpux_sys_lockf_args *uap = v; */
1042:
1043: return (0);
1044: }
1045:
1046:
1047: #ifndef __hppa__
1048: int
1049: hpux_sys_getaccess(p, v, retval)
1050: struct proc *p;
1051: void *v;
1052: register_t *retval;
1053: {
1054: struct hpux_sys_getaccess_args *uap = v;
1055: int lgroups[NGROUPS];
1056: int error = 0;
1057: struct ucred *cred;
1058: struct vnode *vp;
1059: struct nameidata nd;
1060:
1061: /*
1062: * Build an appropriate credential structure
1063: */
1064: cred = crdup(p->p_ucred);
1065: switch (SCARG(uap, uid)) {
1066: case 65502: /* UID_EUID */
1067: break;
1068: case 65503: /* UID_RUID */
1069: cred->cr_uid = p->p_cred->p_ruid;
1070: break;
1071: case 65504: /* UID_SUID */
1072: error = EINVAL;
1073: break;
1074: default:
1075: if (SCARG(uap, uid) > 65504)
1076: error = EINVAL;
1077: cred->cr_uid = SCARG(uap, uid);
1078: break;
1079: }
1080: switch (SCARG(uap, ngroups)) {
1081: case -1: /* NGROUPS_EGID */
1082: cred->cr_ngroups = 1;
1083: break;
1084: case -5: /* NGROUPS_EGID_SUPP */
1085: break;
1086: case -2: /* NGROUPS_RGID */
1087: cred->cr_ngroups = 1;
1088: cred->cr_gid = p->p_cred->p_rgid;
1089: break;
1090: case -6: /* NGROUPS_RGID_SUPP */
1091: cred->cr_gid = p->p_cred->p_rgid;
1092: break;
1093: case -3: /* NGROUPS_SGID */
1094: case -7: /* NGROUPS_SGID_SUPP */
1095: error = EINVAL;
1096: break;
1097: case -4: /* NGROUPS_SUPP */
1098: if (cred->cr_ngroups > 1)
1099: cred->cr_gid = cred->cr_groups[1];
1100: else
1101: error = EINVAL;
1102: break;
1103: default:
1104: if (SCARG(uap, ngroups) > 0 && SCARG(uap, ngroups) <= NGROUPS)
1105: error = copyin((caddr_t)SCARG(uap, gidset),
1106: (caddr_t)&lgroups[0],
1107: SCARG(uap, ngroups) *
1108: sizeof(lgroups[0]));
1109: else
1110: error = EINVAL;
1111: if (error == 0) {
1112: int gid;
1113:
1114: for (gid = 0; gid < SCARG(uap, ngroups); gid++)
1115: cred->cr_groups[gid] = lgroups[gid];
1116: cred->cr_ngroups = SCARG(uap, ngroups);
1117: }
1118: break;
1119: }
1120: /*
1121: * Lookup file using caller's effective IDs.
1122: */
1123: if (error == 0) {
1124: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1125: SCARG(uap, path), p);
1126: error = namei(&nd);
1127: }
1128: if (error) {
1129: crfree(cred);
1130: return (error);
1131: }
1132: /*
1133: * Use the constructed credentials for access checks.
1134: */
1135: vp = nd.ni_vp;
1136: *retval = 0;
1137: if (VOP_ACCESS(vp, VREAD, cred, p) == 0)
1138: *retval |= R_OK;
1139: if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0)
1140: *retval |= W_OK;
1141: if (VOP_ACCESS(vp, VEXEC, cred, p) == 0)
1142: *retval |= X_OK;
1143: vput(vp);
1144: crfree(cred);
1145: return (error);
1146: }
1147: #endif
1148:
1149: /*
1150: * Ancient HP-UX system calls. Some 9.x executables even use them!
1151: */
1152: #define HPUX_HZ 50
1153:
1154: #include <sys/times.h>
1155:
1156:
1157: /*
1158: * SYS V style setpgrp()
1159: */
1160: int
1161: hpux_sys_setpgrp_6x(p, v, retval)
1162: struct proc *p;
1163: void *v;
1164: register_t *retval;
1165: {
1166:
1167: if (p->p_pid != p->p_pgid)
1168: enterpgrp(p, p->p_pid, 0);
1169: *retval = p->p_pgid;
1170: return (0);
1171: }
1172:
1173: int
1174: hpux_sys_time_6x(p, v, retval)
1175: struct proc *p;
1176: void *v;
1177: register_t *retval;
1178: {
1179: struct hpux_sys_time_6x_args /* {
1180: syscallarg(time_t *) t;
1181: } */ *uap = v;
1182: int error = 0;
1183: struct timeval tv;
1184:
1185: microtime(&tv);
1186: if (SCARG(uap, t) != NULL)
1187: error = copyout(&tv.tv_sec, SCARG(uap, t), sizeof(time_t));
1188:
1189: *retval = (register_t)tv.tv_sec;
1190: return (error);
1191: }
1192:
1193: int
1194: hpux_sys_stime_6x(p, v, retval)
1195: struct proc *p;
1196: void *v;
1197: register_t *retval;
1198: {
1199: struct hpux_sys_stime_6x_args /* {
1200: syscallarg(int) time;
1201: } */ *uap = v;
1202: struct timespec ts;
1203: int error;
1204:
1205: ts.tv_sec = SCARG(uap, time);
1206: ts.tv_nsec = 0;
1207: if ((error = suser(p, 0)))
1208: return (error);
1209:
1210: settime(&ts);
1211:
1212: return (0);
1213: }
1214:
1215: int
1216: hpux_sys_ftime_6x(p, v, retval)
1217: struct proc *p;
1218: void *v;
1219: register_t *retval;
1220: {
1221: struct hpux_sys_ftime_6x_args /* {
1222: syscallarg(struct hpux_timeb *) tp;
1223: } */ *uap = v;
1224: struct hpux_otimeb tb;
1225: struct timeval tv;
1226:
1227: microtime(&tv);
1228: tb.time = tv.tv_sec;
1229: tb.millitm = tv.tv_usec / 1000;
1230: tb.timezone = tz.tz_minuteswest;
1231: tb.dstflag = tz.tz_dsttime;
1232: return (copyout((caddr_t)&tb, (caddr_t)SCARG(uap, tp), sizeof (tb)));
1233: }
1234:
1235: int
1236: hpux_sys_alarm_6x(p, v, retval)
1237: struct proc *p;
1238: void *v;
1239: register_t *retval;
1240: {
1241: struct hpux_sys_alarm_6x_args /* {
1242: syscallarg(int) deltat;
1243: } */ *uap = v;
1244: int timo;
1245: struct timeval tv, atv;
1246:
1247: timeout_del(&p->p_realit_to);
1248: timerclear(&p->p_realtimer.it_interval);
1249: *retval = 0;
1250: getmicrouptime(&tv);
1251: if (timerisset(&p->p_realtimer.it_value) &&
1252: timercmp(&p->p_realtimer.it_value, &tv, >))
1253: *retval = p->p_realtimer.it_value.tv_sec - tv.tv_sec;
1254: if (SCARG(uap, deltat) == 0) {
1255: timerclear(&p->p_realtimer.it_value);
1256: return (0);
1257: }
1258: atv.tv_sec = SCARG(uap, deltat);
1259: atv.tv_usec = 0;
1260: p->p_realtimer.it_value = tv;
1261: p->p_realtimer.it_value.tv_sec += SCARG(uap, deltat);
1262: timo = tvtohz(&atv);
1263: if (timo <= 0)
1264: timo = 1;
1265: timeout_add(&p->p_realit_to, timo);
1266: return (0);
1267: }
1268:
1269: int
1270: hpux_sys_nice_6x(p, v, retval)
1271: struct proc *p;
1272: void *v;
1273: register_t *retval;
1274: {
1275: struct hpux_sys_nice_6x_args /* {
1276: syscallarg(int) nval;
1277: } */ *uap = v;
1278: int error;
1279:
1280: error = donice(p, p, (p->p_nice-NZERO)+SCARG(uap, nval));
1281: if (error == 0)
1282: *retval = p->p_nice - NZERO;
1283: return (error);
1284: }
1285:
1286: int
1287: hpux_sys_times_6x(p, v, retval)
1288: struct proc *p;
1289: void *v;
1290: register_t *retval;
1291: {
1292: struct hpux_sys_times_6x_args /* {
1293: syscallarg(struct tms *) tms;
1294: } */ *uap = v;
1295: struct timeval ru, rs;
1296: struct tms atms;
1297: int error;
1298:
1299: calcru(p, &ru, &rs, NULL);
1300: atms.tms_utime = hpux_scale(&ru);
1301: atms.tms_stime = hpux_scale(&rs);
1302: atms.tms_cutime = hpux_scale(&p->p_stats->p_cru.ru_utime);
1303: atms.tms_cstime = hpux_scale(&p->p_stats->p_cru.ru_stime);
1304: error = copyout((caddr_t)&atms, (caddr_t)SCARG(uap, tms),
1305: sizeof (atms));
1306: if (error == 0) {
1307: struct timeval tv;
1308: getmicrouptime(&tv);
1309: *(time_t *)retval = hpux_scale(&tv);
1310: }
1311: return (error);
1312: }
1313:
1314: /*
1315: * Doesn't exactly do what the documentation says.
1316: * What we really do is return 1/HPUX_HZ-th of a second since that
1317: * is what HP-UX returns.
1318: */
1319: static int
1320: hpux_scale(tvp)
1321: struct timeval *tvp;
1322: {
1323: return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000);
1324: }
1325:
1326: /*
1327: * Set IUPD and IACC times on file.
1328: * Can't set ICHG.
1329: */
1330: int
1331: hpux_sys_utime_6x(p, v, retval)
1332: struct proc *p;
1333: void *v;
1334: register_t *retval;
1335: {
1336: struct hpux_sys_utime_6x_args /* {
1337: syscallarg(char *) fname;
1338: syscallarg(time_t *) tptr;
1339: } */ *uap = v;
1340: struct vnode *vp;
1341: struct vattr vattr;
1342: time_t tv[2];
1343: int error;
1344: struct nameidata nd;
1345:
1346: if (SCARG(uap, tptr)) {
1347: error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
1348: sizeof (tv));
1349: if (error)
1350: return (error);
1351: } else
1352: tv[0] = tv[1] = time_second;
1353: vattr_null(&vattr);
1354: vattr.va_atime.tv_sec = tv[0];
1355: vattr.va_atime.tv_nsec = 0;
1356: vattr.va_mtime.tv_sec = tv[1];
1357: vattr.va_mtime.tv_nsec = 0;
1358: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1359: SCARG(uap, fname), p);
1360: if ((error = namei(&nd)))
1361: return (error);
1362: vp = nd.ni_vp;
1363: if (vp->v_mount->mnt_flag & MNT_RDONLY)
1364: error = EROFS;
1365: else
1366: error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p);
1367: vput(vp);
1368: return (error);
1369: }
1370:
1371: int
1372: hpux_sys_pause_6x(p, v, retval)
1373: struct proc *p;
1374: void *v;
1375: register_t *retval;
1376: {
1377: struct sys_sigsuspend_args bsa;
1378:
1379: SCARG(&bsa, mask) = p->p_sigmask;
1380: return (sys_sigsuspend(p, &bsa, retval));
1381: }
CVSweb