|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)sys_generic.c 7.30 (Berkeley) 5/30/91
1.1.1.2 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 1 00061
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 11 Dec 92 Williams Jolitz Fixed tty handling
1.1 root 41: */
42:
43: #include "param.h"
44: #include "systm.h"
45: #include "filedesc.h"
46: #include "ioctl.h"
47: #include "file.h"
48: #include "socketvar.h"
49: #include "proc.h"
50: #include "uio.h"
51: #include "kernel.h"
52: #include "stat.h"
53: #include "malloc.h"
54: #ifdef KTRACE
55: #include "ktrace.h"
56: #endif
57:
58: /*
59: * Read system call.
60: */
61: /* ARGSUSED */
62: read(p, uap, retval)
63: struct proc *p;
64: register struct args {
65: int fdes;
66: char *cbuf;
67: unsigned count;
68: } *uap;
69: int *retval;
70: {
71: register struct file *fp;
72: register struct filedesc *fdp = p->p_fd;
73: struct uio auio;
74: struct iovec aiov;
75: long cnt, error = 0;
76: #ifdef KTRACE
77: struct iovec ktriov;
78: #endif
79:
80: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
81: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
82: (fp->f_flag & FREAD) == 0)
83: return (EBADF);
84: aiov.iov_base = (caddr_t)uap->cbuf;
85: aiov.iov_len = uap->count;
86: auio.uio_iov = &aiov;
87: auio.uio_iovcnt = 1;
88: auio.uio_resid = uap->count;
89: auio.uio_rw = UIO_READ;
90: auio.uio_segflg = UIO_USERSPACE;
91: auio.uio_procp = p;
92: #ifdef KTRACE
93: /*
94: * if tracing, save a copy of iovec
95: */
96: if (KTRPOINT(p, KTR_GENIO))
97: ktriov = aiov;
98: #endif
99: cnt = uap->count;
100: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
101: if (auio.uio_resid != cnt && (error == ERESTART ||
102: error == EINTR || error == EWOULDBLOCK))
103: error = 0;
104: cnt -= auio.uio_resid;
105: #ifdef KTRACE
106: if (KTRPOINT(p, KTR_GENIO) && error == 0)
107: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
108: #endif
109: *retval = cnt;
110: return (error);
111: }
112:
113: /*
114: * Scatter read system call.
115: */
116: /* ARGSUSED */
117: readv(p, uap, retval)
118: struct proc *p;
119: register struct args {
120: int fdes;
121: struct iovec *iovp;
122: unsigned iovcnt;
123: } *uap;
124: int *retval;
125: {
126: register struct file *fp;
127: register struct filedesc *fdp = p->p_fd;
128: struct uio auio;
129: register struct iovec *iov;
130: struct iovec *saveiov;
131: struct iovec aiov[UIO_SMALLIOV];
132: long i, cnt, error = 0;
133: unsigned iovlen;
134: #ifdef KTRACE
135: struct iovec *ktriov = NULL;
136: #endif
137:
138: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
139: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
140: (fp->f_flag & FREAD) == 0)
141: return (EBADF);
142: /* note: can't use iovlen until iovcnt is validated */
143: iovlen = uap->iovcnt * sizeof (struct iovec);
144: if (uap->iovcnt > UIO_SMALLIOV) {
145: if (uap->iovcnt > UIO_MAXIOV)
146: return (EINVAL);
147: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
148: saveiov = iov;
149: } else
150: iov = aiov;
151: auio.uio_iov = iov;
152: auio.uio_iovcnt = uap->iovcnt;
153: auio.uio_rw = UIO_READ;
154: auio.uio_segflg = UIO_USERSPACE;
155: auio.uio_procp = p;
156: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
157: goto done;
158: auio.uio_resid = 0;
159: for (i = 0; i < uap->iovcnt; i++) {
160: if (iov->iov_len < 0) {
161: error = EINVAL;
162: goto done;
163: }
164: auio.uio_resid += iov->iov_len;
165: if (auio.uio_resid < 0) {
166: error = EINVAL;
167: goto done;
168: }
169: iov++;
170: }
171: #ifdef KTRACE
172: /*
173: * if tracing, save a copy of iovec
174: */
175: if (KTRPOINT(p, KTR_GENIO)) {
176: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
177: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
178: }
179: #endif
180: cnt = auio.uio_resid;
181: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
182: if (auio.uio_resid != cnt && (error == ERESTART ||
183: error == EINTR || error == EWOULDBLOCK))
184: error = 0;
185: cnt -= auio.uio_resid;
186: #ifdef KTRACE
187: if (ktriov != NULL) {
188: if (error == 0)
189: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
190: cnt, error);
191: FREE(ktriov, M_TEMP);
192: }
193: #endif
194: *retval = cnt;
195: done:
196: if (uap->iovcnt > UIO_SMALLIOV)
197: FREE(saveiov, M_IOV);
198: return (error);
199: }
200:
201: /*
202: * Write system call
203: */
204: write(p, uap, retval)
205: struct proc *p;
206: register struct args {
207: int fdes;
208: char *cbuf;
209: unsigned count;
210: } *uap;
211: int *retval;
212: {
213: register struct file *fp;
214: register struct filedesc *fdp = p->p_fd;
215: struct uio auio;
216: struct iovec aiov;
217: long cnt, error = 0;
218: #ifdef KTRACE
219: struct iovec ktriov;
220: #endif
221:
222: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
223: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
224: (fp->f_flag & FWRITE) == 0)
225: return (EBADF);
226: aiov.iov_base = (caddr_t)uap->cbuf;
227: aiov.iov_len = uap->count;
228: auio.uio_iov = &aiov;
229: auio.uio_iovcnt = 1;
230: auio.uio_resid = uap->count;
231: auio.uio_rw = UIO_WRITE;
232: auio.uio_segflg = UIO_USERSPACE;
233: auio.uio_procp = p;
234: #ifdef KTRACE
235: /*
236: * if tracing, save a copy of iovec
237: */
238: if (KTRPOINT(p, KTR_GENIO))
239: ktriov = aiov;
240: #endif
241: cnt = uap->count;
242: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
243: if (auio.uio_resid != cnt && (error == ERESTART ||
244: error == EINTR || error == EWOULDBLOCK))
245: error = 0;
246: if (error == EPIPE)
247: psignal(p, SIGPIPE);
248: }
249: cnt -= auio.uio_resid;
250: #ifdef KTRACE
251: if (KTRPOINT(p, KTR_GENIO) && error == 0)
252: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
253: &ktriov, cnt, error);
254: #endif
255: *retval = cnt;
256: return (error);
257: }
258:
259: /*
260: * Gather write system call
261: */
262: writev(p, uap, retval)
263: struct proc *p;
264: register struct args {
265: int fdes;
266: struct iovec *iovp;
267: unsigned iovcnt;
268: } *uap;
269: int *retval;
270: {
271: register struct file *fp;
272: register struct filedesc *fdp = p->p_fd;
273: struct uio auio;
274: register struct iovec *iov;
275: struct iovec *saveiov;
276: struct iovec aiov[UIO_SMALLIOV];
277: long i, cnt, error = 0;
278: unsigned iovlen;
279: #ifdef KTRACE
280: struct iovec *ktriov = NULL;
281: #endif
282:
283: if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
284: (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
285: (fp->f_flag & FWRITE) == 0)
286: return (EBADF);
287: /* note: can't use iovlen until iovcnt is validated */
288: iovlen = uap->iovcnt * sizeof (struct iovec);
289: if (uap->iovcnt > UIO_SMALLIOV) {
290: if (uap->iovcnt > UIO_MAXIOV)
291: return (EINVAL);
292: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
293: saveiov = iov;
294: } else
295: iov = aiov;
296: auio.uio_iov = iov;
297: auio.uio_iovcnt = uap->iovcnt;
298: auio.uio_rw = UIO_WRITE;
299: auio.uio_segflg = UIO_USERSPACE;
300: auio.uio_procp = p;
301: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
302: goto done;
303: auio.uio_resid = 0;
304: for (i = 0; i < uap->iovcnt; i++) {
305: if (iov->iov_len < 0) {
306: error = EINVAL;
307: goto done;
308: }
309: auio.uio_resid += iov->iov_len;
310: if (auio.uio_resid < 0) {
311: error = EINVAL;
312: goto done;
313: }
314: iov++;
315: }
316: #ifdef KTRACE
317: /*
318: * if tracing, save a copy of iovec
319: */
320: if (KTRPOINT(p, KTR_GENIO)) {
321: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
322: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
323: }
324: #endif
325: cnt = auio.uio_resid;
326: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
327: if (auio.uio_resid != cnt && (error == ERESTART ||
328: error == EINTR || error == EWOULDBLOCK))
329: error = 0;
330: if (error == EPIPE)
331: psignal(p, SIGPIPE);
332: }
333: cnt -= auio.uio_resid;
334: #ifdef KTRACE
335: if (ktriov != NULL) {
336: if (error == 0)
337: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
338: ktriov, cnt, error);
339: FREE(ktriov, M_TEMP);
340: }
341: #endif
342: *retval = cnt;
343: done:
344: if (uap->iovcnt > UIO_SMALLIOV)
345: FREE(saveiov, M_IOV);
346: return (error);
347: }
348:
349: /*
350: * Ioctl system call
351: */
352: /* ARGSUSED */
353: ioctl(p, uap, retval)
354: struct proc *p;
355: register struct args {
356: int fdes;
357: int cmd;
358: caddr_t cmarg;
359: } *uap;
360: int *retval;
361: {
362: register struct file *fp;
363: register struct filedesc *fdp = p->p_fd;
364: register int com, error;
365: register u_int size;
366: caddr_t memp = 0;
367: #define STK_PARAMS 128
368: char stkbuf[STK_PARAMS];
369: caddr_t data = stkbuf;
370: int tmp;
371:
372: if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
373: (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
374: return (EBADF);
375: if ((fp->f_flag & (FREAD|FWRITE)) == 0)
376: return (EBADF);
377: com = uap->cmd;
378:
379: if (com == FIOCLEX) {
380: fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
381: return (0);
382: }
383: if (com == FIONCLEX) {
384: fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
385: return (0);
386: }
387:
388: /*
389: * Interpret high order word to find
390: * amount of data to be copied to/from the
391: * user's address space.
392: */
393: size = IOCPARM_LEN(com);
394: if (size > IOCPARM_MAX)
395: return (ENOTTY);
396: if (size > sizeof (stkbuf)) {
397: memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
398: data = memp;
399: }
400: if (com&IOC_IN) {
401: if (size) {
402: error = copyin(uap->cmarg, data, (u_int)size);
403: if (error) {
404: if (memp)
405: free(memp, M_IOCTLOPS);
406: return (error);
407: }
408: } else
409: *(caddr_t *)data = uap->cmarg;
410: } else if ((com&IOC_OUT) && size)
411: /*
412: * Zero the buffer so the user always
413: * gets back something deterministic.
414: */
415: bzero(data, size);
416: else if (com&IOC_VOID)
417: *(caddr_t *)data = uap->cmarg;
418:
419: switch (com) {
420:
421: case FIONBIO:
422: if (tmp = *(int *)data)
423: fp->f_flag |= FNONBLOCK;
424: else
425: fp->f_flag &= ~FNONBLOCK;
426: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
427: break;
428:
429: case FIOASYNC:
430: if (tmp = *(int *)data)
431: fp->f_flag |= FASYNC;
432: else
433: fp->f_flag &= ~FASYNC;
434: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
435: break;
436:
437: case FIOSETOWN:
438: tmp = *(int *)data;
439: if (fp->f_type == DTYPE_SOCKET) {
440: ((struct socket *)fp->f_data)->so_pgid = tmp;
441: error = 0;
442: break;
443: }
444: if (tmp <= 0) {
445: tmp = -tmp;
446: } else {
447: struct proc *p1 = pfind(tmp);
448: if (p1 == 0) {
449: error = ESRCH;
450: break;
451: }
452: tmp = p1->p_pgrp->pg_id;
453: }
454: error = (*fp->f_ops->fo_ioctl)
455: (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
456: break;
457:
458: case FIOGETOWN:
459: if (fp->f_type == DTYPE_SOCKET) {
460: error = 0;
461: *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
462: break;
463: }
464: error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
465: *(int *)data = -*(int *)data;
466: break;
467:
468: default:
469: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
470: /*
471: * Copy any data to user, size was
472: * already set and checked above.
473: */
474: if (error == 0 && (com&IOC_OUT) && size)
475: error = copyout(data, uap->cmarg, (u_int)size);
476: break;
477: }
478: if (memp)
479: free(memp, M_IOCTLOPS);
480: return (error);
481: }
482:
483: int selwait, nselcoll;
484:
485: /*
486: * Select system call.
487: */
488: select(p, uap, retval)
489: register struct proc *p;
490: register struct args {
491: int nd;
492: fd_set *in, *ou, *ex;
493: struct timeval *tv;
494: } *uap;
495: int *retval;
496: {
497: fd_set ibits[3], obits[3];
498: struct timeval atv;
499: int s, ncoll, ni, error = 0, timo;
500:
501: bzero((caddr_t)ibits, sizeof(ibits));
502: bzero((caddr_t)obits, sizeof(obits));
503: if (uap->nd > p->p_fd->fd_nfiles)
504: uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
505: ni = howmany(uap->nd, NFDBITS);
506:
507: #define getbits(name, x) \
508: if (uap->name) { \
509: error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
510: (unsigned)(ni * sizeof(fd_mask))); \
511: if (error) \
512: goto done; \
513: }
514: getbits(in, 0);
515: getbits(ou, 1);
516: getbits(ex, 2);
517: #undef getbits
518:
519: if (uap->tv) {
520: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
521: sizeof (atv));
522: if (error)
523: goto done;
524: if (itimerfix(&atv)) {
525: error = EINVAL;
526: goto done;
527: }
528: s = splhigh(); timevaladd(&atv, &time); splx(s);
529: timo = hzto(&atv);
530: } else
531: timo = 0;
532: retry:
533: ncoll = nselcoll;
534: p->p_flag |= SSEL;
535: error = selscan(p, ibits, obits, uap->nd, retval);
536: if (error || *retval)
537: goto done;
538: s = splhigh();
539: /* this should be timercmp(&time, &atv, >=) */
540: if (uap->tv && (time.tv_sec > atv.tv_sec ||
541: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
542: splx(s);
543: goto done;
544: }
545: if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
546: splx(s);
547: goto retry;
548: }
549: p->p_flag &= ~SSEL;
550: error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
551: splx(s);
552: if (error == 0)
553: goto retry;
554: done:
555: p->p_flag &= ~SSEL;
556: /* select is not restarted after signals... */
557: if (error == ERESTART)
558: error = EINTR;
559: if (error == EWOULDBLOCK)
560: error = 0;
561: #define putbits(name, x) \
562: if (uap->name) { \
563: int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
564: (unsigned)(ni * sizeof(fd_mask))); \
565: if (error2) \
566: error = error2; \
567: }
568: if (error == 0) {
569: putbits(in, 0);
570: putbits(ou, 1);
571: putbits(ex, 2);
572: #undef putbits
573: }
574: return (error);
575: }
576:
1.1.1.2 ! root 577: int
! 578: selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
1.1 root 579: {
580: register struct filedesc *fdp = p->p_fd;
581: register int which, i, j;
582: register fd_mask bits;
583: int flag;
584: struct file *fp;
585: int error = 0, n = 0;
586:
587: for (which = 0; which < 3; which++) {
588: switch (which) {
589:
590: case 0:
591: flag = FREAD; break;
592:
593: case 1:
594: flag = FWRITE; break;
595:
596: case 2:
597: flag = 0; break;
598: }
599: for (i = 0; i < nfd; i += NFDBITS) {
600: bits = ibits[which].fds_bits[i/NFDBITS];
601: while ((j = ffs(bits)) && i + --j < nfd) {
602: bits &= ~(1 << j);
603: fp = fdp->fd_ofiles[i + j];
604: if (fp == NULL) {
605: error = EBADF;
606: break;
607: }
608: if ((*fp->f_ops->fo_select)(fp, flag, p)) {
609: FD_SET(i + j, &obits[which]);
610: n++;
611: }
612: }
613: }
614: }
615: *retval = n;
616: return (error);
617: }
618:
619: /*ARGSUSED*/
1.1.1.2 ! root 620: int
1.1 root 621: seltrue(dev_t dev, int which, struct proc *p)
622: {
623:
624: return (1);
625: }
626:
1.1.1.2 ! root 627: void
! 628: selwakeup(pid_t pid, int coll)
1.1 root 629: {
1.1.1.2 ! root 630: register struct proc *p;
1.1 root 631:
632: if (coll) {
633: nselcoll++;
634: wakeup((caddr_t)&selwait);
635: }
1.1.1.2 ! root 636: if (pid && (p = pfind(pid))) {
1.1 root 637: int s = splhigh();
638: if (p->p_wchan == (caddr_t)&selwait) {
639: if (p->p_stat == SSLEEP)
640: setrun(p);
641: else
642: unsleep(p);
643: } else if (p->p_flag & SSEL)
644: p->p_flag &= ~SSEL;
645: splx(s);
646: }
647: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.