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 | * | |
c9714ae3 | 17 | * @(#)sys_generic.c 7.17 (Berkeley) %G% |
da7c5cc6 | 18 | */ |
ffe28cfe | 19 | |
94368568 JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
c4ec2128 | 22 | #include "syscontext.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) | |
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 KM |
79 | if (KTRPOINT(p, KTR_GENIO) && error == 0) |
80 | ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt); | |
c4ec2128 | 81 | #endif |
c9714ae3 | 82 | *retval = cnt; |
c4ec2128 | 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) | |
110 | RETURN (EBADF); | |
46814581 | 111 | if (uap->iovcnt > UIO_SMALLIOV) { |
c4ec2128 KM |
112 | if (uap->iovcnt > UIO_MAXIOV) |
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) |
c9714ae3 | 158 | ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); |
c4ec2128 KM |
159 | FREE(ktriov, M_TEMP); |
160 | } | |
161 | #endif | |
c9714ae3 | 162 | *retval = cnt; |
46814581 | 163 | done: |
c4ec2128 | 164 | if (uap->iovcnt > UIO_SMALLIOV) |
46814581 | 165 | FREE(iov, M_IOV); |
c4ec2128 | 166 | RETURN (error); |
ffe28cfe BJ |
167 | } |
168 | ||
169 | /* | |
170 | * Write system call | |
171 | */ | |
c9714ae3 KM |
172 | write(p, uap, retval) |
173 | struct proc *p; | |
174 | register struct args { | |
ffe28cfe BJ |
175 | int fdes; |
176 | char *cbuf; | |
31286ce2 | 177 | unsigned count; |
c9714ae3 KM |
178 | } *uap; |
179 | int *retval; | |
180 | { | |
c4ec2128 | 181 | register struct file *fp; |
b9429893 BJ |
182 | struct uio auio; |
183 | struct iovec aiov; | |
c4ec2128 KM |
184 | long cnt, error = 0; |
185 | #ifdef KTRACE | |
186 | struct iovec ktriov; | |
187 | #endif | |
ffe28cfe | 188 | |
c4ec2128 KM |
189 | if (((unsigned)uap->fdes) >= NOFILE || |
190 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
191 | (fp->f_flag & FWRITE) == 0) | |
192 | RETURN (EBADF); | |
c4ec2128 KM |
193 | aiov.iov_base = (caddr_t)uap->cbuf; |
194 | aiov.iov_len = uap->count; | |
b9429893 BJ |
195 | auio.uio_iov = &aiov; |
196 | auio.uio_iovcnt = 1; | |
c4ec2128 KM |
197 | auio.uio_resid = uap->count; |
198 | auio.uio_rw = UIO_WRITE; | |
199 | auio.uio_segflg = UIO_USERSPACE; | |
200 | #ifdef KTRACE | |
201 | /* | |
202 | * if tracing, save a copy of iovec | |
203 | */ | |
c9714ae3 | 204 | if (KTRPOINT(p, KTR_GENIO)) |
c4ec2128 KM |
205 | ktriov = aiov; |
206 | #endif | |
207 | cnt = uap->count; | |
9754d709 MK |
208 | if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { |
209 | if (auio.uio_resid != cnt && (error == ERESTART || | |
210 | error == EINTR || error == EWOULDBLOCK)) | |
211 | error = 0; | |
212 | if (error == EPIPE) | |
c9714ae3 | 213 | psignal(p, SIGPIPE); |
9754d709 | 214 | } |
c4ec2128 KM |
215 | cnt -= auio.uio_resid; |
216 | #ifdef KTRACE | |
c9714ae3 KM |
217 | if (KTRPOINT(p, KTR_GENIO) && error == 0) |
218 | ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, | |
9fcd9e42 | 219 | &ktriov, cnt); |
c4ec2128 | 220 | #endif |
c9714ae3 | 221 | *retval = cnt; |
c4ec2128 | 222 | RETURN (error); |
b9429893 BJ |
223 | } |
224 | ||
c9714ae3 KM |
225 | /* |
226 | * Gather write system call | |
227 | */ | |
228 | writev(p, uap, retval) | |
229 | struct proc *p; | |
230 | register struct args { | |
b9429893 BJ |
231 | int fdes; |
232 | struct iovec *iovp; | |
31286ce2 | 233 | unsigned iovcnt; |
c9714ae3 KM |
234 | } *uap; |
235 | int *retval; | |
236 | { | |
c4ec2128 | 237 | register struct file *fp; |
b9429893 | 238 | struct uio auio; |
c4ec2128 KM |
239 | register struct iovec *iov; |
240 | struct iovec aiov[UIO_SMALLIOV]; | |
241 | long i, cnt, error = 0; | |
242 | #ifdef KTRACE | |
243 | struct iovec *ktriov = NULL; | |
244 | #endif | |
b9429893 | 245 | |
c4ec2128 KM |
246 | if (((unsigned)uap->fdes) >= NOFILE || |
247 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
248 | (fp->f_flag & FWRITE) == 0) | |
249 | RETURN (EBADF); | |
46814581 | 250 | if (uap->iovcnt > UIO_SMALLIOV) { |
c4ec2128 KM |
251 | if (uap->iovcnt > UIO_MAXIOV) |
252 | RETURN (EINVAL); | |
46814581 MK |
253 | MALLOC(iov, struct iovec *, |
254 | sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); | |
46814581 MK |
255 | } else |
256 | iov = aiov; | |
257 | auio.uio_iov = iov; | |
b9429893 | 258 | auio.uio_iovcnt = uap->iovcnt; |
c4ec2128 KM |
259 | auio.uio_rw = UIO_WRITE; |
260 | auio.uio_segflg = UIO_USERSPACE; | |
261 | if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, | |
262 | uap->iovcnt * sizeof (struct iovec))) | |
46814581 | 263 | goto done; |
c4ec2128 KM |
264 | auio.uio_resid = 0; |
265 | for (i = 0; i < uap->iovcnt; i++) { | |
b9429893 | 266 | if (iov->iov_len < 0) { |
c4ec2128 KM |
267 | error = EINVAL; |
268 | goto done; | |
b9429893 | 269 | } |
c4ec2128 KM |
270 | auio.uio_resid += iov->iov_len; |
271 | if (auio.uio_resid < 0) { | |
272 | error = EINVAL; | |
273 | goto done; | |
b9429893 | 274 | } |
2a0114a8 | 275 | iov++; |
b9429893 | 276 | } |
46814581 | 277 | #ifdef KTRACE |
c4ec2128 KM |
278 | /* |
279 | * if tracing, save a copy of iovec | |
280 | */ | |
c9714ae3 | 281 | if (KTRPOINT(p, KTR_GENIO)) { |
92e1705e | 282 | unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); |
46814581 MK |
283 | |
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, |
e64d087d | 301 | ktriov, cnt); |
46814581 MK |
302 | FREE(ktriov, M_TEMP); |
303 | } | |
304 | #endif | |
c9714ae3 | 305 | *retval = cnt; |
c4ec2128 KM |
306 | done: |
307 | if (uap->iovcnt > UIO_SMALLIOV) | |
308 | FREE(iov, M_IOV); | |
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; | |
9754d709 | 326 | register int com, error; |
b9429893 | 327 | register u_int size; |
e0b18aec | 328 | caddr_t memp = 0; |
c0bb7b0e | 329 | #define STK_PARAMS 128 |
08eb908c MK |
330 | char stkbuf[STK_PARAMS]; |
331 | caddr_t data = stkbuf; | |
ffe28cfe | 332 | |
c4ec2128 KM |
333 | if ((unsigned)uap->fdes >= NOFILE || |
334 | (fp = u.u_ofile[uap->fdes]) == NULL) | |
335 | RETURN (EBADF); | |
9754d709 MK |
336 | if ((fp->f_flag & (FREAD|FWRITE)) == 0) |
337 | RETURN (EBADF); | |
4b72e2f9 SL |
338 | com = uap->cmd; |
339 | ||
4b72e2f9 | 340 | if (com == FIOCLEX) { |
3650c37d | 341 | u.u_pofile[uap->fdes] |= UF_EXCLOSE; |
ffe28cfe BJ |
342 | return; |
343 | } | |
4b72e2f9 | 344 | if (com == FIONCLEX) { |
3650c37d | 345 | u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; |
9754d709 | 346 | RETURN (0); |
ffe28cfe | 347 | } |
4b72e2f9 SL |
348 | |
349 | /* | |
350 | * Interpret high order word to find | |
351 | * amount of data to be copied to/from the | |
352 | * user's address space. | |
4b72e2f9 | 353 | */ |
c0bb7b0e | 354 | size = IOCPARM_LEN(com); |
9754d709 MK |
355 | if (size > IOCPARM_MAX) |
356 | RETURN (ENOTTY); | |
08eb908c | 357 | if (size > sizeof (stkbuf)) { |
46814581 | 358 | memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, |
5adcb337 | 359 | 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); | |
9754d709 | 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); | |
9754d709 | 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); | |
9754d709 MK |
466 | if (error == 0) |
467 | error = u.u_error; /* XXX */ | |
c9714ae3 | 468 | if (error || *retval) |
88a7a62a | 469 | goto done; |
c4e1f1e5 | 470 | s = splhigh(); |
e394e134 SL |
471 | /* this should be timercmp(&time, &atv, >=) */ |
472 | if (uap->tv && (time.tv_sec > atv.tv_sec || | |
473 | time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { | |
88a7a62a SL |
474 | splx(s); |
475 | goto done; | |
476 | } | |
c9714ae3 | 477 | if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { |
88a7a62a SL |
478 | splx(s); |
479 | goto retry; | |
480 | } | |
c9714ae3 | 481 | p->p_flag &= ~SSEL; |
9754d709 | 482 | error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); |
88a7a62a | 483 | splx(s); |
9754d709 MK |
484 | if (error == 0) |
485 | goto retry; | |
88a7a62a | 486 | done: |
c9714ae3 | 487 | p->p_flag &= ~SSEL; |
9754d709 MK |
488 | /* select is not restarted after signals... */ |
489 | if (error == ERESTART) | |
490 | error = EINTR; | |
491 | if (error == EWOULDBLOCK) | |
492 | error = 0; | |
88a7a62a SL |
493 | #define putbits(name, x) \ |
494 | if (uap->name) { \ | |
9754d709 | 495 | int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ |
01b0e233 | 496 | (unsigned)(ni * sizeof(fd_mask))); \ |
9754d709 MK |
497 | if (error2) \ |
498 | error = error2; \ | |
88a7a62a | 499 | } |
9754d709 | 500 | if (error == 0) { |
79f403fc MK |
501 | putbits(in, 0); |
502 | putbits(ou, 1); | |
503 | putbits(ex, 2); | |
88a7a62a | 504 | #undef putbits |
79f403fc | 505 | } |
9754d709 | 506 | RETURN (error); |
88a7a62a SL |
507 | } |
508 | ||
c9714ae3 | 509 | selscan(ibits, obits, nfd, retval) |
b8e71e77 | 510 | fd_set *ibits, *obits; |
c9714ae3 | 511 | int nfd, *retval; |
88a7a62a | 512 | { |
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); | |
535 | fp = u.u_ofile[i + j]; | |
536 | if (fp == NULL) { | |
c9714ae3 | 537 | error = EBADF; |
d441e5bc MK |
538 | break; |
539 | } | |
540 | if ((*fp->f_ops->fo_select)(fp, flag)) { | |
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*/ |
88a7a62a SL |
552 | seltrue(dev, flag) |
553 | dev_t dev; | |
554 | int flag; | |
ffe28cfe BJ |
555 | { |
556 | ||
88a7a62a | 557 | return (1); |
ffe28cfe | 558 | } |
1edb1cf8 | 559 | |
88a7a62a SL |
560 | selwakeup(p, coll) |
561 | register struct proc *p; | |
562 | int coll; | |
1edb1cf8 BJ |
563 | { |
564 | ||
88a7a62a SL |
565 | if (coll) { |
566 | nselcoll++; | |
567 | wakeup((caddr_t)&selwait); | |
568 | } | |
569 | if (p) { | |
c4e1f1e5 | 570 | int s = splhigh(); |
6bc3aba9 MK |
571 | if (p->p_wchan == (caddr_t)&selwait) { |
572 | if (p->p_stat == SSLEEP) | |
573 | setrun(p); | |
574 | else | |
575 | unsleep(p); | |
576 | } else if (p->p_flag & SSEL) | |
88a7a62a SL |
577 | p->p_flag &= ~SSEL; |
578 | splx(s); | |
579 | } | |
1edb1cf8 | 580 | } |