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