new signals
[unix-history] / usr / src / sys / kern / sys_generic.c
CommitLineData
dd012d1e 1/* sys_generic.c 5.37 83/06/02 */
ffe28cfe
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
425a48ad 7#include "../h/ioctl.h"
ffe28cfe 8#include "../h/file.h"
ffe28cfe 9#include "../h/proc.h"
6fd40cea 10#include "../h/uio.h"
88a7a62a
SL
11#include "../h/kernel.h"
12#include "../h/stat.h"
ffe28cfe
BJ
13
14/*
15 * Read system call.
16 */
17read()
18{
ffe28cfe
BJ
19 register struct a {
20 int fdes;
21 char *cbuf;
22 unsigned count;
b9429893 23 } *uap = (struct a *)u.u_ap;
32a43ee2
BJ
24 struct uio auio;
25 struct iovec aiov;
ffe28cfe 26
32a43ee2
BJ
27 aiov.iov_base = (caddr_t)uap->cbuf;
28 aiov.iov_len = uap->count;
29 auio.uio_iov = &aiov;
30 auio.uio_iovcnt = 1;
b9429893
BJ
31 rwuio(&auio, UIO_READ);
32}
33
34readv()
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;
127f7d76
SL
50 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
51 (unsigned)(uap->iovcnt * sizeof (struct iovec)));
52 if (u.u_error)
b9429893 53 return;
b9429893 54 rwuio(&auio, UIO_READ);
ffe28cfe
BJ
55}
56
57/*
58 * Write system call
59 */
60write()
61{
ffe28cfe
BJ
62 register struct a {
63 int fdes;
64 char *cbuf;
b9429893
BJ
65 int count;
66 } *uap = (struct a *)u.u_ap;
67 struct uio auio;
68 struct iovec aiov;
ffe28cfe 69
b9429893
BJ
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
77writev()
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])) {
ffe28cfe
BJ
88 u.u_error = EINVAL;
89 return;
90 }
b9429893
BJ
91 auio.uio_iov = aiov;
92 auio.uio_iovcnt = uap->iovcnt;
127f7d76
SL
93 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
94 (unsigned)(uap->iovcnt * sizeof (struct iovec)));
95 if (u.u_error)
b9429893 96 return;
b9429893
BJ
97 rwuio(&auio, UIO_WRITE);
98}
99
100rwuio(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;
b9429893
BJ
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) {
ffe28cfe
BJ
113 u.u_error = EBADF;
114 return;
115 }
b9429893
BJ
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;
88a7a62a 131 uio->uio_offset = fp->f_offset;
dd012d1e 132 if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
b9429893 133 if (uio->uio_resid == count)
ffe28cfe 134 u.u_eosys = RESTARTSYS;
b9429893 135 } else
88a7a62a
SL
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;
4147b3f6 139}
ffe28cfe
BJ
140
141/*
142 * Ioctl system call
ffe28cfe
BJ
143 */
144ioctl()
145{
146 register struct file *fp;
4b72e2f9 147 struct a {
ffe28cfe
BJ
148 int fdes;
149 int cmd;
150 caddr_t cmarg;
151 } *uap;
b9429893
BJ
152 register int com;
153 register u_int size;
4b72e2f9 154 char data[IOCPARM_MASK+1];
ffe28cfe
BJ
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 }
4b72e2f9
SL
163 com = uap->cmd;
164
88a7a62a 165#if defined(vax) && !defined(NOCOMPAT)
4b72e2f9
SL
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) {
3650c37d 179 u.u_pofile[uap->fdes] |= UF_EXCLOSE;
ffe28cfe
BJ
180 return;
181 }
4b72e2f9 182 if (com == FIONCLEX) {
3650c37d 183 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
ffe28cfe
BJ
184 return;
185 }
4b72e2f9
SL
186
187 /*
188 * Interpret high order word to find
189 * amount of data to be copied to/from the
190 * user's address space.
4b72e2f9
SL
191 */
192 size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
193 if (size > sizeof (data)) {
194 u.u_error = EFAULT;
ffe28cfe
BJ
195 return;
196 }
471f17ed
SL
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 */
4b72e2f9 210 bzero((caddr_t)data, size);
a76b60f6
SL
211 else if (com&IOC_VOID)
212 *(caddr_t *)data = uap->cmarg;
4b72e2f9 213
88a7a62a
SL
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;
4b72e2f9 227
88a7a62a
SL
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);
4b72e2f9
SL
233 /*
234 * Copy any data to user, size was
235 * already set and checked above.
236 */
127f7d76
SL
237 if (u.u_error == 0 && (com&IOC_OUT) && size)
238 u.u_error = copyout(data, uap->cmarg, (u_int)size);
ffe28cfe
BJ
239}
240
88a7a62a
SL
241int unselect();
242int nselcoll;
ffe28cfe 243/*
88a7a62a 244 * Select system call.
ffe28cfe 245 */
88a7a62a
SL
246select()
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 }
286retry:
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;
320done:
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
334unselect(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
352selscan(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
ffe28cfe 390/*ARGSUSED*/
88a7a62a
SL
391seltrue(dev, flag)
392 dev_t dev;
393 int flag;
ffe28cfe
BJ
394{
395
88a7a62a 396 return (1);
ffe28cfe 397}
1edb1cf8 398
88a7a62a
SL
399selwakeup(p, coll)
400 register struct proc *p;
401 int coll;
1edb1cf8
BJ
402{
403
88a7a62a
SL
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 }
1edb1cf8
BJ
416}
417
88a7a62a 418fstat()
1edb1cf8 419{
88a7a62a
SL
420 register struct file *fp;
421 register struct a {
422 int fdes;
423 struct stat *sb;
424 } *uap;
425 struct stat ub;
1edb1cf8 426
88a7a62a
SL
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));
1edb1cf8 434}