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 | * |
c4ec2128 KM |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | * | |
d9c2f47f | 17 | * @(#)sys_generic.c 7.21 (Berkeley) %G% |
da7c5cc6 | 18 | */ |
ffe28cfe | 19 | |
94368568 JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
d9c2f47f | 22 | #include "user.h" |
94368568 JB |
23 | #include "ioctl.h" |
24 | #include "file.h" | |
25 | #include "proc.h" | |
26 | #include "uio.h" | |
27 | #include "kernel.h" | |
28 | #include "stat.h" | |
e0b18aec | 29 | #include "malloc.h" |
46814581 MK |
30 | #ifdef KTRACE |
31 | #include "ktrace.h" | |
32 | #endif | |
ffe28cfe BJ |
33 | |
34 | /* | |
35 | * Read system call. | |
36 | */ | |
c9714ae3 KM |
37 | read(p, uap, retval) |
38 | struct proc *p; | |
39 | register struct args { | |
ffe28cfe BJ |
40 | int fdes; |
41 | char *cbuf; | |
42 | unsigned count; | |
c9714ae3 KM |
43 | } *uap; |
44 | int *retval; | |
45 | { | |
c4ec2128 | 46 | register struct file *fp; |
32a43ee2 BJ |
47 | struct uio auio; |
48 | struct iovec aiov; | |
c4ec2128 KM |
49 | long cnt, error = 0; |
50 | #ifdef KTRACE | |
51 | struct iovec ktriov; | |
52 | #endif | |
ffe28cfe | 53 | |
c4ec2128 KM |
54 | if (((unsigned)uap->fdes) >= NOFILE || |
55 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
56 | (fp->f_flag & FREAD) == 0) | |
d9c2f47f | 57 | return (EBADF); |
32a43ee2 BJ |
58 | aiov.iov_base = (caddr_t)uap->cbuf; |
59 | aiov.iov_len = uap->count; | |
60 | auio.uio_iov = &aiov; | |
61 | auio.uio_iovcnt = 1; | |
c4ec2128 KM |
62 | auio.uio_resid = uap->count; |
63 | auio.uio_rw = UIO_READ; | |
64 | auio.uio_segflg = UIO_USERSPACE; | |
65 | #ifdef KTRACE | |
66 | /* | |
67 | * if tracing, save a copy of iovec | |
68 | */ | |
c9714ae3 | 69 | if (KTRPOINT(p, KTR_GENIO)) |
c4ec2128 KM |
70 | ktriov = aiov; |
71 | #endif | |
72 | cnt = uap->count; | |
9754d709 MK |
73 | if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) |
74 | if (auio.uio_resid != cnt && (error == ERESTART || | |
75 | error == EINTR || error == EWOULDBLOCK)) | |
76 | error = 0; | |
c4ec2128 KM |
77 | cnt -= auio.uio_resid; |
78 | #ifdef KTRACE | |
c9714ae3 | 79 | if (KTRPOINT(p, KTR_GENIO) && error == 0) |
51322105 | 80 | ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); |
c4ec2128 | 81 | #endif |
c9714ae3 | 82 | *retval = cnt; |
d9c2f47f | 83 | return (error); |
b9429893 BJ |
84 | } |
85 | ||
c9714ae3 KM |
86 | /* |
87 | * Scatter read system call. | |
88 | */ | |
89 | readv(p, uap, retval) | |
90 | struct proc *p; | |
91 | register struct args { | |
b9429893 BJ |
92 | int fdes; |
93 | struct iovec *iovp; | |
31286ce2 | 94 | unsigned iovcnt; |
c9714ae3 KM |
95 | } *uap; |
96 | int *retval; | |
97 | { | |
c4ec2128 | 98 | register struct file *fp; |
b9429893 | 99 | struct uio auio; |
c4ec2128 KM |
100 | register struct iovec *iov; |
101 | struct iovec aiov[UIO_SMALLIOV]; | |
102 | long i, cnt, error = 0; | |
103 | #ifdef KTRACE | |
104 | struct iovec *ktriov = NULL; | |
105 | #endif | |
b9429893 | 106 | |
c4ec2128 KM |
107 | if (((unsigned)uap->fdes) >= NOFILE || |
108 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
109 | (fp->f_flag & FREAD) == 0) | |
d9c2f47f | 110 | return (EBADF); |
46814581 | 111 | if (uap->iovcnt > UIO_SMALLIOV) { |
c4ec2128 | 112 | if (uap->iovcnt > UIO_MAXIOV) |
d9c2f47f | 113 | return (EINVAL); |
46814581 MK |
114 | MALLOC(iov, struct iovec *, |
115 | sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); | |
46814581 MK |
116 | } else |
117 | iov = aiov; | |
118 | auio.uio_iov = iov; | |
b9429893 | 119 | auio.uio_iovcnt = uap->iovcnt; |
c4ec2128 KM |
120 | auio.uio_rw = UIO_READ; |
121 | auio.uio_segflg = UIO_USERSPACE; | |
122 | if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, | |
123 | uap->iovcnt * sizeof (struct iovec))) | |
46814581 | 124 | goto done; |
c4ec2128 KM |
125 | auio.uio_resid = 0; |
126 | for (i = 0; i < uap->iovcnt; i++) { | |
127 | if (iov->iov_len < 0) { | |
128 | error = EINVAL; | |
129 | goto done; | |
130 | } | |
131 | auio.uio_resid += iov->iov_len; | |
132 | if (auio.uio_resid < 0) { | |
133 | error = EINVAL; | |
134 | goto done; | |
135 | } | |
136 | iov++; | |
137 | } | |
138 | #ifdef KTRACE | |
139 | /* | |
140 | * if tracing, save a copy of iovec | |
141 | */ | |
c9714ae3 | 142 | if (KTRPOINT(p, KTR_GENIO)) { |
92e1705e | 143 | unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); |
c4ec2128 KM |
144 | |
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; | |
9754d709 MK |
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; | |
c4ec2128 KM |
154 | cnt -= auio.uio_resid; |
155 | #ifdef KTRACE | |
156 | if (ktriov != NULL) { | |
e64d087d | 157 | if (error == 0) |
51322105 KM |
158 | ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, |
159 | cnt, error); | |
c4ec2128 KM |
160 | FREE(ktriov, M_TEMP); |
161 | } | |
162 | #endif | |
c9714ae3 | 163 | *retval = cnt; |
46814581 | 164 | done: |
c4ec2128 | 165 | if (uap->iovcnt > UIO_SMALLIOV) |
46814581 | 166 | FREE(iov, M_IOV); |
d9c2f47f | 167 | return (error); |
ffe28cfe BJ |
168 | } |
169 | ||
170 | /* | |
171 | * Write system call | |
172 | */ | |
c9714ae3 KM |
173 | write(p, uap, retval) |
174 | struct proc *p; | |
175 | register struct args { | |
ffe28cfe BJ |
176 | int fdes; |
177 | char *cbuf; | |
31286ce2 | 178 | unsigned count; |
c9714ae3 KM |
179 | } *uap; |
180 | int *retval; | |
181 | { | |
c4ec2128 | 182 | register struct file *fp; |
b9429893 BJ |
183 | struct uio auio; |
184 | struct iovec aiov; | |
c4ec2128 KM |
185 | long cnt, error = 0; |
186 | #ifdef KTRACE | |
187 | struct iovec ktriov; | |
188 | #endif | |
ffe28cfe | 189 | |
c4ec2128 KM |
190 | if (((unsigned)uap->fdes) >= NOFILE || |
191 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
192 | (fp->f_flag & FWRITE) == 0) | |
d9c2f47f | 193 | return (EBADF); |
c4ec2128 KM |
194 | aiov.iov_base = (caddr_t)uap->cbuf; |
195 | aiov.iov_len = uap->count; | |
b9429893 BJ |
196 | auio.uio_iov = &aiov; |
197 | auio.uio_iovcnt = 1; | |
c4ec2128 KM |
198 | auio.uio_resid = uap->count; |
199 | auio.uio_rw = UIO_WRITE; | |
200 | auio.uio_segflg = UIO_USERSPACE; | |
201 | #ifdef KTRACE | |
202 | /* | |
203 | * if tracing, save a copy of iovec | |
204 | */ | |
c9714ae3 | 205 | if (KTRPOINT(p, KTR_GENIO)) |
c4ec2128 KM |
206 | ktriov = aiov; |
207 | #endif | |
208 | cnt = uap->count; | |
9754d709 MK |
209 | if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { |
210 | if (auio.uio_resid != cnt && (error == ERESTART || | |
211 | error == EINTR || error == EWOULDBLOCK)) | |
212 | error = 0; | |
213 | if (error == EPIPE) | |
c9714ae3 | 214 | psignal(p, SIGPIPE); |
9754d709 | 215 | } |
c4ec2128 KM |
216 | cnt -= auio.uio_resid; |
217 | #ifdef KTRACE | |
c9714ae3 KM |
218 | if (KTRPOINT(p, KTR_GENIO) && error == 0) |
219 | ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, | |
51322105 | 220 | &ktriov, cnt, error); |
c4ec2128 | 221 | #endif |
c9714ae3 | 222 | *retval = cnt; |
d9c2f47f | 223 | return (error); |
b9429893 BJ |
224 | } |
225 | ||
c9714ae3 KM |
226 | /* |
227 | * Gather write system call | |
228 | */ | |
229 | writev(p, uap, retval) | |
230 | struct proc *p; | |
231 | register struct args { | |
b9429893 BJ |
232 | int fdes; |
233 | struct iovec *iovp; | |
31286ce2 | 234 | unsigned iovcnt; |
c9714ae3 KM |
235 | } *uap; |
236 | int *retval; | |
237 | { | |
c4ec2128 | 238 | register struct file *fp; |
b9429893 | 239 | struct uio auio; |
c4ec2128 KM |
240 | register struct iovec *iov; |
241 | struct iovec aiov[UIO_SMALLIOV]; | |
242 | long i, cnt, error = 0; | |
243 | #ifdef KTRACE | |
244 | struct iovec *ktriov = NULL; | |
245 | #endif | |
b9429893 | 246 | |
c4ec2128 KM |
247 | if (((unsigned)uap->fdes) >= NOFILE || |
248 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
249 | (fp->f_flag & FWRITE) == 0) | |
d9c2f47f | 250 | return (EBADF); |
46814581 | 251 | if (uap->iovcnt > UIO_SMALLIOV) { |
c4ec2128 | 252 | if (uap->iovcnt > UIO_MAXIOV) |
d9c2f47f | 253 | return (EINVAL); |
46814581 MK |
254 | MALLOC(iov, struct iovec *, |
255 | sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); | |
46814581 MK |
256 | } else |
257 | iov = aiov; | |
258 | auio.uio_iov = iov; | |
b9429893 | 259 | auio.uio_iovcnt = uap->iovcnt; |
c4ec2128 KM |
260 | auio.uio_rw = UIO_WRITE; |
261 | auio.uio_segflg = UIO_USERSPACE; | |
262 | if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, | |
263 | uap->iovcnt * sizeof (struct iovec))) | |
46814581 | 264 | goto done; |
c4ec2128 KM |
265 | auio.uio_resid = 0; |
266 | for (i = 0; i < uap->iovcnt; i++) { | |
b9429893 | 267 | if (iov->iov_len < 0) { |
c4ec2128 KM |
268 | error = EINVAL; |
269 | goto done; | |
b9429893 | 270 | } |
c4ec2128 KM |
271 | auio.uio_resid += iov->iov_len; |
272 | if (auio.uio_resid < 0) { | |
273 | error = EINVAL; | |
274 | goto done; | |
b9429893 | 275 | } |
2a0114a8 | 276 | iov++; |
b9429893 | 277 | } |
46814581 | 278 | #ifdef KTRACE |
c4ec2128 KM |
279 | /* |
280 | * if tracing, save a copy of iovec | |
281 | */ | |
c9714ae3 | 282 | if (KTRPOINT(p, KTR_GENIO)) { |
92e1705e | 283 | unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); |
46814581 MK |
284 | |
285 | MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); | |
c4ec2128 | 286 | bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); |
46814581 MK |
287 | } |
288 | #endif | |
c4ec2128 | 289 | cnt = auio.uio_resid; |
9754d709 MK |
290 | if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { |
291 | if (auio.uio_resid != cnt && (error == ERESTART || | |
292 | error == EINTR || error == EWOULDBLOCK)) | |
293 | error = 0; | |
294 | if (error == EPIPE) | |
c9714ae3 | 295 | psignal(p, SIGPIPE); |
9754d709 | 296 | } |
c4ec2128 | 297 | cnt -= auio.uio_resid; |
46814581 MK |
298 | #ifdef KTRACE |
299 | if (ktriov != NULL) { | |
e64d087d | 300 | if (error == 0) |
c9714ae3 | 301 | ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, |
51322105 | 302 | ktriov, cnt, error); |
46814581 MK |
303 | FREE(ktriov, M_TEMP); |
304 | } | |
305 | #endif | |
c9714ae3 | 306 | *retval = cnt; |
c4ec2128 KM |
307 | done: |
308 | if (uap->iovcnt > UIO_SMALLIOV) | |
309 | FREE(iov, M_IOV); | |
d9c2f47f | 310 | return (error); |
4147b3f6 | 311 | } |
ffe28cfe BJ |
312 | |
313 | /* | |
314 | * Ioctl system call | |
ffe28cfe | 315 | */ |
c9714ae3 KM |
316 | /* ARGSUSED */ |
317 | ioctl(p, uap, retval) | |
318 | struct proc *p; | |
319 | register struct args { | |
ffe28cfe BJ |
320 | int fdes; |
321 | int cmd; | |
322 | caddr_t cmarg; | |
c9714ae3 KM |
323 | } *uap; |
324 | int *retval; | |
325 | { | |
326 | register struct file *fp; | |
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 | |
c4ec2128 KM |
334 | if ((unsigned)uap->fdes >= NOFILE || |
335 | (fp = u.u_ofile[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) { |
3650c37d | 342 | u.u_pofile[uap->fdes] |= UF_EXCLOSE; |
d9c2f47f | 343 | return (0); |
ffe28cfe | 344 | } |
4b72e2f9 | 345 | if (com == FIONCLEX) { |
3650c37d | 346 | u.u_pofile[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: | |
9754d709 | 399 | error = (*fp->f_ops->fo_ioctl)(fp, com, data); |
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)); | |
88a7a62a SL |
433 | if (uap->nd > NOFILE) |
434 | uap->nd = NOFILE; /* forgiving, if 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 KM |
464 | p->p_flag |= SSEL; |
465 | error = selscan(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 | ||
c9714ae3 | 507 | selscan(ibits, obits, nfd, retval) |
b8e71e77 | 508 | fd_set *ibits, *obits; |
c9714ae3 | 509 | int nfd, *retval; |
88a7a62a | 510 | { |
b8e71e77 MK |
511 | register int which, i, j; |
512 | register fd_mask bits; | |
88a7a62a SL |
513 | int flag; |
514 | struct file *fp; | |
c9714ae3 | 515 | int error = 0, n = 0; |
88a7a62a SL |
516 | |
517 | for (which = 0; which < 3; which++) { | |
88a7a62a SL |
518 | switch (which) { |
519 | ||
520 | case 0: | |
521 | flag = FREAD; break; | |
522 | ||
523 | case 1: | |
524 | flag = FWRITE; break; | |
525 | ||
526 | case 2: | |
527 | flag = 0; break; | |
528 | } | |
b8e71e77 MK |
529 | for (i = 0; i < nfd; i += NFDBITS) { |
530 | bits = ibits[which].fds_bits[i/NFDBITS]; | |
d441e5bc MK |
531 | while ((j = ffs(bits)) && i + --j < nfd) { |
532 | bits &= ~(1 << j); | |
533 | fp = u.u_ofile[i + j]; | |
534 | if (fp == NULL) { | |
c9714ae3 | 535 | error = EBADF; |
d441e5bc MK |
536 | break; |
537 | } | |
538 | if ((*fp->f_ops->fo_select)(fp, flag)) { | |
b8e71e77 | 539 | FD_SET(i + j, &obits[which]); |
d441e5bc MK |
540 | n++; |
541 | } | |
88a7a62a SL |
542 | } |
543 | } | |
544 | } | |
c9714ae3 KM |
545 | *retval = n; |
546 | return (error); | |
88a7a62a SL |
547 | } |
548 | ||
ffe28cfe | 549 | /*ARGSUSED*/ |
88a7a62a SL |
550 | seltrue(dev, flag) |
551 | dev_t dev; | |
552 | int flag; | |
ffe28cfe BJ |
553 | { |
554 | ||
88a7a62a | 555 | return (1); |
ffe28cfe | 556 | } |
1edb1cf8 | 557 | |
88a7a62a SL |
558 | selwakeup(p, coll) |
559 | register struct proc *p; | |
560 | int coll; | |
1edb1cf8 BJ |
561 | { |
562 | ||
88a7a62a SL |
563 | if (coll) { |
564 | nselcoll++; | |
565 | wakeup((caddr_t)&selwait); | |
566 | } | |
567 | if (p) { | |
c4e1f1e5 | 568 | int s = splhigh(); |
6bc3aba9 MK |
569 | if (p->p_wchan == (caddr_t)&selwait) { |
570 | if (p->p_stat == SSLEEP) | |
571 | setrun(p); | |
572 | else | |
573 | unsleep(p); | |
574 | } else if (p->p_flag & SSEL) | |
88a7a62a SL |
575 | p->p_flag &= ~SSEL; |
576 | splx(s); | |
577 | } | |
1edb1cf8 | 578 | } |