xref: /csrg-svn/sys/kern/sys_generic.c (revision 17593)
1 /*	sys_generic.c	6.6	84/12/27	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "dir.h"
6 #include "user.h"
7 #include "ioctl.h"
8 #include "file.h"
9 #include "proc.h"
10 #include "uio.h"
11 #include "kernel.h"
12 #include "stat.h"
13 
14 /*
15  * Read system call.
16  */
17 read()
18 {
19 	register struct a {
20 		int	fdes;
21 		char	*cbuf;
22 		unsigned count;
23 	} *uap = (struct a *)u.u_ap;
24 	struct uio auio;
25 	struct iovec aiov;
26 
27 	aiov.iov_base = (caddr_t)uap->cbuf;
28 	aiov.iov_len = uap->count;
29 	auio.uio_iov = &aiov;
30 	auio.uio_iovcnt = 1;
31 	rwuio(&auio, UIO_READ);
32 }
33 
34 readv()
35 {
36 	register struct a {
37 		int	fdes;
38 		struct	iovec *iovp;
39 		int	iovcnt;
40 	} *uap = (struct a *)u.u_ap;
41 	struct uio auio;
42 	struct iovec aiov[16];		/* XXX */
43 
44 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
45 		u.u_error = EINVAL;
46 		return;
47 	}
48 	auio.uio_iov = aiov;
49 	auio.uio_iovcnt = uap->iovcnt;
50 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
51 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
52 	if (u.u_error)
53 		return;
54 	rwuio(&auio, UIO_READ);
55 }
56 
57 /*
58  * Write system call
59  */
60 write()
61 {
62 	register struct a {
63 		int	fdes;
64 		char	*cbuf;
65 		int	count;
66 	} *uap = (struct a *)u.u_ap;
67 	struct uio auio;
68 	struct iovec aiov;
69 
70 	auio.uio_iov = &aiov;
71 	auio.uio_iovcnt = 1;
72 	aiov.iov_base = uap->cbuf;
73 	aiov.iov_len = uap->count;
74 	rwuio(&auio, UIO_WRITE);
75 }
76 
77 writev()
78 {
79 	register struct a {
80 		int	fdes;
81 		struct	iovec *iovp;
82 		int	iovcnt;
83 	} *uap = (struct a *)u.u_ap;
84 	struct uio auio;
85 	struct iovec aiov[16];		/* XXX */
86 
87 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
88 		u.u_error = EINVAL;
89 		return;
90 	}
91 	auio.uio_iov = aiov;
92 	auio.uio_iovcnt = uap->iovcnt;
93 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
94 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
95 	if (u.u_error)
96 		return;
97 	rwuio(&auio, UIO_WRITE);
98 }
99 
100 rwuio(uio, rw)
101 	register struct uio *uio;
102 	enum uio_rw rw;
103 {
104 	struct a {
105 		int	fdes;
106 	};
107 	register struct file *fp;
108 	register struct iovec *iov;
109 	int i, count;
110 
111 	GETF(fp, ((struct a *)u.u_ap)->fdes);
112 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
113 		u.u_error = EBADF;
114 		return;
115 	}
116 	uio->uio_resid = 0;
117 	uio->uio_segflg = UIO_USERSPACE;
118 	iov = uio->uio_iov;
119 	for (i = 0; i < uio->uio_iovcnt; i++) {
120 		if (iov->iov_len < 0) {
121 			u.u_error = EINVAL;
122 			return;
123 		}
124 		uio->uio_resid += iov->iov_len;
125 		if (uio->uio_resid < 0) {
126 			u.u_error = EINVAL;
127 			return;
128 		}
129 		iov++;
130 	}
131 	count = uio->uio_resid;
132 	uio->uio_offset = fp->f_offset;
133 	if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
134 		if (uio->uio_resid == count)
135 			u.u_eosys = RESTARTSYS;
136 	} else
137 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
138 	u.u_r.r_val1 = count - uio->uio_resid;
139 	fp->f_offset += u.u_r.r_val1;
140 }
141 
142 /*
143  * Ioctl system call
144  */
145 ioctl()
146 {
147 	register struct file *fp;
148 	struct a {
149 		int	fdes;
150 		int	cmd;
151 		caddr_t	cmarg;
152 	} *uap;
153 	register int com;
154 	register u_int size;
155 	char data[IOCPARM_MASK+1];
156 
157 	uap = (struct a *)u.u_ap;
158 	GETF(fp, uap->fdes);
159 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
160 		u.u_error = EBADF;
161 		return;
162 	}
163 	com = uap->cmd;
164 
165 #if defined(vax) && defined(COMPAT)
166 	/*
167 	 * Map old style ioctl's into new for the
168 	 * sake of backwards compatibility (sigh).
169 	 */
170 	if ((com&~0xffff) == 0) {
171 		com = mapioctl(com);
172 		if (com == 0) {
173 			u.u_error = EINVAL;
174 			return;
175 		}
176 	}
177 #endif
178 	if (com == FIOCLEX) {
179 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
180 		return;
181 	}
182 	if (com == FIONCLEX) {
183 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
184 		return;
185 	}
186 
187 	/*
188 	 * Interpret high order word to find
189 	 * amount of data to be copied to/from the
190 	 * user's address space.
191 	 */
192 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
193 	if (size > sizeof (data)) {
194 		u.u_error = EFAULT;
195 		return;
196 	}
197 	if (com&IOC_IN) {
198 		if (size) {
199 			u.u_error =
200 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
201 			if (u.u_error)
202 				return;
203 		} else
204 			*(caddr_t *)data = uap->cmarg;
205 	} else if ((com&IOC_OUT) && size)
206 		/*
207 		 * Zero the buffer on the stack so the user
208 		 * always gets back something deterministic.
209 		 */
210 		bzero((caddr_t)data, size);
211 	else if (com&IOC_VOID)
212 		*(caddr_t *)data = uap->cmarg;
213 
214 	switch (com) {
215 
216 	case FIONBIO:
217 		u.u_error = fset(fp, FNDELAY, *(int *)data);
218 		return;
219 
220 	case FIOASYNC:
221 		u.u_error = fset(fp, FASYNC, *(int *)data);
222 		return;
223 
224 	case FIOSETOWN:
225 		u.u_error = fsetown(fp, *(int *)data);
226 		return;
227 
228 	case FIOGETOWN:
229 		u.u_error = fgetown(fp, (int *)data);
230 		return;
231 	}
232 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
233 	/*
234 	 * Copy any data to user, size was
235 	 * already set and checked above.
236 	 */
237 	if (u.u_error == 0 && (com&IOC_OUT) && size)
238 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
239 }
240 
241 int	unselect();
242 int	nselcoll;
243 
244 /*
245  * Select uses bit masks of file descriptors in ints.
246  * These macros manipulate such bit fields (the filesystem macros use chars).
247  */
248 #define NBI		(sizeof(int) * NBBY)		/* bits per int */
249 #define	NI		howmany(NOFILE, NBI)
250 #define	tbit(p, n)	((p)[(n)/NBI] & (1 << ((n) % NBI)))
251 #define	sbit(p, n)	((p)[(n)/NBI] |= (1 << ((n) % NBI)))
252 #define	cbit(p, n)	((p)[(n)/NBI] &= ~(1 << ((n) % NBI)))
253 
254 /*
255  * Select system call.
256  */
257 select()
258 {
259 	register struct uap  {
260 		int	nd;
261 		int	*in, *ou, *ex;
262 		struct	timeval *tv;
263 	} *uap = (struct uap *)u.u_ap;
264 	int ibits[3][NI], obits[3][NI];
265 	struct timeval atv;
266 	int s, ncoll, ni;
267 	label_t lqsave;
268 
269 	bzero(ibits, sizeof(ibits));
270 	bzero(obits, sizeof(obits));
271 	if (uap->nd > NOFILE)
272 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
273 	ni = howmany(uap->nd, NBI);
274 
275 #define	getbits(name, x) \
276 	if (uap->name) { \
277 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \
278 		    ni * sizeof(int)); \
279 		if (u.u_error) \
280 			goto done; \
281 	}
282 	getbits(in, 0);
283 	getbits(ou, 1);
284 	getbits(ex, 2);
285 #undef	getbits
286 
287 	if (uap->tv) {
288 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
289 			sizeof (atv));
290 		if (u.u_error)
291 			goto done;
292 		if (itimerfix(&atv)) {
293 			u.u_error = EINVAL;
294 			goto done;
295 		}
296 		s = spl7(); timevaladd(&atv, &time); splx(s);
297 	}
298 retry:
299 	ncoll = nselcoll;
300 	u.u_procp->p_flag |= SSEL;
301 	u.u_r.r_val1 = selscan(ibits, obits, uap->nd);
302 	if (u.u_error || u.u_r.r_val1)
303 		goto done;
304 	s = spl6();
305 	/* this should be timercmp(&time, &atv, >=) */
306 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
307 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
308 		splx(s);
309 		goto done;
310 	}
311 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
312 		u.u_procp->p_flag &= ~SSEL;
313 		splx(s);
314 		goto retry;
315 	}
316 	u.u_procp->p_flag &= ~SSEL;
317 	if (uap->tv) {
318 		lqsave = u.u_qsave;
319 		if (setjmp(&u.u_qsave)) {
320 			untimeout(unselect, (caddr_t)u.u_procp);
321 			u.u_error = EINTR;
322 			splx(s);
323 			goto done;
324 		}
325 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
326 	}
327 	sleep((caddr_t)&selwait, PZERO+1);
328 	if (uap->tv) {
329 		u.u_qsave = lqsave;
330 		untimeout(unselect, (caddr_t)u.u_procp);
331 	}
332 	splx(s);
333 	goto retry;
334 done:
335 #define	putbits(name, x) \
336 	if (uap->name) { \
337 		int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \
338 		    ni * sizeof(int)); \
339 		if (error) \
340 			u.u_error = error; \
341 	}
342 	putbits(in, 0);
343 	putbits(ou, 1);
344 	putbits(ex, 2);
345 #undef putbits
346 }
347 
348 unselect(p)
349 	register struct proc *p;
350 {
351 	register int s = spl6();
352 
353 	switch (p->p_stat) {
354 
355 	case SSLEEP:
356 		setrun(p);
357 		break;
358 
359 	case SSTOP:
360 		unsleep(p);
361 		break;
362 	}
363 	splx(s);
364 }
365 
366 selscan(ibits, obits, nfd)
367 	int (*ibits)[NI], (*obits)[NI];
368 {
369 	register int which, bits, i, j;
370 	int flag;
371 	struct file *fp;
372 	int n = 0;
373 
374 	for (which = 0; which < 3; which++) {
375 		switch (which) {
376 
377 		case 0:
378 			flag = FREAD; break;
379 
380 		case 1:
381 			flag = FWRITE; break;
382 
383 		case 2:
384 			flag = 0; break;
385 		}
386 		for (i = 0; i < nfd; i += NBI) {
387 			bits = ibits[which][i/NBI];
388 			while ((j = ffs(bits)) && i + --j < nfd) {
389 				bits &= ~(1 << j);
390 				fp = u.u_ofile[i + j];
391 				if (fp == NULL) {
392 					u.u_error = EBADF;
393 					break;
394 				}
395 				if ((*fp->f_ops->fo_select)(fp, flag)) {
396 					sbit(obits[which], i + j);
397 					n++;
398 				}
399 			}
400 		}
401 	}
402 	return (n);
403 }
404 
405 /*ARGSUSED*/
406 seltrue(dev, flag)
407 	dev_t dev;
408 	int flag;
409 {
410 
411 	return (1);
412 }
413 
414 selwakeup(p, coll)
415 	register struct proc *p;
416 	int coll;
417 {
418 
419 	if (coll) {
420 		nselcoll++;
421 		wakeup((caddr_t)&selwait);
422 	}
423 	if (p) {
424 		int s = spl6();
425 		if (p->p_wchan == (caddr_t)&selwait) {
426 			if (p->p_stat == SSLEEP)
427 				setrun(p);
428 			else
429 				unsleep(p);
430 		} else if (p->p_flag & SSEL)
431 			p->p_flag &= ~SSEL;
432 		splx(s);
433 	}
434 }
435