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