Research V4 development
[unix-history] / sys / dmr / tty.c
CommitLineData
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
15struct { int int; };
16#define PS 0177776
17
18struct cblock {
19 struct cblock *c_next;
20 char info[6];
21};
22
23struct cblock cfree[NCLIST];
24struct cblock *cfreelist;
25
26struct {
27 int ttrcsr;
28 int ttrbuf;
29 int tttcsr;
30 int tttbuf;
31};
32
33gtty()
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
46stty()
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
57sgtty(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
72wflushtty(tp)
73struct 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
83cinit()
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 */
98flushtty(tp)
99struct 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 */
118canon(tp)
119struct 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);
126loop:
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 */
163ttyinput(c, tp)
164struct 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 */
198ttyoutput(c, tp)
199struct 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
265ttrstrt(tp)
266{
267 tp->t_state =& ~TIMEOUT;
268 ttstart(tp);
269}
270
271ttstart(tp)
272struct 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
290ttread(tp)
291struct 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
297ttwrite(tp)
298struct 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}