1 /* $NetBSD: osf1_misc.c,v 1.14 1998/05/20 16:34:29 chs Exp $ */
3 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
6 * Author: Chris G. Demetriou
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 * Additional Copyright (c) 1999 by Andrew Gallatin
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
39 #include <sys/fcntl.h>
40 #include <sys/filedesc.h>
41 #include <sys/imgact.h>
42 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/file.h> /* Must come after sys/malloc.h */
47 #include <sys/module.h>
48 #include <sys/mount.h>
49 #include <sys/mutex.h>
50 #include <sys/namei.h>
51 #include <sys/param.h>
53 #include <sys/reboot.h>
54 #include <sys/resource.h>
55 #include <sys/resourcevar.h>
56 #include <sys/selinfo.h>
57 #include <sys/pipe.h> /* Must come after sys/selinfo.h */
58 #include <sys/signal.h>
59 #include <sys/signalvar.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysent.h>
65 #include <sys/sysproto.h>
66 #include <sys/systm.h>
67 #include <sys/unistd.h>
69 #include <sys/utsname.h>
70 #include <sys/vnode.h>
73 #include <vm/vm_kern.h>
74 #include <vm/vm_param.h>
76 #include <vm/vm_map.h>
77 #include <vm/vm_extern.h>
79 #include <machine/cpu.h>
80 #include <machine/cpuconf.h>
81 #include <machine/fpu.h>
82 #include <machine/md_var.h>
83 #include <machine/rpb.h>
85 #include <alpha/osf1/exec_ecoff.h>
86 #include <alpha/osf1/osf1_signal.h>
87 #include <alpha/osf1/osf1_proto.h>
88 #include <alpha/osf1/osf1_syscall.h>
89 #include <alpha/osf1/osf1_util.h>
90 #include <alpha/osf1/osf1.h>
92 static void cvtstat2osf1(struct stat *, struct osf1_stat *);
93 static int osf2bsd_pathconf(int *);
95 static const char osf1_emul_path[] = "/compat/osf1";
97 * [ taken from the linux emulator ]
98 * Search an alternate path before passing pathname arguments on
99 * to system calls. Useful for keeping a separate 'emulation tree'.
101 * If cflag is set, we check if an attempt can be made to create
102 * the named file, i.e. we check if the directory it should
106 osf1_emul_find(td, sgp, prefix, path, pbuf, cflag)
108 caddr_t *sgp; /* Pointer to stackgap memory */
116 char *buf, *cp, *ptr;
119 struct nameidata ndroot;
121 struct vattr vatroot;
123 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
126 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
129 sz = MAXPATHLEN - (ptr - buf);
132 * If sgp is not given then the path is already in kernel space
135 error = copystr(path, ptr, sz, &len);
137 error = copyinstr(path, ptr, sz, &len);
150 * We know that there is a / somewhere in this pathname.
151 * Search backwards for it, to find the file's parent dir
152 * to see if it exists in the alternate tree. If it does,
153 * and we want to create a file (cflag is set). We don't
154 * need to worry about the root comparison in this case.
158 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
162 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
164 if ((error = namei(&nd)) != 0) {
171 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
173 if ((error = namei(&nd)) != 0) {
179 * We now compare the vnode of the osf1_root to the one
180 * vnode asked. If they resolve to be the same, then we
181 * ignore the match so that the real root gets used.
182 * This avoids the problem of traversing "../.." to find the
183 * root directory and never finding it, because "/" resolves
184 * to the emulation root directory. This is expensive :-(
186 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, osf1_emul_path,
189 if ((error = namei(&ndroot)) != 0) {
196 ucred = td->td_ucred;
197 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
201 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
206 if (vat.va_fsid == vatroot.va_fsid &&
207 vat.va_fileid == vatroot.va_fileid) {
216 sz = &ptr[len] - buf;
217 *pbuf = stackgap_alloc(sgp, sz + 1);
218 error = copyout(buf, *pbuf, sz);
239 struct osf1_open_args *uap;
241 struct open_args /* {
242 syscallarg(char *) path;
243 syscallarg(int) flags;
244 syscallarg(int) mode;
248 sg = stackgap_init();
249 CHECKALTEXIST(td, &sg, uap->path);
252 a.flags = uap->flags; /* XXX translate */
258 extern long totalphysmem;
261 osf1_getsysinfo(td, uap)
263 struct osf1_getsysinfo_args *uap;
266 int ncpus = 1; /* XXX until SMP */
271 struct osf1_cpu_info cpuinfo;
276 case OSF_GET_MAX_UPROCS:
277 error = copyout(&maxprocperuid, uap->buffer,
278 sizeof(maxprocperuid));
281 case OSF_GET_PHYSMEM:
282 ophysmem = totalphysmem * (PAGE_SIZE >> 10);
283 error = copyout(&ophysmem, uap->buffer,
287 case OSF_GET_MAX_CPU:
288 case OSF_GET_CPUS_IN_BOX:
289 error = copyout(&ncpus, uap->buffer,
293 case OSF_GET_IEEE_FP_CONTROL:
294 error = copyout(&td->td_pcb->pcb_fp_control,uap->buffer,
295 sizeof(td->td_pcb->pcb_fp_control));
298 case OSF_GET_CPU_INFO:
300 if (uap->nbytes < sizeof(cpuinfo))
303 bzero(&cpuinfo, sizeof(cpuinfo));
304 unit = alpha_pal_whami();
305 cpuinfo.current_cpu = unit;
306 cpuinfo.cpus_in_box = ncpus;
308 LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
309 cpuinfo.ncpus = ncpus;
310 cpuinfo.cpus_present = ncpus;
311 cpuinfo.cpus_running = ncpus;
312 cpuinfo.cpu_binding = 1;
313 cpuinfo.cpu_ex_binding = 0;
314 cpuinfo.mhz = hwrpb->rpb_cc_freq / 1000000;
315 error = copyout(&cpuinfo, uap->buffer,
320 case OSF_GET_PROC_TYPE:
321 if(uap->nbytes < sizeof(proctype))
324 unit = alpha_pal_whami();
325 proctype = LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
326 error = copyout (&proctype, uap->buffer,
331 case OSF_GET_HWRPB: { /* note -- osf/1 doesn't have rpb_tbhint[8] */
332 unsigned long rpb_size;
333 rpb_size = (unsigned long)&hwrpb->rpb_tbhint -
334 (unsigned long)hwrpb;
335 if(uap->nbytes < rpb_size){
336 uprintf("nbytes = %ld, sizeof(struct rpb) = %ld\n",
337 uap->nbytes, rpb_size);
341 error = copyout(hwrpb, uap->buffer, rpb_size);
346 case OSF_GET_PLATFORM_NAME:
347 error = copyout(platform.model, uap->buffer,
348 strlen(platform.model));
352 printf("osf1_getsysinfo called with unknown op=%ld\n", uap->op);
355 td->td_retval[0] = retval;
361 osf1_setsysinfo(td, uap)
363 struct osf1_setsysinfo_args *uap;
370 case OSF_SET_IEEE_FP_CONTROL:
372 u_int64_t temp, *fp_control;
374 if ((error = copyin(uap->buffer, &temp, sizeof(temp))))
376 fp_control = &td->td_pcb->pcb_fp_control;
377 *fp_control = temp & IEEE_TRAP_ENABLE_MASK;
381 uprintf("osf1_setsysinfo called with op=%ld\n", uap->op);
389 osf1_getrlimit(td, uap)
391 struct osf1_getrlimit_args *uap;
393 struct rlimit bsd_rlim;
397 if (uap->which >= OSF1_RLIMIT_NLIMITS)
400 if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
402 else if (uap->which == OSF1_RLIMIT_NOFILE)
403 which = RLIMIT_NOFILE;
409 lim_rlimit(p, which, &bsd_rlim);
411 return (copyout(&bsd_rlim, uap->rlp, sizeof(bsd_rlim)));
416 osf1_setrlimit(td, uap)
418 struct osf1_setrlimit_args *uap;
420 struct rlimit bsd_rlim;
423 if (uap->which >= OSF1_RLIMIT_NLIMITS)
426 if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
428 else if (uap->which == OSF1_RLIMIT_NOFILE)
429 which = RLIMIT_NOFILE;
433 error = copyin(uap->rlp, &bsd_rlim, sizeof(bsd_rlim));
437 return (kern_setrlimit(td, which, &bsd_rlim));
442 * As linux says, this is a total guess.
446 osf1_set_program_attributes(td, uap)
448 struct osf1_set_program_attributes_args *uap;
450 struct vmspace *vm = td->td_proc->p_vmspace;
452 vm->vm_taddr = (caddr_t)uap->text_start;
453 vm->vm_tsize = btoc(round_page(uap->text_len));
454 vm->vm_daddr = (caddr_t)uap->bss_start;
455 vm->vm_dsize = btoc(round_page(uap->bss_len));
457 return(KERN_SUCCESS);
464 struct osf1_mmap_args *uap;
466 struct mmap_args /* {
467 syscallarg(caddr_t) addr;
468 syscallarg(size_t) len;
469 syscallarg(int) prot;
470 syscallarg(int) flags;
472 syscallarg(long) pad;
473 syscallarg(off_t) pos;
477 vm_offset_t addr, len, newaddr;
491 * OSF/1's mmap, unlike FreeBSD's, does its best to map memory at the
492 * user's requested address, even if MAP_FIXED is not set. Here we
493 * try to replicate this behaviour as much as we can because some
494 * applications (like /sbin/loader) depend on having things put as
495 * close to where they've requested as possible.
498 if (uap->addr != NULL)
499 addr = round_page((vm_offset_t)a.addr);
502 * Try to use the apparent OSF/1 default placement of 0x10000 for
503 * NULL addrs, this helps to prevent non-64 bit clean binaries from
506 addr = round_page((vm_offset_t)0x10000UL);
507 len = (vm_offset_t)a.len;
508 map = &td->td_proc->p_vmspace->vm_map;
509 if (!vm_map_findspace(map, addr, len, &newaddr)) {
510 a.addr = (caddr_t) newaddr;
511 a.flags |= (MAP_FIXED);
515 uprintf("osf1_mmap:vm_map_findspace failed for: %p 0x%lx\n",
518 if (uap->flags & OSF1_MAP_SHARED)
519 a.flags |= MAP_SHARED;
520 if (uap->flags & OSF1_MAP_PRIVATE)
521 a.flags |= MAP_PRIVATE;
523 switch (uap->flags & OSF1_MAP_TYPE) {
524 case OSF1_MAP_ANONYMOUS:
533 if (uap->flags & OSF1_MAP_FIXED)
534 a.flags |= MAP_FIXED;
535 if (uap->flags & OSF1_MAP_HASSEMAPHORE)
536 a.flags |= MAP_HASSEMAPHORE;
537 if (uap->flags & OSF1_MAP_INHERIT)
539 if (uap->flags & OSF1_MAP_UNALIGNED)
542 * Emulate an osf/1 bug: Apparently, mmap'ed segments are always
543 * readable even if the user doesn't or in PROT_READ. This causes
544 * some buggy programs to segv.
549 retval = mmap(td, &a);
552 "\nosf1_mmap: addr=%p (%p), len = 0x%lx, prot=0x%x, fd=%d, pad=0, pos=0x%lx",
553 uap->addr, a.addr,uap->len, uap->prot,
555 printf(" flags = 0x%x\n",uap->flags);
563 struct osf1_msync_args *uap;
570 if(uap->flags & OSF1_MS_ASYNC)
572 if(uap->flags & OSF1_MS_SYNC)
574 if(uap->flags & OSF1_MS_INVALIDATE)
575 a.flags |= MS_INVALIDATE;
576 return(msync(td, &a));
588 int32_t st_atime_sec;
590 int32_t st_mtime_sec;
592 int32_t st_ctime_sec;
594 u_int32_t st_blksize;
601 * Get file status; this version follows links.
607 struct osf1_stat_args *uap;
611 struct osf1_stat osb;
615 sg = stackgap_init();
617 CHECKALTEXIST(td, &sg, uap->path);
619 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
621 if ((error = namei(&nd)))
623 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
627 cvtstat2osf1(&sb, &osb);
628 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
634 * Get file status; this version does not follow links.
640 register struct osf1_lstat_args *uap;
643 struct osf1_stat osb;
646 caddr_t sg = stackgap_init();
648 CHECKALTEXIST(td, &sg, uap->path);
650 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
652 if ((error = namei(&nd)))
654 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
658 cvtstat2osf1(&sb, &osb);
659 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
665 * Return status information about a file descriptor.
670 register struct osf1_fstat_args *uap;
674 struct osf1_stat oub;
677 if ((error = fget(td, uap->fd, &fp)) != 0)
679 error = fo_stat(fp, &ub, td->td_ucred, td);
681 cvtstat2osf1(&ub, &oub);
683 error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
689 #define bsd2osf_dev(dev) (umajor(dev) << 20 | uminor(dev))
691 * Convert from a stat structure to an osf1 stat structure.
694 cvtstat2osf1(st, ost)
696 struct osf1_stat *ost;
699 ost->st_dev = bsd2osf_dev(st->st_dev);
700 ost->st_ino = st->st_ino;
701 ost->st_mode = st->st_mode;
702 ost->st_nlink = st->st_nlink;
703 ost->st_uid = st->st_uid == -2 ? (u_int16_t) -2 : st->st_uid;
704 ost->st_gid = st->st_gid == -2 ? (u_int16_t) -2 : st->st_gid;
705 ost->st_rdev = bsd2osf_dev(st->st_rdev);
706 ost->st_size = st->st_size;
707 ost->st_atime_sec = st->st_atime;
709 ost->st_mtime_sec = st->st_mtime;
711 ost->st_ctime_sec = st->st_ctime;
713 ost->st_blksize = st->st_blksize;
714 ost->st_blocks = st->st_blocks;
715 ost->st_flags = st->st_flags;
716 ost->st_gen = st->st_gen;
723 struct osf1_mknod_args *uap;
726 printf("osf1_mknod no longer implemented\n");
734 struct osf1_access_args *uap;
738 sg = stackgap_init();
739 CHECKALTEXIST(td, &sg, uap->path);
741 return access(td, (struct access_args *)uap);
756 struct osf1_fcntl_args *uap;
762 struct osf1_flock osf_flock;
763 struct flock bsd_flock;
764 struct flock *nflock;
773 /* need to translate flags here */
775 if ((long)uap->arg & OSF1_FNONBLOCK)
777 if ((long)uap->arg & OSF1_FAPPEND)
779 if ((long)uap->arg & OSF1_FDEFER)
781 if ((long)uap->arg & OSF1_FASYNC)
783 if ((long)uap->arg & OSF1_FCREAT)
785 if ((long)uap->arg & OSF1_FTRUNC)
787 if ((long)uap->arg & OSF1_FEXCL)
789 if ((long)uap->arg & OSF1_FNDELAY)
791 if ((long)uap->arg & OSF1_FSYNC)
794 error = fcntl(td, &a);
801 * The OSF/1 flock stucture has a different order than
802 * the BSD one, but all else is the same. We must
803 * reorder the one we've gotten so that flock() groks it.
805 if ((error = copyin(uap->arg, &osf_flock, sizeof(osf_flock))))
807 bsd_flock.l_type = osf_flock.l_type;
808 bsd_flock.l_whence = osf_flock.l_whence;
809 bsd_flock.l_start = osf_flock.l_start;
810 bsd_flock.l_len = osf_flock.l_len;
811 bsd_flock.l_pid = osf_flock.l_pid;
812 sg = stackgap_init();
813 nflock = stackgap_alloc(&sg, sizeof(struct flock));
814 if ((error = copyout(&bsd_flock, nflock, sizeof(bsd_flock))) != 0)
818 error = fcntl(td, (struct fcntl_args *) uap);
820 printf("fcntl called with cmd=%d, args=0x%lx\n returns %d\n",uap->cmd,(long)uap->arg,error);
821 printf("bsd_flock.l_type = 0x%x\n", bsd_flock.l_type);
822 printf("bsd_flock.l_whence = 0x%x\n", bsd_flock.l_whence);
823 printf("bsd_flock.l_start = 0x%lx\n", bsd_flock.l_start);
824 printf("bsd_flock.l_len = 0x%lx\n", bsd_flock.l_len);
825 printf("bsd_flock.l_pid = 0x%x\n", bsd_flock.l_pid);
828 if ((uap->cmd == F_GETLK) && !error) {
829 osf_flock.l_type = F_UNLCK;
830 if ((error = copyout(&osf_flock, oarg,
836 error = fcntl(td, (struct fcntl_args *) uap);
838 if ((uap->cmd == OSF1_F_GETFL) && !error ) {
839 tmp = td->td_retval[0] & O_ACCMODE;
840 if (td->td_retval[0] & FNONBLOCK)
841 tmp |= OSF1_FNONBLOCK;
842 if (td->td_retval[0] & FAPPEND)
844 if (td->td_retval[0] & FDEFER)
846 if (td->td_retval[0] & FASYNC)
848 if (td->td_retval[0] & O_CREAT)
850 if (td->td_retval[0] & O_TRUNC)
852 if (td->td_retval[0] & O_EXCL)
854 if (td->td_retval[0] & FNDELAY)
856 if (td->td_retval[0] & FFSYNC)
858 td->td_retval[0] = tmp;
870 struct osf1_fcntl_args *uap;
882 a.arg = (long)uap->arg;
887 a.arg = (long)uap->arg;
892 a.arg = (long)uap->arg;
897 a.arg = (long)uap->arg; /* ignored */
903 if ((long)uap->arg & OSF1_FAPPEND)
905 if ((long)uap->arg & OSF1_FNONBLOCK)
907 if ((long)uap->arg & OSF1_FASYNC)
909 if ((long)uap->arg & OSF1_FSYNC)
914 default: /* XXX other cases */
918 error = fcntl(td, &a);
936 struct osf1_socket_args *uap;
938 struct socket_args a;
940 if (uap->type > AF_LINK)
941 return (EINVAL); /* XXX After AF_LINK, divergence. */
943 a.domain = uap->domain;
945 a.protocol = uap->protocol;
947 return socket(td, &a);
954 register struct osf1_sendto_args *uap;
956 struct sendto_args a;
958 if (uap->flags & ~0x7f) /* unsupported flags */
964 a.flags = uap->flags;
965 a.to = (caddr_t)uap->to;
966 a.tolen = uap->tolen;
968 return sendto(td, &a);
975 struct osf1_reboot_args *uap;
977 struct reboot_args a;
979 if (uap->opt & ~OSF1_RB_ALLFLAGS &&
980 uap->opt & (OSF1_RB_ALTBOOT|OSF1_RB_UNIPROC))
985 if (uap->opt & OSF1_RB_ASKNAME)
987 if (uap->opt & OSF1_RB_SINGLE)
989 if (uap->opt & OSF1_RB_NOSYNC)
991 if (uap->opt & OSF1_RB_HALT)
993 if (uap->opt & OSF1_RB_INITNAME)
994 a.opt |= RB_INITNAME;
995 if (uap->opt & OSF1_RB_DFLTROOT)
996 a.opt |= RB_DFLTROOT;
998 return reboot(td, &a);
1005 struct osf1_lseek_args *uap;
1007 struct lseek_args a;
1011 a.offset = uap->offset;
1012 a.whence = uap->whence;
1014 return lseek(td, &a);
1019 * OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
1020 * setuid() won't work.
1022 * Instead, by P1003.1b-1993, setuid() is supposed to work like:
1023 * If the process has appropriate [super-user] privileges, the
1024 * setuid() function sets the real user ID, effective user
1025 * ID, and the saved set-user-ID to uid.
1026 * If the process does not have appropriate privileges, but uid
1027 * is equal to the real user ID or the saved set-user-ID, the
1028 * setuid() function sets the effective user ID to uid; the
1029 * real user ID and saved set-user-ID remain unchanged by
1030 * this function call.
1033 osf1_setuid(td, uap)
1035 struct osf1_setuid_args *uap;
1040 struct uidinfo *uip;
1041 struct ucred *newcred, *oldcred;
1048 oldcred = p->p_ucred;
1050 if ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 &&
1051 uid != oldcred->cr_ruid && uid != oldcred->cr_svuid) {
1058 crcopy(newcred, oldcred);
1060 if (uid != oldcred->cr_ruid) {
1061 change_ruid(newcred, uip);
1064 if (oldcred->cr_svuid != uid) {
1065 change_svuid(newcred, uid);
1069 if (newcred->cr_uid != uid) {
1070 change_euid(newcred, uip);
1073 p->p_ucred = newcred;
1082 * OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
1083 * setgid() won't work.
1085 * If you change "uid" to "gid" in the discussion, above, about
1086 * setuid(), you'll get a correct description of setgid().
1089 osf1_setgid(td, uap)
1091 struct osf1_setgid_args *uap;
1096 struct ucred *newcred, *oldcred;
1102 oldcred = p->p_ucred;
1104 if (((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 ) &&
1105 gid != oldcred->cr_rgid && gid != oldcred->cr_svgid) {
1111 crcopy(newcred, oldcred);
1113 if (gid != oldcred->cr_rgid) {
1114 change_rgid(newcred, gid);
1117 if (oldcred->cr_svgid != gid) {
1118 change_svgid(newcred, gid);
1122 if (newcred->cr_groups[0] != gid) {
1123 change_egid(newcred, gid);
1126 p->p_ucred = newcred;
1134 * The structures end up being the same... but we can't be sure that
1135 * the other word of our iov_len is zero!
1141 #define STACKGAPLEN 400
1145 struct osf1_readv_args *uap;
1147 int error, osize, nsize, i;
1149 struct readv_args /* {
1151 syscallarg(struct iovec *) iovp;
1152 syscallarg(u_int) iovcnt;
1154 struct osf1_iovec *oio;
1157 sg = stackgap_init();
1159 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
1162 osize = uap->iovcnt * sizeof (struct osf1_iovec);
1163 nsize = uap->iovcnt * sizeof (struct iovec);
1165 oio = malloc(osize, M_TEMP, M_WAITOK);
1166 nio = malloc(nsize, M_TEMP, M_WAITOK);
1169 if ((error = copyin(uap->iovp, oio, osize)))
1171 for (i = 0; i < uap->iovcnt; i++) {
1172 nio[i].iov_base = oio[i].iov_base;
1173 nio[i].iov_len = oio[i].iov_len;
1177 a.iovp = stackgap_alloc(&sg, nsize);
1178 a.iovcnt = uap->iovcnt;
1180 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
1182 error = readv(td, &a);
1192 osf1_writev(td, uap)
1194 struct osf1_writev_args *uap;
1196 int error, i, nsize, osize;
1198 struct writev_args /* {
1200 syscallarg(struct iovec *) iovp;
1201 syscallarg(u_int) iovcnt;
1203 struct osf1_iovec *oio;
1206 sg = stackgap_init();
1208 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
1211 osize = uap->iovcnt * sizeof (struct osf1_iovec);
1212 nsize = uap->iovcnt * sizeof (struct iovec);
1214 oio = malloc(osize, M_TEMP, M_WAITOK);
1215 nio = malloc(nsize, M_TEMP, M_WAITOK);
1218 if ((error = copyin(uap->iovp, oio, osize)))
1220 for (i = 0; i < uap->iovcnt; i++) {
1221 nio[i].iov_base = oio[i].iov_base;
1222 nio[i].iov_len = oio[i].iov_len;
1226 a.iovp = stackgap_alloc(&sg, nsize);
1227 a.iovcnt = uap->iovcnt;
1229 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
1231 error = writev(td, &a);
1241 * More of the stupid off_t padding!
1244 osf1_truncate(td, uap)
1246 struct osf1_truncate_args *uap;
1249 struct truncate_args a;
1251 sg = stackgap_init();
1252 CHECKALTEXIST(td, &sg, uap->path);
1256 a.length = uap->length;
1258 return truncate(td, &a);
1263 osf1_ftruncate(td, uap)
1265 struct osf1_ftruncate_args *uap;
1267 struct ftruncate_args a;
1271 a.length = uap->length;
1273 return ftruncate(td, &a);
1278 osf2bsd_pathconf(name)
1283 case _OSF1_PC_LINK_MAX:
1284 case _OSF1_PC_MAX_CANON:
1285 case _OSF1_PC_MAX_INPUT:
1286 case _OSF1_PC_NAME_MAX:
1290 case _OSF1_PC_PATH_MAX:
1291 case _OSF1_PC_PIPE_BUF:
1294 case _OSF1_PC_NO_TRUNC:
1295 *name = _PC_NO_TRUNC;
1298 case _OSF1_PC_CHOWN_RESTRICTED:
1299 *name = _PC_CHOWN_RESTRICTED;
1302 case _OSF1_PC_VDISABLE:
1303 *name = _PC_VDISABLE;
1314 osf1_pathconf(td, uap)
1316 struct osf1_pathconf_args *uap;
1319 if (osf2bsd_pathconf(&uap->name))
1322 return (pathconf(td, (void *)uap));
1327 osf1_fpathconf(td, uap)
1329 struct osf1_fpathconf_args *uap;
1332 if (osf2bsd_pathconf(&uap->name))
1335 return (fpathconf(td, (void *)uap));
1340 osf1_getrusage(td, uap)
1342 struct osf1_getrusage_args *uap;
1346 struct osf1_rusage oru;
1351 rup = &p->p_stats->p_ru;
1352 mtx_lock_spin(&sched_lock);
1353 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
1354 mtx_unlock_spin(&sched_lock);
1357 case RUSAGE_CHILDREN:
1358 rup = &p->p_stats->p_cru;
1364 TV_CP(rup->ru_utime, oru.ru_utime);
1365 TV_CP(rup->ru_stime, oru.ru_stime);
1366 bcopy(&(rup->ru_first), &(oru.ru_first),
1367 (&(oru.ru_last) - &(oru.ru_first)));
1369 return (copyout((caddr_t)&oru, (caddr_t)uap->rusage,
1370 sizeof (struct osf1_rusage)));
1377 struct osf1_wait4_args *uap;
1381 struct osf1_rusage *orusage, oru;
1382 struct rusage *rusage = NULL, ru;
1384 orusage = uap->rusage;
1386 sg = stackgap_init();
1387 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
1388 uap->rusage = (struct osf1_rusage *)rusage;
1390 if ((error = wait4(td, (struct wait_args *)uap)))
1392 if (orusage && (error = copyin(rusage, &ru, sizeof(ru)) == 0)){
1393 TV_CP(ru.ru_utime, oru.ru_utime);
1394 TV_CP(ru.ru_stime, oru.ru_stime);
1395 bcopy(&ru.ru_first, &oru.ru_first,
1396 (&(oru.ru_last) - &(oru.ru_first)));
1397 copyout(&oru, orusage, sizeof (struct osf1_rusage));
1404 osf1_madvise(td, uap)
1406 struct osf1_madvise_args *uap;
1415 osf1_execve(td, uap)
1417 struct osf1_execve_args *uap;
1420 struct execve_args ap;
1422 sg = stackgap_init();
1423 CHECKALTEXIST(td, &sg, uap->path);
1425 ap.fname = uap->path;
1426 ap.argv = uap->argp;
1427 ap.envv = uap->envp;
1429 return execve(td, &ap);
1434 osf1_usleep_thread(td, uap)
1436 struct osf1_usleep_thread_args *uap;
1439 struct osf1_timeval time;
1440 struct timeval difftv, endtv, sleeptv, tv;
1442 if ((error = copyin(uap->sleep, &time, sizeof time)))
1445 sleeptv.tv_sec = (u_long)time.tv_sec;
1446 sleeptv.tv_usec = (u_long)time.tv_usec;
1447 timo = tvtohz(&sleeptv);
1450 * Some callers use usleep(0) as a sort of thread-yield so make
1451 * sure that the timeout is non-zero.
1460 tsleep(td, PUSER|PCATCH, "OSF/1", timo);
1462 if (uap->slept != NULL) {
1465 timersub(&time, &endtv, &difftv);
1467 if (tv.tv_sec < 0 || tv.tv_usec < 0)
1468 tv.tv_sec = tv.tv_usec = 0;
1470 error = copyout(&time, uap->slept, sizeof time);
1476 int osf1_gettimeofday(td, uap)
1478 register struct osf1_gettimeofday_args *uap;
1483 struct osf1_timeval otv;
1489 otv.tv_sec = atv.tv_sec;
1490 otv.tv_usec = atv.tv_usec;
1491 if ((error = copyout((caddr_t)&otv, (caddr_t)uap->tp,
1496 tz.tz_minuteswest = tz_minuteswest;
1497 tz.tz_dsttime = tz_dsttime;
1498 error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz));
1504 int osf1_select(td, uap)
1506 register struct osf1_select_args *uap;
1511 struct osf1_timeval otv;
1514 sg = stackgap_init();
1516 if ((error=copyin((caddr_t)uap->tv,(caddr_t)&otv,sizeof(otv))))
1519 uap->tv = stackgap_alloc(&sg, sizeof(struct timeval));
1520 if ((error=copyout((caddr_t)&tv, (caddr_t)uap->tv,sizeof(tv))))
1523 return(select(td, (struct select_args *)uap));
1528 osf1_setitimer(td, uap)
1530 struct osf1_setitimer_args *uap;
1534 caddr_t old_oitv, sg;
1535 struct itimerval itv;
1536 struct osf1_itimerval otv;
1539 old_oitv = (caddr_t)uap->oitv;
1540 sg = stackgap_init();
1542 if ((error = copyin((caddr_t)uap->itv,(caddr_t)&otv,sizeof(otv)))) {
1543 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1546 TV_CP(otv.it_interval,itv.it_interval);
1547 TV_CP(otv.it_value,itv.it_value);
1548 uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
1549 if ((error = copyout((caddr_t)&itv,(caddr_t)uap->itv,sizeof(itv)))) {
1550 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1553 uap->oitv = stackgap_alloc(&sg, sizeof(struct itimerval));
1554 if ((error = setitimer(td, (struct setitimer_args *)uap))) {
1555 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1558 if ((error = copyin((caddr_t)uap->oitv,(caddr_t)&itv,sizeof(itv)))) {
1559 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1562 TV_CP(itv.it_interval,otv.it_interval);
1563 TV_CP(itv.it_value,otv.it_value);
1565 && (error = copyout((caddr_t)&otv, old_oitv, sizeof(otv)))) {
1566 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1573 osf1_getitimer(td, uap)
1575 struct osf1_getitimer_args *uap;
1578 caddr_t old_itv, sg;
1579 struct itimerval itv;
1580 struct osf1_itimerval otv;
1583 old_itv = (caddr_t)uap->itv;
1584 sg = stackgap_init();
1586 uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
1587 if ((error = getitimer(td, (struct getitimer_args *)uap))) {
1588 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1591 if ((error = copyin((caddr_t)uap->itv,(caddr_t)&itv,sizeof(itv)))) {
1592 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1595 TV_CP(itv.it_interval,otv.it_interval);
1596 TV_CP(itv.it_value,otv.it_value);
1597 if ((error = copyout((caddr_t)&otv, old_itv, sizeof(otv)))) {
1598 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1605 osf1_proplist_syscall(td, uap)
1607 struct osf1_proplist_syscall_args *uap;
1615 osf1_ntpgettime(td, uap)
1617 struct osf1_ntpgettime_args *uap;
1625 osf1_ntpadjtime(td, uap)
1627 struct osf1_ntpadjtime_args *uap;
1635 osf1_setpgrp(td, uap)
1637 struct osf1_setpgrp_args *uap;
1640 return(setpgid(td, (struct setpgid_args *)uap));
1645 osf1_uswitch(td, uap)
1647 struct osf1_uswitch_args *uap;
1651 vm_map_entry_t entry;
1658 if (uap->cmd == OSF1_USC_GET) {
1659 if (vm_map_lookup_entry(&(p->p_vmspace->vm_map), 0, &entry))
1660 td->td_retval[0] = OSF1_USW_NULLP;
1662 td->td_retval[0] = 0;
1663 return(KERN_SUCCESS);
1664 } else if (uap->cmd == OSF1_USC_SET)
1665 if (uap->mask & OSF1_USW_NULLP) {
1666 rv = vm_mmap(&(p->p_vmspace->vm_map), &zero, PAGE_SIZE,
1667 VM_PROT_READ, VM_PROT_ALL,
1668 MAP_PRIVATE | MAP_FIXED | MAP_ANON, NULL, 0);
1670 return(KERN_SUCCESS);
1673 "osf1_uswitch:vm_mmap of zero page failed with status %d\n",
1683 osf1_classcntl(td, uap)
1685 struct osf1_classcntl_args *uap;
1688 return(EACCES); /* class scheduling not enabled */
1692 struct osf1_tbl_loadavg
1699 long tl_mach_factor[3]; /* ???? */
1702 struct osf1_tbl_sysinfo {
1713 #define TBL_LOADAVG 3
1714 #define TBL_SYSINFO 12
1719 struct osf1_table_args /*{
1728 struct osf1_tbl_loadavg ld;
1729 struct osf1_tbl_sysinfo si;
1734 case TBL_LOADAVG: /* xemacs wants this */
1735 if ((uap->index != 0) || (uap->nel != 1))
1737 bcopy(&averunnable, &ld, sizeof(averunnable));
1738 ld.tl_lscale = (u_int)averunnable.fscale;
1739 retval = copyout(&ld, uap->addr, sizeof(ld));
1742 if ((uap->index != 0) || (uap->nel != 1))
1744 bzero(&si, sizeof(si));
1746 si.si_user = cp_time[CP_USER];
1747 si.si_nice = cp_time[CP_NICE];
1748 si.si_sys = cp_time[CP_SYS];
1749 si.si_idle = cp_time[CP_IDLE];
1750 si.wait = cp_time[CP_INTR];
1754 si.si_boottime = boottime.tv_sec;
1755 retval = copyout(&si, uap->addr, sizeof(si));
1758 printf("osf1_table: %ld, %ld, %p, %ld %ld\n",
1759 uap->id, uap->index, uap->addr, uap->nel, uap->lel);
1770 osf1_sysinfo(td, uap)
1772 struct osf1_sysinfo_args /*{
1778 int name[2], retval;
1788 case 2: /* hostname, from ogethostname */
1791 name[1] = KERN_HOSTNAME;
1793 retval = userland_sysctl(td, name, 2, uap->buf, &len,
1796 td->td_retval[0] = bytes;
1799 case 3: /* release of osf1 */
1802 case 4: /* minor version of osf1 */
1805 case 5: /* machine or arch */
1809 case 7: /* serial number, real osf1 returns 0! */
1812 case 8: /* HW vendor */
1815 case 9: /* dunno, this is what du does.. */
1821 bytes = min(uap->count, strlen(string)+1);
1822 copyout(string, uap->buf, bytes);
1823 td->td_retval[0] = bytes;