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