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