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