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