First working version of new event dispatching framwork.
[screen-lua.git] / src / tty.sh
blobf2afd540b4c3ecc16c2cc7f900d47e86f3c21017
1 #! /bin/sh
2 # sh tty.sh tty.c
3 # This inserts all the needed #ifdefs for IF{} statements
4 # and generates tty.c
7 # Stupid cpp on A/UX barfs on ``#if defined(FOO) && FOO < 17'' when
8 # FOO is undefined. Reported by Robert C. Tindall (rtindall@uidaho.edu)
10 rm -f $1
11 sed -e '1,26d' \
12 -e 's%^IF{\([^}]*\)}\(.*\)%#if defined(\1)\
13 \2\
14 #endif /* \1 */%' \
15 -e 's%^IFN{\([^}]*\)}\(.*\)%#if !defined(\1)\
16 \2\
17 #endif /* \1 */%' \
18 -e 's%^XIF{\([^}]*\)}\(.*\)%#if defined(\1)\
19 #if (\1 < MAXCC)\
20 \2\
21 #endif \
22 #endif /* \1 */%' \
23 < $0 > $1
24 chmod -w $1
25 exit 0
27 /* Copyright (c) 2008, 2009
28 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
29 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
30 * Micah Cowan (micah@cowan.name)
31 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
32 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
33 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
34 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
35 * Copyright (c) 1987 Oliver Laumann
37 * This program is free software; you can redistribute it and/or modify
38 * it under the terms of the GNU General Public License as published by
39 * the Free Software Foundation; either version 3, or (at your option)
40 * any later version.
42 * This program is distributed in the hope that it will be useful,
43 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 * GNU General Public License for more details.
47 * You should have received a copy of the GNU General Public License
48 * along with this program (see the file COPYING); if not, see
49 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
50 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
52 ****************************************************************
56 * NOTICE: tty.c is automatically generated from tty.sh
57 * Do not change anything here. If you then change tty.sh.
60 #include <sys/types.h>
61 #include <signal.h>
62 #include <fcntl.h>
63 #ifndef sgi
64 # include <sys/file.h>
65 #endif
66 #if !defined(sun) || defined(SUNOS3)
67 # include <sys/ioctl.h> /* collosions with termios.h */
68 #else
69 # ifndef TIOCEXCL
70 # include <sys/ttold.h> /* needed for TIOCEXCL */
71 # endif
72 #endif
73 #ifdef __hpux
74 # include <sys/modem.h>
75 #endif
77 #ifdef ISC
78 # include <sys/tty.h>
79 # include <sys/sioctl.h>
80 # include <sys/pty.h>
81 #endif
83 #include "config.h"
84 #ifdef HAVE_STROPTS_H
85 #include <sys/stropts.h> /* for I_POP */
86 #endif
88 #include "screen.h"
89 #include "extern.h"
91 #if !defined(TIOCCONS) && defined(sun) && defined(SVR4)
92 # include <sys/strredir.h>
93 #endif
95 extern struct display *display, *displays;
96 extern int iflag;
97 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
98 extern struct win *console_window;
99 static void consredir_readev_fn __P((struct event *, char *));
100 #endif
102 int separate_sids = 1;
104 static void DoSendBreak __P((int, int, int));
105 static sigret_t SigAlrmDummy __P(SIGPROTOARG);
108 /* Frank Schulz (fschulz@pyramid.com):
109 * I have no idea why VSTART is not defined and my fix is probably not
110 * the cleanest, but it works.
112 #if !defined(VSTART) && defined(_VSTART)
113 #define VSTART _VSTART
114 #endif
115 #if !defined(VSTOP) && defined(_VSTOP)
116 #define VSTOP _VSTOP
117 #endif
119 #ifndef O_NOCTTY
120 # define O_NOCTTY 0
121 #endif
123 #ifndef TTYVMIN
124 # define TTYVMIN 1
125 #endif
126 #ifndef TTYVTIME
127 #define TTYVTIME 0
128 #endif
131 static sigret_t
132 SigAlrmDummy SIGDEFARG
134 debug("SigAlrmDummy()\n");
135 SIGRETURN;
139 * Carefully open a charcter device. Not used to open display ttys.
140 * The second parameter is parsed for a few stty style options.
144 OpenTTY(line, opt)
145 char *line, *opt;
147 int f;
148 struct mode Mode;
149 sigret_t (*sigalrm)__P(SIGPROTOARG);
151 sigalrm = signal(SIGALRM, SigAlrmDummy);
152 alarm(2);
154 /* this open only succeeds, if real uid is allowed */
155 if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1)
157 if (errno == EINTR)
158 Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line);
159 else
160 Msg(errno, "Cannot open line '%s' for R/W", line);
161 alarm(0);
162 signal(SIGALRM, sigalrm);
163 return -1;
165 if (!isatty(f))
167 Msg(0, "'%s' is not a tty", line);
168 alarm(0);
169 signal(SIGALRM, sigalrm);
170 close(f);
171 return -1;
173 #if defined(I_POP) && defined(POP_TTYMODULES)
174 debug("OpenTTY I_POP\n");
175 while (ioctl(f, I_POP, (char *)0) >= 0)
177 #endif
179 * We come here exclusively. This is to stop all kermit and cu type things
180 * accessing the same tty line.
181 * Perhaps we should better create a lock in some /usr/spool/locks directory?
183 #ifdef TIOCEXCL
184 errno = 0;
185 if (ioctl(f, TIOCEXCL, (char *) 0) < 0)
186 Msg(errno, "%s: ioctl TIOCEXCL failed", line);
187 debug3("%d %d %d\n", getuid(), geteuid(), getpid());
188 debug2("%s TIOCEXCL errno %d\n", line, errno);
189 #endif /* TIOCEXCL */
191 * We create a sane tty mode. We do not copy things from the display tty
193 #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE
194 if (display)
196 debug1("OpenTTY: using mode of display for %s\n", line);
197 Mode = D_NewMode;
199 else
200 #endif
201 InitTTY(&Mode, W_TYPE_PLAIN);
203 SttyMode(&Mode, opt);
204 #ifdef DEBUG
205 DebugTTY(&Mode);
206 #endif
207 SetTTY(f, &Mode);
209 #if defined(linux) && defined(TIOCMSET)
211 int mcs = 0;
212 ioctl(f, TIOCMGET, &mcs);
213 mcs |= TIOCM_RTS;
214 ioctl(f, TIOCMSET, &mcs);
216 #endif
218 brktty(f);
219 alarm(0);
220 signal(SIGALRM, sigalrm);
221 debug2("'%s' CONNECT fd=%d.\n", line, f);
222 return f;
227 * Tty mode handling
230 void
231 InitTTY(m, ttyflag)
232 struct mode *m;
233 int ttyflag;
235 bzero((char *)m, sizeof(*m));
236 #ifdef POSIX
237 /* struct termios tio
238 * defaults, as seen on SunOS 4.1.3
240 debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag);
241 IF{BRKINT} m->tio.c_iflag |= BRKINT;
242 IF{IGNPAR} m->tio.c_iflag |= IGNPAR;
243 /* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */
244 IF{IXON} m->tio.c_iflag |= IXON;
245 /* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */
247 if (!ttyflag) /* may not even be good for ptys.. */
249 IF{ICRNL} m->tio.c_iflag |= ICRNL;
250 IF{ONLCR} m->tio.c_oflag |= ONLCR;
251 IF{TAB3} m->tio.c_oflag |= TAB3;
252 IF{OXTABS} m->tio.c_oflag |= OXTABS;
253 /* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */
254 IF{OPOST} m->tio.c_oflag |= OPOST;
259 * Or-ing the speed into c_cflags is dangerous.
260 * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs.
262 * IF{B9600} m->tio.c_cflag |= B9600;
263 * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT;
265 * We hope that we have the posix calls to do it right:
266 * If these are not available you might try the above.
268 IF{B9600} cfsetospeed(&m->tio, B9600);
269 IF{B9600} cfsetispeed(&m->tio, B9600);
271 IF{CS8} m->tio.c_cflag |= CS8;
272 IF{CREAD} m->tio.c_cflag |= CREAD;
273 IF{CLOCAL} m->tio.c_cflag |= CLOCAL;
275 IF{ECHOCTL} m->tio.c_lflag |= ECHOCTL;
276 IF{ECHOKE} m->tio.c_lflag |= ECHOKE;
278 if (!ttyflag)
280 IF{ISIG} m->tio.c_lflag |= ISIG;
281 IF{ICANON} m->tio.c_lflag |= ICANON;
282 IF{ECHO} m->tio.c_lflag |= ECHO;
284 IF{ECHOE} m->tio.c_lflag |= ECHOE;
285 IF{ECHOK} m->tio.c_lflag |= ECHOK;
286 IF{IEXTEN} m->tio.c_lflag |= IEXTEN;
288 XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C');
289 XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\');
290 XIF{VERASE} m->tio.c_cc[VERASE] = 0x7f; /* DEL */
291 XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H');
292 XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D');
293 XIF{VEOL} m->tio.c_cc[VEOL] = 0000;
294 XIF{VEOL2} m->tio.c_cc[VEOL2] = 0000;
295 XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000;
296 XIF{VSTART} m->tio.c_cc[VSTART] = Ctrl('Q');
297 XIF{VSTOP} m->tio.c_cc[VSTOP] = Ctrl('S');
298 XIF{VSUSP} m->tio.c_cc[VSUSP] = Ctrl('Z');
299 XIF{VDSUSP} m->tio.c_cc[VDSUSP] = Ctrl('Y');
300 XIF{VREPRINT} m->tio.c_cc[VREPRINT] = Ctrl('R');
301 XIF{VDISCARD} m->tio.c_cc[VDISCARD] = Ctrl('O');
302 XIF{VWERASE} m->tio.c_cc[VWERASE] = Ctrl('W');
303 XIF{VLNEXT} m->tio.c_cc[VLNEXT] = Ctrl('V');
304 XIF{VSTATUS} m->tio.c_cc[VSTATUS] = Ctrl('T');
306 if (ttyflag)
308 m->tio.c_cc[VMIN] = TTYVMIN;
309 m->tio.c_cc[VTIME] = TTYVTIME;
312 # ifdef HPUX_LTCHARS_HACK
313 m->m_ltchars.t_suspc = Ctrl('Z');
314 m->m_ltchars.t_dsuspc = Ctrl('Y');
315 m->m_ltchars.t_rprntc = Ctrl('R');
316 m->m_ltchars.t_flushc = Ctrl('O');
317 m->m_ltchars.t_werasc = Ctrl('W');
318 m->m_ltchars.t_lnextc = Ctrl('V');
319 # endif /* HPUX_LTCHARS_HACK */
321 #else /* POSIX */
323 # ifdef TERMIO
324 debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag);
325 /* struct termio tio
326 * defaults, as seen on Mototola SYSV68:
327 * input: 7bit, CR->NL, ^S/^Q flow control
328 * output: POSTprocessing: NL->NL-CR, Tabs to spaces
329 * control: 9600baud, 8bit CSIZE, enable input
330 * local: enable signals, erase/kill processing, echo on.
332 IF{ISTRIP} m->tio.c_iflag |= ISTRIP;
333 IF{IXON} m->tio.c_iflag |= IXON;
335 if (!ttyflag) /* may not even be good for ptys.. */
337 IF{OPOST} m->tio.c_oflag |= OPOST;
338 IF{ICRNL} m->tio.c_iflag |= ICRNL;
339 IF{ONLCR} m->tio.c_oflag |= ONLCR;
340 IF{TAB3} m->tio.c_oflag |= TAB3;
343 #ifdef __bsdi__
344 )-: cannot handle BSDI without POSIX
345 #else
346 IF{B9600} m->tio.c_cflag = B9600;
347 #endif
348 IF{CS8} m->tio.c_cflag |= CS8;
349 IF{CREAD} m->tio.c_cflag |= CREAD;
351 if (!ttyflag)
353 IF{ISIG} m->tio.c_lflag |= ISIG;
354 IF{ICANON} m->tio.c_lflag |= ICANON;
355 IF{ECHO} m->tio.c_lflag |= ECHO;
357 IF{ECHOE} m->tio.c_lflag |= ECHOE;
358 IF{ECHOK} m->tio.c_lflag |= ECHOK;
360 XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C');
361 XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\');
362 XIF{VERASE} m->tio.c_cc[VERASE] = 0177; /* DEL */
363 XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H');
364 XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D');
365 XIF{VEOL} m->tio.c_cc[VEOL] = 0377;
366 XIF{VEOL2} m->tio.c_cc[VEOL2] = 0377;
367 XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000;
369 if (ttyflag)
371 m->tio.c_cc[VMIN] = TTYVMIN;
372 m->tio.c_cc[VTIME] = TTYVTIME;
375 # else /* TERMIO */
376 debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag);
377 m->m_ttyb.sg_ispeed = B9600;
378 m->m_ttyb.sg_ospeed = B9600;
379 m->m_ttyb.sg_erase = 0177; /*DEL */
380 m->m_ttyb.sg_kill = Ctrl('H');
381 if (!ttyflag)
382 m->m_ttyb.sg_flags = CRMOD | ECHO
383 IF{ANYP} | ANYP
385 else
386 m->m_ttyb.sg_flags = CBREAK
387 IF{ANYP} | ANYP
390 m->m_tchars.t_intrc = Ctrl('C');
391 m->m_tchars.t_quitc = Ctrl('\\');
392 m->m_tchars.t_startc = Ctrl('Q');
393 m->m_tchars.t_stopc = Ctrl('S');
394 m->m_tchars.t_eofc = Ctrl('D');
395 m->m_tchars.t_brkc = -1;
397 m->m_ltchars.t_suspc = Ctrl('Z');
398 m->m_ltchars.t_dsuspc = Ctrl('Y');
399 m->m_ltchars.t_rprntc = Ctrl('R');
400 m->m_ltchars.t_flushc = Ctrl('O');
401 m->m_ltchars.t_werasc = Ctrl('W');
402 m->m_ltchars.t_lnextc = Ctrl('V');
404 IF{NTTYDISC} m->m_ldisc = NTTYDISC;
406 m->m_lmode = 0
407 IF{LDECCTQ} | LDECCTQ
408 IF{LCTLECH} | LCTLECH
409 IF{LPASS8} | LPASS8
410 IF{LCRTKIL} | LCRTKIL
411 IF{LCRTERA} | LCRTERA
412 IF{LCRTBS} | LCRTBS
414 # endif /* TERMIO */
415 #endif /* POSIX */
417 #if defined(ENCODINGS) && defined(TIOCKSET)
418 m->m_jtchars.t_ascii = 'J';
419 m->m_jtchars.t_kanji = 'B';
420 m->m_knjmode = KM_ASCII | KM_SYSSJIS;
421 #endif
424 void
425 SetTTY(fd, mp)
426 int fd;
427 struct mode *mp;
429 errno = 0;
430 #ifdef POSIX
431 tcsetattr(fd, TCSADRAIN, &mp->tio);
432 # ifdef HPUX_LTCHARS_HACK
433 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars);
434 # endif
435 #else
436 # ifdef TERMIO
437 ioctl(fd, TCSETAW, (char *)&mp->tio);
438 # ifdef CYTERMIO
439 if (mp->tio.c_line == 3)
441 ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey);
442 ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen);
443 ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace);
445 # endif
446 # else
447 /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */
448 ioctl(fd, TIOCSETC, (char *)&mp->m_tchars);
449 ioctl(fd, TIOCLSET, (char *)&mp->m_lmode);
450 ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc);
451 ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb);
452 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */
453 # endif
454 #endif
455 #if defined(ENCODINGS) && defined(TIOCKSET)
456 ioctl(fd, TIOCKSETC, &mp->m_jtchars);
457 ioctl(fd, TIOCKSET, &mp->m_knjmode);
458 #endif
459 if (errno)
460 Msg(errno, "SetTTY (fd %d): ioctl failed", fd);
463 void
464 GetTTY(fd, mp)
465 int fd;
466 struct mode *mp;
468 errno = 0;
469 #ifdef POSIX
470 tcgetattr(fd, &mp->tio);
471 # ifdef HPUX_LTCHARS_HACK
472 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
473 # endif
474 #else
475 # ifdef TERMIO
476 ioctl(fd, TCGETA, (char *)&mp->tio);
477 # ifdef CYTERMIO
478 if (mp->tio.c_line == 3)
480 ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey);
481 ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen);
482 ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace);
484 else
486 mp->m_mapkey = NOMAPKEY;
487 mp->m_mapscreen = NOMAPSCREEN;
488 mp->m_backspace = '\b';
490 # endif
491 # else
492 ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb);
493 ioctl(fd, TIOCGETC, (char *)&mp->m_tchars);
494 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
495 ioctl(fd, TIOCLGET, (char *)&mp->m_lmode);
496 ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc);
497 # endif
498 #endif
499 #if defined(ENCODINGS) && defined(TIOCKSET)
500 ioctl(fd, TIOCKGETC, &mp->m_jtchars);
501 ioctl(fd, TIOCKGET, &mp->m_knjmode);
502 #endif
503 if (errno)
504 Msg(errno, "GetTTY (fd %d): ioctl failed", fd);
508 * needs interrupt = iflag and flow = d->d_flow
510 void
511 SetMode(op, np, flow, interrupt)
512 struct mode *op, *np;
513 int flow, interrupt;
515 *np = *op;
517 ASSERT(display);
518 #if defined(TERMIO) || defined(POSIX)
519 # ifdef CYTERMIO
520 np->m_mapkey = NOMAPKEY;
521 np->m_mapscreen = NOMAPSCREEN;
522 np->tio.c_line = 0;
523 # endif
524 IF{ICRNL} np->tio.c_iflag &= ~ICRNL;
525 IF{ISTRIP} np->tio.c_iflag &= ~ISTRIP;
526 IF{ONLCR} np->tio.c_oflag &= ~ONLCR;
527 np->tio.c_lflag &= ~(ICANON | ECHO);
529 * From Andrew Myers (andru@tonic.lcs.mit.edu)
530 * to avoid ^V^V-Problem on OSF1
532 IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN;
535 * Unfortunately, the master process never will get SIGINT if the real
536 * terminal is different from the one on which it was originaly started
537 * (process group membership has not been restored or the new tty could not
538 * be made controlling again). In my solution, it is the attacher who
539 * receives SIGINT (because it is always correctly associated with the real
540 * tty) and forwards it to the master [kill(MasterPid, SIGINT)].
541 * Marc Boucher (marc@CAM.ORG)
543 if (interrupt)
544 np->tio.c_lflag |= ISIG;
545 else
546 np->tio.c_lflag &= ~ISIG;
548 * careful, careful catche monkey..
549 * never set VMIN and VTIME to zero, if you want blocking io.
551 * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to
552 * reduce interrupt frequency. But then we would not know how to
553 * handle read returning 0. jw.
555 np->tio.c_cc[VMIN] = 1;
556 np->tio.c_cc[VTIME] = 0;
557 if (!interrupt || !flow)
558 np->tio.c_cc[VINTR] = VDISABLE;
559 np->tio.c_cc[VQUIT] = VDISABLE;
560 if (flow == 0)
562 XIF{VSTART} np->tio.c_cc[VSTART] = VDISABLE;
563 XIF{VSTOP} np->tio.c_cc[VSTOP] = VDISABLE;
564 np->tio.c_iflag &= ~IXON;
566 XIF{VDISCARD} np->tio.c_cc[VDISCARD] = VDISABLE;
567 XIF{VLNEXT} np->tio.c_cc[VLNEXT] = VDISABLE;
568 XIF{VSTATUS} np->tio.c_cc[VSTATUS] = VDISABLE;
569 XIF{VSUSP} np->tio.c_cc[VSUSP] = VDISABLE;
570 /* Set VERASE to DEL, rather than VDISABLE, to avoid libvte
571 "autodetect" issues. */
572 XIF{VERASE} np->tio.c_cc[VERASE] = 0x7f;
573 XIF{VKILL} np->tio.c_cc[VKILL] = VDISABLE;
574 # ifdef HPUX_LTCHARS_HACK
575 np->m_ltchars.t_suspc = VDISABLE;
576 np->m_ltchars.t_dsuspc = VDISABLE;
577 np->m_ltchars.t_rprntc = VDISABLE;
578 np->m_ltchars.t_flushc = VDISABLE;
579 np->m_ltchars.t_werasc = VDISABLE;
580 np->m_ltchars.t_lnextc = VDISABLE;
581 # else /* HPUX_LTCHARS_HACK */
582 XIF{VDSUSP} np->tio.c_cc[VDSUSP] = VDISABLE;
583 XIF{VREPRINT} np->tio.c_cc[VREPRINT] = VDISABLE;
584 XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE;
585 # endif /* HPUX_LTCHARS_HACK */
586 #else /* TERMIO || POSIX */
587 if (!interrupt || !flow)
588 np->m_tchars.t_intrc = -1;
589 np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
590 np->m_ttyb.sg_flags |= CBREAK;
591 # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS)
592 np->m_ttyb.sg_flags &= ~CSTYLE;
593 np->m_ttyb.sg_flags |= CS_8BITS;
594 # endif
595 np->m_tchars.t_quitc = -1;
596 if (flow == 0)
598 np->m_tchars.t_startc = -1;
599 np->m_tchars.t_stopc = -1;
601 np->m_ltchars.t_suspc = -1;
602 np->m_ltchars.t_dsuspc = -1;
603 np->m_ltchars.t_flushc = -1;
604 np->m_ltchars.t_lnextc = -1;
605 #endif /* defined(TERMIO) || defined(POSIX) */
608 /* operates on display */
609 void
610 SetFlow(on)
611 int on;
613 ASSERT(display);
614 if (D_flow == on)
615 return;
616 #if defined(TERMIO) || defined(POSIX)
617 if (on)
619 D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE;
620 XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART];
621 XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP];
622 D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON;
624 else
626 D_NewMode.tio.c_cc[VINTR] = VDISABLE;
627 XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = VDISABLE;
628 XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = VDISABLE;
629 D_NewMode.tio.c_iflag &= ~IXON;
631 # ifdef POSIX
632 # ifdef TCOON
633 if (!on)
634 tcflow(D_userfd, TCOON);
635 # endif
636 if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio))
637 # else
638 if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0)
639 # endif
640 debug1("SetFlow: ioctl errno %d\n", errno);
641 #else /* POSIX || TERMIO */
642 if (on)
644 D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1;
645 D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc;
646 D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc;
648 else
650 D_NewMode.m_tchars.t_intrc = -1;
651 D_NewMode.m_tchars.t_startc = -1;
652 D_NewMode.m_tchars.t_stopc = -1;
654 if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0)
655 debug1("SetFlow: ioctl errno %d\n", errno);
656 #endif /* POSIX || TERMIO */
657 D_flow = on;
660 /* parse commands from opt and modify m */
662 SttyMode(m, opt)
663 struct mode *m;
664 char *opt;
666 static const char sep[] = " \t:;,";
668 if (!opt)
669 return 0;
671 while (*opt)
673 while (index(sep, *opt)) opt++;
674 if (*opt >= '0' && *opt <= '9')
676 if (SetBaud(m, atoi(opt), atoi(opt)))
677 return -1;
679 else if (!strncmp("cs7", opt, 3))
681 #if defined(POSIX) || defined(TERMIO)
682 m->tio.c_cflag &= ~CSIZE;
683 m->tio.c_cflag |= CS7;
684 #else
685 m->m_lmode &= ~LPASS8;
686 #endif
688 else if (!strncmp("cs8", opt, 3))
690 #if defined(POSIX) || defined(TERMIO)
691 m->tio.c_cflag &= ~CSIZE;
692 m->tio.c_cflag |= CS8;
693 #else
694 m->m_lmode |= LPASS8;
695 #endif
697 else if (!strncmp("istrip", opt, 6))
699 #if defined(POSIX) || defined(TERMIO)
700 m->tio.c_iflag |= ISTRIP;
701 #else
702 m->m_lmode &= ~LPASS8;
703 #endif
705 else if (!strncmp("-istrip", opt, 7))
707 #if defined(POSIX) || defined(TERMIO)
708 m->tio.c_iflag &= ~ISTRIP;
709 #else
710 m->m_lmode |= LPASS8;
711 #endif
713 else if (!strncmp("ixon", opt, 4))
715 #if defined(POSIX) || defined(TERMIO)
716 m->tio.c_iflag |= IXON;
717 #else
718 debug("SttyMode: no ixon in old bsd land.\n");
719 #endif
721 else if (!strncmp("-ixon", opt, 5))
723 #if defined(POSIX) || defined(TERMIO)
724 m->tio.c_iflag &= ~IXON;
725 #else
726 debug("SttyMode: no -ixon in old bsd land.\n");
727 #endif
729 else if (!strncmp("ixoff", opt, 5))
731 #if defined(POSIX) || defined(TERMIO)
732 m->tio.c_iflag |= IXOFF;
733 #else
734 m->m_ttyb.sg_flags |= TANDEM;
735 #endif
737 else if (!strncmp("-ixoff", opt, 6))
739 #if defined(POSIX) || defined(TERMIO)
740 m->tio.c_iflag &= ~IXOFF;
741 #else
742 m->m_ttyb.sg_flags &= ~TANDEM;
743 #endif
745 else if (!strncmp("crtscts", opt, 7))
747 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
748 m->tio.c_cflag |= CRTSCTS;
749 #endif
751 else if (!strncmp("-crtscts", opt, 8))
753 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
754 m->tio.c_cflag &= ~CRTSCTS;
755 #endif
757 else
758 return -1;
759 while (*opt && !index(sep, *opt)) opt++;
761 return 0;
765 * Job control handling
767 * Somehow the ultrix session handling is broken, so use
768 * the bsdish variant.
771 /*ARGSUSED*/
772 void
773 brktty(fd)
774 int fd;
776 #if defined(POSIX) && !defined(ultrix)
777 if (separate_sids)
778 setsid(); /* will break terminal affiliation */
779 /* GNU added for Hurd systems 2001-10-10 */
780 # if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__)
781 ioctl(fd, TIOCSCTTY, (char *)0);
782 # endif /* BSD && TIOCSCTTY */
783 #else /* POSIX */
784 # ifdef SYSV
785 if (separate_sids)
786 setpgrp(); /* will break terminal affiliation */
787 # else /* SYSV */
788 # ifdef BSDJOBS
789 int devtty;
791 if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0)
793 if (ioctl(devtty, TIOCNOTTY, (char *)0))
794 debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno);
795 close(devtty);
797 # endif /* BSDJOBS */
798 # endif /* SYSV */
799 #endif /* POSIX */
803 fgtty(fd)
804 int fd;
806 #ifdef BSDJOBS
807 int mypid;
809 mypid = getpid();
811 /* The next lines should be obsolete. Can anybody check if they
812 * are really needed on the BSD platforms?
814 * this is to avoid the message:
815 * fgtty: Not a typewriter (25)
817 # if defined(__osf__) || (BSD >= 199103) || defined(ISC)
818 if (separate_sids)
819 setsid(); /* should be already done */
820 # ifdef TIOCSCTTY
821 ioctl(fd, TIOCSCTTY, (char *)0);
822 # endif
823 # endif
825 # ifdef POSIX
826 if (separate_sids)
827 if (tcsetpgrp(fd, mypid))
829 debug1("fgtty: tcsetpgrp: %d\n", errno);
830 return -1;
832 # else /* POSIX */
833 if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0)
834 debug1("fgtty: TIOSETPGRP: %d\n", errno);
835 # ifndef SYSV /* Already done in brktty():setpgrp() */
836 if (separate_sids)
837 if (setpgrp(fd, mypid))
838 debug1("fgtty: setpgrp: %d\n", errno);
839 # endif
840 # endif /* POSIX */
841 #endif /* BSDJOBS */
842 return 0;
846 * The alm boards on our sparc center 1000 have a lousy driver.
847 * We cannot generate long breaks unless we use the most ugly form
848 * of ioctls. jw.
850 #ifdef POSIX
851 int breaktype = 2;
852 #else /* POSIX */
853 # ifdef TCSBRK
854 int breaktype = 1;
855 # else
856 int breaktype = 0;
857 # endif
858 #endif /* POSIX */
860 #if defined(sun) && !defined(SVR4)
861 # define HAVE_SUPER_TCSENDBREAK
862 #endif
865 * type:
866 * 0: TIOCSBRK / TIOCCBRK
867 * 1: TCSBRK
868 * 2: tcsendbreak()
869 * n: approximate duration in 1/4 seconds.
871 static void
872 DoSendBreak(fd, n, type)
873 int fd, n, type;
875 switch (type)
877 case 2: /* tcsendbreak() =============================== */
878 #ifdef POSIX
879 # ifdef HAVE_SUPER_TCSENDBREAK
880 /* There is one rare case that I have tested, where tcsendbreak works
881 * really great: this was an alm driver that came with SunOS 4.1.3
882 * If you have this one, define the above symbol.
883 * here we can use the second parameter to specify the duration.
885 debug2("tcsendbreak(fd=%d, %d)\n", fd, n);
886 if (tcsendbreak(fd, n) < 0)
887 Msg(errno, "cannot send BREAK (tcsendbreak)");
888 # else
890 * here we hope, that multiple calls to tcsendbreak() can
891 * be concatenated to form a long break, as we do not know
892 * what exact interpretation the second parameter has:
894 * - sunos 4: duration in quarter seconds
895 * - sunos 5: 0 a short break, nonzero a tcdrain()
896 * - hpux, irix: ignored
897 * - mot88: duration in milliseconds
898 * - aix: duration in milliseconds, but 0 is 25 milliseconds.
900 debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd);
902 int i;
904 if (!n)
905 n++;
906 for (i = 0; i < n; i++)
907 if (tcsendbreak(fd, 0) < 0)
909 Msg(errno, "cannot send BREAK (tcsendbreak SVR4)");
910 return;
913 # endif
914 #else /* POSIX */
915 Msg(0, "tcsendbreak() not available, change breaktype");
916 #endif /* POSIX */
917 break;
919 case 1: /* TCSBRK ======================================= */
920 #ifdef TCSBRK
921 if (!n)
922 n++;
924 * Here too, we assume that short breaks can be concatenated to
925 * perform long breaks. But for SOLARIS, this is not true, of course.
927 debug2("%d * TCSBRK fd=%d\n", n, fd);
929 int i;
931 for (i = 0; i < n; i++)
932 if (ioctl(fd, TCSBRK, (char *)0) < 0)
934 Msg(errno, "Cannot send BREAK (TCSBRK)");
935 return;
938 #else /* TCSBRK */
939 Msg(0, "TCSBRK not available, change breaktype");
940 #endif /* TCSBRK */
941 break;
943 case 0: /* TIOCSBRK / TIOCCBRK ========================== */
944 #if defined(TIOCSBRK) && defined(TIOCCBRK)
946 * This is very rude. Screen actively celebrates the break.
947 * But it may be the only save way to issue long breaks.
949 debug("TIOCSBRK TIOCCBRK\n");
950 if (ioctl(fd, TIOCSBRK, (char *)0) < 0)
952 Msg(errno, "Can't send BREAK (TIOCSBRK)");
953 return;
955 sleep1000(n ? n * 250 : 250);
956 if (ioctl(fd, TIOCCBRK, (char *)0) < 0)
958 Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)");
959 return;
961 #else /* TIOCSBRK && TIOCCBRK */
962 Msg(0, "TIOCSBRK/CBRK not available, change breaktype");
963 #endif /* TIOCSBRK && TIOCCBRK */
964 break;
966 default: /* unknown ========================== */
967 Msg(0, "Internal SendBreak error: method %d unknown", type);
972 * Send a break for n * 0.25 seconds. Tty must be PLAIN.
973 * The longest possible break allowed here is 15 seconds.
976 void
977 SendBreak(wp, n, closeopen)
978 struct win *wp;
979 int n, closeopen;
981 sigret_t (*sigalrm)__P(SIGPROTOARG);
983 #ifdef BUILTIN_TELNET
984 if (wp->w_type == W_TYPE_TELNET)
986 TelBreak(wp);
987 return;
989 #endif
990 if (wp->w_type != W_TYPE_PLAIN)
991 return;
993 debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd);
995 #ifdef POSIX
996 (void) tcflush(wp->w_ptyfd, TCIOFLUSH);
997 #else
998 # ifdef TIOCFLUSH
999 (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0);
1000 # endif /* TIOCFLUSH */
1001 #endif /* POSIX */
1003 if (closeopen)
1005 close(wp->w_ptyfd);
1006 sleep1000(n ? n * 250 : 250);
1007 if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1)
1009 Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty);
1010 return;
1012 (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK);
1014 else
1016 sigalrm = signal(SIGALRM, SigAlrmDummy);
1017 alarm(15);
1019 DoSendBreak(wp->w_ptyfd, n, breaktype);
1021 alarm(0);
1022 signal(SIGALRM, sigalrm);
1024 debug(" broken.\n");
1028 * Console grabbing
1031 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
1033 static struct event consredir_ev;
1034 static int consredirfd[2] = {-1, -1};
1036 static void
1037 consredir_readev_fn(ev, data)
1038 struct event *ev;
1039 char *data;
1041 char *p, *n, buf[256];
1042 int l;
1044 if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0)
1046 close(consredirfd[0]);
1047 close(consredirfd[1]);
1048 consredirfd[0] = consredirfd[1] = -1;
1049 evdeq(ev);
1050 return;
1052 for (p = n = buf; l > 0; n++, l--)
1053 if (*n == '\n')
1055 if (n > p)
1056 WriteString(console_window, p, n - p);
1057 WriteString(console_window, "\r\n", 2);
1058 p = n + 1;
1060 if (n > p)
1061 WriteString(console_window, p, n - p);
1064 #endif
1066 /*ARGSUSED*/
1068 TtyGrabConsole(fd, on, rc_name)
1069 int fd, on;
1070 char *rc_name;
1072 #if defined(TIOCCONS) && !defined(linux)
1073 struct display *d;
1074 int ret = 0;
1075 int sfd = -1;
1077 if (on < 0)
1078 return 0; /* pty close will ungrab */
1079 if (on)
1081 if (displays == 0)
1083 Msg(0, "I need a display");
1084 return -1;
1086 for (d = displays; d; d = d->d_next)
1087 if (strcmp(d->d_usertty, "/dev/console") == 0)
1088 break;
1089 if (d)
1091 Msg(0, "too dangerous - screen is running on /dev/console");
1092 return -1;
1096 if (!on)
1098 char *slave;
1099 if ((fd = OpenPTY(&slave)) < 0)
1101 Msg(errno, "%s: could not open detach pty master", rc_name);
1102 return -1;
1104 if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0)
1106 Msg(errno, "%s: could not open detach pty slave", rc_name);
1107 close(fd);
1108 return -1;
1111 if (UserContext() == 1)
1112 UserReturn(ioctl(fd, TIOCCONS, (char *)&on));
1113 ret = UserStatus();
1114 if (ret)
1115 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1116 if (!on)
1118 close(sfd);
1119 close(fd);
1121 return ret;
1123 #else
1124 # if defined(SRIOCSREDIR) || defined(linux)
1125 struct display *d;
1126 # ifdef SRIOCSREDIR
1127 int cfd;
1128 # else
1129 struct mode new1, new2;
1130 char *slave;
1131 # endif
1133 if (on > 0)
1135 if (displays == 0)
1137 Msg(0, "I need a display");
1138 return -1;
1140 for (d = displays; d; d = d->d_next)
1141 if (strcmp(d->d_usertty, "/dev/console") == 0)
1142 break;
1143 if (d)
1145 Msg(0, "too dangerous - screen is running on /dev/console");
1146 return -1;
1149 if (consredirfd[0] >= 0)
1151 evdeq(&consredir_ev);
1152 close(consredirfd[0]);
1153 close(consredirfd[1]);
1154 consredirfd[0] = consredirfd[1] = -1;
1156 if (on <= 0)
1157 return 0;
1158 # ifdef SRIOCSREDIR
1159 if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1)
1161 Msg(errno, "/dev/console");
1162 return -1;
1164 if (pipe(consredirfd))
1166 Msg(errno, "pipe");
1167 close(cfd);
1168 consredirfd[0] = consredirfd[1] = -1;
1169 return -1;
1171 if (ioctl(cfd, SRIOCSREDIR, consredirfd[1]))
1173 Msg(errno, "SRIOCSREDIR ioctl");
1174 close(cfd);
1175 close(consredirfd[0]);
1176 close(consredirfd[1]);
1177 consredirfd[0] = consredirfd[1] = -1;
1178 return -1;
1180 close(cfd);
1181 # else
1182 /* special linux workaround for a too restrictive kernel */
1183 if ((consredirfd[0] = OpenPTY(&slave)) < 0)
1185 Msg(errno, "%s: could not open detach pty master", rc_name);
1186 return -1;
1188 if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0)
1190 Msg(errno, "%s: could not open detach pty slave", rc_name);
1191 close(consredirfd[0]);
1192 return -1;
1194 InitTTY(&new1, 0);
1195 SetMode(&new1, &new2, 0, 0);
1196 SetTTY(consredirfd[1], &new2);
1197 if (UserContext() == 1)
1198 UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on));
1199 if (UserStatus())
1201 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1202 close(consredirfd[0]);
1203 close(consredirfd[1]);
1204 return -1;
1206 # endif
1207 consredir_ev.fd = consredirfd[0];
1208 consredir_ev.type = EV_READ;
1209 consredir_ev.handler = consredir_readev_fn;
1210 evenq(&consredir_ev);
1211 return 0;
1212 # else
1213 if (on > 0)
1214 Msg(0, "%s: don't know how to grab the console", rc_name);
1215 return -1;
1216 # endif
1217 #endif
1221 * Read modem control lines of a physical tty and write them to buf
1222 * in a readable format.
1223 * Will not write more than 256 characters to buf.
1224 * Returns buf;
1226 char *
1227 TtyGetModemStatus(fd, buf)
1228 int fd;
1229 char *buf;
1231 char *p = buf;
1232 #ifdef TIOCGSOFTCAR
1233 unsigned int softcar;
1234 #endif
1235 #if defined(TIOCMGET) || defined(TIOCMODG)
1236 unsigned int mflags;
1237 #else
1238 # ifdef MCGETA
1239 /* this is yet another interface, found on hpux. grrr */
1240 mflag mflags;
1241 IF{MDTR}# define TIOCM_DTR MDTR
1242 IF{MRTS}# define TIOCM_RTS MRTS
1243 IF{MDSR}# define TIOCM_DSR MDSR
1244 IF{MDCD}# define TIOCM_CAR MDCD
1245 IF{MRI}# define TIOCM_RNG MRI
1246 IF{MCTS}# define TIOCM_CTS MCTS
1247 # endif
1248 #endif
1249 #if defined(CLOCAL) || defined(CRTSCTS)
1250 struct mode mtio; /* screen.h */
1251 #endif
1252 #if defined(CRTSCTS) || defined(TIOCM_CTS)
1253 int rtscts;
1254 #endif
1255 int clocal;
1257 #if defined(CLOCAL) || defined(CRTSCTS)
1258 GetTTY(fd, &mtio);
1259 #endif
1260 clocal = 0;
1261 #ifdef CLOCAL
1262 if (mtio.tio.c_cflag & CLOCAL)
1264 clocal = 1;
1265 *p++ = '{';
1267 #endif
1269 #ifdef TIOCM_CTS
1270 # ifdef CRTSCTS
1271 if (!(mtio.tio.c_cflag & CRTSCTS))
1272 rtscts = 0;
1273 else
1274 # endif /* CRTSCTS */
1275 rtscts = 1;
1276 #endif /* TIOCM_CTS */
1278 #ifdef TIOCGSOFTCAR
1279 if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0)
1280 softcar = 0;
1281 #endif
1283 #if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA)
1284 # ifdef TIOCMGET
1285 if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0)
1286 # else
1287 # ifdef TIOCMODG
1288 if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0)
1289 # else
1290 if (ioctl(fd, MCGETA, &mflags) < 0)
1291 # endif
1292 # endif
1294 #ifdef TIOCGSOFTCAR
1295 sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD");
1296 #else
1297 sprintf(p, "NO-TTY?");
1298 #endif
1299 p += strlen(p);
1301 else
1303 char *s;
1304 # ifdef FANCY_MODEM
1305 # ifdef TIOCM_LE
1306 if (!(mflags & TIOCM_LE))
1307 for (s = "!LE "; *s; *p++ = *s++);
1308 # endif
1309 # endif /* FANCY_MODEM */
1311 # ifdef TIOCM_RTS
1312 s = "!RTS "; if (mflags & TIOCM_RTS) s++;
1313 while (*s) *p++ = *s++;
1314 # endif
1315 # ifdef TIOCM_CTS
1316 s = "!CTS ";
1317 if (!rtscts)
1319 *p++ = '(';
1320 s = "!CTS) ";
1322 if (mflags & TIOCM_CTS) s++;
1323 while (*s) *p++ = *s++;
1324 # endif
1326 # ifdef TIOCM_DTR
1327 s = "!DTR "; if (mflags & TIOCM_DTR) s++;
1328 while (*s) *p++ = *s++;
1329 # endif
1330 # ifdef TIOCM_DSR
1331 s = "!DSR "; if (mflags & TIOCM_DSR) s++;
1332 while (*s) *p++ = *s++;
1333 # endif
1334 # if defined(TIOCM_CD) || defined(TIOCM_CAR)
1335 s = "!CD ";
1336 # ifdef TIOCGSOFTCAR
1337 if (softcar)
1339 *p++ = '(';
1340 s = "!CD) ";
1342 # endif
1343 # ifdef TIOCM_CD
1344 if (mflags & TIOCM_CD) s++;
1345 # else
1346 if (mflags & TIOCM_CAR) s++;
1347 # endif
1348 while (*s) *p++ = *s++;
1349 # endif
1350 # if defined(TIOCM_RI) || defined(TIOCM_RNG)
1351 # ifdef TIOCM_RI
1352 if (mflags & TIOCM_RI)
1353 # else
1354 if (mflags & TIOCM_RNG)
1355 # endif
1356 for (s = "RI "; *s; *p++ = *s++);
1357 # endif
1358 # ifdef FANCY_MODEM
1359 # ifdef TIOCM_ST
1360 s = "!ST "; if (mflags & TIOCM_ST) s++;
1361 while (*s) *p++ = *s++;
1362 # endif
1363 # ifdef TIOCM_SR
1364 s = "!SR "; if (mflags & TIOCM_SR) s++;
1365 while (*s) *p++ = *s++;
1366 # endif
1367 # endif /* FANCY_MODEM */
1368 if (p > buf && p[-1] == ' ')
1369 p--;
1370 *p = '\0';
1372 #else
1373 # ifdef TIOCGSOFTCAR
1374 sprintf(p, " %s", softcar ? "(CD)", "CD");
1375 p += strlen(p);
1376 # endif
1377 #endif
1378 if (clocal)
1379 *p++ = '}';
1380 *p = '\0';
1381 return buf;
1385 * Old bsd-ish machines may not have any of the baudrate B... symbols.
1386 * We hope to detect them here, so that the btable[] below always has
1387 * many entries.
1389 #ifndef POSIX
1390 # ifndef TERMIO
1391 # if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300)
1392 IFN{B0}#define B0 0
1393 IFN{B50}#define B50 1
1394 IFN{B75}#define B75 2
1395 IFN{B110}#define B110 3
1396 IFN{B134}#define B134 4
1397 IFN{B150}#define B150 5
1398 IFN{B200}#define B200 6
1399 IFN{B300}#define B300 7
1400 IFN{B600}#define B600 8
1401 IFN{B1200}#define B1200 9
1402 IFN{B1800}#define B1800 10
1403 IFN{B2400}#define B2400 11
1404 IFN{B4800}#define B4800 12
1405 IFN{B9600}#define B9600 13
1406 IFN{EXTA}#define EXTA 14
1407 IFN{EXTB}#define EXTB 15
1408 # endif
1409 # endif
1410 #endif
1413 * On hpux, idx and sym will be different.
1414 * Rumor has it that, we need idx in D_dospeed to make tputs
1415 * padding correct.
1416 * Frequently used entries come first.
1418 static struct baud_values btable[] =
1420 IF{B9600} { 13, 9600, B9600 },
1421 IF{B19200} { 14, 19200, B19200 },
1422 IF{EXTA} { 14, 19200, EXTA },
1423 IF{B38400} { 15, 38400, B38400 },
1424 IF{EXTB} { 15, 38400, EXTB },
1425 IF{B57600} { 16, 57600, B57600 },
1426 IF{B115200} { 17, 115200, B115200 },
1427 IF{B230400} { 18, 230400, B230400 },
1428 IF{B460800} { 19, 460800, B460800 },
1429 IF{B7200} { 13, 7200, B7200 },
1430 IF{B4800} { 12, 4800, B4800 },
1431 IF{B3600} { 12, 3600, B3600 },
1432 IF{B2400} { 11, 2400, B2400 },
1433 IF{B1800} { 10, 1800, B1800 },
1434 IF{B1200} { 9, 1200, B1200 },
1435 IF{B900} { 9, 900, B900 },
1436 IF{B600} { 8, 600, B600 },
1437 IF{B300} { 7, 300, B300 },
1438 IF{B200} { 6, 200, B200 },
1439 IF{B150} { 5, 150, B150 },
1440 IF{B134} { 4, 134, B134 },
1441 IF{B110} { 3, 110, B110 },
1442 IF{B75} { 2, 75, B75 },
1443 IF{B50} { 1, 50, B50 },
1444 IF{B0} { 0, 0, B0 },
1445 { -1, -1, -1 }
1449 * baud may either be a bits-per-second value or a symbolic
1450 * value as returned by cfget?speed()
1452 struct baud_values *
1453 lookup_baud(baud)
1454 int baud;
1456 struct baud_values *p;
1458 for (p = btable; p->idx >= 0; p++)
1459 if (baud == p->bps || baud == p->sym)
1460 return p;
1461 return NULL;
1465 * change the baud rate in a mode structure.
1466 * ibaud and obaud are given in bit/second, or at your option as
1467 * termio B... symbols as defined in e.g. suns sys/ttydev.h
1468 * -1 means don't change.
1471 SetBaud(m, ibaud, obaud)
1472 struct mode *m;
1473 int ibaud, obaud;
1475 struct baud_values *ip, *op;
1477 if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) ||
1478 (!(op = lookup_baud(obaud)) && obaud != -1))
1479 return -1;
1481 #ifdef POSIX
1482 if (ip) cfsetispeed(&m->tio, ip->sym);
1483 if (op) cfsetospeed(&m->tio, op->sym);
1484 #else /* POSIX */
1485 # ifdef TERMIO
1486 if (ip)
1488 # ifdef IBSHIFT
1489 m->tio.c_cflag &= ~(CBAUD << IBSHIFT);
1490 m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT;
1491 # else /* IBSHIFT */
1492 if (ibaud != obaud)
1493 return -1;
1494 # endif /* IBSHIFT */
1496 if (op)
1498 m->tio.c_cflag &= ~CBAUD;
1499 m->tio.c_cflag |= op->sym & CBAUD;
1501 # else /* TERMIO */
1502 if (ip) m->m_ttyb.sg_ispeed = ip->idx;
1503 if (op) m->m_ttyb.sg_ospeed = op->idx;
1504 # endif /* TERMIO */
1505 #endif /* POSIX */
1506 return 0;
1510 * Write out the mode struct in a readable form
1513 #ifdef DEBUG
1514 void
1515 DebugTTY(m)
1516 struct mode *m;
1518 int i;
1520 #ifdef POSIX
1521 debug("struct termios tio:\n");
1522 debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag);
1523 debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag);
1524 debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag);
1525 debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag);
1526 debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio));
1527 debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio));
1528 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1530 debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]);
1532 # ifdef HPUX_LTCHARS_HACK
1533 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc);
1534 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc);
1535 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc);
1536 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc);
1537 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc);
1538 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc);
1539 # endif /* HPUX_LTCHARS_HACK */
1540 #else /* POSIX */
1541 # ifdef TERMIO
1542 debug("struct termio tio:\n");
1543 debug1("c_iflag = %04o\n", m->tio.c_iflag);
1544 debug1("c_oflag = %04o\n", m->tio.c_oflag);
1545 debug1("c_cflag = %04o\n", m->tio.c_cflag);
1546 debug1("c_lflag = %04o\n", m->tio.c_lflag);
1547 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1549 debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]);
1551 # else /* TERMIO */
1552 debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed);
1553 debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed);
1554 debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase);
1555 debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill);
1556 debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags);
1557 debug1("intrc = %#02x\n", m->m_tchars.t_intrc);
1558 debug1("quitc = %#02x\n", m->m_tchars.t_quitc);
1559 debug1("startc = %#02x\n", m->m_tchars.t_startc);
1560 debug1("stopc = %#02x\n", m->m_tchars.t_stopc);
1561 debug1("eofc = %#02x\n", m->m_tchars.t_eofc);
1562 debug1("brkc = %#02x\n", m->m_tchars.t_brkc);
1563 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc);
1564 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc);
1565 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc);
1566 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc);
1567 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc);
1568 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc);
1569 debug1("ldisc = %d\n", m->m_ldisc);
1570 debug1("lmode = %#x\n", m->m_lmode);
1571 # endif /* TERMIO */
1572 #endif /* POSIX */
1574 #endif /* DEBUG */