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