1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * $Id: ultrix_misc.c,v 1.2 1994/06/15 05:18:10 glass Exp $ 46 */ 47 48 /* 49 * SunOS compatibility module. 50 * 51 * SunOS system calls that are implemented differently in BSD are 52 * handled here. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/namei.h> 58 #include <ufs/dir.h> 59 #include <sys/proc.h> 60 #include <sys/file.h> 61 #include <sys/stat.h> 62 #include <sys/filedesc.h> 63 #include <sys/ioctl.h> 64 #include <sys/kernel.h> 65 #include <sys/exec.h> 66 #include <sys/malloc.h> 67 #include <sys/mbuf.h> 68 #include <sys/mman.h> 69 #include <sys/mount.h> 70 #include <sys/resource.h> 71 #include <sys/resourcevar.h> 72 #include <sys/signal.h> 73 #include <sys/signalvar.h> 74 #include <sys/socket.h> 75 #include <sys/vnode.h> 76 #include <sys/uio.h> 77 #include <sys/wait.h> 78 #include <sys/utsname.h> 79 #include <sys/unistd.h> 80 81 #include <netinet/in.h> 82 83 #include <miscfs/specfs/specdev.h> 84 85 #include <vm/vm.h> 86 87 struct ultrix_waitpid_args { 88 int pid; 89 int *status; 90 int options; 91 struct rusage *rusage; 92 }; 93 ultrix_waitpid(p, uap, retval) 94 struct proc *p; 95 struct ultrix_waitpid_args *uap; 96 int *retval; 97 { 98 99 uap->rusage = 0; 100 return (wait4(p, uap, retval)); 101 } 102 struct sun_wait4_args { 103 int pid; 104 int *status; 105 int options; 106 struct rusage *rusage; 107 int compat; 108 }; 109 sun_wait4(p, uap, retval) 110 struct proc *p; 111 struct sun_wait4_args *uap; 112 int *retval; 113 { 114 115 if (uap->pid == 0) 116 uap->pid = WAIT_ANY; 117 return (wait4(p, uap, retval)); 118 } 119 120 struct sun_wait3_args { 121 int *status; 122 int options; 123 struct rusage *rusage; 124 }; 125 126 sun_wait3(p, uap, retval) 127 struct proc *p; 128 struct sun_wait3_args *uap; 129 int *retval; 130 { 131 struct sun_wait4_args ua; 132 133 if (uap == NULL) 134 panic("uap == NULL"); 135 ua.pid = -1; 136 ua.status = uap->status; 137 ua.options = uap->options; 138 ua.rusage = uap->rusage; 139 140 return (wait4(p, &ua, retval)); 141 } 142 143 struct sun_creat_args { 144 char *fname; 145 int fmode; 146 }; 147 sun_creat(p, uap, retval) 148 struct proc *p; 149 struct sun_creat_args *uap; 150 int *retval; 151 { 152 struct args { 153 char *fname; 154 int mode; 155 int crtmode; 156 } openuap; 157 158 openuap.fname = uap->fname; 159 openuap.crtmode = uap->fmode; 160 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 161 return (open(p, &openuap, retval)); 162 } 163 164 struct sun_execv_args { 165 char *fname; 166 char **argp; 167 char **envp; /* pseudo */ 168 }; 169 sun_execv(p, uap, retval) 170 struct proc *p; 171 struct sun_execv_args *uap; 172 int *retval; 173 { 174 175 uap->envp = NULL; 176 return (execve(p, uap, retval)); 177 } 178 179 struct sun_omsync_args { 180 caddr_t addr; 181 int len; 182 int flags; 183 }; 184 sun_omsync(p, uap, retval) 185 struct proc *p; 186 struct sun_omsync_args *uap; 187 int *retval; 188 { 189 190 if (uap->flags) 191 return (EINVAL); 192 return (msync(p, uap, retval)); 193 } 194 195 struct sun_unmount_args { 196 char *name; 197 int flags; /* pseudo */ 198 }; 199 sun_unmount(p, uap, retval) 200 struct proc *p; 201 struct sun_unmount_args *uap; 202 int *retval; 203 { 204 205 uap->flags = 0; 206 return (unmount(p, uap, retval)); 207 } 208 209 #define SUNM_RDONLY 0x01 /* mount fs read-only */ 210 #define SUNM_NOSUID 0x02 /* mount fs with setuid disallowed */ 211 #define SUNM_NEWTYPE 0x04 /* type is string (char *), not int */ 212 #define SUNM_GRPID 0x08 /* (bsd semantics; ignored) */ 213 #define SUNM_REMOUNT 0x10 /* update existing mount */ 214 #define SUNM_NOSUB 0x20 /* prevent submounts (rejected) */ 215 #define SUNM_MULTI 0x40 /* (ignored) */ 216 #define SUNM_SYS5 0x80 /* Sys 5-specific semantics (rejected) */ 217 218 struct sun_nfs_args { 219 struct sockaddr_in *addr; /* file server address */ 220 caddr_t fh; /* file handle to be mounted */ 221 int flags; /* flags */ 222 int wsize; /* write size in bytes */ 223 int rsize; /* read size in bytes */ 224 int timeo; /* initial timeout in .1 secs */ 225 int retrans; /* times to retry send */ 226 char *hostname; /* server's hostname */ 227 int acregmin; /* attr cache file min secs */ 228 int acregmax; /* attr cache file max secs */ 229 int acdirmin; /* attr cache dir min secs */ 230 int acdirmax; /* attr cache dir max secs */ 231 char *netname; /* server's netname */ 232 struct pathcnf *pathconf; /* static pathconf kludge */ 233 }; 234 235 struct sun_mount_args { 236 char *type; 237 char *dir; 238 int flags; 239 caddr_t data; 240 }; 241 sun_mount(p, uap, retval) 242 struct proc *p; 243 struct sun_mount_args *uap; 244 int *retval; 245 { 246 int oflags = uap->flags, nflags, error; 247 extern char sigcode[], esigcode[]; 248 char fsname[MFSNAMELEN]; 249 250 #define szsigcode (esigcode - sigcode) 251 252 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 253 return (EINVAL); 254 if ((oflags & SUNM_NEWTYPE) == 0) 255 return (EINVAL); 256 nflags = 0; 257 if (oflags & SUNM_RDONLY) 258 nflags |= MNT_RDONLY; 259 if (oflags & SUNM_NOSUID) 260 nflags |= MNT_NOSUID; 261 if (oflags & SUNM_REMOUNT) 262 nflags |= MNT_UPDATE; 263 uap->flags = nflags; 264 265 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, (u_int *)0)) 266 return (error); 267 268 if (strcmp(fsname, "4.2") == 0) { 269 uap->type = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 270 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 271 return (error); 272 } else if (strcmp(fsname, "nfs") == 0) { 273 struct sun_nfs_args sna; 274 struct sockaddr_in sain; 275 struct nfs_args na; 276 struct sockaddr sa; 277 278 if (error = copyin(uap->data, &sna, sizeof sna)) 279 return (error); 280 if (error = copyin(sna.addr, &sain, sizeof sain)) 281 return (error); 282 bcopy(&sain, &sa, sizeof sa); 283 sa.sa_len = sizeof(sain); 284 uap->data = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 285 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 286 na.sotype = SOCK_DGRAM; 287 na.proto = IPPROTO_UDP; 288 na.fh = (nfsv2fh_t *)sna.fh; 289 na.flags = sna.flags; 290 na.wsize = sna.wsize; 291 na.rsize = sna.rsize; 292 na.timeo = sna.timeo; 293 na.retrans = sna.retrans; 294 na.hostname = sna.hostname; 295 296 if (error = copyout(&sa, na.addr, sizeof sa)) 297 return (error); 298 if (error = copyout(&na, uap->data, sizeof na)) 299 return (error); 300 } 301 return (mount(p, uap, retval)); 302 } 303 304 struct sun_sigpending_args { 305 int *mask; 306 }; 307 sun_sigpending(p, uap, retval) 308 struct proc *p; 309 struct sun_sigpending_args *uap; 310 int *retval; 311 { 312 int mask = p->p_siglist & p->p_sigmask; 313 314 return (copyout((caddr_t)&mask, (caddr_t)uap->mask, sizeof(int))); 315 } 316 317 /* XXX: Temporary until sys/dir.h, include/dirent.h and sys/dirent.h are fixed */ 318 struct dirent { 319 u_long d_fileno; /* file number of entry */ 320 u_short d_reclen; /* length of this record */ 321 u_short d_namlen; /* length of string in d_name */ 322 char d_name[255 + 1]; /* name must be no longer than this */ 323 }; 324 325 /* 326 * Here is the sun layout. (Compare the BSD layout in <sys/dirent.h>.) 327 * We can assume big-endian, so the BSD d_type field is just the high 328 * byte of the SunOS d_namlen field, after adjusting for the extra "long". 329 */ 330 struct sun_dirent { 331 long d_off; 332 u_long d_fileno; 333 u_short d_reclen; 334 u_short d_namlen; 335 char d_name[256]; 336 }; 337 338 /* 339 * Read Sun-style directory entries. We suck them into kernel space so 340 * that they can be massaged before being copied out to user code. Like 341 * SunOS, we squish out `empty' entries. 342 * 343 * This is quite ugly, but what do you expect from compatibility code? 344 */ 345 struct sun_getdents_args { 346 int fd; 347 char *buf; 348 int nbytes; 349 }; 350 sun_getdents(p, uap, retval) 351 struct proc *p; 352 register struct sun_getdents_args *uap; 353 int *retval; 354 { 355 register struct vnode *vp; 356 register caddr_t inp, buf; /* BSD-format */ 357 register int len, reclen; /* BSD-format */ 358 register caddr_t outp; /* Sun-format */ 359 register int resid; /* Sun-format */ 360 struct file *fp; 361 struct uio auio; 362 struct iovec aiov; 363 off_t off; /* true file offset */ 364 long soff; /* Sun file offset */ 365 int buflen, error, eofflag; 366 #define BSD_DIRENT(cp) ((struct dirent *)(cp)) 367 #define SUN_RECLEN(reclen) (reclen + sizeof(long)) 368 369 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 370 return (error); 371 if ((fp->f_flag & FREAD) == 0) 372 return (EBADF); 373 vp = (struct vnode *)fp->f_data; 374 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ 375 return (EINVAL); 376 buflen = min(MAXBSIZE, uap->nbytes); 377 buf = malloc(buflen, M_TEMP, M_WAITOK); 378 VOP_LOCK(vp); 379 off = fp->f_offset; 380 again: 381 aiov.iov_base = buf; 382 aiov.iov_len = buflen; 383 auio.uio_iov = &aiov; 384 auio.uio_iovcnt = 1; 385 auio.uio_rw = UIO_READ; 386 auio.uio_segflg = UIO_SYSSPACE; 387 auio.uio_procp = p; 388 auio.uio_resid = buflen; 389 auio.uio_offset = off; 390 /* 391 * First we read into the malloc'ed buffer, then 392 * we massage it into user space, one record at a time. 393 */ 394 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, 0)) 395 goto out; 396 inp = buf; 397 outp = uap->buf; 398 resid = uap->nbytes; 399 if ((len = buflen - auio.uio_resid) == 0) 400 goto eof; 401 for (; len > 0; len -= reclen) { 402 reclen = ((struct dirent *)inp)->d_reclen; 403 if (reclen & 3) 404 panic("sun_getdents"); 405 off += reclen; /* each entry points to next */ 406 if (BSD_DIRENT(inp)->d_fileno == 0) { 407 inp += reclen; /* it is a hole; squish it out */ 408 continue; 409 } 410 if (reclen > len || resid < SUN_RECLEN(reclen)) { 411 /* entry too big for buffer, so just stop */ 412 outp++; 413 break; 414 } 415 /* 416 * Massage in place to make a Sun-shaped dirent (otherwise 417 * we have to worry about touching user memory outside of 418 * the copyout() call). 419 */ 420 BSD_DIRENT(inp)->d_reclen = SUN_RECLEN(reclen); 421 #if notdef 422 BSD_DIRENT(inp)->d_type = 0; /* 4.4 specific */ 423 #endif 424 soff = off; 425 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 || 426 (error = copyout(inp, outp + sizeof soff, reclen)) != 0) 427 goto out; 428 /* advance past this real entry */ 429 inp += reclen; 430 /* advance output past Sun-shaped entry */ 431 outp += SUN_RECLEN(reclen); 432 resid -= SUN_RECLEN(reclen); 433 } 434 /* if we squished out the whole block, try again */ 435 if (outp == uap->buf) 436 goto again; 437 fp->f_offset = off; /* update the vnode offset */ 438 eof: 439 *retval = uap->nbytes - resid; 440 out: 441 VOP_UNLOCK(vp); 442 free(buf, M_TEMP); 443 return (error); 444 } 445 446 #define SUN__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */ 447 448 struct sun_mmap_args { 449 caddr_t addr; 450 size_t len; 451 int prot; 452 int flags; 453 int fd; 454 long off; /* not off_t! */ 455 off_t qoff; /* created here and fed to mmap() */ 456 }; 457 sun_mmap(p, uap, retval) 458 register struct proc *p; 459 register struct sun_mmap_args *uap; 460 int *retval; 461 { 462 register struct filedesc *fdp; 463 register struct file *fp; 464 register struct vnode *vp; 465 466 /* 467 * Verify the arguments. 468 */ 469 if (uap->prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC)) 470 return (EINVAL); /* XXX still needed? */ 471 472 if ((uap->flags & SUN__MAP_NEW) == 0) 473 return (EINVAL); 474 uap->flags &= ~SUN__MAP_NEW; 475 476 if ((uap->flags & MAP_FIXED) == 0 && 477 uap->addr != 0 && 478 uap->addr < (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ)) 479 uap->addr = (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ); 480 481 /* 482 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX) 483 */ 484 fdp = p->p_fd; 485 if ((unsigned)uap->fd < fdp->fd_nfiles && /*XXX*/ 486 (fp = fdp->fd_ofiles[uap->fd]) != NULL && /*XXX*/ 487 fp->f_type == DTYPE_VNODE && /*XXX*/ 488 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/ 489 iszerodev(vp->v_rdev)) { /*XXX*/ 490 uap->flags |= MAP_ANON; 491 uap->fd = -1; 492 } 493 494 uap->qoff = uap->off; 495 return (mmap(p, uap, retval)); 496 } 497 498 #define MC_SYNC 1 499 #define MC_LOCK 2 500 #define MC_UNLOCK 3 501 #define MC_ADVISE 4 502 #define MC_LOCKAS 5 503 #define MC_UNLOCKAS 6 504 505 struct sun_mctl_args { 506 caddr_t addr; 507 size_t len; 508 int func; 509 void *arg; 510 }; 511 sun_mctl(p, uap, retval) 512 register struct proc *p; 513 register struct sun_mctl_args *uap; 514 int *retval; 515 { 516 517 switch (uap->func) { 518 519 case MC_ADVISE: /* ignore for now */ 520 return (0); 521 522 case MC_SYNC: /* translate to msync */ 523 return (msync(p, uap, retval)); 524 525 default: 526 return (EINVAL); 527 } 528 } 529 530 struct sun_setsockopt_args { 531 int s; 532 int level; 533 int name; 534 caddr_t val; 535 int valsize; 536 }; 537 sun_setsockopt(p, uap, retval) 538 struct proc *p; 539 register struct sun_setsockopt_args *uap; 540 int *retval; 541 { 542 struct file *fp; 543 struct mbuf *m = NULL; 544 int error; 545 546 if (error = getsock(p->p_fd, uap->s, &fp)) 547 return (error); 548 #define SO_DONTLINGER (~SO_LINGER) 549 if (uap->name == SO_DONTLINGER) { 550 m = m_get(M_WAIT, MT_SOOPTS); 551 if (m == NULL) 552 return (ENOBUFS); 553 mtod(m, struct linger *)->l_onoff = 0; 554 m->m_len = sizeof(struct linger); 555 return (sosetopt((struct socket *)fp->f_data, uap->level, 556 SO_LINGER, m)); 557 } 558 if (uap->valsize > MLEN) 559 return (EINVAL); 560 if (uap->val) { 561 m = m_get(M_WAIT, MT_SOOPTS); 562 if (m == NULL) 563 return (ENOBUFS); 564 if (error = copyin(uap->val, mtod(m, caddr_t), 565 (u_int)uap->valsize)) { 566 (void) m_free(m); 567 return (error); 568 } 569 m->m_len = uap->valsize; 570 } 571 return (sosetopt((struct socket *)fp->f_data, uap->level, 572 uap->name, m)); 573 } 574 575 struct sun_fchroot_args { 576 int fdes; 577 }; 578 sun_fchroot(p, uap, retval) 579 register struct proc *p; 580 register struct sun_fchroot_args *uap; 581 int *retval; 582 { 583 register struct filedesc *fdp = p->p_fd; 584 register struct vnode *vp; 585 struct file *fp; 586 int error; 587 588 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 589 return (error); 590 if ((error = getvnode(fdp, uap->fdes, &fp)) != 0) 591 return (error); 592 vp = (struct vnode *)fp->f_data; 593 VOP_LOCK(vp); 594 if (vp->v_type != VDIR) 595 error = ENOTDIR; 596 else 597 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 598 VOP_UNLOCK(vp); 599 if (error) 600 return (error); 601 VREF(vp); 602 if (fdp->fd_rdir != NULL) 603 vrele(fdp->fd_rdir); 604 fdp->fd_rdir = vp; 605 return (0); 606 } 607 608 /* 609 * XXX: This needs cleaning up. 610 */ 611 sun_auditsys(...) 612 { 613 return 0; 614 } 615 616 struct sun_utsname { 617 char sysname[9]; 618 char nodename[9]; 619 char nodeext[65-9]; 620 char release[9]; 621 char version[9]; 622 char machine[9]; 623 }; 624 625 struct sun_uname_args { 626 struct sun_utsname *name; 627 }; 628 sun_uname(p, uap, retval) 629 struct proc *p; 630 struct sun_uname_args *uap; 631 int *retval; 632 { 633 struct sun_utsname sut; 634 extern char ostype[], machine[], osrelease[]; 635 636 bzero(&sut, sizeof(sut)); 637 638 bcopy(ostype, sut.sysname, sizeof(sut.sysname) - 1); 639 bcopy(hostname, sut.nodename, sizeof(sut.nodename)); 640 sut.nodename[sizeof(sut.nodename)-1] = '\0'; 641 bcopy(osrelease, sut.release, sizeof(sut.release) - 1); 642 bcopy("1", sut.version, sizeof(sut.version) - 1); 643 bcopy(machine, sut.machine, sizeof(sut.machine) - 1); 644 645 return copyout((caddr_t)&sut, (caddr_t)uap->name, sizeof(struct sun_utsname)); 646 } 647 648 struct sun_setpgid_args { 649 int pid; /* target process id */ 650 int pgid; /* target pgrp id */ 651 }; 652 int 653 sun_setpgid(p, uap, retval) 654 struct proc *p; 655 struct sun_setpgid_args *uap; 656 int *retval; 657 { 658 /* 659 * difference to our setpgid call is to include backwards 660 * compatibility to pre-setsid() binaries. Do setsid() 661 * instead of setpgid() in those cases where the process 662 * tries to create a new session the old way. 663 */ 664 if (!uap->pgid && (!uap->pid || uap->pid == p->p_pid)) 665 return setsid(p, uap, retval); 666 else 667 return setpgid(p, uap, retval); 668 } 669 670 struct sun_open_args { 671 char *fname; 672 int fmode; 673 int crtmode; 674 }; 675 sun_open(p, uap, retval) 676 struct proc *p; 677 struct sun_open_args *uap; 678 int *retval; 679 { 680 int l, r; 681 int noctty = uap->fmode & 0x8000; 682 int ret; 683 684 /* convert mode into NetBSD mode */ 685 l = uap->fmode; 686 r = (l & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800)); 687 r |= ((l & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0); 688 r |= ((l & 0x0080) ? O_SHLOCK : 0); 689 r |= ((l & 0x0100) ? O_EXLOCK : 0); 690 r |= ((l & 0x2000) ? O_FSYNC : 0); 691 692 uap->fmode = r; 693 ret = open(p, uap, retval); 694 695 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 696 struct filedesc *fdp = p->p_fd; 697 struct file *fp = fdp->fd_ofiles[*retval]; 698 699 /* ignore any error, just give it a try */ 700 if (fp->f_type == DTYPE_VNODE) 701 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 702 } 703 return ret; 704 } 705 706 #if defined (NFSSERVER) 707 struct nfssvc_args { 708 int fd; 709 caddr_t mskval; 710 int msklen; 711 caddr_t mtchval; 712 int mtchlen; 713 }; 714 struct sun_nfssvc_args { 715 int fd; 716 }; 717 sun_nfssvc(p, uap, retval) 718 struct proc *p; 719 struct sun_nfssvc_args *uap; 720 int *retval; 721 { 722 struct nfssvc_args outuap; 723 struct sockaddr sa; 724 int error; 725 extern char sigcode[], esigcode[]; 726 727 bzero(&outuap, sizeof outuap); 728 outuap.fd = uap->fd; 729 outuap.mskval = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 730 outuap.msklen = sizeof sa; 731 outuap.mtchval = outuap.mskval + sizeof sa; 732 outuap.mtchlen = sizeof sa; 733 734 bzero(&sa, sizeof sa); 735 if (error = copyout(&sa, outuap.mskval, outuap.msklen)) 736 return (error); 737 if (error = copyout(&sa, outuap.mtchval, outuap.mtchlen)) 738 return (error); 739 740 return nfssvc(p, &outuap, retval); 741 } 742 #endif /* NFSSERVER */ 743 744 struct sun_ustat { 745 daddr_t f_tfree; /* total free */ 746 ino_t f_tinode; /* total inodes free */ 747 char f_fname[6]; /* filsys name */ 748 char f_fpack[6]; /* filsys pack name */ 749 }; 750 struct sun_ustat_args { 751 int dev; 752 struct sun_ustat *buf; 753 }; 754 sun_ustat(p, uap, retval) 755 struct proc *p; 756 struct sun_ustat_args *uap; 757 int *retval; 758 { 759 struct sun_ustat us; 760 int error; 761 762 bzero(&us, sizeof us); 763 764 /* 765 * XXX: should set f_tfree and f_tinode at least 766 * How do we translate dev -> fstat? (and then to sun_ustat) 767 */ 768 769 if (error = copyout(&us, uap->buf, sizeof us)) 770 return (error); 771 return 0; 772 } 773 774 struct sun_quotactl_args { 775 int cmd; 776 char *special; 777 int uid; 778 caddr_t addr; 779 }; 780 sun_quotactl(p, uap, retval) 781 struct proc *p; 782 struct sun_quotactl_args *uap; 783 int *retval; 784 { 785 return EINVAL; 786 } 787 788 sun_vhangup(p, uap, retval) 789 struct proc *p; 790 void *uap; 791 int *retval; 792 { 793 return 0; 794 } 795 796 struct sun_statfs { 797 long f_type; /* type of info, zero for now */ 798 long f_bsize; /* fundamental file system block size */ 799 long f_blocks; /* total blocks in file system */ 800 long f_bfree; /* free blocks */ 801 long f_bavail; /* free blocks available to non-super-user */ 802 long f_files; /* total file nodes in file system */ 803 long f_ffree; /* free file nodes in fs */ 804 fsid_t f_fsid; /* file system id */ 805 long f_spare[7]; /* spare for later */ 806 }; 807 static 808 sunstatfs(sp, buf) 809 struct statfs *sp; 810 caddr_t buf; 811 { 812 struct sun_statfs ssfs; 813 814 bzero(&ssfs, sizeof ssfs); 815 ssfs.f_type = 0; 816 ssfs.f_bsize = sp->f_bsize; 817 ssfs.f_blocks = sp->f_blocks; 818 ssfs.f_bfree = sp->f_bfree; 819 ssfs.f_bavail = sp->f_bavail; 820 ssfs.f_files = sp->f_files; 821 ssfs.f_ffree = sp->f_ffree; 822 ssfs.f_fsid = sp->f_fsid; 823 return copyout((caddr_t)&ssfs, buf, sizeof ssfs); 824 } 825 826 struct sun_statfs_args { 827 char *path; 828 struct sun_statfs *buf; 829 }; 830 sun_statfs(p, uap, retval) 831 struct proc *p; 832 struct sun_statfs_args *uap; 833 int *retval; 834 { 835 register struct mount *mp; 836 register struct nameidata *ndp; 837 register struct statfs *sp; 838 int error; 839 struct nameidata nd; 840 841 ndp = &nd; 842 ndp->ni_nameiop = LOOKUP | FOLLOW; 843 ndp->ni_segflg = UIO_USERSPACE; 844 ndp->ni_dirp = uap->path; 845 if (error = namei(ndp, p)) 846 return (error); 847 mp = ndp->ni_vp->v_mount; 848 sp = &mp->mnt_stat; 849 vrele(ndp->ni_vp); 850 if (error = VFS_STATFS(mp, sp, p)) 851 return (error); 852 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 853 return sunstatfs(sp, (caddr_t)uap->buf); 854 } 855 856 struct sun_fstatfs_args { 857 int fd; 858 struct sun_statfs *buf; 859 }; 860 sun_fstatfs(p, uap, retval) 861 struct proc *p; 862 struct sun_fstatfs_args *uap; 863 int *retval; 864 { 865 struct file *fp; 866 struct mount *mp; 867 register struct statfs *sp; 868 int error; 869 870 if (error = getvnode(p->p_fd, uap->fd, &fp)) 871 return (error); 872 mp = ((struct vnode *)fp->f_data)->v_mount; 873 sp = &mp->mnt_stat; 874 if (error = VFS_STATFS(mp, sp, p)) 875 return (error); 876 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 877 return sunstatfs(sp, (caddr_t)uap->buf); 878 } 879 880 struct sun_exportfs_args { 881 char *path; 882 char *ex; /* struct sun_export * */ 883 }; 884 sun_exportfs(p, uap, retval) 885 struct proc *p; 886 struct sun_exportfs_args *uap; 887 int *retval; 888 { 889 /* 890 * XXX: should perhaps translate into a mount(2) 891 * with MOUNT_EXPORT? 892 */ 893 return 0; 894 } 895 896 struct sun_mknod_args { 897 char *fname; 898 int fmode; 899 int dev; 900 }; 901 902 sun_mknod(p, uap, retval) 903 struct proc *p; 904 struct sun_mknod_args *uap; 905 int *retval; 906 { 907 if (S_ISFIFO(uap->fmode)) 908 return mkfifo(p, uap, retval); 909 910 return mknod(p, uap, retval); 911 } 912 913 #define SUN_SC_ARG_MAX 1 914 #define SUN_SC_CHILD_MAX 2 915 #define SUN_SC_CLK_TCK 3 916 #define SUN_SC_NGROUPS_MAX 4 917 #define SUN_SC_OPEN_MAX 5 918 #define SUN_SC_JOB_CONTROL 6 919 #define SUN_SC_SAVED_IDS 7 920 #define SUN_SC_VERSION 8 921 922 struct sun_sysconf_args { 923 int name; 924 }; 925 926 sun_sysconf(p, uap, retval) 927 struct proc *p; 928 struct sun_sysconf_args *uap; 929 int *retval; 930 { 931 extern int maxfiles; 932 933 switch(uap->name) { 934 case SUN_SC_ARG_MAX: 935 *retval = ARG_MAX; 936 break; 937 case SUN_SC_CHILD_MAX: 938 *retval = maxproc; 939 break; 940 case SUN_SC_CLK_TCK: 941 *retval = 60; /* should this be `hz', ie. 100? */ 942 break; 943 case SUN_SC_NGROUPS_MAX: 944 *retval = NGROUPS_MAX; 945 break; 946 case SUN_SC_OPEN_MAX: 947 *retval = maxfiles; 948 break; 949 case SUN_SC_JOB_CONTROL: 950 *retval = 1; 951 break; 952 case SUN_SC_SAVED_IDS: 953 #ifdef _POSIX_SAVED_IDS 954 *retval = 1; 955 #else 956 *retval = 0; 957 #endif 958 break; 959 case SUN_SC_VERSION: 960 *retval = 198808; 961 break; 962 default: 963 return EINVAL; 964 } 965 return 0; 966 } 967 968 #define SUN_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */ 969 #define SUN_RLIM_NLIMITS 7 970 971 struct sun_getrlimit_args { 972 int which; 973 struct orlimit *rlp; 974 }; 975 976 sun_getrlimit(p, uap, retval) 977 struct proc *p; 978 struct sun_getrlimit_args *uap; 979 int *retval; 980 { 981 if (uap->which >= SUN_RLIM_NLIMITS) 982 return EINVAL; 983 984 if (uap->which == SUN_RLIMIT_NOFILE) 985 uap->which = RLIMIT_NOFILE; 986 987 return ogetrlimit(p, uap, retval); 988 } 989 990 struct sun_setrlimit_args { 991 int which; 992 struct orlimit *rlp; 993 }; 994 995 sun_setrlimit(p, uap, retval) 996 struct proc *p; 997 struct sun_getrlimit_args *uap; 998 int *retval; 999 { 1000 if (uap->which >= SUN_RLIM_NLIMITS) 1001 return EINVAL; 1002 1003 if (uap->which == SUN_RLIMIT_NOFILE) 1004 uap->which = RLIMIT_NOFILE; 1005 1006 return osetrlimit(p, uap, retval); 1007 } 1008