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