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