xref: /original-bsd/sys/kern/sys_generic.c (revision f82e54c4)
1 /*	sys_generic.c	6.4	84/08/29	*/
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 ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
134 		if (uio->uio_resid == count)
135 			u.u_eosys = RESTARTSYS;
136 	} else
137 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
138 	u.u_r.r_val1 = count - uio->uio_resid;
139 	fp->f_offset += u.u_r.r_val1;
140 }
141 
142 /*
143  * Ioctl system call
144  */
145 ioctl()
146 {
147 	register struct file *fp;
148 	struct a {
149 		int	fdes;
150 		int	cmd;
151 		caddr_t	cmarg;
152 	} *uap;
153 	register int com;
154 	register u_int size;
155 	char data[IOCPARM_MASK+1];
156 
157 	uap = (struct a *)u.u_ap;
158 	GETF(fp, uap->fdes);
159 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
160 		u.u_error = EBADF;
161 		return;
162 	}
163 	com = uap->cmd;
164 
165 #if defined(vax) && defined(COMPAT)
166 	/*
167 	 * Map old style ioctl's into new for the
168 	 * sake of backwards compatibility (sigh).
169 	 */
170 	if ((com&~0xffff) == 0) {
171 		com = mapioctl(com);
172 		if (com == 0) {
173 			u.u_error = EINVAL;
174 			return;
175 		}
176 	}
177 #endif
178 	if (com == FIOCLEX) {
179 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
180 		return;
181 	}
182 	if (com == FIONCLEX) {
183 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
184 		return;
185 	}
186 
187 	/*
188 	 * Interpret high order word to find
189 	 * amount of data to be copied to/from the
190 	 * user's address space.
191 	 */
192 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
193 	if (size > sizeof (data)) {
194 		u.u_error = EFAULT;
195 		return;
196 	}
197 	if (com&IOC_IN) {
198 		if (size) {
199 			u.u_error =
200 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
201 			if (u.u_error)
202 				return;
203 		} else
204 			*(caddr_t *)data = uap->cmarg;
205 	} else if ((com&IOC_OUT) && size)
206 		/*
207 		 * Zero the buffer on the stack so the user
208 		 * always gets back something deterministic.
209 		 */
210 		bzero((caddr_t)data, size);
211 	else if (com&IOC_VOID)
212 		*(caddr_t *)data = uap->cmarg;
213 
214 	switch (com) {
215 
216 	case FIONBIO:
217 		u.u_error = fset(fp, FNDELAY, *(int *)data);
218 		return;
219 
220 	case FIOASYNC:
221 		u.u_error = fset(fp, FASYNC, *(int *)data);
222 		return;
223 
224 	case FIOSETOWN:
225 		u.u_error = fsetown(fp, *(int *)data);
226 		return;
227 
228 	case FIOGETOWN:
229 		u.u_error = fgetown(fp, (int *)data);
230 		return;
231 	}
232 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
233 	/*
234 	 * Copy any data to user, size was
235 	 * already set and checked above.
236 	 */
237 	if (u.u_error == 0 && (com&IOC_OUT) && size)
238 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
239 }
240 
241 int	unselect();
242 int	nselcoll;
243 /*
244  * Select system call.
245  */
246 select()
247 {
248 	register struct uap  {
249 		int	nd;
250 		long	*in, *ou, *ex;
251 		struct	timeval *tv;
252 	} *uap = (struct uap *)u.u_ap;
253 	int ibits[3], obits[3];
254 	struct timeval atv;
255 	int s, ncoll, mask;
256 	label_t lqsave;
257 
258 	obits[0] = obits[1] = obits[2] = 0;
259 	if (uap->nd > NOFILE)
260 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
261 	mask = (1 << uap->nd) - 1;
262 
263 #define	getbits(name, x) \
264 	if (uap->name) { \
265 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
266 		    sizeof (ibits[x])); \
267 		if (u.u_error) \
268 			goto done; \
269 		ibits[x] &= mask; \
270 	} else \
271 		ibits[x] = 0;
272 	getbits(in, 0);
273 	getbits(ou, 1);
274 	getbits(ex, 2);
275 #undef	getbits
276 
277 	if (uap->tv) {
278 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
279 			sizeof (atv));
280 		if (u.u_error)
281 			goto done;
282 		if (itimerfix(&atv)) {
283 			u.u_error = EINVAL;
284 			goto done;
285 		}
286 		s = spl7(); timevaladd(&atv, &time); splx(s);
287 	}
288 retry:
289 	ncoll = nselcoll;
290 	u.u_procp->p_flag |= SSEL;
291 	u.u_r.r_val1 = selscan(ibits, obits);
292 	if (u.u_error || u.u_r.r_val1)
293 		goto done;
294 	s = spl6();
295 	/* this should be timercmp(&time, &atv, >=) */
296 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
297 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
298 		splx(s);
299 		goto done;
300 	}
301 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
302 		u.u_procp->p_flag &= ~SSEL;
303 		splx(s);
304 		goto retry;
305 	}
306 	u.u_procp->p_flag &= ~SSEL;
307 	if (uap->tv) {
308 		lqsave = u.u_qsave;
309 		if (setjmp(&u.u_qsave)) {
310 			untimeout(unselect, (caddr_t)u.u_procp);
311 			u.u_error = EINTR;
312 			splx(s);
313 			goto done;
314 		}
315 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
316 	}
317 	sleep((caddr_t)&selwait, PZERO+1);
318 	if (uap->tv) {
319 		u.u_qsave = lqsave;
320 		untimeout(unselect, (caddr_t)u.u_procp);
321 	}
322 	splx(s);
323 	goto retry;
324 done:
325 #define	putbits(name, x) \
326 	if (uap->name) { \
327 		int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
328 		    sizeof (obits[x])); \
329 		if (error) \
330 			u.u_error = error; \
331 	}
332 	putbits(in, 0);
333 	putbits(ou, 1);
334 	putbits(ex, 2);
335 #undef putbits
336 }
337 
338 unselect(p)
339 	register struct proc *p;
340 {
341 	register int s = spl6();
342 
343 	switch (p->p_stat) {
344 
345 	case SSLEEP:
346 		setrun(p);
347 		break;
348 
349 	case SSTOP:
350 		unsleep(p);
351 		break;
352 	}
353 	splx(s);
354 }
355 
356 selscan(ibits, obits)
357 	int *ibits, *obits;
358 {
359 	register int which, bits, i;
360 	int flag;
361 	struct file *fp;
362 	int n = 0;
363 
364 	for (which = 0; which < 3; which++) {
365 		bits = ibits[which];
366 		obits[which] = 0;
367 		switch (which) {
368 
369 		case 0:
370 			flag = FREAD; break;
371 
372 		case 1:
373 			flag = FWRITE; break;
374 
375 		case 2:
376 			flag = 0; break;
377 		}
378 		while (i = ffs(bits)) {
379 			bits &= ~(1<<(i-1));
380 			fp = u.u_ofile[i-1];
381 			if (fp == NULL) {
382 				u.u_error = EBADF;
383 				break;
384 			}
385 			if ((*fp->f_ops->fo_select)(fp, flag)) {
386 				obits[which] |= (1<<(i-1));
387 				n++;
388 			}
389 		}
390 	}
391 	return (n);
392 }
393 
394 /*ARGSUSED*/
395 seltrue(dev, flag)
396 	dev_t dev;
397 	int flag;
398 {
399 
400 	return (1);
401 }
402 
403 selwakeup(p, coll)
404 	register struct proc *p;
405 	int coll;
406 {
407 
408 	if (coll) {
409 		nselcoll++;
410 		wakeup((caddr_t)&selwait);
411 	}
412 	if (p) {
413 		int s = spl6();
414 		if (p->p_wchan == (caddr_t)&selwait)
415 			setrun(p);
416 		else if (p->p_flag & SSEL)
417 			p->p_flag &= ~SSEL;
418 		splx(s);
419 	}
420 }
421