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