xref: /csrg-svn/sys/kern/kern_descrip.c (revision 7422)
1 /*	kern_descrip.c	5.1	82/07/15	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/reg.h"
8 #include "../h/inode.h"
9 #include "../h/proc.h"
10 #include "../h/clock.h"
11 #include "../h/mtpr.h"
12 #include "../h/timeb.h"
13 #include "../h/times.h"
14 #include "../h/reboot.h"
15 #include "../h/fs.h"
16 #include "../h/conf.h"
17 #include "../h/buf.h"
18 #include "../h/mount.h"
19 #include "../h/file.h"
20 #include "../h/inline.h"
21 #include "../h/socket.h"
22 #include "../h/socketvar.h"
23 
24 /*
25  * the dup system call.
26  */
27 dup()
28 {
29 	register struct file *fp;
30 	register struct a {
31 		int	fdes;
32 		int	fdes2;
33 	} *uap;
34 	register i, m;
35 
36 	uap = (struct a *)u.u_ap;
37 	m = uap->fdes & ~077;
38 	uap->fdes &= 077;
39 	fp = getf(uap->fdes);
40 	if (fp == NULL)
41 		return;
42 	if ((m&0100) == 0) {
43 		if ((i = ufalloc()) < 0)
44 			return;
45 	} else {
46 		i = uap->fdes2;
47 		if (i<0 || i>=NOFILE) {
48 			u.u_error = EBADF;
49 			return;
50 		}
51 		u.u_r.r_val1 = i;
52 	}
53 	if (i != uap->fdes) {
54 		if (u.u_ofile[i]!=NULL)
55 			closef(u.u_ofile[i], 0);
56 		if (u.u_error)
57 			return;
58 		u.u_ofile[i] = fp;
59 		fp->f_count++;
60 	}
61 }
62 
63 int	nselcoll;
64 /*
65  * Select system call.
66  */
67 select()
68 {
69 	register struct uap  {
70 		int	nfd;
71 		fd_set	*rp, *wp;
72 		int	timo;
73 	} *ap = (struct uap *)u.u_ap;
74 	fd_set rd, wr;
75 	int nfds = 0, readable = 0, writeable = 0;
76 	time_t t = time;
77 	int s, tsel, ncoll, rem;
78 
79 	if (ap->nfd > NOFILE)
80 		ap->nfd = NOFILE;
81 	if (ap->nfd < 0) {
82 		u.u_error = EBADF;
83 		return;
84 	}
85 	if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set)))
86 		return;
87 	if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set)))
88 		return;
89 retry:
90 	ncoll = nselcoll;
91 	u.u_procp->p_flag |= SSEL;
92 	if (ap->rp)
93 		readable = selscan(ap->nfd, rd, &nfds, FREAD);
94 	if (ap->wp)
95 		writeable = selscan(ap->nfd, wr, &nfds, FWRITE);
96 	if (u.u_error)
97 		goto done;
98 	if (readable || writeable)
99 		goto done;
100 	rem = (ap->timo+999)/1000 - (time - t);
101 	if (ap->timo == 0 || rem <= 0)
102 		goto done;
103 	s = spl6();
104 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
105 		u.u_procp->p_flag &= ~SSEL;
106 		splx(s);
107 		goto retry;
108 	}
109 	u.u_procp->p_flag &= ~SSEL;
110 	tsel = tsleep((caddr_t)&selwait, PZERO+1, rem);
111 	splx(s);
112 	switch (tsel) {
113 
114 	case TS_OK:
115 		goto retry;
116 
117 	case TS_SIG:
118 		u.u_error = EINTR;
119 		return;
120 
121 	case TS_TIME:
122 		break;
123 	}
124 done:
125 	rd.fds_bits[0] = readable;
126 	wr.fds_bits[0] = writeable;
127 	s = sizeof (fd_set);
128 	if (s * NBBY > ap->nfd)
129 		s = (ap->nfd + NBBY - 1) / NBBY;
130 	u.u_r.r_val1 = nfds;
131 	if (ap->rp)
132 		(void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set));
133 	if (ap->wp)
134 		(void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set));
135 }
136 
137 selscan(nfd, fds, nfdp, flag)
138 	int nfd;
139 	fd_set fds;
140 	int *nfdp, flag;
141 {
142 	struct file *fp;
143 	struct inode *ip;
144 	register int bits;
145 	int i, able, res = 0;
146 
147 	bits = fds.fds_bits[0];
148 	while (i = ffs(bits)) {
149 		if (i > nfd)
150 			break;
151 		bits &= ~(1<<(i-1));
152 		fp = u.u_ofile[i-1];
153 		if (fp == NULL) {
154 			u.u_error = EBADF;
155 			return (0);
156 		}
157 		if (fp->f_flag & FSOCKET)
158 			able = soselect(fp->f_socket, flag);
159 		else {
160 			ip = fp->f_inode;
161 			switch (ip->i_mode & IFMT) {
162 
163 			case IFCHR:
164 				able =
165 				    (*cdevsw[major(ip->i_rdev)].d_select)
166 					(ip->i_rdev, flag);
167 				break;
168 
169 			case IFBLK:
170 			case IFREG:
171 			case IFDIR:
172 				able = 1;
173 				break;
174 			}
175 		}
176 		if (able) {
177 			res |= (1<<(i-1));
178 			(*nfdp)++;
179 		}
180 	}
181 	return (res);
182 }
183 
184 /*ARGSUSED*/
185 seltrue(dev, flag)
186 	dev_t dev;
187 	int flag;
188 {
189 
190 	return (1);
191 }
192 
193 selwakeup(p, coll)
194 	register struct proc *p;
195 	int coll;
196 {
197 	int s;
198 
199 	if (coll) {
200 		nselcoll++;
201 		wakeup((caddr_t)&selwait);
202 	}
203 	if (p) {
204 		if (p->p_wchan == (caddr_t)&selwait)
205 			setrun(p);
206 		else {
207 			s = spl6();
208 			if (p->p_flag & SSEL)
209 				p->p_flag &= ~SSEL;
210 			splx(s);
211 		}
212 	}
213 }
214 
215 /*
216  * Close system call
217  */
218 close()
219 {
220 	register struct file *fp;
221 	register struct a {
222 		int	fdes;
223 	} *uap;
224 
225 	uap = (struct a *)u.u_ap;
226 	fp = getf(uap->fdes);
227 	if (fp == NULL)
228 		return;
229 	if (u.u_vrpages[uap->fdes]) {
230 		u.u_error = ETXTBSY;
231 		return;
232 	}
233 	u.u_ofile[uap->fdes] = NULL;
234 	closef(fp, 0);
235 }
236