xref: /original-bsd/sys/kern/sys_generic.c (revision 81f6297c)
1 /*	sys_generic.c	6.10	85/05/27	*/
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_error = EINTR;
137 			else
138 				u.u_eosys = RESTARTSYS;
139 		}
140 	} else
141 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
142 	u.u_r.r_val1 = count - uio->uio_resid;
143 	fp->f_offset += u.u_r.r_val1;
144 }
145 
146 /*
147  * Ioctl system call
148  */
149 ioctl()
150 {
151 	register struct file *fp;
152 	struct a {
153 		int	fdes;
154 		int	cmd;
155 		caddr_t	cmarg;
156 	} *uap;
157 	register int com;
158 	register u_int size;
159 	char data[IOCPARM_MASK+1];
160 
161 	uap = (struct a *)u.u_ap;
162 	GETF(fp, uap->fdes);
163 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
164 		u.u_error = EBADF;
165 		return;
166 	}
167 	com = uap->cmd;
168 
169 #if defined(vax) && defined(COMPAT)
170 	/*
171 	 * Map old style ioctl's into new for the
172 	 * sake of backwards compatibility (sigh).
173 	 */
174 	if ((com&~0xffff) == 0) {
175 		com = mapioctl(com);
176 		if (com == 0) {
177 			u.u_error = EINVAL;
178 			return;
179 		}
180 	}
181 #endif
182 	if (com == FIOCLEX) {
183 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
184 		return;
185 	}
186 	if (com == FIONCLEX) {
187 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
188 		return;
189 	}
190 
191 	/*
192 	 * Interpret high order word to find
193 	 * amount of data to be copied to/from the
194 	 * user's address space.
195 	 */
196 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
197 	if (size > sizeof (data)) {
198 		u.u_error = EFAULT;
199 		return;
200 	}
201 	if (com&IOC_IN) {
202 		if (size) {
203 			u.u_error =
204 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
205 			if (u.u_error)
206 				return;
207 		} else
208 			*(caddr_t *)data = uap->cmarg;
209 	} else if ((com&IOC_OUT) && size)
210 		/*
211 		 * Zero the buffer on the stack so the user
212 		 * always gets back something deterministic.
213 		 */
214 		bzero((caddr_t)data, size);
215 	else if (com&IOC_VOID)
216 		*(caddr_t *)data = uap->cmarg;
217 
218 	switch (com) {
219 
220 	case FIONBIO:
221 		u.u_error = fset(fp, FNDELAY, *(int *)data);
222 		return;
223 
224 	case FIOASYNC:
225 		u.u_error = fset(fp, FASYNC, *(int *)data);
226 		return;
227 
228 	case FIOSETOWN:
229 		u.u_error = fsetown(fp, *(int *)data);
230 		return;
231 
232 	case FIOGETOWN:
233 		u.u_error = fgetown(fp, (int *)data);
234 		return;
235 	}
236 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
237 	/*
238 	 * Copy any data to user, size was
239 	 * already set and checked above.
240 	 */
241 	if (u.u_error == 0 && (com&IOC_OUT) && size)
242 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
243 }
244 
245 int	unselect();
246 int	nselcoll;
247 
248 /*
249  * Select uses bit masks of file descriptors in ints.
250  * These macros manipulate such bit fields (the filesystem macros use chars).
251  */
252 #define NBI		(sizeof(int) * NBBY)		/* bits per int */
253 #define	NI		howmany(NOFILE, NBI)
254 #define	tbit(p, n)	((p)[(n)/NBI] & (1 << ((n) % NBI)))
255 #define	sbit(p, n)	((p)[(n)/NBI] |= (1 << ((n) % NBI)))
256 #define	cbit(p, n)	((p)[(n)/NBI] &= ~(1 << ((n) % NBI)))
257 
258 /*
259  * Select system call.
260  */
261 select()
262 {
263 	register struct uap  {
264 		int	nd;
265 		int	*in, *ou, *ex;
266 		struct	timeval *tv;
267 	} *uap = (struct uap *)u.u_ap;
268 	int ibits[3][NI], obits[3][NI];
269 	struct timeval atv;
270 	int s, ncoll, ni;
271 	label_t lqsave;
272 
273 	bzero(ibits, sizeof(ibits));
274 	bzero(obits, sizeof(obits));
275 	if (uap->nd > NOFILE)
276 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
277 	ni = howmany(uap->nd, NBI);
278 
279 #define	getbits(name, x) \
280 	if (uap->name) { \
281 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \
282 		    ni * sizeof(int)); \
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 		u.u_procp->p_flag &= ~SSEL;
317 		splx(s);
318 		goto retry;
319 	}
320 	u.u_procp->p_flag &= ~SSEL;
321 	if (uap->tv) {
322 		lqsave = u.u_qsave;
323 		if (setjmp(&u.u_qsave)) {
324 			untimeout(unselect, (caddr_t)u.u_procp);
325 			u.u_error = EINTR;
326 			splx(s);
327 			goto done;
328 		}
329 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
330 	}
331 	sleep((caddr_t)&selwait, PZERO+1);
332 	if (uap->tv) {
333 		u.u_qsave = lqsave;
334 		untimeout(unselect, (caddr_t)u.u_procp);
335 	}
336 	splx(s);
337 	goto retry;
338 done:
339 #define	putbits(name, x) \
340 	if (uap->name) { \
341 		int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \
342 		    ni * sizeof(int)); \
343 		if (error) \
344 			u.u_error = error; \
345 	}
346 	if (u.u_error != EINTR) {
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 	int (*ibits)[NI], (*obits)[NI];
374 {
375 	register int which, bits, i, j;
376 	int flag;
377 	struct file *fp;
378 	int n = 0;
379 
380 	for (which = 0; which < 3; which++) {
381 		switch (which) {
382 
383 		case 0:
384 			flag = FREAD; break;
385 
386 		case 1:
387 			flag = FWRITE; break;
388 
389 		case 2:
390 			flag = 0; break;
391 		}
392 		for (i = 0; i < nfd; i += NBI) {
393 			bits = ibits[which][i/NBI];
394 			while ((j = ffs(bits)) && i + --j < nfd) {
395 				bits &= ~(1 << j);
396 				fp = u.u_ofile[i + j];
397 				if (fp == NULL) {
398 					u.u_error = EBADF;
399 					break;
400 				}
401 				if ((*fp->f_ops->fo_select)(fp, flag)) {
402 					sbit(obits[which], i + j);
403 					n++;
404 				}
405 			}
406 		}
407 	}
408 	return (n);
409 }
410 
411 /*ARGSUSED*/
412 seltrue(dev, flag)
413 	dev_t dev;
414 	int flag;
415 {
416 
417 	return (1);
418 }
419 
420 selwakeup(p, coll)
421 	register struct proc *p;
422 	int coll;
423 {
424 
425 	if (coll) {
426 		nselcoll++;
427 		wakeup((caddr_t)&selwait);
428 	}
429 	if (p) {
430 		int s = splhigh();
431 		if (p->p_wchan == (caddr_t)&selwait) {
432 			if (p->p_stat == SSLEEP)
433 				setrun(p);
434 			else
435 				unsleep(p);
436 		} else if (p->p_flag & SSEL)
437 			p->p_flag &= ~SSEL;
438 		splx(s);
439 	}
440 }
441