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  *	%sccs.include.redist.c%
10  *
11  *	@(#)news_compat.c	8.2 (Berkeley) 05/14/95
12  *
13  * from: $Hdr: sun_misc.c,v 1.12 92/07/12 13:26:10 torek Exp $
14  */
15 
16 /*
17  * NEWS-OS compatibility module.
18  *
19  * NEWS-OS system calls that are implemented differently in BSD are
20  * handled here.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/proc.h>
26 #include <sys/file.h>
27 #include <sys/filedesc.h>
28 #include <sys/ioctl.h>
29 #include <sys/malloc.h>
30 #include <sys/mbuf.h>
31 #include <sys/mman.h>
32 #include <sys/mount.h>
33 #include <sys/resource.h>
34 #include <sys/resourcevar.h>
35 #include <sys/signal.h>
36 #include <sys/signalvar.h>
37 #include <sys/socket.h>
38 #include <sys/vnode.h>
39 #include <sys/uio.h>
40 #include <sys/wait.h>
41 
42 #include <miscfs/specfs/specdev.h>
43 
44 #include <vm/vm.h>
45 
46 #if 0
47 /* here is the sun layout (not used directly): */
48 struct sun_dirent {
49 	long	d_off;
50 	u_long	d_fileno;
51 	u_short	d_reclen;
52 	u_short	d_namlen;
53 	char	d_name[256];
54 };
55 #endif
56 /* and the BSD layout: */
57 struct bsd_dirent {
58 	u_long	d_fileno;
59 	u_short	d_reclen;
60 	u_short	d_namlen;
61 	char	d_name[256];
62 };
63 
64 /*
65  * Read Sun-style directory entries.  We suck them into kernel space so
66  * that they can be massaged before being copied out to user code.  Like
67  * SunOS, we squish out `empty' entries.
68  *
69  * This is quite ugly, but what do you expect from compatibility code?
70  */
71 struct sun_getdents_args {
72 	int	fd;
73 	char	*buf;
74 	int	nbytes;
75 };
76 sun_getdents(p, uap, retval)
77 	struct proc *p;
78 	register struct sun_getdents_args *uap;
79 	int *retval;
80 {
81 	register struct vnode *vp;
82 	register caddr_t inp, buf;	/* BSD-format */
83 	register int len, reclen;	/* BSD-format */
84 	register caddr_t outp;		/* Sun-format */
85 	register int resid;		/* Sun-format */
86 	struct file *fp;
87 	struct uio auio;
88 	struct iovec aiov;
89 	off_t off;			/* true file offset */
90 	long soff;			/* Sun file offset */
91 	int buflen, error, eofflag;
92 #define	SUN_RECLEN(reclen) (reclen + sizeof(long))
93 
94 	if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0)
95 		return (error);
96 	if ((fp->f_flag & FREAD) == 0)
97 		return (EBADF);
98 	vp = (struct vnode *)fp->f_data;
99 	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
100 		return (EINVAL);
101 	buflen = min(MAXBSIZE, uap->nbytes);
102 	buf = malloc(buflen, M_TEMP, M_WAITOK);
103 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p)
104 	off = fp->f_offset;
105 again:
106 	aiov.iov_base = buf;
107 	aiov.iov_len = buflen;
108 	auio.uio_iov = &aiov;
109 	auio.uio_iovcnt = 1;
110 	auio.uio_rw = UIO_READ;
111 	auio.uio_segflg = UIO_SYSSPACE;
112 	auio.uio_procp = p;
113 	auio.uio_resid = buflen;
114 	auio.uio_offset = off;
115 	/*
116 	 * First we read into the malloc'ed buffer, then
117 	 * we massage it into user space, one record at a time.
118 	 */
119 	if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag))
120 		goto out;
121 	inp = buf;
122 	outp = uap->buf;
123 	resid = uap->nbytes;
124 	if ((len = buflen - auio.uio_resid) == 0)
125 		goto eof;
126 	for (; len > 0; len -= reclen) {
127 		reclen = ((struct bsd_dirent *)inp)->d_reclen;
128 		if (reclen & 3)
129 			panic("sun_getdents");
130 		off += reclen;		/* each entry points to next */
131 		if (((struct bsd_dirent *)inp)->d_fileno == 0) {
132 			inp += reclen;	/* it is a hole; squish it out */
133 			continue;
134 		}
135 		if (reclen > len || resid < SUN_RECLEN(reclen)) {
136 			/* entry too big for buffer, so just stop */
137 			outp++;
138 			break;
139 		}
140 		/* copy out a Sun-shaped dirent */
141 		((struct bsd_dirent *)inp)->d_reclen = SUN_RECLEN(reclen);
142 		soff = off;
143 		if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 ||
144 		    (error = copyout(inp, outp + sizeof soff, reclen)) != 0)
145 			goto out;
146 		/* advance past this real entry */
147 		inp += reclen;
148 		/* advance output past Sun-shaped entry */
149 		outp += SUN_RECLEN(reclen);
150 		resid -= SUN_RECLEN(reclen);
151 	}
152 	/* if we squished out the whole block, try again */
153 	if (outp == uap->buf)
154 		goto again;
155 	fp->f_offset = off;		/* update the vnode offset */
156 eof:
157 	*retval = uap->nbytes - resid;
158 out:
159 	VOP_UNLOCK(vp, 0, p);
160 	free(buf, M_TEMP);
161 	return (error);
162 }
163 
164 #define	MAXDOMAINNAME	64
165 char	sun_domainname[MAXDOMAINNAME];
166 int	sun_domainnamelen = 1;
167 
168 struct sun_getdomainname_args {
169 	char	*name;
170 	int	namelen;
171 };
172 sun_getdomainname(p, uap, retval)
173 	struct proc *p;
174 	struct sun_getdomainname_args *uap;
175 	int *retval;
176 {
177 	register int l = min(uap->namelen, sun_domainnamelen + 1);
178 
179 	return (copyout(sun_domainname, uap->name, l));
180 }
181 
182 struct sun_setdomainname_args {
183 	char	*name;
184 	int	namelen;
185 };
186 sun_setdomainname(p, uap, retval)
187 	struct proc *p;
188 	struct sun_setdomainname_args *uap;
189 	int *retval;
190 {
191 	register int l = uap->namelen, error;
192 
193 	if (l >= MAXDOMAINNAME)
194 		return (EINVAL);	/* ??? ENAMETOOLONG? */
195 	if (error = suser(p->p_ucred, &p->p_acflag))
196 		return (error);
197 	if (error = copyin(uap->name, sun_domainname, l))
198 		return (error);
199 	sun_domainname[l] = 0;
200 	return (0);
201 }
202 
203 /*
204  * setenvp system call
205  */
206 struct news_setenvp_args {
207 	char	**envp;
208 };
209 news_setenvp(p, args, retval)
210 	struct proc *p;
211 	struct news_setenvp_args *args;
212 	int *retval;
213 {
214 
215 	return (0);
216 }
217 
218 /*
219  * sysnews system call
220  */
221 struct news_sysnews_args {
222 	int	ctrltype;
223 	int	arg1, arg2, arg3, arg4;
224 };
225 news_sysnews(p, args, retval)
226 	struct proc *p;
227 	struct news_sysnews_args *args;
228 	int *retval;
229 {
230 
231 	return (0);
232 }
233