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