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