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