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