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