Commit | Line | Data |
---|---|---|
a8fd2d0d KM |
1 | /* |
2 | * Copyright (c) 1988 University of Utah. | |
3 | * Copyright (c) 1990 The Regents of the University of California. | |
4 | * All rights reserved. | |
5 | * | |
6 | * This code is derived from software contributed to Berkeley by | |
7 | * the Systems Programming Group of the University of Utah Computer | |
8 | * Science Department. | |
9 | * | |
10 | * %sccs.include.redist.c% | |
11 | * | |
12 | * from: Utah $Hdr: hpux_tty.c 1.7 89/04/11$ | |
13 | * | |
14 | * @(#)hpux_tty.c 7.1 (Berkeley) %G% | |
15 | */ | |
16 | ||
17 | /* | |
18 | * stty/gtty/termio emulation stuff | |
19 | */ | |
20 | #ifdef HPUXCOMPAT | |
21 | ||
22 | #include "param.h" | |
23 | #include "systm.h" | |
24 | #include "user.h" | |
25 | #include "ioctl.h" | |
26 | #include "tty.h" | |
27 | #include "proc.h" | |
28 | #include "file.h" | |
29 | #include "conf.h" | |
30 | #include "buf.h" | |
31 | #include "uio.h" | |
32 | #include "kernel.h" | |
33 | ||
34 | #include "hpux.h" | |
35 | #include "hpux_termio.h" | |
36 | ||
37 | char hpuxtobsdbaud[32] = { | |
38 | B0, B50, B75, B110, B134, B150, B200, B300, | |
39 | B600, B0, B1200, B1800, B2400, B0, B4800, B0, | |
40 | B9600, EXTA, EXTB, B0, B0, B0, B0, B0, | |
41 | B0, B0, B0, B0, B0, B0, B0, B0 | |
42 | }; | |
43 | ||
44 | char bsdtohpuxbaud[16] = { | |
45 | TIO_B0, TIO_B50, TIO_B75, TIO_B110, | |
46 | TIO_B134, TIO_B150, TIO_B200, TIO_B300, | |
47 | TIO_B600, TIO_B1200, TIO_B1800, TIO_B2400, | |
48 | TIO_B4800, TIO_B9600, TIO_B19200, TIO_B38400 | |
49 | }; | |
50 | ||
51 | /* | |
52 | * Map BSD style sgtty info to and from SYS5 style termio stuff. | |
53 | * Map BSD style sgtty info to and from V7 style sgtty stuff. | |
54 | */ | |
55 | hpuxtermio(fp, com, data) | |
56 | struct file *fp; | |
57 | caddr_t data; | |
58 | { | |
59 | struct sgttyb sg; | |
60 | struct bsdtchars { /* avoid problem with ttychars.h */ | |
61 | char bsdt_intrc; | |
62 | char bsdt_quitc; | |
63 | char bsdt_startc; | |
64 | char bsdt_stopc; | |
65 | char bsdt_eofc; | |
66 | char bsdt_brkc; | |
67 | } tc; | |
68 | struct bsdltchars { /* avoid problem with ttychars.h */ | |
69 | char bsdt_suspc; | |
70 | char bsdt_dsuspc; | |
71 | char bsdt_rprntc; | |
72 | char bsdt_flushc; | |
73 | char bsdt_werasc; | |
74 | char bsdt_lnextc; | |
75 | } ltc; | |
76 | int lmode, (*ioctlrout)(); | |
77 | register u_short flag; | |
78 | register struct hpuxtermio *tiop; | |
79 | ||
80 | ioctlrout = fp->f_ops->fo_ioctl; | |
81 | tiop = (struct hpuxtermio *)data; | |
82 | switch (com) { | |
83 | case HPUXTCGETA: | |
84 | /* get everything we might need */ | |
85 | bzero(data, sizeof(struct hpuxtermio)); | |
86 | if (u.u_error = ioctlrout(fp, TIOCGETP, (caddr_t)&sg)) | |
87 | break; | |
88 | (void) ioctlrout(fp, TIOCGETC, (caddr_t)&tc); | |
89 | (void) ioctlrout(fp, TIOCLGET, (caddr_t)&lmode); | |
90 | ||
91 | /* set baud rate */ | |
92 | tiop->c_cflag = (u_short)bsdtohpuxbaud[sg.sg_ispeed&0xF]; | |
93 | ||
94 | /* set editing chars except for EOF/EOL (set below) */ | |
95 | tiop->c_cc[HPUXVINTR] = tc.bsdt_intrc; | |
96 | tiop->c_cc[HPUXVQUIT] = tc.bsdt_quitc; | |
97 | tiop->c_cc[HPUXVERASE] = sg.sg_erase; | |
98 | tiop->c_cc[HPUXVKILL] = sg.sg_kill; | |
99 | ||
100 | /* set flags */ | |
101 | flag = sg.sg_flags; | |
102 | if ((flag & TBDELAY) == XTABS) | |
103 | tiop->c_oflag |= TIO_TAB3; | |
104 | else if (flag & TBDELAY) | |
105 | tiop->c_oflag |= TIO_TAB1; | |
106 | if (flag & LCASE) { | |
107 | tiop->c_iflag |= TIO_IUCLC; | |
108 | tiop->c_oflag |= TIO_OLCUC; | |
109 | tiop->c_lflag |= TIO_XCASE; | |
110 | } | |
111 | if (flag & ECHO) | |
112 | tiop->c_lflag |= TIO_ECHO; | |
113 | if (flag & CRMOD) { | |
114 | tiop->c_iflag |= TIO_ICRNL; | |
115 | tiop->c_oflag |= TIO_ONLCR; | |
116 | if (flag & CR1) | |
117 | tiop->c_oflag |= TIO_CR1; | |
118 | if (flag & CR2) | |
119 | tiop->c_oflag |= TIO_CR2|TIO_ONOCR; | |
120 | } else { | |
121 | tiop->c_oflag |= TIO_ONLRET; | |
122 | if (flag & NL1) | |
123 | tiop->c_oflag |= TIO_CR1; | |
124 | if (flag & NL2) | |
125 | tiop->c_oflag |= TIO_CR2; | |
126 | } | |
127 | if (flag & RAW) { | |
128 | tiop->c_cflag |= TIO_CS8; | |
129 | tiop->c_iflag &= ~(TIO_ICRNL|TIO_IUCLC); | |
130 | tiop->c_cc[HPUXVMIN] = 6; | |
131 | tiop->c_cc[HPUXVTIME] = 1; | |
132 | } else { | |
133 | tiop->c_iflag |= TIO_BRKINT; | |
134 | if (tc.bsdt_startc == CSTART && tc.bsdt_stopc == CSTOP) | |
135 | tiop->c_iflag |= TIO_IXON; | |
136 | if (flag & TANDEM) | |
137 | tiop->c_iflag |= TIO_IXOFF; | |
138 | else if ((lmode & LDECCTQ) == 0) | |
139 | tiop->c_iflag |= TIO_IXANY; | |
140 | if ((lmode & LLITOUT) == 0) { | |
141 | tiop->c_iflag |= TIO_IGNPAR; | |
142 | tiop->c_oflag |= TIO_OPOST; | |
143 | } | |
144 | if (lmode & LPASS8) | |
145 | tiop->c_cflag |= TIO_CS8; | |
146 | else | |
147 | tiop->c_iflag |= TIO_ISTRIP; | |
148 | tiop->c_cflag |= TIO_CS7|TIO_PARENB; | |
149 | tiop->c_lflag |= TIO_ISIG; | |
150 | if (flag & CBREAK) { | |
151 | tiop->c_cc[HPUXVMIN] = 6; | |
152 | tiop->c_cc[HPUXVTIME] = 1; | |
153 | } else { | |
154 | tiop->c_lflag |= TIO_ICANON|TIO_ECHOK; | |
155 | if (lmode & LCRTERA) | |
156 | tiop->c_lflag |= TIO_ECHOE; | |
157 | tiop->c_cc[HPUXVEOF] = tc.bsdt_eofc; | |
158 | tiop->c_cc[HPUXVEOL] = tc.bsdt_brkc; | |
159 | } | |
160 | } | |
161 | tiop->c_cflag |= TIO_PARENB; | |
162 | if (flag & ODDP) { | |
163 | if (flag & EVENP) | |
164 | tiop->c_cflag &= ~TIO_PARENB; | |
165 | tiop->c_cflag |= TIO_PARODD; | |
166 | } | |
167 | if (tiop->c_cflag & TIO_PARENB) | |
168 | tiop->c_iflag |= TIO_INPCK; | |
169 | if (flag & VTDELAY) | |
170 | tiop->c_oflag |= TIO_FFDLY; | |
171 | if (flag & BSDELAY) | |
172 | tiop->c_oflag |= TIO_BSDLY; | |
173 | break; | |
174 | ||
175 | case HPUXTCSETA: | |
176 | case HPUXTCSETAW: | |
177 | case HPUXTCSETAF: | |
178 | /* get old lmode and determine if we are a tty */ | |
179 | if (u.u_error = ioctlrout(fp, TIOCLGET, (caddr_t)&lmode)) | |
180 | break; | |
181 | (void) ioctlrout(fp, TIOCGLTC, (caddr_t)<c); | |
182 | ||
183 | /* set baud rate */ | |
184 | sg.sg_ispeed = hpuxtobsdbaud[tiop->c_cflag&TIO_CBAUD]; | |
185 | sg.sg_ospeed = sg.sg_ispeed; | |
186 | ||
187 | /* set special chars to defaults for cooked mode */ | |
188 | sg.sg_erase = tiop->c_cc[HPUXVERASE]; | |
189 | sg.sg_kill = tiop->c_cc[HPUXVKILL]; | |
190 | tc.bsdt_intrc = tiop->c_cc[HPUXVINTR]; | |
191 | tc.bsdt_quitc = tiop->c_cc[HPUXVQUIT]; | |
192 | tc.bsdt_startc = CSTART; | |
193 | tc.bsdt_stopc = CSTOP; | |
194 | tc.bsdt_eofc = tiop->c_cc[HPUXVEOF]; | |
195 | tc.bsdt_brkc = tiop->c_cc[HPUXVEOL]; | |
196 | ltc.bsdt_suspc = CSUSP; | |
197 | ltc.bsdt_dsuspc = CDSUSP; | |
198 | ltc.bsdt_flushc = CFLUSH; | |
199 | ltc.bsdt_lnextc = CLNEXT; | |
200 | ||
201 | /* set flags */ | |
202 | flag = 0; | |
203 | if (tiop->c_oflag & TIO_BSDLY) | |
204 | flag |= BSDELAY; | |
205 | if (tiop->c_oflag & TIO_FFDLY) | |
206 | flag |= VTDELAY; | |
207 | if (tiop->c_oflag & TIO_TAB1) { | |
208 | if (tiop->c_oflag & TIO_TAB2) | |
209 | flag |= XTABS; | |
210 | else | |
211 | flag |= TAB1; | |
212 | } else if (tiop->c_oflag & TIO_TAB2) | |
213 | flag |= TAB2; | |
214 | if (tiop->c_oflag & TIO_CR1) { | |
215 | flag |= CR1; | |
216 | if (tiop->c_oflag & TIO_ONLRET) | |
217 | flag |= NL1; | |
218 | } | |
219 | if (tiop->c_oflag & TIO_CR2) { | |
220 | flag |= CR2; | |
221 | if (tiop->c_oflag & TIO_ONLRET) | |
222 | flag |= NL2; | |
223 | } | |
224 | if ((tiop->c_oflag & (TIO_NLDLY|TIO_ONLRET)) == TIO_NLDLY) | |
225 | flag |= NL2; | |
226 | if ((tiop->c_cflag & TIO_PARENB) == 0) | |
227 | flag |= ODDP|EVENP; | |
228 | else if (tiop->c_cflag & TIO_PARODD) | |
229 | flag |= ODDP; | |
230 | else | |
231 | flag |= EVENP; | |
232 | if ((tiop->c_iflag & TIO_ICRNL) || (tiop->c_oflag & TIO_ONLCR)) | |
233 | flag |= CRMOD; | |
234 | if (tiop->c_lflag & TIO_ECHO) | |
235 | flag |= ECHO; | |
236 | if (tiop->c_iflag & TIO_IUCLC) | |
237 | flag |= LCASE; | |
238 | if (tiop->c_iflag & TIO_IXOFF) | |
239 | flag |= TANDEM; | |
240 | if ((tiop->c_lflag & TIO_ICANON) == 0) { | |
241 | if (tiop->c_lflag & TIO_ISIG) | |
242 | flag |= CBREAK; | |
243 | else | |
244 | flag |= RAW; | |
245 | } | |
246 | if (flag & CBREAK) { | |
247 | ltc.bsdt_suspc = ltc.bsdt_dsuspc = -1; | |
248 | ltc.bsdt_flushc = ltc.bsdt_lnextc = -1; | |
249 | if ((tiop->c_iflag & TIO_IXON) == 0) | |
250 | tc.bsdt_startc = tc.bsdt_stopc = -1; | |
251 | } | |
252 | sg.sg_flags = flag; | |
253 | lmode &= ~(LCRTERA|LLITOUT|LDECCTQ|LPASS8); | |
254 | if (tiop->c_lflag & TIO_ECHOE) | |
255 | lmode |= LCRTERA; | |
256 | if ((tiop->c_oflag & TIO_OPOST) == 0) | |
257 | lmode |= LLITOUT; | |
258 | if ((tiop->c_iflag & TIO_IXANY) == 0) | |
259 | lmode |= LDECCTQ; | |
260 | if ((tiop->c_cflag & TIO_CS8) && | |
261 | (tiop->c_iflag & TIO_ISTRIP) == 0) | |
262 | lmode |= LPASS8; | |
263 | ||
264 | /* set the new stuff */ | |
265 | if (com == HPUXTCSETA) | |
266 | com = TIOCSETN; | |
267 | else | |
268 | com = TIOCSETP; | |
269 | (void) ioctlrout(fp, com, (caddr_t)&sg); | |
270 | (void) ioctlrout(fp, TIOCSETC, (caddr_t)&tc); | |
271 | (void) ioctlrout(fp, TIOCSLTC, (caddr_t)<c); | |
272 | (void) ioctlrout(fp, TIOCLSET, (caddr_t)&lmode); | |
273 | if (tiop->c_cflag & TIO_HUPCL) | |
274 | (void) ioctlrout(fp, TIOCHPCL, (caddr_t)0); | |
275 | break; | |
276 | ||
277 | case HPUXTIOCGETP: | |
278 | u.u_error = ioctlrout(fp, TIOCGETP, (caddr_t)&sg); | |
279 | if (u.u_error) | |
280 | break; | |
281 | flag = sg.sg_flags; | |
282 | sg.sg_flags &= ~(V7_HUPCL|V7_XTABS|V7_NOAL); | |
283 | if (flag & XTABS) | |
284 | sg.sg_flags |= V7_XTABS; | |
285 | bcopy((caddr_t)&sg, data, sizeof sg); | |
286 | break; | |
287 | ||
288 | case HPUXTIOCSETP: | |
289 | bcopy(data, (caddr_t)&sg, sizeof sg); | |
290 | flag = sg.sg_flags; | |
291 | sg.sg_flags &= ~(V7_HUPCL|V7_XTABS|V7_NOAL); | |
292 | if (flag & V7_XTABS) | |
293 | sg.sg_flags |= XTABS; | |
294 | u.u_error = ioctlrout(fp, TIOCSETP, (caddr_t)&sg); | |
295 | if (flag & V7_HUPCL) | |
296 | (void) ioctlrout(fp, TIOCHPCL, (caddr_t)0); | |
297 | break; | |
298 | ||
299 | default: | |
300 | break; | |
301 | } | |
302 | return(u.u_error); | |
303 | } | |
304 | ||
305 | /* #ifdef COMPAT */ | |
306 | ohpuxgtty() | |
307 | { | |
308 | struct a { | |
309 | int fdes; | |
310 | caddr_t cmarg; | |
311 | } *uap = (struct a *)u.u_ap; | |
312 | ||
313 | getsettty(uap->fdes, HPUXTIOCGETP, uap->cmarg); | |
314 | } | |
315 | ||
316 | ohpuxstty() | |
317 | { | |
318 | struct a { | |
319 | int fdes; | |
320 | caddr_t cmarg; | |
321 | } *uap = (struct a *)u.u_ap; | |
322 | ||
323 | getsettty(uap->fdes, HPUXTIOCSETP, uap->cmarg); | |
324 | } | |
325 | ||
326 | /* | |
327 | * Simplified version of ioctl() for use by | |
328 | * gtty/stty and TIOCGETP/TIOCSETP. | |
329 | */ | |
330 | getsettty(fdes, com, cmarg) | |
331 | int fdes, com; | |
332 | caddr_t cmarg; | |
333 | { | |
334 | register struct file *fp; | |
335 | struct hpuxsgttyb hsb; | |
336 | struct sgttyb sb; | |
337 | ||
338 | if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { | |
339 | u.u_error = EBADF; | |
340 | return; | |
341 | } | |
342 | if ((fp->f_flag & (FREAD|FWRITE)) == 0) { | |
343 | u.u_error = EBADF; | |
344 | return; | |
345 | } | |
346 | if (com == HPUXTIOCSETP) { | |
347 | u.u_error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb); | |
348 | if (u.u_error) | |
349 | return; | |
350 | sb.sg_ispeed = hsb.sg_ispeed; | |
351 | sb.sg_ospeed = hsb.sg_ospeed; | |
352 | sb.sg_erase = hsb.sg_erase; | |
353 | sb.sg_kill = hsb.sg_kill; | |
354 | sb.sg_flags = (short) hsb.sg_flags; | |
355 | com = TIOCSETP; | |
356 | } else { | |
357 | bzero((caddr_t)&hsb, sizeof hsb); | |
358 | com = TIOCGETP; | |
359 | } | |
360 | u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb); | |
361 | if (u.u_error == 0 && com == TIOCGETP) { | |
362 | hsb.sg_ispeed = sb.sg_ispeed; | |
363 | hsb.sg_ospeed = sb.sg_ospeed; | |
364 | hsb.sg_erase = sb.sg_erase; | |
365 | hsb.sg_kill = sb.sg_kill; | |
366 | hsb.sg_flags = (int) sb.sg_flags; | |
367 | u.u_error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); | |
368 | } | |
369 | } | |
370 | /* #endif */ | |
371 | #endif |