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