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 | * | |
9fcd9e42 | 17 | * @(#)sys_generic.c 7.12 (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 | */ | |
37 | read() | |
38 | { | |
ffe28cfe BJ |
39 | register struct a { |
40 | int fdes; | |
41 | char *cbuf; | |
42 | unsigned count; | |
b9429893 | 43 | } *uap = (struct a *)u.u_ap; |
c4ec2128 | 44 | register struct file *fp; |
32a43ee2 BJ |
45 | struct uio auio; |
46 | struct iovec aiov; | |
c4ec2128 KM |
47 | long cnt, error = 0; |
48 | #ifdef KTRACE | |
49 | struct iovec ktriov; | |
50 | #endif | |
ffe28cfe | 51 | |
c4ec2128 KM |
52 | if (((unsigned)uap->fdes) >= NOFILE || |
53 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
54 | (fp->f_flag & FREAD) == 0) | |
55 | RETURN (EBADF); | |
56 | if (uap->count < 0) | |
57 | RETURN (EINVAL); | |
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 | */ | |
69 | if (KTRPOINT(u.u_procp, KTR_GENIO)) | |
70 | ktriov = aiov; | |
71 | #endif | |
72 | cnt = uap->count; | |
73 | if (setjmp(&u.u_qsave)) { | |
74 | if (auio.uio_resid == cnt) { | |
75 | if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) | |
76 | error = EINTR; | |
77 | else | |
78 | u.u_eosys = RESTARTSYS; | |
79 | } | |
80 | } else | |
ceeca39b | 81 | error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); |
c4ec2128 KM |
82 | cnt -= auio.uio_resid; |
83 | #ifdef KTRACE | |
84 | if (KTRPOINT(u.u_procp, KTR_GENIO)) | |
9fcd9e42 | 85 | ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt); |
c4ec2128 KM |
86 | #endif |
87 | u.u_r.r_val1 = cnt; | |
88 | RETURN (error); | |
b9429893 BJ |
89 | } |
90 | ||
91 | readv() | |
92 | { | |
93 | register struct a { | |
94 | int fdes; | |
95 | struct iovec *iovp; | |
31286ce2 | 96 | unsigned iovcnt; |
b9429893 | 97 | } *uap = (struct a *)u.u_ap; |
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 | */ | |
142 | if (KTRPOINT(u.u_procp, KTR_GENIO)) { | |
143 | int iovlen = auio.uio_iovcnt * sizeof (struct iovec); | |
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; | |
150 | if (setjmp(&u.u_qsave)) { | |
151 | if (auio.uio_resid == cnt) { | |
152 | if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) | |
153 | error = EINTR; | |
154 | else | |
155 | u.u_eosys = RESTARTSYS; | |
156 | } | |
157 | } else | |
ceeca39b | 158 | error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); |
c4ec2128 KM |
159 | cnt -= auio.uio_resid; |
160 | #ifdef KTRACE | |
161 | if (ktriov != NULL) { | |
162 | ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); | |
163 | FREE(ktriov, M_TEMP); | |
164 | } | |
165 | #endif | |
166 | u.u_r.r_val1 = cnt; | |
46814581 | 167 | done: |
c4ec2128 | 168 | if (uap->iovcnt > UIO_SMALLIOV) |
46814581 | 169 | FREE(iov, M_IOV); |
c4ec2128 | 170 | RETURN (error); |
ffe28cfe BJ |
171 | } |
172 | ||
173 | /* | |
174 | * Write system call | |
175 | */ | |
176 | write() | |
177 | { | |
ffe28cfe BJ |
178 | register struct a { |
179 | int fdes; | |
180 | char *cbuf; | |
31286ce2 | 181 | unsigned count; |
b9429893 | 182 | } *uap = (struct a *)u.u_ap; |
c4ec2128 | 183 | register struct file *fp; |
b9429893 BJ |
184 | struct uio auio; |
185 | struct iovec aiov; | |
c4ec2128 KM |
186 | long cnt, error = 0; |
187 | #ifdef KTRACE | |
188 | struct iovec ktriov; | |
189 | #endif | |
ffe28cfe | 190 | |
c4ec2128 KM |
191 | if (((unsigned)uap->fdes) >= NOFILE || |
192 | (fp = u.u_ofile[uap->fdes]) == NULL || | |
193 | (fp->f_flag & FWRITE) == 0) | |
194 | RETURN (EBADF); | |
195 | if (uap->count < 0) | |
196 | RETURN (EINVAL); | |
197 | aiov.iov_base = (caddr_t)uap->cbuf; | |
198 | aiov.iov_len = uap->count; | |
b9429893 BJ |
199 | auio.uio_iov = &aiov; |
200 | auio.uio_iovcnt = 1; | |
c4ec2128 KM |
201 | auio.uio_resid = uap->count; |
202 | auio.uio_rw = UIO_WRITE; | |
203 | auio.uio_segflg = UIO_USERSPACE; | |
204 | #ifdef KTRACE | |
205 | /* | |
206 | * if tracing, save a copy of iovec | |
207 | */ | |
208 | if (KTRPOINT(u.u_procp, KTR_GENIO)) | |
209 | ktriov = aiov; | |
210 | #endif | |
211 | cnt = uap->count; | |
212 | if (setjmp(&u.u_qsave)) { | |
213 | if (auio.uio_resid == cnt) { | |
214 | if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) | |
215 | error = EINTR; | |
216 | else | |
217 | u.u_eosys = RESTARTSYS; | |
218 | } | |
219 | } else | |
ceeca39b | 220 | error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); |
c4ec2128 KM |
221 | cnt -= auio.uio_resid; |
222 | #ifdef KTRACE | |
223 | if (KTRPOINT(u.u_procp, KTR_GENIO)) | |
224 | ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, | |
9fcd9e42 | 225 | &ktriov, cnt); |
c4ec2128 KM |
226 | #endif |
227 | u.u_r.r_val1 = cnt; | |
228 | RETURN (error); | |
b9429893 BJ |
229 | } |
230 | ||
231 | writev() | |
232 | { | |
233 | register struct a { | |
234 | int fdes; | |
235 | struct iovec *iovp; | |
31286ce2 | 236 | unsigned iovcnt; |
b9429893 | 237 | } *uap = (struct a *)u.u_ap; |
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) | |
250 | RETURN (EBADF); | |
46814581 | 251 | if (uap->iovcnt > UIO_SMALLIOV) { |
c4ec2128 KM |
252 | if (uap->iovcnt > UIO_MAXIOV) |
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 | */ | |
46814581 | 282 | if (KTRPOINT(u.u_procp, KTR_GENIO)) { |
c4ec2128 | 283 | int 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; |
fe7f81f4 | 290 | if (setjmp(&u.u_qsave)) { |
c4ec2128 | 291 | if (auio.uio_resid == cnt) { |
9f49ba41 | 292 | if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) |
c4ec2128 | 293 | error = EINTR; |
fe7f81f4 KM |
294 | else |
295 | u.u_eosys = RESTARTSYS; | |
296 | } | |
b9429893 | 297 | } else |
ceeca39b | 298 | error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); |
c4ec2128 | 299 | cnt -= auio.uio_resid; |
46814581 MK |
300 | #ifdef KTRACE |
301 | if (ktriov != NULL) { | |
c4ec2128 KM |
302 | ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, |
303 | ktriov, cnt); | |
46814581 MK |
304 | FREE(ktriov, M_TEMP); |
305 | } | |
306 | #endif | |
c4ec2128 KM |
307 | u.u_r.r_val1 = cnt; |
308 | done: | |
309 | if (uap->iovcnt > UIO_SMALLIOV) | |
310 | FREE(iov, M_IOV); | |
311 | RETURN (error); | |
4147b3f6 | 312 | } |
ffe28cfe BJ |
313 | |
314 | /* | |
315 | * Ioctl system call | |
ffe28cfe BJ |
316 | */ |
317 | ioctl() | |
318 | { | |
319 | register struct file *fp; | |
4b72e2f9 | 320 | struct a { |
ffe28cfe BJ |
321 | int fdes; |
322 | int cmd; | |
323 | caddr_t cmarg; | |
c4ec2128 | 324 | } *uap = (struct a *)u.u_ap; |
b9429893 BJ |
325 | register int com; |
326 | register u_int size; | |
e0b18aec | 327 | caddr_t memp = 0; |
c0bb7b0e | 328 | #define STK_PARAMS 128 |
08eb908c MK |
329 | char stkbuf[STK_PARAMS]; |
330 | caddr_t data = stkbuf; | |
ffe28cfe | 331 | |
c4ec2128 KM |
332 | if ((unsigned)uap->fdes >= NOFILE || |
333 | (fp = u.u_ofile[uap->fdes]) == NULL) | |
334 | RETURN (EBADF); | |
ffe28cfe BJ |
335 | if ((fp->f_flag & (FREAD|FWRITE)) == 0) { |
336 | u.u_error = EBADF; | |
337 | return; | |
338 | } | |
4b72e2f9 SL |
339 | com = uap->cmd; |
340 | ||
4b72e2f9 | 341 | if (com == FIOCLEX) { |
3650c37d | 342 | u.u_pofile[uap->fdes] |= UF_EXCLOSE; |
ffe28cfe BJ |
343 | return; |
344 | } | |
4b72e2f9 | 345 | if (com == FIONCLEX) { |
3650c37d | 346 | u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; |
ffe28cfe BJ |
347 | return; |
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 MK |
355 | size = IOCPARM_LEN(com); |
356 | if (size > IOCPARM_MAX) { | |
46814581 | 357 | u.u_error = ENOTTY; |
ffe28cfe BJ |
358 | return; |
359 | } | |
08eb908c | 360 | if (size > sizeof (stkbuf)) { |
46814581 | 361 | memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, |
5adcb337 | 362 | M_WAITOK); |
e0b18aec | 363 | data = memp; |
c0bb7b0e | 364 | } |
471f17ed SL |
365 | if (com&IOC_IN) { |
366 | if (size) { | |
46814581 | 367 | u.u_error = copyin(uap->cmarg, data, (u_int)size); |
e0b18aec KM |
368 | if (u.u_error) { |
369 | if (memp) | |
370 | free(memp, M_IOCTLOPS); | |
471f17ed | 371 | return; |
e0b18aec | 372 | } |
471f17ed SL |
373 | } else |
374 | *(caddr_t *)data = uap->cmarg; | |
375 | } else if ((com&IOC_OUT) && size) | |
376 | /* | |
46814581 MK |
377 | * Zero the buffer so the user always |
378 | * gets back something deterministic. | |
471f17ed | 379 | */ |
c0bb7b0e | 380 | bzero(data, size); |
a76b60f6 SL |
381 | else if (com&IOC_VOID) |
382 | *(caddr_t *)data = uap->cmarg; | |
4b72e2f9 | 383 | |
88a7a62a SL |
384 | switch (com) { |
385 | ||
386 | case FIONBIO: | |
387 | u.u_error = fset(fp, FNDELAY, *(int *)data); | |
c0bb7b0e | 388 | break; |
88a7a62a SL |
389 | |
390 | case FIOASYNC: | |
391 | u.u_error = fset(fp, FASYNC, *(int *)data); | |
c0bb7b0e | 392 | break; |
88a7a62a SL |
393 | |
394 | case FIOSETOWN: | |
395 | u.u_error = fsetown(fp, *(int *)data); | |
c0bb7b0e | 396 | break; |
4b72e2f9 | 397 | |
88a7a62a SL |
398 | case FIOGETOWN: |
399 | u.u_error = fgetown(fp, (int *)data); | |
c0bb7b0e MK |
400 | break; |
401 | default: | |
402 | if (setjmp(&u.u_qsave)) | |
403 | u.u_error = EINTR; | |
404 | else | |
405 | u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); | |
406 | /* | |
407 | * Copy any data to user, size was | |
408 | * already set and checked above. | |
409 | */ | |
410 | if (u.u_error == 0 && (com&IOC_OUT) && size) | |
411 | u.u_error = copyout(data, uap->cmarg, (u_int)size); | |
412 | break; | |
88a7a62a | 413 | } |
e0b18aec KM |
414 | if (memp) |
415 | free(memp, M_IOCTLOPS); | |
ffe28cfe BJ |
416 | } |
417 | ||
88a7a62a SL |
418 | int unselect(); |
419 | int nselcoll; | |
d441e5bc | 420 | |
ffe28cfe | 421 | /* |
88a7a62a | 422 | * Select system call. |
ffe28cfe | 423 | */ |
88a7a62a SL |
424 | select() |
425 | { | |
426 | register struct uap { | |
427 | int nd; | |
b8e71e77 | 428 | fd_set *in, *ou, *ex; |
88a7a62a SL |
429 | struct timeval *tv; |
430 | } *uap = (struct uap *)u.u_ap; | |
b8e71e77 | 431 | fd_set ibits[3], obits[3]; |
88a7a62a | 432 | struct timeval atv; |
d441e5bc | 433 | int s, ncoll, ni; |
88a7a62a SL |
434 | label_t lqsave; |
435 | ||
01b0e233 MK |
436 | bzero((caddr_t)ibits, sizeof(ibits)); |
437 | bzero((caddr_t)obits, sizeof(obits)); | |
88a7a62a SL |
438 | if (uap->nd > NOFILE) |
439 | uap->nd = NOFILE; /* forgiving, if slightly wrong */ | |
b8e71e77 | 440 | ni = howmany(uap->nd, NFDBITS); |
88a7a62a SL |
441 | |
442 | #define getbits(name, x) \ | |
443 | if (uap->name) { \ | |
b8e71e77 | 444 | u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ |
01b0e233 | 445 | (unsigned)(ni * sizeof(fd_mask))); \ |
88a7a62a SL |
446 | if (u.u_error) \ |
447 | goto done; \ | |
d441e5bc | 448 | } |
88a7a62a SL |
449 | getbits(in, 0); |
450 | getbits(ou, 1); | |
451 | getbits(ex, 2); | |
452 | #undef getbits | |
453 | ||
454 | if (uap->tv) { | |
455 | u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, | |
456 | sizeof (atv)); | |
457 | if (u.u_error) | |
458 | goto done; | |
459 | if (itimerfix(&atv)) { | |
460 | u.u_error = EINVAL; | |
461 | goto done; | |
462 | } | |
c4e1f1e5 | 463 | s = splhigh(); timevaladd(&atv, &time); splx(s); |
88a7a62a SL |
464 | } |
465 | retry: | |
466 | ncoll = nselcoll; | |
467 | u.u_procp->p_flag |= SSEL; | |
d441e5bc | 468 | u.u_r.r_val1 = selscan(ibits, obits, uap->nd); |
88a7a62a SL |
469 | if (u.u_error || u.u_r.r_val1) |
470 | goto done; | |
c4e1f1e5 | 471 | s = splhigh(); |
e394e134 SL |
472 | /* this should be timercmp(&time, &atv, >=) */ |
473 | if (uap->tv && (time.tv_sec > atv.tv_sec || | |
474 | time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { | |
88a7a62a SL |
475 | splx(s); |
476 | goto done; | |
477 | } | |
478 | if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { | |
88a7a62a SL |
479 | splx(s); |
480 | goto retry; | |
481 | } | |
482 | u.u_procp->p_flag &= ~SSEL; | |
483 | if (uap->tv) { | |
484 | lqsave = u.u_qsave; | |
485 | if (setjmp(&u.u_qsave)) { | |
486 | untimeout(unselect, (caddr_t)u.u_procp); | |
487 | u.u_error = EINTR; | |
488 | splx(s); | |
489 | goto done; | |
490 | } | |
491 | timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); | |
492 | } | |
493 | sleep((caddr_t)&selwait, PZERO+1); | |
494 | if (uap->tv) { | |
495 | u.u_qsave = lqsave; | |
496 | untimeout(unselect, (caddr_t)u.u_procp); | |
497 | } | |
498 | splx(s); | |
499 | goto retry; | |
500 | done: | |
b894ed59 | 501 | u.u_procp->p_flag &= ~SSEL; |
88a7a62a SL |
502 | #define putbits(name, x) \ |
503 | if (uap->name) { \ | |
b8e71e77 | 504 | int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ |
01b0e233 | 505 | (unsigned)(ni * sizeof(fd_mask))); \ |
88a7a62a SL |
506 | if (error) \ |
507 | u.u_error = error; \ | |
508 | } | |
87a3ba07 | 509 | if (u.u_error == 0) { |
79f403fc MK |
510 | putbits(in, 0); |
511 | putbits(ou, 1); | |
512 | putbits(ex, 2); | |
88a7a62a | 513 | #undef putbits |
79f403fc | 514 | } |
88a7a62a SL |
515 | } |
516 | ||
517 | unselect(p) | |
518 | register struct proc *p; | |
519 | { | |
c4e1f1e5 | 520 | register int s = splhigh(); |
88a7a62a SL |
521 | |
522 | switch (p->p_stat) { | |
523 | ||
524 | case SSLEEP: | |
525 | setrun(p); | |
526 | break; | |
527 | ||
528 | case SSTOP: | |
529 | unsleep(p); | |
530 | break; | |
531 | } | |
532 | splx(s); | |
533 | } | |
534 | ||
d441e5bc | 535 | selscan(ibits, obits, nfd) |
b8e71e77 | 536 | fd_set *ibits, *obits; |
88a7a62a | 537 | { |
b8e71e77 MK |
538 | register int which, i, j; |
539 | register fd_mask bits; | |
88a7a62a SL |
540 | int flag; |
541 | struct file *fp; | |
542 | int n = 0; | |
543 | ||
544 | for (which = 0; which < 3; which++) { | |
88a7a62a SL |
545 | switch (which) { |
546 | ||
547 | case 0: | |
548 | flag = FREAD; break; | |
549 | ||
550 | case 1: | |
551 | flag = FWRITE; break; | |
552 | ||
553 | case 2: | |
554 | flag = 0; break; | |
555 | } | |
b8e71e77 MK |
556 | for (i = 0; i < nfd; i += NFDBITS) { |
557 | bits = ibits[which].fds_bits[i/NFDBITS]; | |
d441e5bc MK |
558 | while ((j = ffs(bits)) && i + --j < nfd) { |
559 | bits &= ~(1 << j); | |
560 | fp = u.u_ofile[i + j]; | |
561 | if (fp == NULL) { | |
562 | u.u_error = EBADF; | |
563 | break; | |
564 | } | |
565 | if ((*fp->f_ops->fo_select)(fp, flag)) { | |
b8e71e77 | 566 | FD_SET(i + j, &obits[which]); |
d441e5bc MK |
567 | n++; |
568 | } | |
88a7a62a SL |
569 | } |
570 | } | |
571 | } | |
572 | return (n); | |
573 | } | |
574 | ||
ffe28cfe | 575 | /*ARGSUSED*/ |
88a7a62a SL |
576 | seltrue(dev, flag) |
577 | dev_t dev; | |
578 | int flag; | |
ffe28cfe BJ |
579 | { |
580 | ||
88a7a62a | 581 | return (1); |
ffe28cfe | 582 | } |
1edb1cf8 | 583 | |
88a7a62a SL |
584 | selwakeup(p, coll) |
585 | register struct proc *p; | |
586 | int coll; | |
1edb1cf8 BJ |
587 | { |
588 | ||
88a7a62a SL |
589 | if (coll) { |
590 | nselcoll++; | |
591 | wakeup((caddr_t)&selwait); | |
592 | } | |
593 | if (p) { | |
c4e1f1e5 | 594 | int s = splhigh(); |
6bc3aba9 MK |
595 | if (p->p_wchan == (caddr_t)&selwait) { |
596 | if (p->p_stat == SSLEEP) | |
597 | setrun(p); | |
598 | else | |
599 | unsleep(p); | |
600 | } else if (p->p_flag & SSEL) | |
88a7a62a SL |
601 | p->p_flag &= ~SSEL; |
602 | splx(s); | |
603 | } | |
1edb1cf8 | 604 | } |