xref: /original-bsd/sys/kern/sys_generic.c (revision 3705696b)
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.1 (Berkeley) 07/19/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	fdes;
30 	char	*cbuf;
31 	unsigned count;
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 (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
49 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
50 	    (fp->f_flag & FREAD) == 0)
51 		return (EBADF);
52 	aiov.iov_base = (caddr_t)uap->cbuf;
53 	aiov.iov_len = uap->count;
54 	auio.uio_iov = &aiov;
55 	auio.uio_iovcnt = 1;
56 	auio.uio_resid = uap->count;
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->count;
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->fdes, 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 	unsigned 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 	unsigned iovlen;
102 #ifdef KTRACE
103 	struct iovec *ktriov = NULL;
104 #endif
105 
106 	if (((unsigned)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	fdes;
176 	char	*cbuf;
177 	unsigned count;
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 (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
194 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
195 	    (fp->f_flag & FWRITE) == 0)
196 		return (EBADF);
197 	aiov.iov_base = (caddr_t)uap->cbuf;
198 	aiov.iov_len = uap->count;
199 	auio.uio_iov = &aiov;
200 	auio.uio_iovcnt = 1;
201 	auio.uio_resid = uap->count;
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->count;
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->fdes, 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	fdes;
235 	struct	iovec *iovp;
236 	unsigned 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 	unsigned iovlen;
251 #ifdef KTRACE
252 	struct iovec *ktriov = NULL;
253 #endif
254 
255 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
256 	    (fp = fdp->fd_ofiles[uap->fdes]) == 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->fdes, 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	fdes;
328 	int	cmd;
329 	caddr_t	cmarg;
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 = p->p_fd;
339 	register int com, error;
340 	register u_int size;
341 	caddr_t memp = 0;
342 #define STK_PARAMS	128
343 	char stkbuf[STK_PARAMS];
344 	caddr_t data = stkbuf;
345 	int tmp;
346 
347 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
348 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
349 		return (EBADF);
350 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
351 		return (EBADF);
352 	com = uap->cmd;
353 
354 	if (com == FIOCLEX) {
355 		fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
356 		return (0);
357 	}
358 	if (com == FIONCLEX) {
359 		fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
360 		return (0);
361 	}
362 
363 	/*
364 	 * Interpret high order word to find
365 	 * amount of data to be copied to/from the
366 	 * user's address space.
367 	 */
368 	size = IOCPARM_LEN(com);
369 	if (size > IOCPARM_MAX)
370 		return (ENOTTY);
371 	if (size > sizeof (stkbuf)) {
372 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
373 		data = memp;
374 	}
375 	if (com&IOC_IN) {
376 		if (size) {
377 			error = copyin(uap->cmarg, data, (u_int)size);
378 			if (error) {
379 				if (memp)
380 					free(memp, M_IOCTLOPS);
381 				return (error);
382 			}
383 		} else
384 			*(caddr_t *)data = uap->cmarg;
385 	} else if ((com&IOC_OUT) && size)
386 		/*
387 		 * Zero the buffer so the user always
388 		 * gets back something deterministic.
389 		 */
390 		bzero(data, size);
391 	else if (com&IOC_VOID)
392 		*(caddr_t *)data = uap->cmarg;
393 
394 	switch (com) {
395 
396 	case FIONBIO:
397 		if (tmp = *(int *)data)
398 			fp->f_flag |= FNONBLOCK;
399 		else
400 			fp->f_flag &= ~FNONBLOCK;
401 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
402 		break;
403 
404 	case FIOASYNC:
405 		if (tmp = *(int *)data)
406 			fp->f_flag |= FASYNC;
407 		else
408 			fp->f_flag &= ~FASYNC;
409 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
410 		break;
411 
412 	case FIOSETOWN:
413 		tmp = *(int *)data;
414 		if (fp->f_type == DTYPE_SOCKET) {
415 			((struct socket *)fp->f_data)->so_pgid = tmp;
416 			error = 0;
417 			break;
418 		}
419 		if (tmp <= 0) {
420 			tmp = -tmp;
421 		} else {
422 			struct proc *p1 = pfind(tmp);
423 			if (p1 == 0) {
424 				error = ESRCH;
425 				break;
426 			}
427 			tmp = p1->p_pgrp->pg_id;
428 		}
429 		error = (*fp->f_ops->fo_ioctl)
430 			(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
431 		break;
432 
433 	case FIOGETOWN:
434 		if (fp->f_type == DTYPE_SOCKET) {
435 			error = 0;
436 			*(int *)data = ((struct socket *)fp->f_data)->so_pgid;
437 			break;
438 		}
439 		error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
440 		*(int *)data = -*(int *)data;
441 		break;
442 
443 	default:
444 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
445 		/*
446 		 * Copy any data to user, size was
447 		 * already set and checked above.
448 		 */
449 		if (error == 0 && (com&IOC_OUT) && size)
450 			error = copyout(data, uap->cmarg, (u_int)size);
451 		break;
452 	}
453 	if (memp)
454 		free(memp, M_IOCTLOPS);
455 	return (error);
456 }
457 
458 int	selwait, nselcoll;
459 
460 /*
461  * Select system call.
462  */
463 struct select_args {
464 	u_int	nd;
465 	fd_set	*in, *ou, *ex;
466 	struct	timeval *tv;
467 };
468 select(p, uap, retval)
469 	register struct proc *p;
470 	register struct select_args *uap;
471 	int *retval;
472 {
473 	fd_set ibits[3], obits[3];
474 	struct timeval atv;
475 	int s, ncoll, error = 0, timo;
476 	u_int ni;
477 
478 	bzero((caddr_t)ibits, sizeof(ibits));
479 	bzero((caddr_t)obits, sizeof(obits));
480 	if (uap->nd > FD_SETSIZE)
481 		return (EINVAL);
482 	if (uap->nd > p->p_fd->fd_nfiles)
483 		uap->nd = p->p_fd->fd_nfiles;	/* forgiving; slightly wrong */
484 	ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
485 
486 #define	getbits(name, x) \
487 	if (uap->name && \
488 	    (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \
489 		goto done;
490 	getbits(in, 0);
491 	getbits(ou, 1);
492 	getbits(ex, 2);
493 #undef	getbits
494 
495 	if (uap->tv) {
496 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
497 			sizeof (atv));
498 		if (error)
499 			goto done;
500 		if (itimerfix(&atv)) {
501 			error = EINVAL;
502 			goto done;
503 		}
504 		s = splclock();
505 		timevaladd(&atv, (struct timeval *)&time);
506 		timo = hzto(&atv);
507 		/*
508 		 * Avoid inadvertently sleeping forever.
509 		 */
510 		if (timo == 0)
511 			timo = 1;
512 		splx(s);
513 	} else
514 		timo = 0;
515 retry:
516 	ncoll = nselcoll;
517 	p->p_flag |= SSEL;
518 	error = selscan(p, ibits, obits, uap->nd, retval);
519 	if (error || *retval)
520 		goto done;
521 	s = splhigh();
522 	/* this should be timercmp(&time, &atv, >=) */
523 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
524 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
525 		splx(s);
526 		goto done;
527 	}
528 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
529 		splx(s);
530 		goto retry;
531 	}
532 	p->p_flag &= ~SSEL;
533 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
534 	splx(s);
535 	if (error == 0)
536 		goto retry;
537 done:
538 	p->p_flag &= ~SSEL;
539 	/* select is not restarted after signals... */
540 	if (error == ERESTART)
541 		error = EINTR;
542 	if (error == EWOULDBLOCK)
543 		error = 0;
544 #define	putbits(name, x) \
545 	if (uap->name && \
546 	    (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \
547 		error = error2;
548 	if (error == 0) {
549 		int error2;
550 
551 		putbits(in, 0);
552 		putbits(ou, 1);
553 		putbits(ex, 2);
554 #undef putbits
555 	}
556 	return (error);
557 }
558 
559 selscan(p, ibits, obits, nfd, retval)
560 	struct proc *p;
561 	fd_set *ibits, *obits;
562 	int nfd, *retval;
563 {
564 	register struct filedesc *fdp = p->p_fd;
565 	register int msk, i, j, fd;
566 	register fd_mask bits;
567 	struct file *fp;
568 	int n = 0;
569 	static int flag[3] = { FREAD, FWRITE, 0 };
570 
571 	for (msk = 0; msk < 3; msk++) {
572 		for (i = 0; i < nfd; i += NFDBITS) {
573 			bits = ibits[msk].fds_bits[i/NFDBITS];
574 			while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
575 				bits &= ~(1 << j);
576 				fp = fdp->fd_ofiles[fd];
577 				if (fp == NULL)
578 					return (EBADF);
579 				if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
580 					FD_SET(fd, &obits[msk]);
581 					n++;
582 				}
583 			}
584 		}
585 	}
586 	*retval = n;
587 	return (0);
588 }
589 
590 /*ARGSUSED*/
591 seltrue(dev, flag, p)
592 	dev_t dev;
593 	int flag;
594 	struct proc *p;
595 {
596 
597 	return (1);
598 }
599 
600 /*
601  * Record a select request.
602  */
603 void
604 selrecord(selector, sip)
605 	struct proc *selector;
606 	struct selinfo *sip;
607 {
608 	struct proc *p;
609 	pid_t mypid;
610 
611 	mypid = selector->p_pid;
612 	if (sip->si_pid == mypid)
613 		return;
614 	if (sip->si_pid && (p = pfind(sip->si_pid)) &&
615 	    p->p_wchan == (caddr_t)&selwait)
616 		sip->si_flags |= SI_COLL;
617 	else
618 		sip->si_pid = mypid;
619 }
620 
621 /*
622  * Do a wakeup when a selectable event occurs.
623  */
624 void
625 selwakeup(sip)
626 	register struct selinfo *sip;
627 {
628 	register struct proc *p;
629 	int s;
630 
631 	if (sip->si_pid == 0)
632 		return;
633 	if (sip->si_flags & SI_COLL) {
634 		nselcoll++;
635 		sip->si_flags &= ~SI_COLL;
636 		wakeup((caddr_t)&selwait);
637 	}
638 	p = pfind(sip->si_pid);
639 	sip->si_pid = 0;
640 	if (p != NULL) {
641 		s = splhigh();
642 		if (p->p_wchan == (caddr_t)&selwait) {
643 			if (p->p_stat == SSLEEP)
644 				setrun(p);
645 			else
646 				unsleep(p);
647 		} else if (p->p_flag & SSEL)
648 			p->p_flag &= ~SSEL;
649 		splx(s);
650 	}
651 }
652