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