xref: /original-bsd/sys/kern/sys_generic.c (revision 3ca00c4d)
1 /*	sys_generic.c	5.36	83/05/27	*/
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 	}
130 	count = uio->uio_resid;
131 	uio->uio_offset = fp->f_offset;
132 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
133 		if (uio->uio_resid == count)
134 			u.u_eosys = RESTARTSYS;
135 	} else
136 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
137 	u.u_r.r_val1 = count - uio->uio_resid;
138 	fp->f_offset += u.u_r.r_val1;
139 }
140 
141 /*
142  * Ioctl system call
143  */
144 ioctl()
145 {
146 	register struct file *fp;
147 	struct a {
148 		int	fdes;
149 		int	cmd;
150 		caddr_t	cmarg;
151 	} *uap;
152 	register int com;
153 	register u_int size;
154 	char data[IOCPARM_MASK+1];
155 
156 	uap = (struct a *)u.u_ap;
157 	if ((fp = getf(uap->fdes)) == NULL)
158 		return;
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(NOCOMPAT)
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;
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 
262 #define	getbits(name, x) \
263 	if (uap->name) { \
264 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
265 		    sizeof (ibits[x])); \
266 		if (u.u_error) \
267 			goto done; \
268 	} else \
269 		ibits[x] = 0;
270 	getbits(in, 0);
271 	getbits(ou, 1);
272 	getbits(ex, 2);
273 #undef	getbits
274 
275 	if (uap->tv) {
276 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
277 			sizeof (atv));
278 		if (u.u_error)
279 			goto done;
280 		if (itimerfix(&atv)) {
281 			u.u_error = EINVAL;
282 			goto done;
283 		}
284 		s = spl7(); timevaladd(&atv, &time); splx(s);
285 	}
286 retry:
287 	ncoll = nselcoll;
288 	u.u_procp->p_flag |= SSEL;
289 	u.u_r.r_val1 = selscan(ibits, obits);
290 	if (u.u_error || u.u_r.r_val1)
291 		goto done;
292 	s = spl6();
293 	if (uap->tv && timercmp(&time, &atv, >=)) {
294 		splx(s);
295 		goto done;
296 	}
297 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
298 		u.u_procp->p_flag &= ~SSEL;
299 		splx(s);
300 		goto retry;
301 	}
302 	u.u_procp->p_flag &= ~SSEL;
303 	if (uap->tv) {
304 		lqsave = u.u_qsave;
305 		if (setjmp(&u.u_qsave)) {
306 			untimeout(unselect, (caddr_t)u.u_procp);
307 			u.u_error = EINTR;
308 			splx(s);
309 			goto done;
310 		}
311 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
312 	}
313 	sleep((caddr_t)&selwait, PZERO+1);
314 	if (uap->tv) {
315 		u.u_qsave = lqsave;
316 		untimeout(unselect, (caddr_t)u.u_procp);
317 	}
318 	splx(s);
319 	goto retry;
320 done:
321 #define	putbits(name, x) \
322 	if (uap->name) { \
323 		int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
324 		    sizeof (obits[x])); \
325 		if (error) \
326 			u.u_error = error; \
327 	}
328 	putbits(in, 0);
329 	putbits(ou, 1);
330 	putbits(ex, 2);
331 #undef putbits
332 }
333 
334 unselect(p)
335 	register struct proc *p;
336 {
337 	register int s = spl6();
338 
339 	switch (p->p_stat) {
340 
341 	case SSLEEP:
342 		setrun(p);
343 		break;
344 
345 	case SSTOP:
346 		unsleep(p);
347 		break;
348 	}
349 	splx(s);
350 }
351 
352 selscan(ibits, obits)
353 	int *ibits, *obits;
354 {
355 	register int which, bits, i;
356 	int flag;
357 	struct file *fp;
358 	int n = 0;
359 
360 	for (which = 0; which < 3; which++) {
361 		bits = ibits[which];
362 		obits[which] = 0;
363 		switch (which) {
364 
365 		case 0:
366 			flag = FREAD; break;
367 
368 		case 1:
369 			flag = FWRITE; break;
370 
371 		case 2:
372 			flag = 0; break;
373 		}
374 		while (i = ffs(bits)) {
375 			bits &= ~(1<<(i-1));
376 			fp = u.u_ofile[i-1];
377 			if (fp == NULL) {
378 				u.u_error = EBADF;
379 				break;
380 			}
381 			if ((*fp->f_ops->fo_select)(fp, flag)) {
382 				obits[which] |= (1<<(i-1));
383 				n++;
384 			}
385 		}
386 	}
387 	return (n);
388 }
389 
390 /*ARGSUSED*/
391 seltrue(dev, flag)
392 	dev_t dev;
393 	int flag;
394 {
395 
396 	return (1);
397 }
398 
399 selwakeup(p, coll)
400 	register struct proc *p;
401 	int coll;
402 {
403 
404 	if (coll) {
405 		nselcoll++;
406 		wakeup((caddr_t)&selwait);
407 	}
408 	if (p) {
409 		int s = spl6();
410 		if (p->p_wchan == (caddr_t)&selwait)
411 			setrun(p);
412 		else if (p->p_flag & SSEL)
413 			p->p_flag &= ~SSEL;
414 		splx(s);
415 	}
416 }
417 
418 fstat()
419 {
420 	register struct file *fp;
421 	register struct a {
422 		int	fdes;
423 		struct	stat *sb;
424 	} *uap;
425 	struct stat ub;
426 
427 	uap = (struct a *)u.u_ap;
428 	fp = getf(uap->fdes);
429 	if (fp == 0)
430 		return;
431 	u.u_error = (*fp->f_ops->fo_stat)(fp, &ub);
432 	if (u.u_error == 0)
433 		u.u_error = copyout(&ub, uap->sb, sizeof (ub));
434 }
435