Research V5 development
[unix-history] / usr / sys / dmr / tty.c
CommitLineData
20c73af6
DR
1#
2/*
3 * Copyright 1973 Bell Telephone Laboratories Inc
4 */
5
6/*
7 * general TTY subroutines
8 */
9#include "../param.h"
10#include "../systm.h"
11#include "../user.h"
12#include "../tty.h"
13#include "../proc.h"
14#include "../inode.h"
15#include "../file.h"
16#include "../reg.h"
17#include "../conf.h"
18
19struct { int int; };
20#define PS 0177776
21
22char maptab[]
23{
24 000,000,000,000,004,000,000,000,
25 000,000,000,000,000,000,000,000,
26 000,000,000,000,000,000,000,000,
27 000,000,000,000,000,000,000,000,
28 000,'|',000,'#',000,000,000,'`',
29 '{','}',000,000,000,000,000,000,
30 000,000,000,000,000,000,000,000,
31 000,000,000,000,000,000,000,000,
32 '@',000,000,000,000,000,000,000,
33 000,000,000,000,000,000,000,000,
34 000,000,000,000,000,000,000,000,
35 000,000,000,000,000,000,'~',000,
36 000,'A','B','C','D','E','F','G',
37 'H','I','J','K','L','M','N','O',
38 'P','Q','R','S','T','U','V','W',
39 'X','Y','Z',000,000,000,000,000,
40};
41
42struct cblock {
43 struct cblock *c_next;
44 char info[6];
45};
46
47struct cblock cfree[NCLIST];
48struct cblock *cfreelist;
49
50struct {
51 int ttrcsr;
52 int ttrbuf;
53 int tttcsr;
54 int tttbuf;
55};
56
57gtty()
58{
59 int v[3];
60 register *up, *vp;
61
62 vp = v;
63 sgtty(vp);
64 if (u.u_error)
65 return;
66 up = u.u_arg[0];
67 suword(up, *vp++);
68 suword(++up, *vp++);
69 suword(++up, *vp++);
70}
71
72stty()
73{
74 register int *up;
75
76 up = u.u_arg[0];
77 u.u_arg[0] = fuword(up);
78 u.u_arg[1] = fuword(++up);
79 u.u_arg[2] = fuword(++up);
80 sgtty(0);
81}
82
83sgtty(v)
84{
85 register struct file *fp;
86 register struct inode *ip;
87
88 if ((fp = getf(u.u_ar0[R0])) == NULL)
89 return;
90 ip = fp->f_inode;
91 if ((ip->i_mode&IFMT) != IFCHR) {
92 u.u_error = ENOTTY;
93 return;
94 }
95 (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
96}
97
98wflushtty(atp)
99struct tty *atp;
100{
101 register struct tty *tp;
102
103 tp = atp;
104 spl5();
105 while (tp->t_outq.c_cc)
106 sleep(&tp->t_outq, TTOPRI);
107 flushtty(tp);
108 spl0();
109}
110
111cinit()
112{
113 register int ccp;
114 register struct cblock *cp;
115 register struct cdevsw *cdp;
116
117 ccp = cfree;
118 for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
119 cp->c_next = cfreelist;
120 cfreelist = cp;
121 }
122 ccp = 0;
123 for(cdp = cdevsw; cdp->d_open; cdp++)
124 ccp++;
125 nchrdev = ccp;
126}
127
128/*
129 * flush all TTY queues
130 */
131flushtty(atp)
132struct tty *atp;
133{
134 register struct tty *tp;
135 register int sps;
136
137 tp = atp;
138 while (getc(&tp->t_canq) >= 0);
139 while (getc(&tp->t_outq) >= 0);
140 wakeup(&tp->t_rawq);
141 wakeup(&tp->t_outq);
142 sps = PS->int;
143 spl5();
144 while (getc(&tp->t_rawq) >= 0);
145 tp->t_delct = 0;
146 PS->int = sps;
147}
148
149/*
150 * transfer raw list to canonical list,
151 * doing code conversion.
152 */
153canon(atp)
154struct tty *atp;
155{
156 register char *bp;
157 char *bp1;
158 register struct tty *tp;
159 register int c;
160
161 tp = atp;
162 spl5();
163 while (tp->t_delct==0) {
164 if ((tp->t_state&CARR_ON)==0)
165 return(0);
166 sleep(&tp->t_rawq, TTIPRI);
167 }
168 spl0();
169loop:
170 bp = &canonb[2];
171 while ((c=getc(&tp->t_rawq)) >= 0) {
172 if (c==0377) {
173 tp->t_delct--;
174 break;
175 }
176 if ((tp->t_flags&RAW)==0) {
177 if (bp[-1]!='\\') {
178 if (c==tp->t_erase) {
179 if (bp > &canonb[2])
180 bp--;
181 continue;
182 }
183 if (c==tp->t_kill)
184 goto loop;
185 if (c==CEOT)
186 continue;
187 } else
188 if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
189 if (bp[-2] != '\\')
190 c = maptab[c];
191 bp--;
192 }
193 }
194 *bp++ = c;
195 if (bp>=canonb+CANBSIZ)
196 break;
197 }
198 bp1 = bp;
199 bp = &canonb[2];
200 c = &tp->t_canq;
201 while (bp<bp1)
202 putc(*bp++, c);
203 return(1);
204}
205
206/*
207 * place a character on raw TTY input queue, putting in delimiters
208 * and waking up top half as needed.
209 * also echo if required.
210 */
211ttyinput(ac, atp)
212struct tty *atp;
213{
214 register int t_flags, c;
215 register struct tty *tp;
216
217 tp = atp;
218 c = ac;
219 t_flags = tp->t_flags;
220 if ((c =& 0177) == '\r' && t_flags&CRMOD)
221 c = '\n';
222 if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
223 signal(tp, c==CINTR? SIGINT:SIGQIT);
224 flushtty(tp);
225 return;
226 }
227 if (tp->t_rawq.c_cc>=TTYHOG) {
228 flushtty(tp);
229 return;
230 }
231 if (t_flags&LCASE && c>='A' && c<='Z')
232 c =+ 'a'-'A';
233 putc(c, &tp->t_rawq);
234 if (t_flags&RAW || c=='\n' || c==004) {
235 wakeup(&tp->t_rawq);
236 if (putc(0377, &tp->t_rawq)==0)
237 tp->t_delct++;
238 }
239 if (t_flags&ECHO) {
240 ttyoutput(c, tp);
241 ttstart(tp);
242 }
243}
244
245/*
246 * put character on TTY output queue, adding delays,
247 * expanding tabs, and handling the CR/NL bit.
248 */
249ttyoutput(ac, tp)
250struct tty *tp;
251{
252 register int c;
253 register struct tty *rtp;
254 register char *colp;
255 int ctype;
256
257 rtp = tp;
258 c = ac&0177;
259 if (c==004 && (rtp->t_flags&RAW)==0)
260 return;
261 if (c=='\t' && rtp->t_flags&XTABS) {
262 do
263 ttyoutput(' ', rtp);
264 while (rtp->t_col&07);
265 return;
266 }
267 if (rtp->t_flags&LCASE) {
268 colp = "({)}!|^~'`";
269 while(*colp++)
270 if(c == *colp++) {
271 ttyoutput('\\', rtp);
272 c = colp[-2];
273 break;
274 }
275 if ('a'<=c && c<='z')
276 c =+ 'A' - 'a';
277 }
278 if (c=='\n' && rtp->t_flags&CRMOD)
279 ttyoutput('\r', rtp);
280 if (putc(c, &rtp->t_outq))
281 return;
282 colp = &rtp->t_col;
283 ctype = partab[c];
284 c = 0;
285 switch (ctype&077) {
286
287 /* ordinary */
288 case 0:
289 (*colp)++;
290
291 /* non-printing */
292 case 1:
293 break;
294
295 /* backspace */
296 case 2:
297 if (*colp)
298 (*colp)--;
299 break;
300
301 /* newline */
302 case 3:
303 if (*colp)
304 c = max((*colp>>4) + 3, 6);
305 *colp = 0;
306 break;
307
308 /* tab */
309 case 4:
310 if ((rtp->t_flags&NTDELAY)==0)
311 c = 1 - (*colp | ~07);
312 *colp =| 07;
313 (*colp)++;
314 break;
315
316 /* vertical motion */
317 case 5:
318 c = 0177;
319 break;
320
321 /* carriage return */
322 case 6:
323 c = 6;
324 *colp = 0;
325 }
326 if (c && (rtp->t_flags&NODELAY)==0)
327 putc(c|0200, &rtp->t_outq);
328}
329
330ttrstrt(atp)
331{
332 register struct tty *tp;
333
334 tp = atp;
335 tp->t_state =& ~TIMEOUT;
336 ttstart(tp);
337}
338
339ttstart(atp)
340struct tty *atp;
341{
342 register int *addr, c;
343 register struct tty *tp;
344 struct { int (*func)(); };
345
346 tp = atp;
347 addr = tp->t_addr;
348 if (tp->t_state&SSTART) {
349 (*addr.func)(tp);
350 return;
351 }
352 if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
353 return;
354 if ((c=getc(&tp->t_outq)) >= 0) {
355 if (c<=0177)
356 addr->tttbuf = c | (partab[c]&0200);
357 else {
358 timeout(ttrstrt, tp, c&0177);
359 tp->t_state =| TIMEOUT;
360 }
361 }
362}
363
364ttread(atp)
365struct tty *atp;
366{
367 register struct tty *tp;
368
369 tp = atp;
370 if (tp->t_canq.c_cc || canon(tp))
371 while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
372}
373
374ttwrite(atp)
375struct tty *atp;
376{
377 register struct tty *tp;
378 register int c;
379
380 tp = atp;
381 while ((c=cpass())>=0) {
382 spl5();
383 while (tp->t_outq.c_cc > TTHIWAT) {
384 ttstart(tp);
385 sleep(&tp->t_outq, TTOPRI);
386 }
387 spl0();
388 ttyoutput(c, tp);
389 }
390 ttstart(tp);
391}
392
393ttystty(atp, av)
394int *atp, *av;
395{
396 register *tp, *v;
397
398 tp = atp;
399 if(v = av) {
400 *v++ = tp->t_speeds;
401 v->lobyte = tp->t_erase;
402 v->hibyte = tp->t_kill;
403 v[1] = tp->t_flags;
404 return(1);
405 }
406 wflushtty(tp);
407 v = u.u_arg;
408 tp->t_speeds = *v++;
409 tp->t_erase = v->lobyte;
410 tp->t_kill = v->hibyte;
411 tp->t_flags = v[1];
412 return(0);
413}