xref: /original-bsd/sys/kern/sys_generic.c (revision 4463b7c2)
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.36 (Berkeley) 07/10/92
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "filedesc.h"
13 #include "ioctl.h"
14 #include "file.h"
15 #include "proc.h"
16 #include "socketvar.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 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 	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, ni, error = 0, timo;
476 
477 	bzero((caddr_t)ibits, sizeof(ibits));
478 	bzero((caddr_t)obits, sizeof(obits));
479 	if (uap->nd > p->p_fd->fd_nfiles)
480 		uap->nd = p->p_fd->fd_nfiles;	/* forgiving; slightly wrong */
481 	ni = howmany(uap->nd, NFDBITS);
482 
483 #define	getbits(name, x) \
484 	if (uap->name) { \
485 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
486 		    (unsigned)(ni * sizeof(fd_mask))); \
487 		if (error) \
488 			goto done; \
489 	}
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 		splx(s);
508 	} else
509 		timo = 0;
510 retry:
511 	ncoll = nselcoll;
512 	p->p_flag |= SSEL;
513 	error = selscan(p, ibits, obits, uap->nd, retval);
514 	if (error || *retval)
515 		goto done;
516 	s = splhigh();
517 	/* this should be timercmp(&time, &atv, >=) */
518 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
519 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
520 		splx(s);
521 		goto done;
522 	}
523 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
524 		splx(s);
525 		goto retry;
526 	}
527 	p->p_flag &= ~SSEL;
528 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
529 	splx(s);
530 	if (error == 0)
531 		goto retry;
532 done:
533 	p->p_flag &= ~SSEL;
534 	/* select is not restarted after signals... */
535 	if (error == ERESTART)
536 		error = EINTR;
537 	if (error == EWOULDBLOCK)
538 		error = 0;
539 #define	putbits(name, x) \
540 	if (uap->name) { \
541 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
542 		    (unsigned)(ni * sizeof(fd_mask))); \
543 		if (error2) \
544 			error = error2; \
545 	}
546 	if (error == 0) {
547 		putbits(in, 0);
548 		putbits(ou, 1);
549 		putbits(ex, 2);
550 #undef putbits
551 	}
552 	return (error);
553 }
554 
555 selscan(p, ibits, obits, nfd, retval)
556 	struct proc *p;
557 	fd_set *ibits, *obits;
558 	int nfd, *retval;
559 {
560 	register struct filedesc *fdp = p->p_fd;
561 	register int msk, i, j, fd;
562 	register fd_mask bits;
563 	struct file *fp;
564 	int n = 0;
565 	static int flag[3] = { FREAD, FWRITE, 0 };
566 
567 	for (msk = 0; msk < 3; msk++) {
568 		for (i = 0; i < nfd; i += NFDBITS) {
569 			bits = ibits[msk].fds_bits[i/NFDBITS];
570 			while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
571 				bits &= ~(1 << j);
572 				fp = fdp->fd_ofiles[fd];
573 				if (fp == NULL)
574 					return (EBADF);
575 				if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
576 					FD_SET(fd, &obits[msk]);
577 					n++;
578 				}
579 			}
580 		}
581 	}
582 	*retval = n;
583 	return (0);
584 }
585 
586 /*ARGSUSED*/
587 seltrue(dev, flag, p)
588 	dev_t dev;
589 	int flag;
590 	struct proc *p;
591 {
592 
593 	return (1);
594 }
595 
596 /*
597  * Record a select request.
598  */
599 void
600 selrecord(selector, sip)
601 	struct proc *selector;
602 	struct selinfo *sip;
603 {
604 	struct proc *p;
605 	pid_t mypid;
606 
607 	mypid = selector->p_pid;
608 	if (sip->si_pid == mypid)
609 		return;
610 	if (sip->si_pid && (p = pfind(sip->si_pid)) &&
611 	    p->p_wchan == (caddr_t)&selwait)
612 		sip->si_flags |= SI_COLL;
613 	else
614 		sip->si_pid = mypid;
615 }
616 
617 /*
618  * Do a wakeup when a selectable event occurs.
619  */
620 void
621 selwakeup(sip)
622 	register struct selinfo *sip;
623 {
624 	register struct proc *p;
625 	int s;
626 
627 	if (sip->si_pid == 0)
628 		return;
629 	if (sip->si_flags & SI_COLL) {
630 		nselcoll++;
631 		sip->si_flags &= ~SI_COLL;
632 		wakeup((caddr_t)&selwait);
633 	}
634 	p = pfind(sip->si_pid);
635 	sip->si_pid = 0;
636 	if (p != NULL) {
637 		s = splhigh();
638 		if (p->p_wchan == (caddr_t)&selwait) {
639 			if (p->p_stat == SSLEEP)
640 				setrun(p);
641 			else
642 				unsleep(p);
643 		} else if (p->p_flag & SSEL)
644 			p->p_flag &= ~SSEL;
645 		splx(s);
646 	}
647 }
648