opause not here
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
8d528261 1/* kern_descrip.c 5.9 82/09/08 */
40056b21
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
3ebb7a40 7#include "../h/kernel.h"
40056b21
BJ
8#include "../h/inode.h"
9#include "../h/proc.h"
40056b21 10#include "../h/conf.h"
40056b21
BJ
11#include "../h/file.h"
12#include "../h/inline.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
4147b3f6
BJ
15#include "../h/mount.h"
16
17#include "../h/descrip.h"
18
19/*
20 * Descriptor management.
21 */
22
23/*
24 * TODO:
25 * getf should be renamed
26 * ufalloc side effects are gross
27 */
40056b21
BJ
28
29/*
4147b3f6 30 * System calls on descriptors.
40056b21 31 */
3ebb7a40 32getdtablesize()
4147b3f6
BJ
33{
34
35 u.u_r.r_val1 = NOFILE;
36}
37
27b91f59
BJ
38getdprop()
39{
40 register struct a {
41 int d;
42 struct dtype *dtypeb;
43 } *uap = (struct a *)u.u_ap;
44 register struct file *fp;
45 struct dtype adtype;
46
47 fp = getf(uap->d);
48 if (fp == 0)
49 return;
50 adtype.dt_type = 0; /* XXX */
51 adtype.dt_protocol = 0; /* XXX */
52 if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb,
53 sizeof (struct dtype)) < 0) {
54 u.u_error = EFAULT;
55 return;
56 }
57}
58
59getdopt()
60{
61
62}
63
64setdopt()
65{
66
67}
68
40056b21
BJ
69dup()
70{
4147b3f6
BJ
71 register struct a {
72 int i;
73 } *uap = (struct a *) u.u_ap;
a81e9a81
SL
74 struct file *fp;
75 int j;
4147b3f6
BJ
76
77 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
78
79 fp = getf(uap->i);
80 if (fp == 0)
81 return;
82 j = ufalloc();
83 if (j < 0)
84 return;
a81e9a81 85 dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK));
4147b3f6
BJ
86}
87
88dup2()
89{
40056b21 90 register struct a {
4147b3f6
BJ
91 int i, j;
92 } *uap = (struct a *) u.u_ap;
93 register struct file *fp;
40056b21 94
4147b3f6
BJ
95 fp = getf(uap->i);
96 if (fp == 0)
97 return;
98 if (uap->j < 0 || uap->j >= NOFILE) {
99 u.u_error = EBADF;
40056b21 100 return;
40056b21 101 }
4147b3f6
BJ
102 u.u_r.r_val1 = uap->j;
103 if (uap->i == uap->j)
104 return;
105 if (u.u_ofile[uap->j]) {
a81e9a81 106 closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]);
40056b21
BJ
107 if (u.u_error)
108 return;
4147b3f6 109 /* u.u_ofile[uap->j] = 0; */
a81e9a81 110 /* u.u_pofile[uap->j] = 0; */
4147b3f6 111 }
a81e9a81
SL
112 dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK));
113}
114
115dupit(fd, fp, lockflags)
116 int fd;
117 register struct file *fp;
118 register int lockflags;
119{
120
121 u.u_ofile[fd] = fp;
122 u.u_pofile[fd] = lockflags;
4147b3f6 123 fp->f_count++;
a81e9a81
SL
124 if (lockflags&RDLOCK)
125 fp->f_inode->i_rdlockc++;
126 if (lockflags&WRLOCK)
127 fp->f_inode->i_wrlockc++;
4147b3f6
BJ
128}
129
130close()
131{
132 register struct a {
133 int i;
134 } *uap = (struct a *)u.u_ap;
135 register struct file *fp;
136
137 fp = getf(uap->i);
138 if (fp == 0)
139 return;
a81e9a81 140 closef(fp, 0, u.u_pofile[uap->i]);
4147b3f6 141 /* WHAT IF u.u_error ? */
a81e9a81
SL
142 u.u_ofile[uap->i] = NULL;
143 u.u_pofile[uap->i] = 0;
4147b3f6
BJ
144}
145
3ebb7a40 146wrap()
4147b3f6
BJ
147{
148 register struct a {
149 int d;
150 struct dtype *dtypeb;
151 } *uap = (struct a *)u.u_ap;
152 register struct file *fp;
153 struct dtype adtype;
154
155 fp = getf(uap->d);
156 if (fp == 0)
157 return;
158 if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype,
159 sizeof (struct dtype)) < 0) {
160 u.u_error = EFAULT;
161 return;
40056b21 162 }
4147b3f6
BJ
163 /* DO WRAP */
164}
165
12438177 166int unselect();
40056b21
BJ
167int nselcoll;
168/*
169 * Select system call.
170 */
27b91f59 171select()
40056b21
BJ
172{
173 register struct uap {
12438177
BJ
174 long *ibits;
175 long *obits;
3ebb7a40
BJ
176 struct timeval *tv;
177 } *uap = (struct uap *)u.u_ap;
12438177
BJ
178 int ibits[3], obits[3];
179 struct timeval atv;
40056b21 180 int s, tsel, ncoll, rem;
12438177 181 label_t lqsave;
40056b21 182
3ebb7a40
BJ
183 if (uap->tv) {
184 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) {
185 u.u_error = EFAULT;
186 return;
187 }
12438177
BJ
188 if (itimerfix(&atv)) {
189 u.u_error = EINVAL;
190 return;
191 }
192 s = spl7(); timevaladd(&atv, &time); splx(s);
193 }
194 if (copyin((caddr_t)uap->ibits, (caddr_t)ibits, sizeof (ibits))) {
195 u.u_error = EFAULT;
40056b21 196 return;
12438177 197 }
40056b21
BJ
198retry:
199 ncoll = nselcoll;
200 u.u_procp->p_flag |= SSEL;
12438177 201 u.u_r.r_val1 = selscan(ibits, obits);
40056b21 202 if (u.u_error)
12438177
BJ
203 return;
204 if (u.u_r.r_val1)
40056b21
BJ
205 goto done;
206 s = spl6();
12438177
BJ
207 if (uap->tv && timercmp(&atv, &time, >=)) {
208 splx(s);
209 goto done;
210 }
40056b21
BJ
211 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
212 u.u_procp->p_flag &= ~SSEL;
213 splx(s);
214 goto retry;
215 }
216 u.u_procp->p_flag &= ~SSEL;
12438177
BJ
217 if (uap->tv) {
218 lqsave = u.u_qsave;
219 if (setjmp(&u.u_qsave)) {
220 untimeout(unselect, u.u_procp);
221 u.u_error = EINTR;
222 splx(s);
223 return;
224 }
225 timeout(unselect, u.u_procp, hzto(&atv));
226 }
227 sleep((caddr_t)&selwait, PZERO+1);
228 if (uap->tv) {
229 u.u_qsave = lqsave;
230 untimeout(unselect, u.u_procp);
231 }
40056b21 232 splx(s);
12438177
BJ
233 goto retry;
234done:
235 if (copyout((caddr_t)obits, (caddr_t)uap->obits, sizeof (obits))) {
236 u.u_error = EFAULT;
40056b21 237 return;
12438177
BJ
238 }
239}
240
241unselect(p)
242 register struct proc *p;
243{
244 register int s = spl6();
40056b21 245
12438177
BJ
246 switch (p->p_stat) {
247
248 case SSLEEP:
249 setrun(p);
250 break;
251
252 case SSTOP:
253 unsleep(p);
40056b21
BJ
254 break;
255 }
12438177 256 splx(s);
40056b21
BJ
257}
258
12438177
BJ
259selscan(ibits, obits)
260 int *ibits, *obits;
40056b21 261{
12438177
BJ
262 register int which, bits, i;
263 int flag;
40056b21 264 struct file *fp;
12438177 265 int able;
40056b21 266 struct inode *ip;
12438177 267 int n = 0;
40056b21 268
12438177
BJ
269 for (which = 0; which < 3; which++) {
270 bits = ibits[which];
271 obits[which] = 0;
272 switch (which) {
273
274 case 0:
275 flag = FREAD; break;
40056b21 276
12438177
BJ
277 case 1:
278 flag = FWRITE; break;
279
280 case 2:
281 flag = 0; break;
282 }
283 while (i = ffs(bits)) {
284 bits &= ~(1<<(i-1));
285 fp = u.u_ofile[i-1];
286 if (fp == NULL) {
287 u.u_error = EBADF;
40056b21
BJ
288 break;
289 }
12438177
BJ
290 if (fp->f_type == DTYPE_SOCKET)
291 able = soselect(fp->f_socket, flag);
292 else {
293 ip = fp->f_inode;
294 switch (ip->i_mode & IFMT) {
295
296 case IFCHR:
297 able =
298 (*cdevsw[major(ip->i_rdev)].d_select)
299 (ip->i_rdev, flag);
300 break;
301
302 case IFBLK:
303 case IFREG:
304 case IFDIR:
305 able = 1;
306 break;
307 }
4147b3f6 308
12438177
BJ
309 }
310 if (able) {
311 obits[which] |= (1<<(i-1));
312 n++;
313 }
40056b21
BJ
314 }
315 }
12438177 316 return (n);
40056b21
BJ
317}
318
319/*ARGSUSED*/
320seltrue(dev, flag)
321 dev_t dev;
322 int flag;
323{
324
325 return (1);
326}
327
328selwakeup(p, coll)
329 register struct proc *p;
330 int coll;
331{
332 int s;
333
334 if (coll) {
335 nselcoll++;
336 wakeup((caddr_t)&selwait);
337 }
338 if (p) {
339 if (p->p_wchan == (caddr_t)&selwait)
340 setrun(p);
341 else {
342 s = spl6();
343 if (p->p_flag & SSEL)
344 p->p_flag &= ~SSEL;
345 splx(s);
346 }
347 }
348}
349
3ebb7a40
BJ
350revoke()
351{
352
353 /* XXX */
354}
355
40056b21 356/*
4147b3f6 357 * Allocate a user file descriptor.
40056b21 358 */
4147b3f6
BJ
359ufalloc()
360{
361 register i;
362
363 for (i=0; i<NOFILE; i++)
364 if (u.u_ofile[i] == NULL) {
365 u.u_r.r_val1 = i;
366 u.u_pofile[i] = 0;
367 return (i);
368 }
369 u.u_error = EMFILE;
370 return (-1);
371}
372
373struct file *lastf;
374/*
375 * Allocate a user file descriptor
376 * and a file structure.
377 * Initialize the descriptor
378 * to point at the file structure.
379 */
380struct file *
381falloc()
382{
383 register struct file *fp;
384 register i;
385
386 i = ufalloc();
387 if (i < 0)
388 return (NULL);
389 if (lastf == 0)
390 lastf = file;
391 for (fp = lastf; fp < fileNFILE; fp++)
392 if (fp->f_count == 0)
393 goto slot;
394 for (fp = file; fp < lastf; fp++)
395 if (fp->f_count == 0)
396 goto slot;
397 tablefull("file");
398 u.u_error = ENFILE;
399 return (NULL);
400slot:
401 u.u_ofile[i] = fp;
402 fp->f_count++;
403 fp->f_offset = 0;
404 fp->f_inode = 0;
405 lastf = fp + 1;
406 return (fp);
407}
408/*
409 * Convert a user supplied file descriptor into a pointer
410 * to a file structure. Only task is to check range of the descriptor.
411 * Critical paths should use the GETF macro, defined in inline.h.
412 */
413struct file *
414getf(f)
415 register int f;
40056b21
BJ
416{
417 register struct file *fp;
40056b21 418
4147b3f6
BJ
419 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
420 u.u_error = EBADF;
421 return (NULL);
422 }
423 return (fp);
424}
425
426/*
427 * Internal form of close.
428 * Decrement reference count on
429 * file structure.
430 * Also make sure the pipe protocol
431 * does not constipate.
432 *
433 * Decrement reference count on the inode following
434 * removal to the referencing file structure.
435 * Call device handler on last close.
436 * Nouser indicates that the user isn't available to present
437 * errors to.
a81e9a81
SL
438 *
439 * Handling locking at this level is RIDICULOUS.
4147b3f6 440 */
a81e9a81 441closef(fp, nouser, flags)
4147b3f6 442 register struct file *fp;
a81e9a81 443 int nouser, flags;
4147b3f6
BJ
444{
445 register struct inode *ip;
446 register struct mount *mp;
447 int flag, mode;
448 dev_t dev;
449 register int (*cfunc)();
450
40056b21
BJ
451 if (fp == NULL)
452 return;
4147b3f6
BJ
453 if (fp->f_count > 1) {
454 fp->f_count--;
40056b21
BJ
455 return;
456 }
4147b3f6
BJ
457 if (fp->f_type == DTYPE_SOCKET) {
458 u.u_error = 0; /* XXX */
459 soclose(fp->f_socket, nouser);
460 if (nouser == 0 && u.u_error)
461 return;
462 fp->f_socket = 0;
463 fp->f_count = 0;
464 return;
465 }
466 flag = fp->f_flag;
467 ip = fp->f_inode;
468 dev = (dev_t)ip->i_rdev;
469 mode = ip->i_mode & IFMT;
a81e9a81
SL
470 flags &= RDLOCK|WRLOCK; /* conservative */
471 if (flags)
472 funlocki(ip, flags);
4147b3f6
BJ
473 ilock(ip);
474 iput(ip);
475 fp->f_count = 0;
476
477 switch (mode) {
478
479 case IFCHR:
480 cfunc = cdevsw[major(dev)].d_close;
4147b3f6
BJ
481 break;
482
483 case IFBLK:
484 /*
485 * We don't want to really close the device if it is mounted
486 */
487 for (mp = mount; mp < &mount[NMOUNT]; mp++)
488 if (mp->m_bufp != NULL && mp->m_dev == dev)
489 return;
490 cfunc = bdevsw[major(dev)].d_close;
491 break;
492
493 default:
494 return;
495 }
496 for (fp = file; fp < fileNFILE; fp++) {
497 if (fp->f_type == DTYPE_SOCKET) /* XXX */
498 continue;
499 if (fp->f_count && (ip = fp->f_inode) &&
500 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
501 return;
502 }
503 if (mode == IFBLK) {
504 /*
505 * On last close of a block device (that isn't mounted)
506 * we must invalidate any in core blocks
507 */
508 bflush(dev);
509 binval(dev);
510 }
511 (*cfunc)(dev, flag, fp);
512}
8d528261
BJ
513
514opause()
515{
516
517 for (;;)
518 sleep((caddr_t)&u, PSLEP);
519}