1 /* $NetBSD: sunos_misc.c,v 1.47 1995/04/27 12:05:40 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * @(#)sunos_misc.c 8.1 (Berkeley) 6/18/93 45 * 46 * Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 47 */ 48 49 /* 50 * SunOS compatibility module. 51 * 52 * SunOS system calls that are implemented differently in BSD are 53 * handled here. 54 */ 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/namei.h> 59 #include <sys/proc.h> 60 #include <sys/dir.h> 61 #include <sys/file.h> 62 #include <sys/stat.h> 63 #include <sys/filedesc.h> 64 #include <sys/ioctl.h> 65 #include <sys/kernel.h> 66 #include <sys/reboot.h> 67 #include <sys/exec.h> 68 #include <sys/malloc.h> 69 #include <sys/mbuf.h> 70 #include <sys/mman.h> 71 #include <sys/mount.h> 72 #include <sys/ptrace.h> 73 #include <sys/resource.h> 74 #include <sys/resourcevar.h> 75 #include <sys/signal.h> 76 #include <sys/signalvar.h> 77 #include <sys/socket.h> 78 #include <sys/vnode.h> 79 #include <sys/uio.h> 80 #include <sys/wait.h> 81 #include <sys/utsname.h> 82 #include <sys/unistd.h> 83 #include <sys/syscallargs.h> 84 #include <compat/sunos/sunos.h> 85 #include <compat/sunos/sunos_syscallargs.h> 86 87 #include <netinet/in.h> 88 89 #include <miscfs/specfs/specdev.h> 90 91 #include <nfs/rpcv2.h> 92 #include <nfs/nfsv2.h> 93 #include <nfs/nfs.h> 94 95 #include <vm/vm.h> 96 97 int 98 sunos_wait4(p, uap, retval) 99 struct proc *p; 100 struct sunos_wait4_args *uap; 101 register_t *retval; 102 { 103 if (SCARG(uap, pid) == 0) 104 SCARG(uap, pid) = WAIT_ANY; 105 return (wait4(p, uap, retval, 1)); 106 } 107 108 int 109 sunos_creat(p, uap, retval) 110 struct proc *p; 111 struct sunos_creat_args *uap; 112 register_t *retval; 113 { 114 struct sunos_open_args ouap; 115 116 SCARG(&ouap, path) = SCARG(uap, path); 117 SCARG(&ouap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 118 SCARG(&ouap, mode) = SCARG(uap, mode); 119 return (open(p, &ouap, retval)); 120 } 121 122 int 123 sunos_execv(p, uap, retval) 124 struct proc *p; 125 struct sunos_execv_args *uap; 126 register_t *retval; 127 { 128 struct execve_args ouap; 129 130 SCARG(&ouap, path) = SCARG(uap, path); 131 SCARG(&ouap, argp) = SCARG(uap, argp); 132 SCARG(&ouap, envp) = NULL; 133 return (execve(p, &ouap, retval)); 134 } 135 136 int 137 sunos_omsync(p, uap, retval) 138 struct proc *p; 139 struct sunos_omsync_args *uap; 140 register_t *retval; 141 { 142 struct msync_args ouap; 143 144 if (SCARG(uap, flags)) 145 return (EINVAL); 146 SCARG(&ouap, addr) = SCARG(uap, addr); 147 SCARG(&ouap, len) = SCARG(uap, len); 148 return (msync(p, &ouap, retval)); 149 } 150 151 int 152 sunos_unmount(p, uap, retval) 153 struct proc *p; 154 struct sunos_unmount_args *uap; 155 register_t *retval; 156 { 157 SCARG(uap, flags) = 0; 158 return (unmount(p, (struct unmount_args *)uap, retval)); 159 } 160 161 int 162 sunos_mount(p, uap, retval) 163 struct proc *p; 164 struct sunos_mount_args *uap; 165 register_t *retval; 166 { 167 int oflags = SCARG(uap, flags), nflags, error; 168 extern char sigcode[], esigcode[]; 169 char fsname[MFSNAMELEN]; 170 171 #define szsigcode (esigcode - sigcode) 172 173 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 174 return (EINVAL); 175 if ((oflags & SUNM_NEWTYPE) == 0) 176 return (EINVAL); 177 nflags = 0; 178 if (oflags & SUNM_RDONLY) 179 nflags |= MNT_RDONLY; 180 if (oflags & SUNM_NOSUID) 181 nflags |= MNT_NOSUID; 182 if (oflags & SUNM_REMOUNT) 183 nflags |= MNT_UPDATE; 184 SCARG(uap, flags) = nflags; 185 186 if (error = copyinstr((caddr_t)SCARG(uap, type), fsname, 187 sizeof fsname, (size_t *)0)) 188 return (error); 189 190 if (strcmp(fsname, "4.2") == 0) { 191 SCARG(uap, type) = STACKGAPBASE; 192 if (error = copyout("ufs", SCARG(uap, type), sizeof("ufs"))) 193 return (error); 194 } else if (strcmp(fsname, "nfs") == 0) { 195 struct sunos_nfs_args sna; 196 struct sockaddr_in sain; 197 struct nfs_args na; 198 struct sockaddr sa; 199 200 if (error = copyin(SCARG(uap, data), &sna, sizeof sna)) 201 return (error); 202 if (error = copyin(sna.addr, &sain, sizeof sain)) 203 return (error); 204 bcopy(&sain, &sa, sizeof sa); 205 sa.sa_len = sizeof(sain); 206 SCARG(uap, data) = STACKGAPBASE; 207 na.addr = (struct sockaddr *)((int)SCARG(uap, data) + sizeof na); 208 na.addrlen = sizeof(struct sockaddr); 209 na.sotype = SOCK_DGRAM; 210 na.proto = IPPROTO_UDP; 211 na.fh = (nfsv2fh_t *)sna.fh; 212 na.flags = sna.flags; 213 na.wsize = sna.wsize; 214 na.rsize = sna.rsize; 215 na.timeo = sna.timeo; 216 na.retrans = sna.retrans; 217 na.hostname = sna.hostname; 218 219 if (error = copyout(&sa, na.addr, sizeof sa)) 220 return (error); 221 if (error = copyout(&na, SCARG(uap, data), sizeof na)) 222 return (error); 223 } 224 return (mount(p, (struct mount_args *)uap, retval)); 225 } 226 227 #if defined(NFSCLIENT) 228 int 229 async_daemon(p, uap, retval) 230 struct proc *p; 231 void *uap; 232 register_t *retval; 233 { 234 struct nfssvc_args ouap; 235 236 SCARG(&ouap, flag) = NFSSVC_BIOD; 237 SCARG(&ouap, argp) = NULL; 238 return nfssvc(p, &ouap, retval); 239 } 240 #endif /* NFSCLIENT */ 241 242 int 243 sunos_sigpending(p, uap, retval) 244 struct proc *p; 245 struct sunos_sigpending_args *uap; 246 register_t *retval; 247 { 248 int mask = p->p_siglist & p->p_sigmask; 249 250 return (copyout((caddr_t)&mask, (caddr_t)SCARG(uap, mask), sizeof(int))); 251 } 252 253 /* 254 * Read Sun-style directory entries. We suck them into kernel space so 255 * that they can be massaged before being copied out to user code. Like 256 * SunOS, we squish out `empty' entries. 257 * 258 * This is quite ugly, but what do you expect from compatibility code? 259 */ 260 int 261 sunos_getdents(p, uap, retval) 262 struct proc *p; 263 register struct sunos_getdents_args *uap; 264 register_t *retval; 265 { 266 register struct vnode *vp; 267 register caddr_t inp, buf; /* BSD-format */ 268 register int len, reclen; /* BSD-format */ 269 register caddr_t outp; /* Sun-format */ 270 register int resid; /* Sun-format */ 271 struct file *fp; 272 struct uio auio; 273 struct iovec aiov; 274 off_t off; /* true file offset */ 275 long soff; /* Sun file offset */ 276 int buflen, error, eofflag; 277 #define BSD_DIRENT(cp) ((struct dirent *)(cp)) 278 #define SUNOS_RECLEN(reclen) (reclen + sizeof(long)) 279 280 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 281 return (error); 282 if ((fp->f_flag & FREAD) == 0) 283 return (EBADF); 284 vp = (struct vnode *)fp->f_data; 285 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ 286 return (EINVAL); 287 buflen = min(MAXBSIZE, SCARG(uap, nbytes)); 288 buf = malloc(buflen, M_TEMP, M_WAITOK); 289 VOP_LOCK(vp); 290 off = fp->f_offset; 291 again: 292 aiov.iov_base = buf; 293 aiov.iov_len = buflen; 294 auio.uio_iov = &aiov; 295 auio.uio_iovcnt = 1; 296 auio.uio_rw = UIO_READ; 297 auio.uio_segflg = UIO_SYSSPACE; 298 auio.uio_procp = p; 299 auio.uio_resid = buflen; 300 auio.uio_offset = off; 301 /* 302 * First we read into the malloc'ed buffer, then 303 * we massage it into user space, one record at a time. 304 */ 305 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 306 (u_long *)0, 0)) 307 goto out; 308 inp = buf; 309 outp = SCARG(uap, buf); 310 resid = SCARG(uap, nbytes); 311 if ((len = buflen - auio.uio_resid) == 0) 312 goto eof; 313 for (; len > 0; len -= reclen) { 314 reclen = ((struct dirent *)inp)->d_reclen; 315 if (reclen & 3) 316 panic("sunos_getdents"); 317 off += reclen; /* each entry points to next */ 318 if (BSD_DIRENT(inp)->d_fileno == 0) { 319 inp += reclen; /* it is a hole; squish it out */ 320 continue; 321 } 322 if (reclen > len || resid < SUNOS_RECLEN(reclen)) { 323 /* entry too big for buffer, so just stop */ 324 outp++; 325 break; 326 } 327 /* 328 * Massage in place to make a Sun-shaped dirent (otherwise 329 * we have to worry about touching user memory outside of 330 * the copyout() call). 331 */ 332 BSD_DIRENT(inp)->d_reclen = SUNOS_RECLEN(reclen); 333 #if notdef 334 BSD_DIRENT(inp)->d_type = 0; /* 4.4 specific */ 335 #endif 336 soff = off; 337 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 || 338 (error = copyout(inp, outp + sizeof soff, reclen)) != 0) 339 goto out; 340 /* advance past this real entry */ 341 inp += reclen; 342 /* advance output past Sun-shaped entry */ 343 outp += SUNOS_RECLEN(reclen); 344 resid -= SUNOS_RECLEN(reclen); 345 } 346 /* if we squished out the whole block, try again */ 347 if (outp == SCARG(uap, buf)) 348 goto again; 349 fp->f_offset = off; /* update the vnode offset */ 350 eof: 351 *retval = SCARG(uap, nbytes) - resid; 352 out: 353 VOP_UNLOCK(vp); 354 free(buf, M_TEMP); 355 return (error); 356 } 357 358 #define SUNOS__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */ 359 360 int 361 sunos_mmap(p, uap, retval) 362 register struct proc *p; 363 register struct sunos_mmap_args *uap; 364 register_t *retval; 365 { 366 struct mmap_args ouap; 367 register struct filedesc *fdp; 368 register struct file *fp; 369 register struct vnode *vp; 370 371 /* 372 * Verify the arguments. 373 */ 374 if (SCARG(uap, prot) & ~(PROT_READ|PROT_WRITE|PROT_EXEC)) 375 return (EINVAL); /* XXX still needed? */ 376 377 if ((SCARG(uap, flags) & SUNOS__MAP_NEW) == 0) 378 return (EINVAL); 379 380 SCARG(&ouap, flags) = SCARG(uap, flags) & ~SUNOS__MAP_NEW; 381 SCARG(&ouap, addr) = SCARG(uap, addr); 382 383 if ((SCARG(&ouap, flags) & MAP_FIXED) == 0 && 384 SCARG(&ouap, addr) != 0 && 385 SCARG(&ouap, addr) < (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ)) 386 SCARG(&ouap, addr) = (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ); 387 388 SCARG(&ouap, len) = SCARG(uap, len); 389 SCARG(&ouap, prot) = SCARG(uap, prot); 390 SCARG(&ouap, fd) = SCARG(uap, fd); 391 SCARG(&ouap, pos) = SCARG(uap, pos); 392 393 /* 394 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX) 395 */ 396 fdp = p->p_fd; 397 if ((unsigned)SCARG(&ouap, fd) < fdp->fd_nfiles && /*XXX*/ 398 (fp = fdp->fd_ofiles[SCARG(&ouap, fd)]) != NULL && /*XXX*/ 399 fp->f_type == DTYPE_VNODE && /*XXX*/ 400 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/ 401 iszerodev(vp->v_rdev)) { /*XXX*/ 402 SCARG(&ouap, flags) |= MAP_ANON; 403 SCARG(&ouap, fd) = -1; 404 } 405 406 return (mmap(p, &ouap, retval)); 407 } 408 409 #define MC_SYNC 1 410 #define MC_LOCK 2 411 #define MC_UNLOCK 3 412 #define MC_ADVISE 4 413 #define MC_LOCKAS 5 414 #define MC_UNLOCKAS 6 415 416 int 417 sunos_mctl(p, uap, retval) 418 register struct proc *p; 419 register struct sunos_mctl_args *uap; 420 register_t *retval; 421 { 422 423 switch (SCARG(uap, func)) { 424 case MC_ADVISE: /* ignore for now */ 425 return (0); 426 case MC_SYNC: /* translate to msync */ 427 return (msync(p, uap, retval)); 428 default: 429 return (EINVAL); 430 } 431 } 432 433 int 434 sunos_setsockopt(p, uap, retval) 435 struct proc *p; 436 register struct sunos_setsockopt_args *uap; 437 register_t *retval; 438 { 439 struct file *fp; 440 struct mbuf *m = NULL; 441 int error; 442 443 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 444 return (error); 445 #define SO_DONTLINGER (~SO_LINGER) 446 if (SCARG(uap, name) == SO_DONTLINGER) { 447 m = m_get(M_WAIT, MT_SOOPTS); 448 if (m == NULL) 449 return (ENOBUFS); 450 mtod(m, struct linger *)->l_onoff = 0; 451 m->m_len = sizeof(struct linger); 452 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 453 SO_LINGER, m)); 454 } 455 if (SCARG(uap, level) == IPPROTO_IP) { 456 #define SUNOS_IP_MULTICAST_IF 2 457 #define SUNOS_IP_MULTICAST_TTL 3 458 #define SUNOS_IP_MULTICAST_LOOP 4 459 #define SUNOS_IP_ADD_MEMBERSHIP 5 460 #define SUNOS_IP_DROP_MEMBERSHIP 6 461 static int ipoptxlat[] = { 462 IP_MULTICAST_IF, 463 IP_MULTICAST_TTL, 464 IP_MULTICAST_LOOP, 465 IP_ADD_MEMBERSHIP, 466 IP_DROP_MEMBERSHIP 467 }; 468 if (SCARG(uap, name) >= SUNOS_IP_MULTICAST_IF && 469 SCARG(uap, name) <= SUNOS_IP_DROP_MEMBERSHIP) { 470 SCARG(uap, name) = 471 ipoptxlat[SCARG(uap, name) - SUNOS_IP_MULTICAST_IF]; 472 } 473 } 474 if (SCARG(uap, valsize) > MLEN) 475 return (EINVAL); 476 if (SCARG(uap, val)) { 477 m = m_get(M_WAIT, MT_SOOPTS); 478 if (m == NULL) 479 return (ENOBUFS); 480 if (error = copyin(SCARG(uap, val), mtod(m, caddr_t), 481 (u_int)SCARG(uap, valsize))) { 482 (void) m_free(m); 483 return (error); 484 } 485 m->m_len = SCARG(uap, valsize); 486 } 487 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 488 SCARG(uap, name), m)); 489 } 490 491 int 492 sunos_fchroot(p, uap, retval) 493 register struct proc *p; 494 register struct sunos_fchroot_args *uap; 495 register_t *retval; 496 { 497 register struct filedesc *fdp = p->p_fd; 498 register struct vnode *vp; 499 struct file *fp; 500 int error; 501 502 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 503 return (error); 504 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 505 return (error); 506 vp = (struct vnode *)fp->f_data; 507 VOP_LOCK(vp); 508 if (vp->v_type != VDIR) 509 error = ENOTDIR; 510 else 511 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 512 VOP_UNLOCK(vp); 513 if (error) 514 return (error); 515 VREF(vp); 516 if (fdp->fd_rdir != NULL) 517 vrele(fdp->fd_rdir); 518 fdp->fd_rdir = vp; 519 return (0); 520 } 521 522 /* 523 * XXX: This needs cleaning up. 524 */ 525 int 526 sunos_auditsys(p, uap, retval) 527 struct proc *p; 528 void *uap; 529 register_t *retval; 530 { 531 return 0; 532 } 533 534 int 535 sunos_uname(p, uap, retval) 536 struct proc *p; 537 struct sunos_uname_args *uap; 538 register_t *retval; 539 { 540 struct sunos_utsname sut; 541 extern char ostype[], machine[], osrelease[]; 542 543 bzero(&sut, sizeof(sut)); 544 545 bcopy(ostype, sut.sysname, sizeof(sut.sysname) - 1); 546 bcopy(hostname, sut.nodename, sizeof(sut.nodename)); 547 sut.nodename[sizeof(sut.nodename)-1] = '\0'; 548 bcopy(osrelease, sut.release, sizeof(sut.release) - 1); 549 bcopy("1", sut.version, sizeof(sut.version) - 1); 550 bcopy(machine, sut.machine, sizeof(sut.machine) - 1); 551 552 return copyout((caddr_t)&sut, (caddr_t)SCARG(uap, name), 553 sizeof(struct sunos_utsname)); 554 } 555 556 int 557 sunos_setpgid(p, uap, retval) 558 struct proc *p; 559 struct sunos_setpgid_args *uap; 560 register_t *retval; 561 { 562 /* 563 * difference to our setpgid call is to include backwards 564 * compatibility to pre-setsid() binaries. Do setsid() 565 * instead of setpgid() in those cases where the process 566 * tries to create a new session the old way. 567 */ 568 if (!SCARG(uap, pgid) && (!SCARG(uap, pid) || SCARG(uap, pid) == p->p_pid)) 569 return setsid(p, uap, retval); 570 else 571 return setpgid(p, uap, retval); 572 } 573 574 int 575 sunos_open(p, uap, retval) 576 struct proc *p; 577 struct sunos_open_args *uap; 578 register_t *retval; 579 { 580 int l, r; 581 int noctty; 582 int ret; 583 584 /* convert mode into NetBSD mode */ 585 l = SCARG(uap, flags); 586 noctty = l & 0x8000; 587 r = (l & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800)); 588 r |= ((l & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0); 589 r |= ((l & 0x0080) ? O_SHLOCK : 0); 590 r |= ((l & 0x0100) ? O_EXLOCK : 0); 591 r |= ((l & 0x2000) ? O_FSYNC : 0); 592 593 SCARG(uap, flags) = r; 594 ret = open(p, (struct open_args *)uap, retval); 595 596 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 597 struct filedesc *fdp = p->p_fd; 598 struct file *fp = fdp->fd_ofiles[*retval]; 599 600 /* ignore any error, just give it a try */ 601 if (fp->f_type == DTYPE_VNODE) 602 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 603 } 604 return ret; 605 } 606 607 #if defined (NFSSERVER) 608 int 609 sunos_nfssvc(p, uap, retval) 610 struct proc *p; 611 struct sunos_nfssvc_args *uap; 612 register_t *retval; 613 { 614 struct nfssvc_args outuap; 615 struct nfsd_srvargs nfsdarg; 616 struct sockaddr sa; 617 int error; 618 extern char sigcode[], esigcode[]; 619 620 #if 0 621 bzero(&outuap, sizeof outuap); 622 SCARG(&outuap, fd) = SCARG(uap, fd); 623 SCARG(&outuap, mskval) = STACKGAPBASE; 624 SCARG(&outuap, msklen) = sizeof sa; 625 SCARG(&outuap, mtchval) = SCARG(&outuap, mskval) + sizeof sa; 626 SCARG(&outuap, mtchlen) = sizeof sa; 627 628 bzero(&sa, sizeof sa); 629 if (error = copyout(&sa, SCARG(&outuap, mskval), SCARG(&outuap, msklen))) 630 return (error); 631 if (error = copyout(&sa, SCARG(&outuap, mtchval), SCARG(&outuap, mtchlen))) 632 return (error); 633 634 return nfssvc(p, &outuap, retval); 635 #else 636 return (ENOSYS); 637 #endif 638 } 639 #endif /* NFSSERVER */ 640 641 int 642 sunos_ustat(p, uap, retval) 643 struct proc *p; 644 struct sunos_ustat_args *uap; 645 register_t *retval; 646 { 647 struct sunos_ustat us; 648 int error; 649 650 bzero(&us, sizeof us); 651 652 /* 653 * XXX: should set f_tfree and f_tinode at least 654 * How do we translate dev -> fstat? (and then to sunos_ustat) 655 */ 656 657 if (error = copyout(&us, SCARG(uap, buf), sizeof us)) 658 return (error); 659 return 0; 660 } 661 662 int 663 sunos_quotactl(p, uap, retval) 664 struct proc *p; 665 struct sunos_quotactl_args *uap; 666 register_t *retval; 667 { 668 return EINVAL; 669 } 670 671 int 672 sunos_vhangup(p, uap, retval) 673 struct proc *p; 674 void *uap; 675 register_t *retval; 676 { 677 return 0; 678 } 679 680 static 681 sunstatfs(sp, buf) 682 struct statfs *sp; 683 caddr_t buf; 684 { 685 struct sunos_statfs ssfs; 686 687 bzero(&ssfs, sizeof ssfs); 688 ssfs.f_type = 0; 689 ssfs.f_bsize = sp->f_bsize; 690 ssfs.f_blocks = sp->f_blocks; 691 ssfs.f_bfree = sp->f_bfree; 692 ssfs.f_bavail = sp->f_bavail; 693 ssfs.f_files = sp->f_files; 694 ssfs.f_ffree = sp->f_ffree; 695 ssfs.f_fsid = sp->f_fsid; 696 return copyout((caddr_t)&ssfs, buf, sizeof ssfs); 697 } 698 699 int 700 sunos_statfs(p, uap, retval) 701 struct proc *p; 702 struct sunos_statfs_args *uap; 703 register_t *retval; 704 { 705 register struct mount *mp; 706 register struct statfs *sp; 707 int error; 708 struct nameidata nd; 709 710 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 711 if (error = namei(&nd)) 712 return (error); 713 mp = nd.ni_vp->v_mount; 714 sp = &mp->mnt_stat; 715 vrele(nd.ni_vp); 716 if (error = VFS_STATFS(mp, sp, p)) 717 return (error); 718 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 719 return sunstatfs(sp, (caddr_t)SCARG(uap, buf)); 720 } 721 722 int 723 sunos_fstatfs(p, uap, retval) 724 struct proc *p; 725 struct sunos_fstatfs_args *uap; 726 register_t *retval; 727 { 728 struct file *fp; 729 struct mount *mp; 730 register struct statfs *sp; 731 int error; 732 733 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 734 return (error); 735 mp = ((struct vnode *)fp->f_data)->v_mount; 736 sp = &mp->mnt_stat; 737 if (error = VFS_STATFS(mp, sp, p)) 738 return (error); 739 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 740 return sunstatfs(sp, (caddr_t)SCARG(uap, buf)); 741 } 742 743 int 744 sunos_exportfs(p, uap, retval) 745 struct proc *p; 746 struct sunos_exportfs_args *uap; 747 register_t *retval; 748 { 749 /* 750 * XXX: should perhaps translate into a mount(2) 751 * with MOUNT_EXPORT? 752 */ 753 return 0; 754 } 755 756 int 757 sunos_mknod(p, uap, retval) 758 struct proc *p; 759 struct sunos_mknod_args *uap; 760 register_t *retval; 761 { 762 if (S_ISFIFO(SCARG(uap, mode))) 763 return mkfifo(p, uap, retval); 764 765 return mknod(p, (struct mknod_args *)uap, retval); 766 } 767 768 #define SUNOS_SC_ARG_MAX 1 769 #define SUNOS_SC_CHILD_MAX 2 770 #define SUNOS_SC_CLK_TCK 3 771 #define SUNOS_SC_NGROUPS_MAX 4 772 #define SUNOS_SC_OPEN_MAX 5 773 #define SUNOS_SC_JOB_CONTROL 6 774 #define SUNOS_SC_SAVED_IDS 7 775 #define SUNOS_SC_VERSION 8 776 777 int 778 sunos_sysconf(p, uap, retval) 779 struct proc *p; 780 struct sunos_sysconf_args *uap; 781 register_t *retval; 782 { 783 extern int maxfiles; 784 785 switch(SCARG(uap, name)) { 786 case SUNOS_SC_ARG_MAX: 787 *retval = ARG_MAX; 788 break; 789 case SUNOS_SC_CHILD_MAX: 790 *retval = maxproc; 791 break; 792 case SUNOS_SC_CLK_TCK: 793 *retval = 60; /* should this be `hz', ie. 100? */ 794 break; 795 case SUNOS_SC_NGROUPS_MAX: 796 *retval = NGROUPS_MAX; 797 break; 798 case SUNOS_SC_OPEN_MAX: 799 *retval = maxfiles; 800 break; 801 case SUNOS_SC_JOB_CONTROL: 802 *retval = 1; 803 break; 804 case SUNOS_SC_SAVED_IDS: 805 #ifdef _POSIX_SAVED_IDS 806 *retval = 1; 807 #else 808 *retval = 0; 809 #endif 810 break; 811 case SUNOS_SC_VERSION: 812 *retval = 198808; 813 break; 814 default: 815 return EINVAL; 816 } 817 return 0; 818 } 819 820 #define SUNOS_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */ 821 #define SUNOS_RLIM_NLIMITS 7 822 823 int 824 sunos_getrlimit(p, uap, retval) 825 struct proc *p; 826 struct sunos_getrlimit_args *uap; 827 register_t *retval; 828 { 829 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS) 830 return EINVAL; 831 832 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE) 833 SCARG(uap, which) = RLIMIT_NOFILE; 834 835 return compat_43_getrlimit(p, uap, retval); 836 } 837 838 int 839 sunos_setrlimit(p, uap, retval) 840 struct proc *p; 841 struct sunos_getrlimit_args *uap; 842 register_t *retval; 843 { 844 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS) 845 return EINVAL; 846 847 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE) 848 SCARG(uap, which) = RLIMIT_NOFILE; 849 850 return compat_43_setrlimit(p, uap, retval); 851 } 852 853 /* for the m68k machines */ 854 #ifndef PT_GETFPREGS 855 #define PT_GETFPREGS -1 856 #endif 857 #ifndef PT_SETFPREGS 858 #define PT_SETFPREGS -1 859 #endif 860 861 static int sreq2breq[] = { 862 PT_TRACE_ME, PT_READ_I, PT_READ_D, -1, 863 PT_WRITE_I, PT_WRITE_D, -1, PT_CONTINUE, 864 PT_KILL, -1, PT_ATTACH, PT_DETACH, 865 PT_GETREGS, PT_SETREGS, PT_GETFPREGS, PT_SETFPREGS 866 }; 867 static int nreqs = sizeof(sreq2breq) / sizeof(sreq2breq[0]); 868 869 sunos_ptrace(p, uap, retval) 870 struct proc *p; 871 struct sunos_ptrace_args *uap; 872 int *retval; 873 { 874 struct ptrace_args pa; 875 int req; 876 877 req = SCARG(uap, req); 878 879 if (req < 0 || req >= nreqs) 880 return (EINVAL); 881 882 req = sreq2breq[req]; 883 if (req == -1) 884 return (EINVAL); 885 886 SCARG(&pa, req) = req; 887 SCARG(&pa, pid) = (pid_t)SCARG(uap, pid); 888 SCARG(&pa, addr) = (caddr_t)SCARG(uap, addr); 889 SCARG(&pa, data) = SCARG(uap, data); 890 891 return ptrace(p, &pa, retval); 892 } 893 894 static void 895 sunos_pollscan(p, pl, nfd, retval) 896 struct proc *p; 897 struct sunos_pollfd *pl; 898 int nfd; 899 register_t *retval; 900 { 901 register struct filedesc *fdp = p->p_fd; 902 register int msk, i; 903 struct file *fp; 904 int n = 0; 905 static int flag[3] = { FREAD, FWRITE, 0 }; 906 static int pflag[3] = { SUNOS_POLLIN|SUNOS_POLLRDNORM, 907 SUNOS_POLLOUT, SUNOS_POLLERR }; 908 909 /* 910 * XXX: We need to implement the rest of the flags. 911 */ 912 for (i = 0; i < nfd; i++) { 913 fp = fdp->fd_ofiles[pl[i].fd]; 914 if (fp == NULL) { 915 if (pl[i].events & SUNOS_POLLNVAL) { 916 pl[i].revents |= SUNOS_POLLNVAL; 917 n++; 918 } 919 continue; 920 } 921 for (msk = 0; msk < 3; msk++) { 922 if (pl[i].events & pflag[msk]) { 923 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 924 pl[i].revents |= 925 pflag[msk] & pl[i].events; 926 n++; 927 } 928 } 929 } 930 } 931 *retval = n; 932 } 933 934 935 /* 936 * We are using the same mechanism as select only we encode/decode args 937 * differently. 938 */ 939 int 940 sunos_poll(p, uap, retval) 941 struct proc *p; 942 struct sunos_poll_args *uap; 943 register_t *retval; 944 { 945 int i, s; 946 int error, error2; 947 size_t sz = sizeof(struct sunos_pollfd) * SCARG(uap, nfds); 948 struct sunos_pollfd *pl; 949 int msec = SCARG(uap, timeout); 950 struct timeval atv; 951 int timo; 952 u_int ni; 953 int ncoll; 954 extern int nselcoll, selwait; 955 956 pl = (struct sunos_pollfd *) malloc(sz, M_TEMP, M_WAITOK); 957 958 if (error = copyin(SCARG(uap, fds), pl, sz)) 959 goto bad; 960 961 for (i = 0; i < SCARG(uap, nfds); i++) 962 pl[i].revents = 0; 963 964 if (msec != -1) { 965 atv.tv_sec = msec / 1000; 966 atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000; 967 968 if (itimerfix(&atv)) { 969 error = EINVAL; 970 goto done; 971 } 972 s = splclock(); 973 timeradd(&atv, &time, &atv); 974 timo = hzto(&atv); 975 /* 976 * Avoid inadvertently sleeping forever. 977 */ 978 if (timo == 0) 979 timo = 1; 980 splx(s); 981 } else 982 timo = 0; 983 984 retry: 985 ncoll = nselcoll; 986 p->p_flag |= P_SELECT; 987 sunos_pollscan(p, pl, SCARG(uap, nfds), retval); 988 if (*retval) 989 goto done; 990 s = splhigh(); 991 if (timo && timercmp(&time, &atv, >=)) { 992 splx(s); 993 goto done; 994 } 995 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 996 splx(s); 997 goto retry; 998 } 999 p->p_flag &= ~P_SELECT; 1000 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "sunos_poll", timo); 1001 splx(s); 1002 if (error == 0) 1003 goto retry; 1004 1005 done: 1006 p->p_flag &= ~P_SELECT; 1007 /* poll is not restarted after signals... */ 1008 if (error == ERESTART) 1009 error = EINTR; 1010 if (error == EWOULDBLOCK) 1011 error = 0; 1012 1013 if (error2 = copyout(pl, SCARG(uap, fds), sz)) 1014 error = error2; 1015 1016 bad: 1017 free((char *) pl, M_TEMP); 1018 1019 return (error); 1020 } 1021 1022 /* 1023 * SunOS reboot system call (for compatibility). 1024 * Sun lets you pass in a boot string which the PROM 1025 * saves and provides to the next boot program. 1026 */ 1027 static struct sunos_howto_conv { 1028 int sun_howto; 1029 int bsd_howto; 1030 } sunos_howto_conv[] = { 1031 { 0x001, RB_ASKNAME }, 1032 { 0x002, RB_SINGLE }, 1033 { 0x004, RB_NOSYNC }, 1034 { 0x008, RB_HALT }, 1035 { 0x080, RB_DUMP }, 1036 { 0x000, 0 }, 1037 }; 1038 #define SUNOS_RB_STRING 0x200 1039 1040 int 1041 sunos_reboot(p, uap, retval) 1042 struct proc *p; 1043 struct sunos_reboot_args *uap; 1044 register_t *retval; 1045 { 1046 struct sunos_howto_conv *convp; 1047 int error, bsd_howto, sun_howto; 1048 1049 if (error = suser(p->p_ucred, &p->p_acflag)) 1050 return (error); 1051 1052 /* 1053 * Convert howto bits to BSD format. 1054 */ 1055 sun_howto = SCARG(uap, howto); 1056 bsd_howto = 0; 1057 convp = sunos_howto_conv; 1058 while (convp->sun_howto) { 1059 if (sun_howto & convp->sun_howto) 1060 bsd_howto |= convp->bsd_howto; 1061 convp++; 1062 } 1063 1064 #ifdef sun3 1065 /* 1066 * Sun RB_STRING (Get user supplied bootstring.) 1067 * If the machine supports passing a string to the 1068 * next booted kernel, add the machine name above 1069 * and provide a reboot2() function (see sun3). 1070 */ 1071 if (sun_howto & SUNOS_RB_STRING) { 1072 char bs[128]; 1073 1074 error = copyinstr(SCARG(uap, bootstr), bs, sizeof(bs), 0); 1075 if (error) 1076 return error; 1077 1078 return (reboot2(bsd_howto, bs)); 1079 } 1080 #endif /* sun3 */ 1081 1082 return (boot(bsd_howto)); 1083 } 1084