xref: /original-bsd/sys/kern/sys_generic.c (revision d54be081)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)sys_generic.c	7.30 (Berkeley) 05/30/91
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "filedesc.h"
13 #include "ioctl.h"
14 #include "file.h"
15 #include "socketvar.h"
16 #include "proc.h"
17 #include "uio.h"
18 #include "kernel.h"
19 #include "stat.h"
20 #include "malloc.h"
21 #ifdef KTRACE
22 #include "ktrace.h"
23 #endif
24 
25 /*
26  * Read system call.
27  */
28 /* ARGSUSED */
29 read(p, uap, retval)
30 	struct proc *p;
31 	register struct args {
32 		int	fdes;
33 		char	*cbuf;
34 		unsigned count;
35 	} *uap;
36 	int *retval;
37 {
38 	register struct file *fp;
39 	register struct filedesc *fdp = p->p_fd;
40 	struct uio auio;
41 	struct iovec aiov;
42 	long cnt, error = 0;
43 #ifdef KTRACE
44 	struct iovec ktriov;
45 #endif
46 
47 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
48 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
49 	    (fp->f_flag & FREAD) == 0)
50 		return (EBADF);
51 	aiov.iov_base = (caddr_t)uap->cbuf;
52 	aiov.iov_len = uap->count;
53 	auio.uio_iov = &aiov;
54 	auio.uio_iovcnt = 1;
55 	auio.uio_resid = uap->count;
56 	auio.uio_rw = UIO_READ;
57 	auio.uio_segflg = UIO_USERSPACE;
58 	auio.uio_procp = p;
59 #ifdef KTRACE
60 	/*
61 	 * if tracing, save a copy of iovec
62 	 */
63 	if (KTRPOINT(p, KTR_GENIO))
64 		ktriov = aiov;
65 #endif
66 	cnt = uap->count;
67 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
68 		if (auio.uio_resid != cnt && (error == ERESTART ||
69 		    error == EINTR || error == EWOULDBLOCK))
70 			error = 0;
71 	cnt -= auio.uio_resid;
72 #ifdef KTRACE
73 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
74 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
75 #endif
76 	*retval = cnt;
77 	return (error);
78 }
79 
80 /*
81  * Scatter read system call.
82  */
83 /* ARGSUSED */
84 readv(p, uap, retval)
85 	struct proc *p;
86 	register struct args {
87 		int	fdes;
88 		struct	iovec *iovp;
89 		unsigned iovcnt;
90 	} *uap;
91 	int *retval;
92 {
93 	register struct file *fp;
94 	register struct filedesc *fdp = p->p_fd;
95 	struct uio auio;
96 	register struct iovec *iov;
97 	struct iovec *saveiov;
98 	struct iovec aiov[UIO_SMALLIOV];
99 	long i, cnt, error = 0;
100 	unsigned iovlen;
101 #ifdef KTRACE
102 	struct iovec *ktriov = NULL;
103 #endif
104 
105 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
106 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
107 	    (fp->f_flag & FREAD) == 0)
108 		return (EBADF);
109 	/* note: can't use iovlen until iovcnt is validated */
110 	iovlen = uap->iovcnt * sizeof (struct iovec);
111 	if (uap->iovcnt > UIO_SMALLIOV) {
112 		if (uap->iovcnt > UIO_MAXIOV)
113 			return (EINVAL);
114 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
115 		saveiov = iov;
116 	} else
117 		iov = aiov;
118 	auio.uio_iov = iov;
119 	auio.uio_iovcnt = uap->iovcnt;
120 	auio.uio_rw = UIO_READ;
121 	auio.uio_segflg = UIO_USERSPACE;
122 	auio.uio_procp = p;
123 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
124 		goto done;
125 	auio.uio_resid = 0;
126 	for (i = 0; i < uap->iovcnt; i++) {
127 		if (iov->iov_len < 0) {
128 			error = EINVAL;
129 			goto done;
130 		}
131 		auio.uio_resid += iov->iov_len;
132 		if (auio.uio_resid < 0) {
133 			error = EINVAL;
134 			goto done;
135 		}
136 		iov++;
137 	}
138 #ifdef KTRACE
139 	/*
140 	 * if tracing, save a copy of iovec
141 	 */
142 	if (KTRPOINT(p, KTR_GENIO))  {
143 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
144 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
145 	}
146 #endif
147 	cnt = auio.uio_resid;
148 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
149 		if (auio.uio_resid != cnt && (error == ERESTART ||
150 		    error == EINTR || error == EWOULDBLOCK))
151 			error = 0;
152 	cnt -= auio.uio_resid;
153 #ifdef KTRACE
154 	if (ktriov != NULL) {
155 		if (error == 0)
156 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
157 			    cnt, error);
158 		FREE(ktriov, M_TEMP);
159 	}
160 #endif
161 	*retval = cnt;
162 done:
163 	if (uap->iovcnt > UIO_SMALLIOV)
164 		FREE(saveiov, M_IOV);
165 	return (error);
166 }
167 
168 /*
169  * Write system call
170  */
171 write(p, uap, retval)
172 	struct proc *p;
173 	register struct args {
174 		int	fdes;
175 		char	*cbuf;
176 		unsigned count;
177 	} *uap;
178 	int *retval;
179 {
180 	register struct file *fp;
181 	register struct filedesc *fdp = p->p_fd;
182 	struct uio auio;
183 	struct iovec aiov;
184 	long cnt, error = 0;
185 #ifdef KTRACE
186 	struct iovec ktriov;
187 #endif
188 
189 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
190 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
191 	    (fp->f_flag & FWRITE) == 0)
192 		return (EBADF);
193 	aiov.iov_base = (caddr_t)uap->cbuf;
194 	aiov.iov_len = uap->count;
195 	auio.uio_iov = &aiov;
196 	auio.uio_iovcnt = 1;
197 	auio.uio_resid = uap->count;
198 	auio.uio_rw = UIO_WRITE;
199 	auio.uio_segflg = UIO_USERSPACE;
200 	auio.uio_procp = p;
201 #ifdef KTRACE
202 	/*
203 	 * if tracing, save a copy of iovec
204 	 */
205 	if (KTRPOINT(p, KTR_GENIO))
206 		ktriov = aiov;
207 #endif
208 	cnt = uap->count;
209 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
210 		if (auio.uio_resid != cnt && (error == ERESTART ||
211 		    error == EINTR || error == EWOULDBLOCK))
212 			error = 0;
213 		if (error == EPIPE)
214 			psignal(p, SIGPIPE);
215 	}
216 	cnt -= auio.uio_resid;
217 #ifdef KTRACE
218 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
219 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
220 		    &ktriov, cnt, error);
221 #endif
222 	*retval = cnt;
223 	return (error);
224 }
225 
226 /*
227  * Gather write system call
228  */
229 writev(p, uap, retval)
230 	struct proc *p;
231 	register struct args {
232 		int	fdes;
233 		struct	iovec *iovp;
234 		unsigned iovcnt;
235 	} *uap;
236 	int *retval;
237 {
238 	register struct file *fp;
239 	register struct filedesc *fdp = p->p_fd;
240 	struct uio auio;
241 	register struct iovec *iov;
242 	struct iovec *saveiov;
243 	struct iovec aiov[UIO_SMALLIOV];
244 	long i, cnt, error = 0;
245 	unsigned iovlen;
246 #ifdef KTRACE
247 	struct iovec *ktriov = NULL;
248 #endif
249 
250 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
251 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
252 	    (fp->f_flag & FWRITE) == 0)
253 		return (EBADF);
254 	/* note: can't use iovlen until iovcnt is validated */
255 	iovlen = uap->iovcnt * sizeof (struct iovec);
256 	if (uap->iovcnt > UIO_SMALLIOV) {
257 		if (uap->iovcnt > UIO_MAXIOV)
258 			return (EINVAL);
259 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
260 		saveiov = iov;
261 	} else
262 		iov = aiov;
263 	auio.uio_iov = iov;
264 	auio.uio_iovcnt = uap->iovcnt;
265 	auio.uio_rw = UIO_WRITE;
266 	auio.uio_segflg = UIO_USERSPACE;
267 	auio.uio_procp = p;
268 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
269 		goto done;
270 	auio.uio_resid = 0;
271 	for (i = 0; i < uap->iovcnt; i++) {
272 		if (iov->iov_len < 0) {
273 			error = EINVAL;
274 			goto done;
275 		}
276 		auio.uio_resid += iov->iov_len;
277 		if (auio.uio_resid < 0) {
278 			error = EINVAL;
279 			goto done;
280 		}
281 		iov++;
282 	}
283 #ifdef KTRACE
284 	/*
285 	 * if tracing, save a copy of iovec
286 	 */
287 	if (KTRPOINT(p, KTR_GENIO))  {
288 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
289 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
290 	}
291 #endif
292 	cnt = auio.uio_resid;
293 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
294 		if (auio.uio_resid != cnt && (error == ERESTART ||
295 		    error == EINTR || error == EWOULDBLOCK))
296 			error = 0;
297 		if (error == EPIPE)
298 			psignal(p, SIGPIPE);
299 	}
300 	cnt -= auio.uio_resid;
301 #ifdef KTRACE
302 	if (ktriov != NULL) {
303 		if (error == 0)
304 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
305 				ktriov, cnt, error);
306 		FREE(ktriov, M_TEMP);
307 	}
308 #endif
309 	*retval = cnt;
310 done:
311 	if (uap->iovcnt > UIO_SMALLIOV)
312 		FREE(saveiov, M_IOV);
313 	return (error);
314 }
315 
316 /*
317  * Ioctl system call
318  */
319 /* ARGSUSED */
320 ioctl(p, uap, retval)
321 	struct proc *p;
322 	register struct args {
323 		int	fdes;
324 		int	cmd;
325 		caddr_t	cmarg;
326 	} *uap;
327 	int *retval;
328 {
329 	register struct file *fp;
330 	register struct filedesc *fdp = p->p_fd;
331 	register int com, error;
332 	register u_int size;
333 	caddr_t memp = 0;
334 #define STK_PARAMS	128
335 	char stkbuf[STK_PARAMS];
336 	caddr_t data = stkbuf;
337 	int tmp;
338 
339 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
340 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
341 		return (EBADF);
342 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
343 		return (EBADF);
344 	com = uap->cmd;
345 
346 	if (com == FIOCLEX) {
347 		fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
348 		return (0);
349 	}
350 	if (com == FIONCLEX) {
351 		fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
352 		return (0);
353 	}
354 
355 	/*
356 	 * Interpret high order word to find
357 	 * amount of data to be copied to/from the
358 	 * user's address space.
359 	 */
360 	size = IOCPARM_LEN(com);
361 	if (size > IOCPARM_MAX)
362 		return (ENOTTY);
363 	if (size > sizeof (stkbuf)) {
364 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
365 		data = memp;
366 	}
367 	if (com&IOC_IN) {
368 		if (size) {
369 			error = copyin(uap->cmarg, data, (u_int)size);
370 			if (error) {
371 				if (memp)
372 					free(memp, M_IOCTLOPS);
373 				return (error);
374 			}
375 		} else
376 			*(caddr_t *)data = uap->cmarg;
377 	} else if ((com&IOC_OUT) && size)
378 		/*
379 		 * Zero the buffer so the user always
380 		 * gets back something deterministic.
381 		 */
382 		bzero(data, size);
383 	else if (com&IOC_VOID)
384 		*(caddr_t *)data = uap->cmarg;
385 
386 	switch (com) {
387 
388 	case FIONBIO:
389 		if (tmp = *(int *)data)
390 			fp->f_flag |= FNONBLOCK;
391 		else
392 			fp->f_flag &= ~FNONBLOCK;
393 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
394 		break;
395 
396 	case FIOASYNC:
397 		if (tmp = *(int *)data)
398 			fp->f_flag |= FASYNC;
399 		else
400 			fp->f_flag &= ~FASYNC;
401 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
402 		break;
403 
404 	case FIOSETOWN:
405 		tmp = *(int *)data;
406 		if (fp->f_type == DTYPE_SOCKET) {
407 			((struct socket *)fp->f_data)->so_pgid = tmp;
408 			error = 0;
409 			break;
410 		}
411 		if (tmp <= 0) {
412 			tmp = -tmp;
413 		} else {
414 			struct proc *p1 = pfind(tmp);
415 			if (p1 == 0) {
416 				error = ESRCH;
417 				break;
418 			}
419 			tmp = p1->p_pgrp->pg_id;
420 		}
421 		error = (*fp->f_ops->fo_ioctl)
422 			(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
423 		break;
424 
425 	case FIOGETOWN:
426 		if (fp->f_type == DTYPE_SOCKET) {
427 			error = 0;
428 			*(int *)data = ((struct socket *)fp->f_data)->so_pgid;
429 			break;
430 		}
431 		error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
432 		*(int *)data = -*(int *)data;
433 		break;
434 
435 	default:
436 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
437 		/*
438 		 * Copy any data to user, size was
439 		 * already set and checked above.
440 		 */
441 		if (error == 0 && (com&IOC_OUT) && size)
442 			error = copyout(data, uap->cmarg, (u_int)size);
443 		break;
444 	}
445 	if (memp)
446 		free(memp, M_IOCTLOPS);
447 	return (error);
448 }
449 
450 int	selwait, nselcoll;
451 
452 /*
453  * Select system call.
454  */
455 select(p, uap, retval)
456 	register struct proc *p;
457 	register struct args {
458 		int	nd;
459 		fd_set	*in, *ou, *ex;
460 		struct	timeval *tv;
461 	} *uap;
462 	int *retval;
463 {
464 	fd_set ibits[3], obits[3];
465 	struct timeval atv;
466 	int s, ncoll, ni, error = 0, timo;
467 
468 	bzero((caddr_t)ibits, sizeof(ibits));
469 	bzero((caddr_t)obits, sizeof(obits));
470 	if (uap->nd > p->p_fd->fd_nfiles)
471 		uap->nd = p->p_fd->fd_nfiles;	/* forgiving; slightly wrong */
472 	ni = howmany(uap->nd, NFDBITS);
473 
474 #define	getbits(name, x) \
475 	if (uap->name) { \
476 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
477 		    (unsigned)(ni * sizeof(fd_mask))); \
478 		if (error) \
479 			goto done; \
480 	}
481 	getbits(in, 0);
482 	getbits(ou, 1);
483 	getbits(ex, 2);
484 #undef	getbits
485 
486 	if (uap->tv) {
487 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
488 			sizeof (atv));
489 		if (error)
490 			goto done;
491 		if (itimerfix(&atv)) {
492 			error = EINVAL;
493 			goto done;
494 		}
495 		s = splhigh(); timevaladd(&atv, &time); splx(s);
496 		timo = hzto(&atv);
497 	} else
498 		timo = 0;
499 retry:
500 	ncoll = nselcoll;
501 	p->p_flag |= SSEL;
502 	error = selscan(p, ibits, obits, uap->nd, retval);
503 	if (error || *retval)
504 		goto done;
505 	s = splhigh();
506 	/* this should be timercmp(&time, &atv, >=) */
507 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
508 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
509 		splx(s);
510 		goto done;
511 	}
512 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
513 		splx(s);
514 		goto retry;
515 	}
516 	p->p_flag &= ~SSEL;
517 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
518 	splx(s);
519 	if (error == 0)
520 		goto retry;
521 done:
522 	p->p_flag &= ~SSEL;
523 	/* select is not restarted after signals... */
524 	if (error == ERESTART)
525 		error = EINTR;
526 	if (error == EWOULDBLOCK)
527 		error = 0;
528 #define	putbits(name, x) \
529 	if (uap->name) { \
530 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
531 		    (unsigned)(ni * sizeof(fd_mask))); \
532 		if (error2) \
533 			error = error2; \
534 	}
535 	if (error == 0) {
536 		putbits(in, 0);
537 		putbits(ou, 1);
538 		putbits(ex, 2);
539 #undef putbits
540 	}
541 	return (error);
542 }
543 
544 selscan(p, ibits, obits, nfd, retval)
545 	struct proc *p;
546 	fd_set *ibits, *obits;
547 	int nfd, *retval;
548 {
549 	register struct filedesc *fdp = p->p_fd;
550 	register int which, i, j;
551 	register fd_mask bits;
552 	int flag;
553 	struct file *fp;
554 	int error = 0, n = 0;
555 
556 	for (which = 0; which < 3; which++) {
557 		switch (which) {
558 
559 		case 0:
560 			flag = FREAD; break;
561 
562 		case 1:
563 			flag = FWRITE; break;
564 
565 		case 2:
566 			flag = 0; break;
567 		}
568 		for (i = 0; i < nfd; i += NFDBITS) {
569 			bits = ibits[which].fds_bits[i/NFDBITS];
570 			while ((j = ffs(bits)) && i + --j < nfd) {
571 				bits &= ~(1 << j);
572 				fp = fdp->fd_ofiles[i + j];
573 				if (fp == NULL) {
574 					error = EBADF;
575 					break;
576 				}
577 				if ((*fp->f_ops->fo_select)(fp, flag, p)) {
578 					FD_SET(i + j, &obits[which]);
579 					n++;
580 				}
581 			}
582 		}
583 	}
584 	*retval = n;
585 	return (error);
586 }
587 
588 /*ARGSUSED*/
589 #ifdef __STDC__
590 seltrue(dev_t dev, int which, struct proc *p)
591 #else
592 seltrue(dev, flag, p)
593 	dev_t dev;
594 	int flag;
595 	struct proc *p;
596 #endif
597 {
598 
599 	return (1);
600 }
601 
602 selwakeup(p, coll)
603 	register struct proc *p;
604 	int coll;
605 {
606 
607 	if (coll) {
608 		nselcoll++;
609 		wakeup((caddr_t)&selwait);
610 	}
611 	if (p) {
612 		int s = splhigh();
613 		if (p->p_wchan == (caddr_t)&selwait) {
614 			if (p->p_stat == SSLEEP)
615 				setrun(p);
616 			else
617 				unsleep(p);
618 		} else if (p->p_flag & SSEL)
619 			p->p_flag &= ~SSEL;
620 		splx(s);
621 	}
622 }
623