xref: /original-bsd/sys/kern/kern_descrip.c (revision 3ca00c4d)
1 /*	kern_descrip.c	5.24	83/05/27	*/
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/ioctl.h"
17 
18 /*
19  * Descriptor management.
20  */
21 
22 /*
23  * TODO:
24  *	increase NOFILE
25  *	eliminate u.u_error side effects
26  */
27 
28 /*
29  * System calls on descriptors.
30  */
31 getdtablesize()
32 {
33 
34 	u.u_r.r_val1 = NOFILE;
35 }
36 
37 getdopt()
38 {
39 
40 }
41 
42 setdopt()
43 {
44 
45 }
46 
47 dup()
48 {
49 	register struct a {
50 		int	i;
51 	} *uap = (struct a *) u.u_ap;
52 	struct file *fp;
53 	int j;
54 
55 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
56 
57 	fp = getf(uap->i);
58 	if (fp == 0)
59 		return;
60 	j = ufalloc(0);
61 	if (j < 0)
62 		return;
63 	dupit(j, fp, u.u_pofile[uap->i]);
64 }
65 
66 dup2()
67 {
68 	register struct a {
69 		int	i, j;
70 	} *uap = (struct a *) u.u_ap;
71 	register struct file *fp;
72 
73 	fp = getf(uap->i);
74 	if (fp == 0)
75 		return;
76 	if (uap->j < 0 || uap->j >= NOFILE) {
77 		u.u_error = EBADF;
78 		return;
79 	}
80 	u.u_r.r_val1 = uap->j;
81 	if (uap->i == uap->j)
82 		return;
83 	if (u.u_ofile[uap->j]) {
84 		if (u.u_pofile[uap->j] & UF_MAPPED)
85 			munmapfd(uap->j);
86 		closef(u.u_ofile[uap->j], u.u_pofile[uap->j]);
87 		if (u.u_error)
88 			return;
89 		/* u.u_ofile[uap->j] = 0; */
90 		/* u.u_pofile[uap->j] = 0; */
91 	}
92 	dupit(uap->j, fp, u.u_pofile[uap->i]);
93 }
94 
95 dupit(fd, fp, lockflags)
96 	int fd;
97 	register struct file *fp;
98 	register int lockflags;
99 {
100 
101 	u.u_ofile[fd] = fp;
102 	u.u_pofile[fd] = lockflags;
103 	fp->f_count++;
104 /* THIS DOESN'T BELONG HERE */
105 	if (lockflags&UF_SHLOCK)
106 		((struct inode *)fp->f_data)->i_shlockc++;
107 	if (lockflags&UF_EXLOCK)
108 		((struct inode *)fp->f_data)->i_exlockc++;
109 /* END DOESN'T BELONG */
110 }
111 
112 /*
113  * The file control system call.
114  */
115 fcntl()
116 {
117 	register struct file *fp;
118 	register struct a {
119 		int	fdes;
120 		int	cmd;
121 		int	arg;
122 	} *uap;
123 	register i;
124 	register char *pop;
125 
126 	uap = (struct a *)u.u_ap;
127 	fp = getf(uap->fdes);
128 	if (fp == NULL)
129 		return;
130 	pop = &u.u_pofile[uap->fdes];
131 	switch(uap->cmd) {
132 	case 0:
133 		i = uap->arg;
134 		if (i < 0 || i > NOFILE) {
135 			u.u_error = EINVAL;
136 			return;
137 		}
138 		if ((i = ufalloc(i)) < 0)
139 			return;
140 		dupit(i, fp, *pop);
141 		break;
142 
143 	case 1:
144 		u.u_r.r_val1 = *pop & 1;
145 		break;
146 
147 	case 2:
148 		*pop = (*pop &~ 1) | (uap->arg & 1);
149 		break;
150 
151 	case 3:
152 		u.u_r.r_val1 = fp->f_flag+FOPEN;
153 		break;
154 
155 	case 4:
156 		fp->f_flag &= FCNTLCANT;
157 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
158 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
159 		if (u.u_error)
160 			break;
161 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
162 		if (u.u_error)
163 			(void) fset(fp, FNDELAY, 0);
164 		break;
165 
166 	case 5:
167 		u.u_error = fsetown(fp, uap->arg);
168 		break;
169 
170 	case 6:
171 		u.u_error = fgetown(fp, &u.u_r.r_val1);
172 		break;
173 
174 	default:
175 		u.u_error = EINVAL;
176 	}
177 }
178 
179 fset(fp, bit, value)
180 	struct file *fp;
181 	int bit, value;
182 {
183 
184 	if (value)
185 		fp->f_flag |= bit;
186 	else
187 		fp->f_flag &= ~bit;
188 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
189 	    (caddr_t)&value));
190 }
191 
192 fgetown(fp, valuep)
193 	struct file *fp;
194 	int *valuep;
195 {
196 	int error;
197 
198 	switch (fp->f_type) {
199 
200 	case DTYPE_SOCKET:
201 		*valuep = ((struct socket *)fp->f_data)->so_pgrp;
202 		return (0);
203 
204 	default:
205 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
206 		*valuep = -*valuep;
207 		return (error);
208 	}
209 }
210 
211 fsetown(fp, value)
212 	struct file *fp;
213 	int value;
214 {
215 
216 	if (fp->f_type == DTYPE_SOCKET) {
217 		((struct socket *)fp->f_data)->so_pgrp = value;
218 		return (0);
219 	}
220 	if (value > 0) {
221 		struct proc *p = pfind(value);
222 		if (p == 0)
223 			return (EINVAL);
224 		value = p->p_pgrp;
225 	} else
226 		value = -value;
227 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
228 }
229 
230 fioctl(fp, cmd, value)
231 	struct file *fp;
232 	int cmd;
233 	caddr_t value;
234 {
235 
236 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
237 }
238 
239 close()
240 {
241 	register struct a {
242 		int	i;
243 	} *uap = (struct a *)u.u_ap;
244 	register struct file *fp;
245 
246 	fp = getf(uap->i);
247 	if (fp == 0)
248 		return;
249 	if (u.u_pofile[uap->i] & UF_MAPPED)
250 		munmapfd(uap->i);
251 	closef(fp, u.u_pofile[uap->i]);
252 	/* WHAT IF u.u_error ? */
253 	u.u_ofile[uap->i] = NULL;
254 	u.u_pofile[uap->i] = 0;
255 }
256 
257 /*
258  * Allocate a user file descriptor.
259  */
260 ufalloc(i)
261 	register int i;
262 {
263 
264 	for (; i < NOFILE; i++)
265 		if (u.u_ofile[i] == NULL) {
266 			u.u_r.r_val1 = i;
267 			u.u_pofile[i] = 0;
268 			return (i);
269 		}
270 	u.u_error = EMFILE;
271 	return (-1);
272 }
273 
274 ufavail()
275 {
276 	register int i, avail = 0;
277 
278 	for (i = 0; i < NOFILE; i++)
279 		if (u.u_ofile[i] == NULL)
280 			avail++;
281 	return (avail);
282 }
283 
284 struct	file *lastf;
285 /*
286  * Allocate a user file descriptor
287  * and a file structure.
288  * Initialize the descriptor
289  * to point at the file structure.
290  */
291 struct file *
292 falloc()
293 {
294 	register struct file *fp;
295 	register i;
296 
297 	i = ufalloc(0);
298 	if (i < 0)
299 		return (NULL);
300 	if (lastf == 0)
301 		lastf = file;
302 	for (fp = lastf; fp < fileNFILE; fp++)
303 		if (fp->f_count == 0)
304 			goto slot;
305 	for (fp = file; fp < lastf; fp++)
306 		if (fp->f_count == 0)
307 			goto slot;
308 	tablefull("file");
309 	u.u_error = ENFILE;
310 	return (NULL);
311 slot:
312 	u.u_ofile[i] = fp;
313 	fp->f_count = 1;
314 	fp->f_data = 0;
315 	fp->f_offset = 0;
316 	lastf = fp + 1;
317 	return (fp);
318 }
319 
320 /*
321  * Convert a user supplied file descriptor into a pointer
322  * to a file structure.  Only task is to check range of the descriptor.
323  * Critical paths should use the GETF macro.
324  */
325 struct file *
326 getf(f)
327 	register int f;
328 {
329 	register struct file *fp;
330 
331 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
332 		u.u_error = EBADF;
333 		return (NULL);
334 	}
335 	return (fp);
336 }
337 
338 /*
339  * Internal form of close.
340  * Decrement reference count on file structure.
341  * If last reference not going away, but no more
342  * references except in message queues, run a
343  * garbage collect.  This would better be done by
344  * forcing a gc() to happen sometime soon, rather
345  * than running one each time.
346  */
347 closef(fp, flags)
348 	register struct file *fp;
349 	int flags;					/* XXX */
350 {
351 
352 	if (fp == NULL)
353 		return;
354 	if (fp->f_count > 1) {
355 		fp->f_count--;
356 		if (fp->f_count == fp->f_msgcount)
357 			unp_gc();
358 		return;
359 	}
360 	(*fp->f_ops->fo_close)(fp, flags);
361 	fp->f_count = 0;
362 }
363