xref: /original-bsd/sys/hp/hpux/hpux_tty.c (revision 860e07fc)
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.1 90/07/09$
13  *
14  *	@(#)hpux_tty.c	7.11 (Berkeley) 08/03/92
15  */
16 
17 /*
18  * stty/gtty/termio emulation stuff
19  */
20 #ifdef HPUXCOMPAT
21 
22 #include "param.h"
23 #include "systm.h"
24 #include "filedesc.h"
25 #include "ioctl.h"
26 #include "proc.h"
27 #include "tty.h"
28 #include "file.h"
29 #include "conf.h"
30 #include "buf.h"
31 #include "kernel.h"
32 
33 #include "hpux.h"
34 #include "hpux_termio.h"
35 
36 /*
37  * Map BSD/POSIX style termios info to and from SYS5 style termio stuff.
38  */
39 hpuxtermio(fp, com, data, p)
40 	struct file *fp;
41 	caddr_t data;
42 	struct proc *p;
43 {
44 	struct termios tios;
45 	struct hpuxtermios htios;
46 	int line, error, (*ioctlrout)();
47 	int newi = 0;
48 
49 	ioctlrout = fp->f_ops->fo_ioctl;
50 	switch (com) {
51 	case HPUXTCGETATTR:
52 		newi = 1;
53 		/* fall into ... */
54 	case HPUXTCGETA:
55 		/*
56 		 * Get BSD terminal state
57 		 */
58 		if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p))
59 			break;
60 		bzero((char *)&htios, sizeof htios);
61 		/*
62 		 * Set iflag.
63 		 * Same through ICRNL, no BSD equivs for IUCLC, IENQAK
64 		 */
65 		htios.c_iflag = tios.c_iflag & 0x1ff;
66 		if (tios.c_iflag & IXON)
67 			htios.c_iflag |= TIO_IXON;
68 		if (tios.c_iflag & IXOFF)
69 			htios.c_iflag |= TIO_IXOFF;
70 		if (tios.c_iflag & IXANY)
71 			htios.c_iflag |= TIO_IXANY;
72 		/*
73 		 * Set oflag.
74 		 * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL
75 		 * or any of the delays.
76 		 */
77 		if (tios.c_oflag & OPOST)
78 			htios.c_oflag |= TIO_OPOST;
79 		if (tios.c_oflag & ONLCR)
80 			htios.c_oflag |= TIO_ONLCR;
81 		if (tios.c_oflag & OXTABS)
82 			htios.c_oflag |= TIO_TAB3;
83 		/*
84 		 * Set cflag.
85 		 * Baud from ospeed, rest from cflag.
86 		 */
87 		htios.c_cflag = bsdtohpuxbaud(tios.c_ospeed);
88 		switch (tios.c_cflag & CSIZE) {
89 		case CS5:
90 			htios.c_cflag |= TIO_CS5; break;
91 		case CS6:
92 			htios.c_cflag |= TIO_CS6; break;
93 		case CS7:
94 			htios.c_cflag |= TIO_CS7; break;
95 		case CS8:
96 			htios.c_cflag |= TIO_CS8; break;
97 		}
98 		if (tios.c_cflag & CSTOPB)
99 			htios.c_cflag |= TIO_CSTOPB;
100 		if (tios.c_cflag & CREAD)
101 			htios.c_cflag |= TIO_CREAD;
102 		if (tios.c_cflag & PARENB)
103 			htios.c_cflag |= TIO_PARENB;
104 		if (tios.c_cflag & PARODD)
105 			htios.c_cflag |= TIO_PARODD;
106 		if (tios.c_cflag & HUPCL)
107 			htios.c_cflag |= TIO_HUPCL;
108 		if (tios.c_cflag & CLOCAL)
109 			htios.c_cflag |= TIO_CLOCAL;
110 		/*
111 		 * Set lflag.
112 		 * No BSD equiv for XCASE.
113 		 */
114 		if (tios.c_lflag & ECHOE)
115 			htios.c_lflag |= TIO_ECHOE;
116 		if (tios.c_lflag & ECHOK)
117 			htios.c_lflag |= TIO_ECHOK;
118 		if (tios.c_lflag & ECHO)
119 			htios.c_lflag |= TIO_ECHO;
120 		if (tios.c_lflag & ECHONL)
121 			htios.c_lflag |= TIO_ECHONL;
122 		if (tios.c_lflag & ISIG)
123 			htios.c_lflag |= TIO_ISIG;
124 		if (tios.c_lflag & ICANON)
125 			htios.c_lflag |= TIO_ICANON;
126 		if (tios.c_lflag & NOFLSH)
127 			htios.c_lflag |= TIO_NOFLSH;
128 		/*
129 		 * Line discipline
130 		 */
131 		if (!newi) {
132 			line = 0;
133 			(void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line, p);
134 			htios.c_reserved = line;
135 		}
136 		/*
137 		 * Set editing chars.
138 		 * No BSD equiv for VSWTCH.
139 		 */
140 		htios.c_cc[HPUXVINTR] = tios.c_cc[VINTR];
141 		htios.c_cc[HPUXVQUIT] = tios.c_cc[VQUIT];
142 		htios.c_cc[HPUXVERASE] = tios.c_cc[VERASE];
143 		htios.c_cc[HPUXVKILL] = tios.c_cc[VKILL];
144 		htios.c_cc[HPUXVEOF] = tios.c_cc[VEOF];
145 		htios.c_cc[HPUXVEOL] = tios.c_cc[VEOL];
146 		htios.c_cc[HPUXVEOL2] = tios.c_cc[VEOL2];
147 		htios.c_cc[HPUXVSWTCH] = 0;
148 		htios.c_cc[HPUXVMINS] = tios.c_cc[VMIN];
149 		htios.c_cc[HPUXVTIMES] = tios.c_cc[VTIME];
150 		htios.c_cc[HPUXVSUSP] = tios.c_cc[VSUSP];
151 		htios.c_cc[HPUXVSTART] = tios.c_cc[VSTART];
152 		htios.c_cc[HPUXVSTOP] = tios.c_cc[VSTOP];
153 		if (newi)
154 			bcopy((char *)&htios, data, sizeof htios);
155 		else
156 			termiostotermio(&htios, (struct hpuxtermio *)data);
157 		break;
158 
159 	case HPUXTCSETATTR:
160 	case HPUXTCSETATTRD:
161 	case HPUXTCSETATTRF:
162 		newi = 1;
163 		/* fall into ... */
164 	case HPUXTCSETA:
165 	case HPUXTCSETAW:
166 	case HPUXTCSETAF:
167 		if (newi)
168 			bcopy(data, (char *)&htios, sizeof htios);
169 		else
170 			termiototermios((struct termio *)data, &htios);
171 		/*
172 		 * Get old characteristics and determine if we are a tty.
173 		 */
174 		if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p))
175 			break;
176 		/*
177 		 * Set iflag.
178 		 * Same through ICRNL, no HP-UX equiv for IMAXBEL
179 		 */
180 		tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff);
181 		tios.c_iflag |= htios.c_iflag & 0x1ff;
182 		if (htios.c_iflag & TIO_IXON)
183 			tios.c_iflag |= IXON;
184 		if (htios.c_iflag & TIO_IXOFF)
185 			tios.c_iflag |= IXOFF;
186 		if (htios.c_iflag & TIO_IXANY)
187 			tios.c_iflag |= IXANY;
188 		/*
189 		 * Set oflag.
190 		 * No HP-UX equiv for ONOEOT
191 		 */
192 		tios.c_oflag &= ~(OPOST|ONLCR|OXTABS);
193 		if (htios.c_oflag & TIO_OPOST)
194 			tios.c_oflag |= OPOST;
195 		if (htios.c_oflag & TIO_ONLCR)
196 			tios.c_oflag |= ONLCR;
197 		if (htios.c_oflag & TIO_TAB3)
198 			tios.c_oflag |= OXTABS;
199 		/*
200 		 * Set cflag.
201 		 * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF
202 		 */
203 		tios.c_cflag &=
204 			~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL);
205 		switch (htios.c_cflag & TIO_CSIZE) {
206 		case TIO_CS5:
207 			tios.c_cflag |= CS5; break;
208 		case TIO_CS6:
209 			tios.c_cflag |= CS6; break;
210 		case TIO_CS7:
211 			tios.c_cflag |= CS7; break;
212 		case TIO_CS8:
213 			tios.c_cflag |= CS8; break;
214 		}
215 		if (htios.c_cflag & TIO_CSTOPB)
216 			tios.c_cflag |= CSTOPB;
217 		if (htios.c_cflag & TIO_CREAD)
218 			tios.c_cflag |= CREAD;
219 		if (htios.c_cflag & TIO_PARENB)
220 			tios.c_cflag |= PARENB;
221 		if (htios.c_cflag & TIO_PARODD)
222 			tios.c_cflag |= PARODD;
223 		if (htios.c_cflag & TIO_HUPCL)
224 			tios.c_cflag |= HUPCL;
225 		if (htios.c_cflag & TIO_CLOCAL)
226 			tios.c_cflag |= CLOCAL;
227 		/*
228 		 * Set lflag.
229 		 * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL
230 		 * IEXTEN treated as part of ICANON
231 		 */
232 		tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH);
233 		if (htios.c_lflag & TIO_ECHOE)
234 			tios.c_lflag |= ECHOE;
235 		if (htios.c_lflag & TIO_ECHOK)
236 			tios.c_lflag |= ECHOK;
237 		if (htios.c_lflag & TIO_ECHO)
238 			tios.c_lflag |= ECHO;
239 		if (htios.c_lflag & TIO_ECHONL)
240 			tios.c_lflag |= ECHONL;
241 		if (htios.c_lflag & TIO_ISIG)
242 			tios.c_lflag |= ISIG;
243 		if (htios.c_lflag & TIO_ICANON)
244 			tios.c_lflag |= (ICANON|IEXTEN);
245 		if (htios.c_lflag & TIO_NOFLSH)
246 			tios.c_lflag |= NOFLSH;
247 		/*
248 		 * Set editing chars.
249 		 * No HP-UX equivs of VWERASE/VREPRINT/VDSUSP/VLNEXT
250 		 * /VDISCARD/VSTATUS/VERASE2
251 		 */
252 		tios.c_cc[VINTR] = htios.c_cc[HPUXVINTR];
253 		tios.c_cc[VQUIT] = htios.c_cc[HPUXVQUIT];
254 		tios.c_cc[VERASE] = htios.c_cc[HPUXVERASE];
255 		tios.c_cc[VKILL] = htios.c_cc[HPUXVKILL];
256 		tios.c_cc[VEOF] = htios.c_cc[HPUXVEOF];
257 		tios.c_cc[VEOL] = htios.c_cc[HPUXVEOL];
258 		tios.c_cc[VEOL2] = htios.c_cc[HPUXVEOL2];
259 		tios.c_cc[VMIN] = htios.c_cc[HPUXVMINS];
260 		tios.c_cc[VTIME] = htios.c_cc[HPUXVTIMES];
261 		tios.c_cc[VSUSP] = htios.c_cc[HPUXVSUSP];
262 		tios.c_cc[VSTART] = htios.c_cc[HPUXVSTART];
263 		tios.c_cc[VSTOP] = htios.c_cc[HPUXVSTOP];
264 
265 		/*
266 		 * Set the new stuff
267 		 */
268 		if (com == HPUXTCSETA || com == HPUXTCSETATTR)
269 			com = TIOCSETA;
270 		else if (com == HPUXTCSETAW || com == HPUXTCSETATTRD)
271 			com = TIOCSETAW;
272 		else
273 			com = TIOCSETAF;
274 		error = (*ioctlrout)(fp, com, (caddr_t)&tios, p);
275 		if (error == 0) {
276 			/*
277 			 * Set line discipline
278 			 */
279 			if (!newi) {
280 				line = htios.c_reserved;
281 				(void) (*ioctlrout)(fp, TIOCSETD,
282 						    (caddr_t)&line, p);
283 			}
284 			/*
285 			 * Set non-blocking IO if VMIN == VTIME == 0.
286 			 * Should handle the other cases as well.  It also
287 			 * isn't correct to just turn it off as it could be
288 			 * on as the result of a fcntl operation.
289 			 * XXX - wouldn't need to do this at all if VMIN/VTIME
290 			 * were implemented.
291 			 */
292 			line = (htios.c_cc[HPUXVMIN] == 0 &&
293 				htios.c_cc[HPUXVTIME] == 0);
294 			if (line)
295 				fp->f_flag |= FNONBLOCK;
296 			else
297 				fp->f_flag &= ~FNONBLOCK;
298 			(void) (*ioctlrout)(fp, FIONBIO, (caddr_t)&line, p);
299 		}
300 		break;
301 
302 	default:
303 		error = EINVAL;
304 		break;
305 	}
306 	return(error);
307 }
308 
309 termiototermios(tio, tios)
310 	struct hpuxtermio *tio;
311 	struct hpuxtermios *tios;
312 {
313 	int i;
314 
315 	bzero((char *)tios, sizeof *tios);
316 	tios->c_iflag = tio->c_iflag;
317 	tios->c_oflag = tio->c_oflag;
318 	tios->c_cflag = tio->c_cflag;
319 	tios->c_lflag = tio->c_lflag;
320 	tios->c_reserved = tio->c_line;
321 	for (i = 0; i <= HPUXVSWTCH; i++)
322 		tios->c_cc[i] = tio->c_cc[i];
323 	if (tios->c_lflag & TIO_ICANON) {
324 		tios->c_cc[HPUXVEOF] = tio->c_cc[HPUXVEOF];
325 		tios->c_cc[HPUXVEOL] = tio->c_cc[HPUXVEOL];
326 		tios->c_cc[HPUXVMINS] = tios->c_cc[HPUXVTIMES] = 0;
327 	} else {
328 		tios->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOL] = 0;
329 		tios->c_cc[HPUXVMINS] = tio->c_cc[HPUXVMIN];
330 		tios->c_cc[HPUXVTIMES] = tio->c_cc[HPUXVTIME];
331 	}
332 }
333 
334 termiostotermio(tios, tio)
335 	struct hpuxtermios *tios;
336 	struct hpuxtermio *tio;
337 {
338 	int i;
339 
340 	tio->c_iflag = tios->c_iflag;
341 	tio->c_oflag = tios->c_oflag;
342 	tio->c_cflag = tios->c_cflag;
343 	tio->c_lflag = tios->c_lflag;
344 	tio->c_line = tios->c_reserved;
345 	for (i = 0; i <= HPUXVSWTCH; i++)
346 		tio->c_cc[i] = tios->c_cc[i];
347 	if (tios->c_lflag & ICANON) {
348 		tio->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOF];
349 		tio->c_cc[HPUXVEOL] = tios->c_cc[HPUXVEOL];
350 	} else {
351 		tio->c_cc[HPUXVMIN] = tios->c_cc[HPUXVMINS];
352 		tio->c_cc[HPUXVTIME] = tios->c_cc[HPUXVTIMES];
353 	}
354 }
355 
356 bsdtohpuxbaud(bsdspeed)
357 	long bsdspeed;
358 {
359 	switch (bsdspeed) {
360 	case B0:     return(TIO_B0);
361 	case B50:    return(TIO_B50);
362 	case B75:    return(TIO_B75);
363 	case B110:   return(TIO_B110);
364 	case B134:   return(TIO_B134);
365 	case B150:   return(TIO_B150);
366 	case B200:   return(TIO_B200);
367 	case B300:   return(TIO_B300);
368 	case B600:   return(TIO_B600);
369 	case B1200:  return(TIO_B1200);
370 	case B1800:  return(TIO_B1800);
371 	case B2400:  return(TIO_B2400);
372 	case B4800:  return(TIO_B4800);
373 	case B9600:  return(TIO_B9600);
374 	case B19200: return(TIO_B19200);
375 	case B38400: return(TIO_B38400);
376 	default:     return(TIO_B0);
377 	}
378 }
379 
380 hpuxtobsdbaud(hpuxspeed)
381 	int hpuxspeed;
382 {
383 	static char hpuxtobsdbaudtab[32] = {
384 		B0,	B50,	B75,	B110,	B134,	B150,	B200,	B300,
385 		B600,	B0,	B1200,	B1800,	B2400,	B0,	B4800,	B0,
386 		B9600,	B19200,	B38400,	B0,	B0,	B0,	B0,	B0,
387 		B0,	B0,	B0,	B0,	B0,	B0,	EXTA,	EXTB
388 	};
389 
390 	return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]);
391 }
392 
393 #ifdef COMPAT_OHPUX
394 ohpuxgtty(p, uap, retval)
395 	struct proc *p;
396 	struct args {
397 		int	fdes;
398 		caddr_t	cmarg;
399 	} *uap;
400 	int *retval;
401 {
402 
403 	return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg));
404 }
405 
406 ohpuxstty(p, uap, retval)
407 	struct proc *p;
408 	struct args {
409 		int	fdes;
410 		caddr_t	cmarg;
411 	} *uap;
412 	int *retval;
413 {
414 
415 	return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg));
416 }
417 
418 /*
419  * Simplified version of ioctl() for use by
420  * gtty/stty and TIOCGETP/TIOCSETP.
421  */
422 getsettty(p, fdes, com, cmarg)
423 	struct proc *p;
424 	int fdes, com;
425 	caddr_t cmarg;
426 {
427 	register struct filedesc *fdp = p->p_fd;
428 	register struct file *fp;
429 	struct hpuxsgttyb hsb;
430 	struct sgttyb sb;
431 	int error;
432 
433 	if (((unsigned)fdes) >= fdp->fd_nfiles ||
434 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
435 		return (EBADF);
436 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
437 		return (EBADF);
438 	if (com == HPUXTIOCSETP) {
439 		if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb))
440 			return (error);
441 		sb.sg_ispeed = hsb.sg_ispeed;
442 		sb.sg_ospeed = hsb.sg_ospeed;
443 		sb.sg_erase = hsb.sg_erase;
444 		sb.sg_kill = hsb.sg_kill;
445 		sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL);
446 		if (hsb.sg_flags & V7_XTABS)
447 			sb.sg_flags |= XTABS;
448 		if (hsb.sg_flags & V7_HUPCL)
449 			(void)(*fp->f_ops->fo_ioctl)
450 				(fp, TIOCHPCL, (caddr_t)0, p);
451 		com = TIOCSETP;
452 	} else {
453 		bzero((caddr_t)&hsb, sizeof hsb);
454 		com = TIOCGETP;
455 	}
456 	error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb, p);
457 	if (error == 0 && com == TIOCGETP) {
458 		hsb.sg_ispeed = sb.sg_ispeed;
459 		hsb.sg_ospeed = sb.sg_ospeed;
460 		hsb.sg_erase = sb.sg_erase;
461 		hsb.sg_kill = sb.sg_kill;
462 		hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL);
463 		if (sb.sg_flags & XTABS)
464 			hsb.sg_flags |= V7_XTABS;
465 		error = copyout((caddr_t)&hsb, cmarg, sizeof hsb);
466 	}
467 	return (error);
468 }
469 #endif
470 #endif
471