Commit | Line | Data |
---|---|---|
a0afbc8c DR |
1 | # |
2 | /* | |
3 | * general TTY subroutines | |
4 | */ | |
5 | #include "/sys/nsys/param.h" | |
6 | #include "/sys/nsys/systm.h" | |
7 | #include "/sys/nsys/user.h" | |
8 | #include "/sys/nsys/tty.h" | |
9 | #include "/sys/nsys/proc.h" | |
10 | #include "/sys/nsys/inode.h" | |
11 | #include "/sys/nsys/file.h" | |
12 | #include "/sys/nsys/reg.h" | |
13 | #include "/sys/nsys/conf.h" | |
14 | ||
15 | struct { int int; }; | |
16 | #define PS 0177776 | |
17 | ||
18 | struct cblock { | |
19 | struct cblock *c_next; | |
20 | char info[6]; | |
21 | }; | |
22 | ||
23 | struct cblock cfree[NCLIST]; | |
24 | struct cblock *cfreelist; | |
25 | ||
26 | struct { | |
27 | int ttrcsr; | |
28 | int ttrbuf; | |
29 | int tttcsr; | |
30 | int tttbuf; | |
31 | }; | |
32 | ||
33 | gtty() | |
34 | { | |
35 | int v[3], *up; | |
36 | ||
37 | sgtty(v); | |
38 | if (u.u_error) | |
39 | return; | |
40 | up = u.u_arg[0]; | |
41 | suword(up, v[0]); | |
42 | suword(++up, v[1]); | |
43 | suword(++up, v[2]); | |
44 | } | |
45 | ||
46 | stty() | |
47 | { | |
48 | int *up; | |
49 | ||
50 | up = u.u_arg[0]; | |
51 | u.u_arg[0] = fuword(up); | |
52 | u.u_arg[1] = fuword(++up); | |
53 | u.u_arg[2] = fuword(++up); | |
54 | sgtty(0); | |
55 | } | |
56 | ||
57 | sgtty(v) | |
58 | { | |
59 | register struct file *fp; | |
60 | register struct inode *ip; | |
61 | ||
62 | if ((fp = getf(u.u_ar0[R0])) == NULL) | |
63 | return; | |
64 | ip = fp->f_inode; | |
65 | if ((ip->i_mode&IFMT) != IFCHR) { | |
66 | u.u_error = ENOTTY; | |
67 | return; | |
68 | } | |
69 | (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v); | |
70 | } | |
71 | ||
72 | wflushtty(tp) | |
73 | struct tty *tp; | |
74 | { | |
75 | ||
76 | spl5(); | |
77 | while (tp->t_outq.c_cc) | |
78 | sleep(&tp->t_outq, TTOPRI); | |
79 | flushtty(tp); | |
80 | spl0(); | |
81 | } | |
82 | ||
83 | cinit() | |
84 | { | |
85 | int ccp; | |
86 | register struct cblock *cp; | |
87 | ||
88 | ccp = cfree; | |
89 | for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) { | |
90 | cp->c_next = cfreelist; | |
91 | cfreelist = cp; | |
92 | } | |
93 | } | |
94 | ||
95 | /* | |
96 | * flush all TTY queues | |
97 | */ | |
98 | flushtty(tp) | |
99 | struct tty *tp; | |
100 | { | |
101 | int sps; | |
102 | ||
103 | while (getc(&tp->t_canq) >= 0); | |
104 | while (getc(&tp->t_outq) >= 0); | |
105 | wakeup(&tp->t_rawq); | |
106 | wakeup(&tp->t_outq); | |
107 | sps = PS->int; | |
108 | spl5(); | |
109 | while (getc(&tp->t_rawq) >= 0); | |
110 | tp->t_delct = 0; | |
111 | PS->int = sps; | |
112 | } | |
113 | ||
114 | /* | |
115 | * transfer raw list to canonical list, | |
116 | * doing code conversion. | |
117 | */ | |
118 | canon(tp) | |
119 | struct tty *tp; | |
120 | { | |
121 | register char *bp, *bp1; | |
122 | register int c; | |
123 | ||
124 | while (tp->t_delct==0) | |
125 | sleep(&tp->t_rawq, TTIPRI); | |
126 | loop: | |
127 | bp = &canonb[1]; | |
128 | while ((c=getc(&tp->t_rawq)) >= 0) { | |
129 | if ((tp->t_flags&RAW)==0) { | |
130 | if (bp[-1]!='\\') { | |
131 | if (c==CERASE) { | |
132 | if (bp > &canonb[1]) | |
133 | bp--; | |
134 | continue; | |
135 | } | |
136 | if (c==CKILL) | |
137 | goto loop; | |
138 | if (c==CEOT) | |
139 | continue; | |
140 | } else if (c==CERASE||c==CKILL||c==CEOT) | |
141 | bp--; | |
142 | } | |
143 | if (c==0377) { | |
144 | tp->t_delct--; | |
145 | break; | |
146 | } | |
147 | *bp++ = c; | |
148 | if (bp>=canonb+CANBSIZ) | |
149 | break; | |
150 | } | |
151 | bp1 = &canonb[1]; | |
152 | c = &tp->t_canq; | |
153 | while (bp1<bp) | |
154 | putc(*bp1++, c); | |
155 | return(1); | |
156 | } | |
157 | ||
158 | /* | |
159 | * place a character on raw TTY input queue, putting in delimiters | |
160 | * and waking up top half as needed. | |
161 | * also echo if required. | |
162 | */ | |
163 | ttyinput(c, tp) | |
164 | struct tty *tp; | |
165 | { | |
166 | int t_flags; | |
167 | ||
168 | t_flags = tp->t_flags; | |
169 | if ((c =& 0177) == '\r' && t_flags&CRMOD) | |
170 | c = '\n'; | |
171 | if ((t_flags&RAW)==0 && (c==tp->t_quit || c==tp->t_intrup)) { | |
172 | signal(tp, c==tp->t_intrup? SIGINT:SIGQIT); | |
173 | flushtty(tp); | |
174 | return; | |
175 | } | |
176 | if (tp->t_rawq.c_cc>=TTYHOG) { | |
177 | flushtty(tp); | |
178 | return; | |
179 | } | |
180 | if (t_flags&LCASE && c>='A' && c<='Z') | |
181 | c =+ 'a'-'A'; | |
182 | putc(c, &tp->t_rawq); | |
183 | if (t_flags&RAW || c=='\n' || c==004) { | |
184 | wakeup(&tp->t_rawq); | |
185 | if (putc(0377, &tp->t_rawq)==0) | |
186 | tp->t_delct++; | |
187 | } | |
188 | if (t_flags&ECHO) { | |
189 | ttyoutput(c, tp); | |
190 | ttstart(tp); | |
191 | } | |
192 | } | |
193 | ||
194 | /* | |
195 | * put character on TTY output queue, adding delays, | |
196 | * expanding tabs, and handling the CR/NL bit. | |
197 | */ | |
198 | ttyoutput(c, tp) | |
199 | struct tty *tp; | |
200 | { | |
201 | int delay; | |
202 | register struct tty *rtp; | |
203 | register char *colp; | |
204 | ||
205 | rtp = tp; | |
206 | if ((c=&0177)==004 && (rtp->t_flags&RAW)==0) | |
207 | return; | |
208 | if (c=='\t' && rtp->t_flags&XTABS) { | |
209 | do | |
210 | ttyoutput(' ', rtp); | |
211 | while (rtp->t_col&07); | |
212 | return; | |
213 | } | |
214 | if (c=='\n' && rtp->t_flags&CRMOD) | |
215 | ttyoutput('\r', rtp); | |
216 | if (putc(c, &rtp->t_outq)) | |
217 | return; | |
218 | delay = 0; | |
219 | colp = &rtp->t_col; | |
220 | if ((rtp->t_flags&NODELAY)==0) switch (partab[c]&077) { | |
221 | ||
222 | /* ordinary */ | |
223 | case 0: | |
224 | (*colp)++; | |
225 | ||
226 | /* non-printing */ | |
227 | case 1: | |
228 | break; | |
229 | ||
230 | /* backspace */ | |
231 | case 2: | |
232 | if (*colp) | |
233 | (*colp)--; | |
234 | break; | |
235 | ||
236 | /* newline */ | |
237 | case 3: | |
238 | if (*colp) | |
239 | delay = max((*colp>>4) + 3, 6); | |
240 | *colp = 0; | |
241 | break; | |
242 | ||
243 | /* tab */ | |
244 | case 4: | |
245 | if ((rtp->t_flags&NTDELAY)==0) | |
246 | delay = 1 - (*colp | ~07); | |
247 | *colp =| 07; | |
248 | (*colp)++; | |
249 | break; | |
250 | ||
251 | /* vertical motion */ | |
252 | case 5: | |
253 | delay = 0177; | |
254 | break; | |
255 | ||
256 | /* carriage return */ | |
257 | case 6: | |
258 | delay = 6; | |
259 | *colp = 0; | |
260 | } | |
261 | if (delay) | |
262 | putc(delay|0200, &rtp->t_outq); | |
263 | } | |
264 | ||
265 | ttrstrt(tp) | |
266 | { | |
267 | tp->t_state =& ~TIMEOUT; | |
268 | ttstart(tp); | |
269 | } | |
270 | ||
271 | ttstart(tp) | |
272 | struct tty *tp; | |
273 | { | |
274 | int *addr; | |
275 | int c; | |
276 | ||
277 | addr = tp->t_addr; | |
278 | if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT) | |
279 | return; | |
280 | if ((c=getc(&tp->t_outq)) >= 0) { | |
281 | if (c<=0177) | |
282 | addr->tttbuf = c | (partab[c]&0200); | |
283 | else { | |
284 | timeout(ttrstrt, tp, c&0177); | |
285 | tp->t_state =| TIMEOUT; | |
286 | } | |
287 | } | |
288 | } | |
289 | ||
290 | ttread(tp) | |
291 | struct tty *tp; | |
292 | { | |
293 | if (tp->t_canq.c_cc || canon(tp)) | |
294 | while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); | |
295 | } | |
296 | ||
297 | ttwrite(tp) | |
298 | struct tty *tp; | |
299 | { | |
300 | int c; | |
301 | ||
302 | while (cpass(&c)>=0) { | |
303 | while (tp->t_outq.c_cc > TTHIWAT) { | |
304 | ttstart(tp); | |
305 | sleep(&tp->t_outq, TTOPRI); | |
306 | } | |
307 | ttyoutput(c, tp); | |
308 | } | |
309 | ttstart(tp); | |
310 | } |