xref: /original-bsd/sys/kern/sys_generic.c (revision 4ad1d170)
1 /*	sys_generic.c	6.8	85/03/12	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "dir.h"
6 #include "user.h"
7 #include "ioctl.h"
8 #include "file.h"
9 #include "proc.h"
10 #include "uio.h"
11 #include "kernel.h"
12 #include "stat.h"
13 
14 /*
15  * Read system call.
16  */
17 read()
18 {
19 	register struct a {
20 		int	fdes;
21 		char	*cbuf;
22 		unsigned count;
23 	} *uap = (struct a *)u.u_ap;
24 	struct uio auio;
25 	struct iovec aiov;
26 
27 	aiov.iov_base = (caddr_t)uap->cbuf;
28 	aiov.iov_len = uap->count;
29 	auio.uio_iov = &aiov;
30 	auio.uio_iovcnt = 1;
31 	rwuio(&auio, UIO_READ);
32 }
33 
34 readv()
35 {
36 	register struct a {
37 		int	fdes;
38 		struct	iovec *iovp;
39 		int	iovcnt;
40 	} *uap = (struct a *)u.u_ap;
41 	struct uio auio;
42 	struct iovec aiov[16];		/* XXX */
43 
44 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
45 		u.u_error = EINVAL;
46 		return;
47 	}
48 	auio.uio_iov = aiov;
49 	auio.uio_iovcnt = uap->iovcnt;
50 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
51 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
52 	if (u.u_error)
53 		return;
54 	rwuio(&auio, UIO_READ);
55 }
56 
57 /*
58  * Write system call
59  */
60 write()
61 {
62 	register struct a {
63 		int	fdes;
64 		char	*cbuf;
65 		int	count;
66 	} *uap = (struct a *)u.u_ap;
67 	struct uio auio;
68 	struct iovec aiov;
69 
70 	auio.uio_iov = &aiov;
71 	auio.uio_iovcnt = 1;
72 	aiov.iov_base = uap->cbuf;
73 	aiov.iov_len = uap->count;
74 	rwuio(&auio, UIO_WRITE);
75 }
76 
77 writev()
78 {
79 	register struct a {
80 		int	fdes;
81 		struct	iovec *iovp;
82 		int	iovcnt;
83 	} *uap = (struct a *)u.u_ap;
84 	struct uio auio;
85 	struct iovec aiov[16];		/* XXX */
86 
87 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
88 		u.u_error = EINVAL;
89 		return;
90 	}
91 	auio.uio_iov = aiov;
92 	auio.uio_iovcnt = uap->iovcnt;
93 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
94 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
95 	if (u.u_error)
96 		return;
97 	rwuio(&auio, UIO_WRITE);
98 }
99 
100 rwuio(uio, rw)
101 	register struct uio *uio;
102 	enum uio_rw rw;
103 {
104 	struct a {
105 		int	fdes;
106 	};
107 	register struct file *fp;
108 	register struct iovec *iov;
109 	int i, count;
110 
111 	GETF(fp, ((struct a *)u.u_ap)->fdes);
112 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
113 		u.u_error = EBADF;
114 		return;
115 	}
116 	uio->uio_resid = 0;
117 	uio->uio_segflg = UIO_USERSPACE;
118 	iov = uio->uio_iov;
119 	for (i = 0; i < uio->uio_iovcnt; i++) {
120 		if (iov->iov_len < 0) {
121 			u.u_error = EINVAL;
122 			return;
123 		}
124 		uio->uio_resid += iov->iov_len;
125 		if (uio->uio_resid < 0) {
126 			u.u_error = EINVAL;
127 			return;
128 		}
129 		iov++;
130 	}
131 	count = uio->uio_resid;
132 	uio->uio_offset = fp->f_offset;
133 	if (setjmp(&u.u_qsave)) {
134 		if (uio->uio_resid == count) {
135 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0 ||
136 			    (u.u_procp->p_flag & SOUSIG) != 0)
137 				u.u_error = EINTR;
138 			else
139 				u.u_eosys = RESTARTSYS;
140 		}
141 	} else
142 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
143 	u.u_r.r_val1 = count - uio->uio_resid;
144 	fp->f_offset += u.u_r.r_val1;
145 }
146 
147 /*
148  * Ioctl system call
149  */
150 ioctl()
151 {
152 	register struct file *fp;
153 	struct a {
154 		int	fdes;
155 		int	cmd;
156 		caddr_t	cmarg;
157 	} *uap;
158 	register int com;
159 	register u_int size;
160 	char data[IOCPARM_MASK+1];
161 
162 	uap = (struct a *)u.u_ap;
163 	GETF(fp, uap->fdes);
164 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
165 		u.u_error = EBADF;
166 		return;
167 	}
168 	com = uap->cmd;
169 
170 #if defined(vax) && defined(COMPAT)
171 	/*
172 	 * Map old style ioctl's into new for the
173 	 * sake of backwards compatibility (sigh).
174 	 */
175 	if ((com&~0xffff) == 0) {
176 		com = mapioctl(com);
177 		if (com == 0) {
178 			u.u_error = EINVAL;
179 			return;
180 		}
181 	}
182 #endif
183 	if (com == FIOCLEX) {
184 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
185 		return;
186 	}
187 	if (com == FIONCLEX) {
188 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
189 		return;
190 	}
191 
192 	/*
193 	 * Interpret high order word to find
194 	 * amount of data to be copied to/from the
195 	 * user's address space.
196 	 */
197 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
198 	if (size > sizeof (data)) {
199 		u.u_error = EFAULT;
200 		return;
201 	}
202 	if (com&IOC_IN) {
203 		if (size) {
204 			u.u_error =
205 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
206 			if (u.u_error)
207 				return;
208 		} else
209 			*(caddr_t *)data = uap->cmarg;
210 	} else if ((com&IOC_OUT) && size)
211 		/*
212 		 * Zero the buffer on the stack so the user
213 		 * always gets back something deterministic.
214 		 */
215 		bzero((caddr_t)data, size);
216 	else if (com&IOC_VOID)
217 		*(caddr_t *)data = uap->cmarg;
218 
219 	switch (com) {
220 
221 	case FIONBIO:
222 		u.u_error = fset(fp, FNDELAY, *(int *)data);
223 		return;
224 
225 	case FIOASYNC:
226 		u.u_error = fset(fp, FASYNC, *(int *)data);
227 		return;
228 
229 	case FIOSETOWN:
230 		u.u_error = fsetown(fp, *(int *)data);
231 		return;
232 
233 	case FIOGETOWN:
234 		u.u_error = fgetown(fp, (int *)data);
235 		return;
236 	}
237 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
238 	/*
239 	 * Copy any data to user, size was
240 	 * already set and checked above.
241 	 */
242 	if (u.u_error == 0 && (com&IOC_OUT) && size)
243 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
244 }
245 
246 int	unselect();
247 int	nselcoll;
248 
249 /*
250  * Select uses bit masks of file descriptors in ints.
251  * These macros manipulate such bit fields (the filesystem macros use chars).
252  */
253 #define NBI		(sizeof(int) * NBBY)		/* bits per int */
254 #define	NI		howmany(NOFILE, NBI)
255 #define	tbit(p, n)	((p)[(n)/NBI] & (1 << ((n) % NBI)))
256 #define	sbit(p, n)	((p)[(n)/NBI] |= (1 << ((n) % NBI)))
257 #define	cbit(p, n)	((p)[(n)/NBI] &= ~(1 << ((n) % NBI)))
258 
259 /*
260  * Select system call.
261  */
262 select()
263 {
264 	register struct uap  {
265 		int	nd;
266 		int	*in, *ou, *ex;
267 		struct	timeval *tv;
268 	} *uap = (struct uap *)u.u_ap;
269 	int ibits[3][NI], obits[3][NI];
270 	struct timeval atv;
271 	int s, ncoll, ni;
272 	label_t lqsave;
273 
274 	bzero(ibits, sizeof(ibits));
275 	bzero(obits, sizeof(obits));
276 	if (uap->nd > NOFILE)
277 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
278 	ni = howmany(uap->nd, NBI);
279 
280 #define	getbits(name, x) \
281 	if (uap->name) { \
282 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \
283 		    ni * sizeof(int)); \
284 		if (u.u_error) \
285 			goto done; \
286 	}
287 	getbits(in, 0);
288 	getbits(ou, 1);
289 	getbits(ex, 2);
290 #undef	getbits
291 
292 	if (uap->tv) {
293 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
294 			sizeof (atv));
295 		if (u.u_error)
296 			goto done;
297 		if (itimerfix(&atv)) {
298 			u.u_error = EINVAL;
299 			goto done;
300 		}
301 		s = splhigh(); timevaladd(&atv, &time); splx(s);
302 	}
303 retry:
304 	ncoll = nselcoll;
305 	u.u_procp->p_flag |= SSEL;
306 	u.u_r.r_val1 = selscan(ibits, obits, uap->nd);
307 	if (u.u_error || u.u_r.r_val1)
308 		goto done;
309 	s = splhigh();
310 	/* this should be timercmp(&time, &atv, >=) */
311 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
312 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
313 		splx(s);
314 		goto done;
315 	}
316 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
317 		u.u_procp->p_flag &= ~SSEL;
318 		splx(s);
319 		goto retry;
320 	}
321 	u.u_procp->p_flag &= ~SSEL;
322 	if (uap->tv) {
323 		lqsave = u.u_qsave;
324 		if (setjmp(&u.u_qsave)) {
325 			untimeout(unselect, (caddr_t)u.u_procp);
326 			u.u_error = EINTR;
327 			splx(s);
328 			goto done;
329 		}
330 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
331 	}
332 	sleep((caddr_t)&selwait, PZERO+1);
333 	if (uap->tv) {
334 		u.u_qsave = lqsave;
335 		untimeout(unselect, (caddr_t)u.u_procp);
336 	}
337 	splx(s);
338 	goto retry;
339 done:
340 #define	putbits(name, x) \
341 	if (uap->name) { \
342 		int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \
343 		    ni * sizeof(int)); \
344 		if (error) \
345 			u.u_error = error; \
346 	}
347 	putbits(in, 0);
348 	putbits(ou, 1);
349 	putbits(ex, 2);
350 #undef putbits
351 }
352 
353 unselect(p)
354 	register struct proc *p;
355 {
356 	register int s = splhigh();
357 
358 	switch (p->p_stat) {
359 
360 	case SSLEEP:
361 		setrun(p);
362 		break;
363 
364 	case SSTOP:
365 		unsleep(p);
366 		break;
367 	}
368 	splx(s);
369 }
370 
371 selscan(ibits, obits, nfd)
372 	int (*ibits)[NI], (*obits)[NI];
373 {
374 	register int which, bits, i, j;
375 	int flag;
376 	struct file *fp;
377 	int n = 0;
378 
379 	for (which = 0; which < 3; which++) {
380 		switch (which) {
381 
382 		case 0:
383 			flag = FREAD; break;
384 
385 		case 1:
386 			flag = FWRITE; break;
387 
388 		case 2:
389 			flag = 0; break;
390 		}
391 		for (i = 0; i < nfd; i += NBI) {
392 			bits = ibits[which][i/NBI];
393 			while ((j = ffs(bits)) && i + --j < nfd) {
394 				bits &= ~(1 << j);
395 				fp = u.u_ofile[i + j];
396 				if (fp == NULL) {
397 					u.u_error = EBADF;
398 					break;
399 				}
400 				if ((*fp->f_ops->fo_select)(fp, flag)) {
401 					sbit(obits[which], i + j);
402 					n++;
403 				}
404 			}
405 		}
406 	}
407 	return (n);
408 }
409 
410 /*ARGSUSED*/
411 seltrue(dev, flag)
412 	dev_t dev;
413 	int flag;
414 {
415 
416 	return (1);
417 }
418 
419 selwakeup(p, coll)
420 	register struct proc *p;
421 	int coll;
422 {
423 
424 	if (coll) {
425 		nselcoll++;
426 		wakeup((caddr_t)&selwait);
427 	}
428 	if (p) {
429 		int s = splhigh();
430 		if (p->p_wchan == (caddr_t)&selwait) {
431 			if (p->p_stat == SSLEEP)
432 				setrun(p);
433 			else
434 				unsleep(p);
435 		} else if (p->p_flag & SSEL)
436 			p->p_flag &= ~SSEL;
437 		splx(s);
438 	}
439 }
440