Fix some more windowlist glitches
[screen-lua.git] / src / tty.c.dist
blob688cf621b7009c1f8405d30a3a81dc2ae25f4480
1 /* Copyright (c) 1993-2002
2  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4  * Copyright (c) 1987 Oliver Laumann
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *  
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file COPYING); if not, write to the
18  * Free Software Foundation, Inc.,
19  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
20  *
21  ****************************************************************
22  */
25  * NOTICE: tty.c is automatically generated from tty.sh
26  * Do not change anything here. If you then change tty.sh.
27  */
29 #include <sys/types.h>
30 #include <signal.h>
31 #include <fcntl.h>
32 #ifndef sgi
33 # include <sys/file.h>
34 #endif
35 #if !defined(sun) || defined(SUNOS3)
36 # include <sys/ioctl.h> /* collosions with termios.h */
37 #else
38 # ifndef TIOCEXCL
39 #  include <sys/ttold.h>        /* needed for TIOCEXCL */
40 # endif
41 #endif
42 #ifdef __hpux
43 # include <sys/modem.h>
44 #endif
46 #ifdef ISC
47 # include <sys/tty.h>
48 # include <sys/sioctl.h>
49 # include <sys/pty.h>
50 #endif
52 #include "config.h"
53 #ifdef SVR4
54 #include <sys/stropts.h>        /* for I_POP */
55 #endif
57 #include "screen.h"
58 #include "extern.h"
60 #if !defined(TIOCCONS) && defined(sun) && defined(SVR4)
61 # include <sys/strredir.h>
62 #endif
64 extern struct display *display, *displays;
65 extern int iflag;
66 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
67 extern struct win *console_window;
68 static void consredir_readev_fn __P((struct event *, char *));
69 #endif
71 int separate_sids = 1;
73 static void DoSendBreak __P((int, int, int));
74 static sigret_t SigAlrmDummy __P(SIGPROTOARG);
77 /* Frank Schulz (fschulz@pyramid.com):
78  * I have no idea why VSTART is not defined and my fix is probably not
79  * the cleanest, but it works.
80  */
81 #if !defined(VSTART) && defined(_VSTART)
82 #define VSTART _VSTART
83 #endif
84 #if !defined(VSTOP) && defined(_VSTOP)
85 #define VSTOP _VSTOP
86 #endif
88 #ifndef O_NOCTTY
89 # define O_NOCTTY 0
90 #endif
92 #ifndef TTYVMIN
93 # define TTYVMIN 1
94 #endif
95 #ifndef TTYVTIME
96 #define TTYVTIME 0
97 #endif
100 static sigret_t
101 SigAlrmDummy SIGDEFARG
103   debug("SigAlrmDummy()\n");
104   SIGRETURN;
108  *  Carefully open a charcter device. Not used to open display ttys.
109  *  The second parameter is parsed for a few stty style options.
110  */
113 OpenTTY(line, opt)
114 char *line, *opt;
116   int f;
117   struct mode Mode;
118   sigret_t (*sigalrm)__P(SIGPROTOARG);
120   sigalrm = signal(SIGALRM, SigAlrmDummy);
121   alarm(2);
123   /* this open only succeeds, if real uid is allowed */
124   if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1)
125     {
126       if (errno == EINTR)
127         Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line);
128       else
129         Msg(errno, "Cannot open line '%s' for R/W", line);
130       alarm(0);
131       signal(SIGALRM, sigalrm);
132       return -1;
133     }
134   if (!isatty(f))
135     {
136       Msg(0, "'%s' is not a tty", line);
137       alarm(0);
138       signal(SIGALRM, sigalrm);
139       close(f);
140       return -1;
141     }
142 #if defined(I_POP) && defined(POP_TTYMODULES)
143   debug("OpenTTY I_POP\n");
144   while (ioctl(f, I_POP, (char *)0) >= 0)
145     ;
146 #endif
147   /*
148    * We come here exclusively. This is to stop all kermit and cu type things
149    * accessing the same tty line.
150    * Perhaps we should better create a lock in some /usr/spool/locks directory?
151    */
152 #ifdef TIOCEXCL
153  errno = 0;
154  if (ioctl(f, TIOCEXCL, (char *) 0) < 0)
155    Msg(errno, "%s: ioctl TIOCEXCL failed", line);
156  debug3("%d %d %d\n", getuid(), geteuid(), getpid());
157  debug2("%s TIOCEXCL errno %d\n", line, errno);
158 #endif  /* TIOCEXCL */
159   /*
160    * We create a sane tty mode. We do not copy things from the display tty
161    */
162 #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE
163   if (display)
164     {
165       debug1("OpenTTY: using mode of display for %s\n", line);
166       Mode = D_NewMode;
167     }
168   else
169 #endif
170     InitTTY(&Mode, W_TYPE_PLAIN);
171   
172   SttyMode(&Mode, opt);
173 #ifdef DEBUG
174   DebugTTY(&Mode);
175 #endif
176   SetTTY(f, &Mode);
178 #if defined(linux) && defined(TIOCMSET)
179   {
180     int mcs = 0;
181     ioctl(f, TIOCMGET, &mcs);
182     mcs |= TIOCM_RTS;
183     ioctl(f, TIOCMSET, &mcs);
184   }
185 #endif
187   brktty(f);
188   alarm(0);
189   signal(SIGALRM, sigalrm);
190   debug2("'%s' CONNECT fd=%d.\n", line, f);
191   return f;
196  *  Tty mode handling
197  */
199 void
200 InitTTY(m, ttyflag)
201 struct mode *m;
202 int ttyflag;
204   bzero((char *)m, sizeof(*m));
205 #ifdef POSIX
206   /* struct termios tio 
207    * defaults, as seen on SunOS 4.1.3
208    */
209   debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag);
210 #if defined(BRKINT)
211         m->tio.c_iflag |= BRKINT;
212 #endif /* BRKINT */
213 #if defined(IGNPAR)
214         m->tio.c_iflag |= IGNPAR;
215 #endif /* IGNPAR */
216 /* IF{ISTRIP}   m->tio.c_iflag |= ISTRIP;  may be needed, let's try. jw. */
217 #if defined(IXON)
218         m->tio.c_iflag |= IXON;
219 #endif /* IXON */
220 /* IF{IMAXBEL}  m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */
222   if (!ttyflag) /* may not even be good for ptys.. */
223     {
224 #if defined(ICRNL)
225         m->tio.c_iflag |= ICRNL;
226 #endif /* ICRNL */
227 #if defined(ONLCR)
228         m->tio.c_oflag |= ONLCR; 
229 #endif /* ONLCR */
230 #if defined(TAB3)
231         m->tio.c_oflag |= TAB3; 
232 #endif /* TAB3 */
233 #if defined(OXTABS)
234       m->tio.c_oflag |= OXTABS;
235 #endif /* OXTABS */
236 /* IF{PARENB}   m->tio.c_cflag |= PARENB;       nah! jw. */
237 #if defined(OPOST)
238         m->tio.c_oflag |= OPOST;
239 #endif /* OPOST */
240     }
244  * Or-ing the speed into c_cflags is dangerous.
245  * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs.
247  * IF{B9600}    m->tio.c_cflag |= B9600;
248  * IF{IBSHIFT) && defined(B9600}        m->tio.c_cflag |= B9600 << IBSHIFT;
250  * We hope that we have the posix calls to do it right:
251  * If these are not available you might try the above.
252  */
253 #if defined(B9600)
254        cfsetospeed(&m->tio, B9600);
255 #endif /* B9600 */
256 #if defined(B9600)
257        cfsetispeed(&m->tio, B9600);
258 #endif /* B9600 */
260 #if defined(CS8)
261         m->tio.c_cflag |= CS8;
262 #endif /* CS8 */
263 #if defined(CREAD)
264         m->tio.c_cflag |= CREAD;
265 #endif /* CREAD */
266 #if defined(CLOCAL)
267         m->tio.c_cflag |= CLOCAL;
268 #endif /* CLOCAL */
270 #if defined(ECHOCTL)
271         m->tio.c_lflag |= ECHOCTL;
272 #endif /* ECHOCTL */
273 #if defined(ECHOKE)
274         m->tio.c_lflag |= ECHOKE;
275 #endif /* ECHOKE */
277   if (!ttyflag)
278     {
279 #if defined(ISIG)
280         m->tio.c_lflag |= ISIG;
281 #endif /* ISIG */
282 #if defined(ICANON)
283         m->tio.c_lflag |= ICANON;
284 #endif /* ICANON */
285 #if defined(ECHO)
286         m->tio.c_lflag |= ECHO;
287 #endif /* ECHO */
288     }
289 #if defined(ECHOE)
290         m->tio.c_lflag |= ECHOE;
291 #endif /* ECHOE */
292 #if defined(ECHOK)
293         m->tio.c_lflag |= ECHOK;
294 #endif /* ECHOK */
295 #if defined(IEXTEN)
296         m->tio.c_lflag |= IEXTEN;
297 #endif /* IEXTEN */
299 #if defined(VINTR)
300 #if (VINTR < MAXCC)
301         m->tio.c_cc[VINTR]    = Ctrl('C');
302 #endif 
303 #endif /* VINTR */
304 #if defined(VQUIT)
305 #if (VQUIT < MAXCC)
306         m->tio.c_cc[VQUIT]    = Ctrl('\\');
307 #endif 
308 #endif /* VQUIT */
309 #if defined(VERASE)
310 #if (VERASE < MAXCC)
311         m->tio.c_cc[VERASE]   = 0x7f; /* DEL */
312 #endif 
313 #endif /* VERASE */
314 #if defined(VKILL)
315 #if (VKILL < MAXCC)
316         m->tio.c_cc[VKILL]    = Ctrl('H');
317 #endif 
318 #endif /* VKILL */
319 #if defined(VEOF)
320 #if (VEOF < MAXCC)
321         m->tio.c_cc[VEOF]     = Ctrl('D');
322 #endif 
323 #endif /* VEOF */
324 #if defined(VEOL)
325 #if (VEOL < MAXCC)
326         m->tio.c_cc[VEOL]     = 0000;
327 #endif 
328 #endif /* VEOL */
329 #if defined(VEOL2)
330 #if (VEOL2 < MAXCC)
331         m->tio.c_cc[VEOL2]    = 0000;
332 #endif 
333 #endif /* VEOL2 */
334 #if defined(VSWTCH)
335 #if (VSWTCH < MAXCC)
336         m->tio.c_cc[VSWTCH]   = 0000;
337 #endif 
338 #endif /* VSWTCH */
339 #if defined(VSTART)
340 #if (VSTART < MAXCC)
341         m->tio.c_cc[VSTART]   = Ctrl('Q');
342 #endif 
343 #endif /* VSTART */
344 #if defined(VSTOP)
345 #if (VSTOP < MAXCC)
346         m->tio.c_cc[VSTOP]    = Ctrl('S');
347 #endif 
348 #endif /* VSTOP */
349 #if defined(VSUSP)
350 #if (VSUSP < MAXCC)
351         m->tio.c_cc[VSUSP]    = Ctrl('Z');
352 #endif 
353 #endif /* VSUSP */
354 #if defined(VDSUSP)
355 #if (VDSUSP < MAXCC)
356         m->tio.c_cc[VDSUSP]   = Ctrl('Y');
357 #endif 
358 #endif /* VDSUSP */
359 #if defined(VREPRINT)
360 #if (VREPRINT < MAXCC)
361         m->tio.c_cc[VREPRINT] = Ctrl('R');
362 #endif 
363 #endif /* VREPRINT */
364 #if defined(VDISCARD)
365 #if (VDISCARD < MAXCC)
366         m->tio.c_cc[VDISCARD] = Ctrl('O');
367 #endif 
368 #endif /* VDISCARD */
369 #if defined(VWERASE)
370 #if (VWERASE < MAXCC)
371         m->tio.c_cc[VWERASE]  = Ctrl('W');
372 #endif 
373 #endif /* VWERASE */
374 #if defined(VLNEXT)
375 #if (VLNEXT < MAXCC)
376         m->tio.c_cc[VLNEXT]   = Ctrl('V');
377 #endif 
378 #endif /* VLNEXT */
379 #if defined(VSTATUS)
380 #if (VSTATUS < MAXCC)
381         m->tio.c_cc[VSTATUS]  = Ctrl('T');
382 #endif 
383 #endif /* VSTATUS */
385   if (ttyflag)
386     {
387       m->tio.c_cc[VMIN] = TTYVMIN;
388       m->tio.c_cc[VTIME] = TTYVTIME;
389     }
391 # ifdef HPUX_LTCHARS_HACK
392   m->m_ltchars.t_suspc =  Ctrl('Z');
393   m->m_ltchars.t_dsuspc = Ctrl('Y');
394   m->m_ltchars.t_rprntc = Ctrl('R');
395   m->m_ltchars.t_flushc = Ctrl('O');
396   m->m_ltchars.t_werasc = Ctrl('W');
397   m->m_ltchars.t_lnextc = Ctrl('V');
398 # endif /* HPUX_LTCHARS_HACK */
400 #else /* POSIX */
402 # ifdef TERMIO
403   debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag);
404   /* struct termio tio 
405    * defaults, as seen on Mototola SYSV68:
406    * input: 7bit, CR->NL, ^S/^Q flow control 
407    * output: POSTprocessing: NL->NL-CR, Tabs to spaces
408    * control: 9600baud, 8bit CSIZE, enable input
409    * local: enable signals, erase/kill processing, echo on.
410    */
411 #if defined(ISTRIP)
412         m->tio.c_iflag |= ISTRIP;
413 #endif /* ISTRIP */
414 #if defined(IXON)
415         m->tio.c_iflag |= IXON;
416 #endif /* IXON */
418   if (!ttyflag) /* may not even be good for ptys.. */
419     {
420 #if defined(OPOST)
421         m->tio.c_oflag |= OPOST;
422 #endif /* OPOST */
423 #if defined(ICRNL)
424         m->tio.c_iflag |= ICRNL;
425 #endif /* ICRNL */
426 #if defined(ONLCR)
427         m->tio.c_oflag |= ONLCR;
428 #endif /* ONLCR */
429 #if defined(TAB3)
430         m->tio.c_oflag |= TAB3;
431 #endif /* TAB3 */
432     }
434 #ifdef __bsdi__
435                 )-: cannot handle BSDI without POSIX
436 #else
437 #if defined(B9600)
438         m->tio.c_cflag  = B9600;
439 #endif /* B9600 */
440 #endif
441 #if defined(CS8)
442         m->tio.c_cflag |= CS8;
443 #endif /* CS8 */
444 #if defined(CREAD)
445         m->tio.c_cflag |= CREAD;
446 #endif /* CREAD */
448   if (!ttyflag)
449     {
450 #if defined(ISIG)
451         m->tio.c_lflag |= ISIG;
452 #endif /* ISIG */
453 #if defined(ICANON)
454         m->tio.c_lflag |= ICANON;
455 #endif /* ICANON */
456 #if defined(ECHO)
457         m->tio.c_lflag |= ECHO;
458 #endif /* ECHO */
459     }
460 #if defined(ECHOE)
461         m->tio.c_lflag |= ECHOE;
462 #endif /* ECHOE */
463 #if defined(ECHOK)
464         m->tio.c_lflag |= ECHOK;
465 #endif /* ECHOK */
467 #if defined(VINTR)
468 #if (VINTR < MAXCC)
469         m->tio.c_cc[VINTR]  = Ctrl('C');
470 #endif 
471 #endif /* VINTR */
472 #if defined(VQUIT)
473 #if (VQUIT < MAXCC)
474         m->tio.c_cc[VQUIT]  = Ctrl('\\');
475 #endif 
476 #endif /* VQUIT */
477 #if defined(VERASE)
478 #if (VERASE < MAXCC)
479         m->tio.c_cc[VERASE] = 0177; /* DEL */
480 #endif 
481 #endif /* VERASE */
482 #if defined(VKILL)
483 #if (VKILL < MAXCC)
484         m->tio.c_cc[VKILL]  = Ctrl('H');
485 #endif 
486 #endif /* VKILL */
487 #if defined(VEOF)
488 #if (VEOF < MAXCC)
489         m->tio.c_cc[VEOF]   = Ctrl('D');
490 #endif 
491 #endif /* VEOF */
492 #if defined(VEOL)
493 #if (VEOL < MAXCC)
494         m->tio.c_cc[VEOL]   = 0377;
495 #endif 
496 #endif /* VEOL */
497 #if defined(VEOL2)
498 #if (VEOL2 < MAXCC)
499         m->tio.c_cc[VEOL2]  = 0377;
500 #endif 
501 #endif /* VEOL2 */
502 #if defined(VSWTCH)
503 #if (VSWTCH < MAXCC)
504         m->tio.c_cc[VSWTCH] = 0000;
505 #endif 
506 #endif /* VSWTCH */
508   if (ttyflag)
509    {
510       m->tio.c_cc[VMIN] = TTYVMIN;
511       m->tio.c_cc[VTIME] = TTYVTIME;
512     } 
514 # else /* TERMIO */
515   debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag);
516   m->m_ttyb.sg_ispeed = B9600;
517   m->m_ttyb.sg_ospeed = B9600;
518   m->m_ttyb.sg_erase  = 0177; /*DEL */
519   m->m_ttyb.sg_kill   = Ctrl('H');
520   if (!ttyflag)
521     m->m_ttyb.sg_flags = CRMOD | ECHO
522 #if defined(ANYP)
523         | ANYP
524 #endif /* ANYP */
525     ;
526   else
527     m->m_ttyb.sg_flags = CBREAK
528 #if defined(ANYP)
529         | ANYP
530 #endif /* ANYP */
531     ;
533   m->m_tchars.t_intrc   = Ctrl('C');
534   m->m_tchars.t_quitc   = Ctrl('\\');
535   m->m_tchars.t_startc  = Ctrl('Q');
536   m->m_tchars.t_stopc   = Ctrl('S');
537   m->m_tchars.t_eofc    = Ctrl('D');
538   m->m_tchars.t_brkc    = -1;
540   m->m_ltchars.t_suspc  = Ctrl('Z');
541   m->m_ltchars.t_dsuspc = Ctrl('Y');
542   m->m_ltchars.t_rprntc = Ctrl('R');
543   m->m_ltchars.t_flushc = Ctrl('O');
544   m->m_ltchars.t_werasc = Ctrl('W');
545   m->m_ltchars.t_lnextc = Ctrl('V');
547 #if defined(NTTYDISC)
548         m->m_ldisc = NTTYDISC;
549 #endif /* NTTYDISC */
551   m->m_lmode = 0
552 #if defined(LDECCTQ)
553         | LDECCTQ
554 #endif /* LDECCTQ */
555 #if defined(LCTLECH)
556         | LCTLECH
557 #endif /* LCTLECH */
558 #if defined(LPASS8)
559         | LPASS8
560 #endif /* LPASS8 */
561 #if defined(LCRTKIL)
562         | LCRTKIL
563 #endif /* LCRTKIL */
564 #if defined(LCRTERA)
565         | LCRTERA
566 #endif /* LCRTERA */
567 #if defined(LCRTBS)
568         | LCRTBS
569 #endif /* LCRTBS */
570   ;
571 # endif /* TERMIO */
572 #endif /* POSIX */
574 #if defined(ENCODINGS) && defined(TIOCKSET)
575   m->m_jtchars.t_ascii = 'J';
576   m->m_jtchars.t_kanji = 'B';
577   m->m_knjmode = KM_ASCII | KM_SYSSJIS;
578 #endif
581 void 
582 SetTTY(fd, mp)
583 int fd;
584 struct mode *mp;
586   errno = 0;
587 #ifdef POSIX
588   tcsetattr(fd, TCSADRAIN, &mp->tio);
589 # ifdef HPUX_LTCHARS_HACK
590   ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars);
591 # endif
592 #else
593 # ifdef TERMIO
594   ioctl(fd, TCSETAW, (char *)&mp->tio);
595 #  ifdef CYTERMIO
596   if (mp->tio.c_line == 3)
597     {
598       ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey);
599       ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen);
600       ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace);
601     }
602 #  endif
603 # else
604   /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */
605   ioctl(fd, TIOCSETC, (char *)&mp->m_tchars);
606   ioctl(fd, TIOCLSET, (char *)&mp->m_lmode);
607   ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc);
608   ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb);
609   ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */
610 # endif
611 #endif
612 #if defined(ENCODINGS) && defined(TIOCKSET)
613   ioctl(fd, TIOCKSETC, &mp->m_jtchars);
614   ioctl(fd, TIOCKSET, &mp->m_knjmode);
615 #endif
616   if (errno)
617     Msg(errno, "SetTTY (fd %d): ioctl failed", fd);
620 void
621 GetTTY(fd, mp)
622 int fd;
623 struct mode *mp;
625   errno = 0;
626 #ifdef POSIX
627   tcgetattr(fd, &mp->tio);
628 # ifdef HPUX_LTCHARS_HACK
629   ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
630 # endif
631 #else
632 # ifdef TERMIO
633   ioctl(fd, TCGETA, (char *)&mp->tio);
634 #  ifdef CYTERMIO
635   if (mp->tio.c_line == 3)
636     {
637       ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey);
638       ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen);
639       ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace);
640     }
641   else
642     {
643       mp->m_mapkey = NOMAPKEY;
644       mp->m_mapscreen = NOMAPSCREEN;
645       mp->m_backspace = '\b';
646     }
647 #  endif
648 # else
649   ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb);
650   ioctl(fd, TIOCGETC, (char *)&mp->m_tchars);
651   ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
652   ioctl(fd, TIOCLGET, (char *)&mp->m_lmode);
653   ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc);
654 # endif
655 #endif
656 #if defined(ENCODINGS) && defined(TIOCKSET)
657   ioctl(fd, TIOCKGETC, &mp->m_jtchars);
658   ioctl(fd, TIOCKGET, &mp->m_knjmode);
659 #endif
660   if (errno)
661     Msg(errno, "GetTTY (fd %d): ioctl failed", fd);
665  * needs interrupt = iflag and flow = d->d_flow
666  */
667 void
668 SetMode(op, np, flow, interrupt)
669 struct mode *op, *np;
670 int flow, interrupt;
672   *np = *op;
674   ASSERT(display);
675 #if defined(TERMIO) || defined(POSIX)
676 # ifdef CYTERMIO
677   np->m_mapkey = NOMAPKEY;
678   np->m_mapscreen = NOMAPSCREEN;
679   np->tio.c_line = 0;
680 # endif
681 #if defined(ICRNL)
682   np->tio.c_iflag &= ~ICRNL;
683 #endif /* ICRNL */
684 #if defined(ISTRIP)
685   np->tio.c_iflag &= ~ISTRIP;
686 #endif /* ISTRIP */
687 #if defined(ONLCR)
688   np->tio.c_oflag &= ~ONLCR;
689 #endif /* ONLCR */
690   np->tio.c_lflag &= ~(ICANON | ECHO);
691   /*
692    * From Andrew Myers (andru@tonic.lcs.mit.edu)
693    * to avoid ^V^V-Problem on OSF1
694    */
695 #if defined(IEXTEN)
696   np->tio.c_lflag &= ~IEXTEN;
697 #endif /* IEXTEN */
699   /*
700    * Unfortunately, the master process never will get SIGINT if the real
701    * terminal is different from the one on which it was originaly started
702    * (process group membership has not been restored or the new tty could not
703    * be made controlling again). In my solution, it is the attacher who
704    * receives SIGINT (because it is always correctly associated with the real
705    * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. 
706    * Marc Boucher (marc@CAM.ORG)
707    */
708   if (interrupt)
709     np->tio.c_lflag |= ISIG;
710   else
711     np->tio.c_lflag &= ~ISIG;
712   /* 
713    * careful, careful catche monkey..
714    * never set VMIN and VTIME to zero, if you want blocking io.
715    *
716    * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to 
717    * reduce interrupt frequency.  But then we would not know how to 
718    * handle read returning 0. jw.
719    */
720   np->tio.c_cc[VMIN] = 1;
721   np->tio.c_cc[VTIME] = 0;
722   if (!interrupt || !flow)
723     np->tio.c_cc[VINTR] = VDISABLE;
724   np->tio.c_cc[VQUIT] = VDISABLE;
725   if (flow == 0)
726     {
727 #if defined(VSTART)
728 #if (VSTART < MAXCC)
729         np->tio.c_cc[VSTART] = VDISABLE;
730 #endif 
731 #endif /* VSTART */
732 #if defined(VSTOP)
733 #if (VSTOP < MAXCC)
734         np->tio.c_cc[VSTOP] = VDISABLE;
735 #endif 
736 #endif /* VSTOP */
737       np->tio.c_iflag &= ~IXON;
738     }
739 #if defined(VDISCARD)
740 #if (VDISCARD < MAXCC)
741         np->tio.c_cc[VDISCARD] = VDISABLE;
742 #endif 
743 #endif /* VDISCARD */
744 #if defined(VLNEXT)
745 #if (VLNEXT < MAXCC)
746         np->tio.c_cc[VLNEXT] = VDISABLE;
747 #endif 
748 #endif /* VLNEXT */
749 #if defined(VSTATUS)
750 #if (VSTATUS < MAXCC)
751         np->tio.c_cc[VSTATUS] = VDISABLE;
752 #endif 
753 #endif /* VSTATUS */
754 #if defined(VSUSP)
755 #if (VSUSP < MAXCC)
756         np->tio.c_cc[VSUSP] = VDISABLE;
757 #endif 
758 #endif /* VSUSP */
759 #if defined(VERASE)
760 #if (VERASE < MAXCC)
761         np->tio.c_cc[VERASE] = VDISABLE;
762 #endif 
763 #endif /* VERASE */
764 #if defined(VKILL)
765 #if (VKILL < MAXCC)
766         np->tio.c_cc[VKILL] = VDISABLE;
767 #endif 
768 #endif /* VKILL */
769 # ifdef HPUX_LTCHARS_HACK
770   np->m_ltchars.t_suspc  = VDISABLE;
771   np->m_ltchars.t_dsuspc = VDISABLE;
772   np->m_ltchars.t_rprntc = VDISABLE;
773   np->m_ltchars.t_flushc = VDISABLE;
774   np->m_ltchars.t_werasc = VDISABLE;
775   np->m_ltchars.t_lnextc = VDISABLE;
776 # else /* HPUX_LTCHARS_HACK */
777 #if defined(VDSUSP)
778 #if (VDSUSP < MAXCC)
779         np->tio.c_cc[VDSUSP] = VDISABLE;
780 #endif 
781 #endif /* VDSUSP */
782 #if defined(VREPRINT)
783 #if (VREPRINT < MAXCC)
784         np->tio.c_cc[VREPRINT] = VDISABLE;
785 #endif 
786 #endif /* VREPRINT */
787 #if defined(VWERASE)
788 #if (VWERASE < MAXCC)
789         np->tio.c_cc[VWERASE] = VDISABLE;
790 #endif 
791 #endif /* VWERASE */
792 # endif /* HPUX_LTCHARS_HACK */
793 #else /* TERMIO || POSIX */
794   if (!interrupt || !flow)
795     np->m_tchars.t_intrc = -1;
796   np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
797   np->m_ttyb.sg_flags |= CBREAK;
798 # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS)
799   np->m_ttyb.sg_flags &= ~CSTYLE;
800   np->m_ttyb.sg_flags |= CS_8BITS;
801 # endif
802   np->m_tchars.t_quitc = -1;
803   if (flow == 0)
804     {
805       np->m_tchars.t_startc = -1;
806       np->m_tchars.t_stopc = -1;
807     }
808   np->m_ltchars.t_suspc = -1;
809   np->m_ltchars.t_dsuspc = -1;
810   np->m_ltchars.t_flushc = -1;
811   np->m_ltchars.t_lnextc = -1;
812 #endif /* defined(TERMIO) || defined(POSIX) */
815 /* operates on display */
816 void
817 SetFlow(on)
818 int on;
820   ASSERT(display);
821   if (D_flow == on)
822     return;
823 #if defined(TERMIO) || defined(POSIX)
824   if (on)
825     {
826       D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE;
827 #if defined(VSTART)
828 #if (VSTART < MAXCC)
829         D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART];
830 #endif 
831 #endif /* VSTART */
832 #if defined(VSTOP)
833 #if (VSTOP < MAXCC)
834         D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP];
835 #endif 
836 #endif /* VSTOP */
837       D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON;
838     }
839   else
840     {
841       D_NewMode.tio.c_cc[VINTR] = VDISABLE;
842 #if defined(VSTART)
843 #if (VSTART < MAXCC)
844         D_NewMode.tio.c_cc[VSTART] = VDISABLE;
845 #endif 
846 #endif /* VSTART */
847 #if defined(VSTOP)
848 #if (VSTOP < MAXCC)
849         D_NewMode.tio.c_cc[VSTOP] = VDISABLE;
850 #endif 
851 #endif /* VSTOP */
852       D_NewMode.tio.c_iflag &= ~IXON;
853     }
854 # ifdef POSIX
855   if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio))
856 # else
857   if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0)
858 # endif
859     debug1("SetFlow: ioctl errno %d\n", errno);
860 #else /* POSIX || TERMIO */
861   if (on)
862     {
863       D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1;
864       D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc;
865       D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc;
866     }
867   else
868     {
869       D_NewMode.m_tchars.t_intrc = -1;
870       D_NewMode.m_tchars.t_startc = -1;
871       D_NewMode.m_tchars.t_stopc = -1;
872     }
873   if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0)
874     debug1("SetFlow: ioctl errno %d\n", errno);
875 #endif /* POSIX || TERMIO */
876   D_flow = on;
879 /* parse commands from opt and modify m */
881 SttyMode(m, opt)
882 struct mode *m;
883 char *opt;
885   static const char sep[] = " \t:;,";
887   if (!opt)
888     return 0;
890   while (*opt)
891     {
892       while (index(sep, *opt)) opt++;
893       if (*opt >= '0' && *opt <= '9')
894         {
895           if (SetBaud(m, atoi(opt), atoi(opt)))
896             return -1;
897         }
898       else if (!strncmp("cs7", opt, 3))
899         {
900 #if defined(POSIX) || defined(TERMIO)
901           m->tio.c_cflag &= ~CSIZE;
902           m->tio.c_cflag |= CS7;
903 #else
904           m->m_lmode &= ~LPASS8;
905 #endif
906         }
907       else if (!strncmp("cs8", opt, 3))
908         {
909 #if defined(POSIX) || defined(TERMIO)
910           m->tio.c_cflag &= ~CSIZE;
911           m->tio.c_cflag |= CS8;
912 #else
913           m->m_lmode |= LPASS8;
914 #endif
915         }
916       else if (!strncmp("istrip", opt, 6))
917         {
918 #if defined(POSIX) || defined(TERMIO)
919           m->tio.c_iflag |= ISTRIP;
920 #else
921           m->m_lmode &= ~LPASS8;
922 #endif
923         }
924       else if (!strncmp("-istrip", opt, 7))
925         {
926 #if defined(POSIX) || defined(TERMIO)
927           m->tio.c_iflag &= ~ISTRIP;
928 #else
929           m->m_lmode |= LPASS8;
930 #endif
931         }
932       else if (!strncmp("ixon", opt, 4))
933         {
934 #if defined(POSIX) || defined(TERMIO)
935           m->tio.c_iflag |= IXON;
936 #else
937           debug("SttyMode: no ixon in old bsd land.\n");
938 #endif
939         }
940       else if (!strncmp("-ixon", opt, 5))
941         {
942 #if defined(POSIX) || defined(TERMIO)
943           m->tio.c_iflag &= ~IXON;
944 #else
945           debug("SttyMode: no -ixon in old bsd land.\n");
946 #endif
947         }
948       else if (!strncmp("ixoff", opt, 5))
949         {
950 #if defined(POSIX) || defined(TERMIO)
951           m->tio.c_iflag |= IXOFF;
952 #else
953           m->m_ttyb.sg_flags |= TANDEM;
954 #endif
955         }
956       else if (!strncmp("-ixoff", opt, 6))
957         {
958 #if defined(POSIX) || defined(TERMIO)
959           m->tio.c_iflag &= ~IXOFF;
960 #else
961           m->m_ttyb.sg_flags &= ~TANDEM;
962 #endif
963         }
964       else if (!strncmp("crtscts", opt, 7))
965         {
966 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
967           m->tio.c_cflag |= CRTSCTS;
968 #endif
969         }
970       else if (!strncmp("-crtscts", opt, 8))
971         {
972 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
973           m->tio.c_cflag &= ~CRTSCTS;
974 #endif
975         }
976       else
977         return -1;
978       while (*opt && !index(sep, *opt)) opt++;
979     }
980   return 0;
984  *  Job control handling
986  *  Somehow the ultrix session handling is broken, so use
987  *  the bsdish variant.
988  */
990 /*ARGSUSED*/
991 void
992 brktty(fd)
993 int fd;
995 #if defined(POSIX) && !defined(ultrix)
996   if (separate_sids)
997     setsid();           /* will break terminal affiliation */
998   /* GNU added for Hurd systems 2001-10-10 */
999 # if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__)
1000   ioctl(fd, TIOCSCTTY, (char *)0);
1001 # endif /* BSD && TIOCSCTTY */
1002 #else /* POSIX */
1003 # ifdef SYSV
1004   if (separate_sids)
1005     setpgrp();          /* will break terminal affiliation */
1006 # else /* SYSV */
1007 #  ifdef BSDJOBS
1008   int devtty;
1010   if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0)
1011     {
1012       if (ioctl(devtty, TIOCNOTTY, (char *)0))
1013         debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno);
1014       close(devtty);
1015     }
1016 #  endif /* BSDJOBS */
1017 # endif /* SYSV */
1018 #endif /* POSIX */
1022 fgtty(fd)
1023 int fd;
1025 #ifdef BSDJOBS
1026   int mypid;
1028   mypid = getpid();
1030   /* The next lines should be obsolete. Can anybody check if they
1031    * are really needed on the BSD platforms?
1032    *
1033    * this is to avoid the message:
1034    *    fgtty: Not a typewriter (25)
1035    */
1036 # if defined(__osf__) || (BSD >= 199103) || defined(ISC)
1037   if (separate_sids)
1038     setsid();   /* should be already done */
1039 #  ifdef TIOCSCTTY
1040   ioctl(fd, TIOCSCTTY, (char *)0);
1041 #  endif
1042 # endif
1044 # ifdef POSIX
1045   if (separate_sids)
1046     if (tcsetpgrp(fd, mypid))
1047       {
1048         debug1("fgtty: tcsetpgrp: %d\n", errno);
1049         return -1;
1050       }
1051 # else /* POSIX */
1052   if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0)
1053     debug1("fgtty: TIOSETPGRP: %d\n", errno);
1054 #  ifndef SYSV  /* Already done in brktty():setpgrp() */
1055   if (separate_sids)
1056     if (setpgrp(fd, mypid))
1057       debug1("fgtty: setpgrp: %d\n", errno);
1058 #  endif
1059 # endif /* POSIX */
1060 #endif /* BSDJOBS */
1061   return 0;
1064 /* 
1065  * The alm boards on our sparc center 1000 have a lousy driver.
1066  * We cannot generate long breaks unless we use the most ugly form
1067  * of ioctls. jw.
1068  */
1069 #ifdef POSIX
1070 int breaktype = 2;
1071 #else /* POSIX */
1072 # ifdef TCSBRK
1073 int breaktype = 1;
1074 # else
1075 int breaktype = 0;
1076 # endif
1077 #endif /* POSIX */
1079 #if defined(sun) && !defined(SVR4)
1080 # define HAVE_SUPER_TCSENDBREAK
1081 #endif
1084  * type:
1085  *  0:  TIOCSBRK / TIOCCBRK
1086  *  1:  TCSBRK
1087  *  2:  tcsendbreak()
1088  * n: approximate duration in 1/4 seconds.
1089  */
1090 static void
1091 DoSendBreak(fd, n, type)
1092 int fd, n, type;
1094   switch (type)
1095     {
1096     case 2:     /* tcsendbreak() =============================== */
1097 #ifdef POSIX
1098 # ifdef HAVE_SUPER_TCSENDBREAK
1099       /* There is one rare case that I have tested, where tcsendbreak works
1100        * really great: this was an alm driver that came with SunOS 4.1.3
1101        * If you have this one, define the above symbol.
1102        * here we can use the second parameter to specify the duration.
1103        */
1104       debug2("tcsendbreak(fd=%d, %d)\n", fd, n);
1105       if (tcsendbreak(fd, n) < 0)
1106         Msg(errno, "cannot send BREAK (tcsendbreak)");
1107 # else
1108       /* 
1109        * here we hope, that multiple calls to tcsendbreak() can
1110        * be concatenated to form a long break, as we do not know 
1111        * what exact interpretation the second parameter has:
1112        *
1113        * - sunos 4: duration in quarter seconds
1114        * - sunos 5: 0 a short break, nonzero a tcdrain()
1115        * - hpux, irix: ignored
1116        * - mot88: duration in milliseconds
1117        * - aix: duration in milliseconds, but 0 is 25 milliseconds.
1118        */
1119       debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd);
1120         {
1121           int i;
1123           if (!n)
1124             n++;
1125           for (i = 0; i < n; i++)
1126             if (tcsendbreak(fd, 0) < 0)
1127               {
1128                 Msg(errno, "cannot send BREAK (tcsendbreak SVR4)");
1129                 return;
1130               }
1131         }
1132 # endif
1133 #else /* POSIX */
1134       Msg(0, "tcsendbreak() not available, change breaktype");
1135 #endif /* POSIX */
1136       break;
1138     case 1:     /* TCSBRK ======================================= */
1139 #ifdef TCSBRK
1140       if (!n)
1141         n++;
1142       /*
1143        * Here too, we assume that short breaks can be concatenated to 
1144        * perform long breaks. But for SOLARIS, this is not true, of course.
1145        */
1146       debug2("%d * TCSBRK fd=%d\n", n, fd);
1147         {
1148           int i;
1150           for (i = 0; i < n; i++)
1151             if (ioctl(fd, TCSBRK, (char *)0) < 0)
1152               {
1153                 Msg(errno, "Cannot send BREAK (TCSBRK)");
1154                 return;
1155               }
1156         }
1157 #else /* TCSBRK */
1158       Msg(0, "TCSBRK not available, change breaktype");
1159 #endif /* TCSBRK */
1160       break;
1162     case 0:     /* TIOCSBRK / TIOCCBRK ========================== */
1163 #if defined(TIOCSBRK) && defined(TIOCCBRK)
1164       /*
1165        * This is very rude. Screen actively celebrates the break.
1166        * But it may be the only save way to issue long breaks.
1167        */
1168       debug("TIOCSBRK TIOCCBRK\n");
1169       if (ioctl(fd, TIOCSBRK, (char *)0) < 0)
1170         {
1171           Msg(errno, "Can't send BREAK (TIOCSBRK)");
1172           return;
1173         }
1174       sleep1000(n ? n * 250 : 250);
1175       if (ioctl(fd, TIOCCBRK, (char *)0) < 0)
1176         {
1177           Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)");
1178           return;
1179         }
1180 #else /* TIOCSBRK && TIOCCBRK */
1181       Msg(0, "TIOCSBRK/CBRK not available, change breaktype");
1182 #endif /* TIOCSBRK && TIOCCBRK */
1183       break;
1185     default:    /* unknown ========================== */
1186       Msg(0, "Internal SendBreak error: method %d unknown", type);
1187     }
1190 /* 
1191  * Send a break for n * 0.25 seconds. Tty must be PLAIN.
1192  * The longest possible break allowed here is 15 seconds.
1193  */
1195 void 
1196 SendBreak(wp, n, closeopen)
1197 struct win *wp;
1198 int n, closeopen;
1200   sigret_t (*sigalrm)__P(SIGPROTOARG);
1202 #ifdef BUILTIN_TELNET
1203   if (wp->w_type == W_TYPE_TELNET)
1204     {
1205       TelBreak(wp);
1206       return;
1207     }
1208 #endif
1209   if (wp->w_type != W_TYPE_PLAIN)
1210     return;
1212   debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd);
1214 #ifdef POSIX
1215   (void) tcflush(wp->w_ptyfd, TCIOFLUSH);
1216 #else
1217 # ifdef TIOCFLUSH
1218   (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0);
1219 # endif /* TIOCFLUSH */
1220 #endif /* POSIX */
1222   if (closeopen)
1223     {
1224       close(wp->w_ptyfd);
1225       sleep1000(n ? n * 250 : 250);
1226       if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1)
1227         {
1228           Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty);
1229           return;
1230         }
1231       (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK);
1232     }
1233   else
1234     {
1235       sigalrm = signal(SIGALRM, SigAlrmDummy);
1236       alarm(15);
1238       DoSendBreak(wp->w_ptyfd, n, breaktype);
1240       alarm(0);
1241       signal(SIGALRM, sigalrm);
1242     }
1243   debug("            broken.\n");
1247  *  Console grabbing
1248  */
1250 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
1252 static struct event consredir_ev;
1253 static int consredirfd[2] = {-1, -1};
1255 static void
1256 consredir_readev_fn(ev, data)
1257 struct event *ev;
1258 char *data;
1260   char *p, *n, buf[256];
1261   int l;
1263   if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0)
1264     {
1265       close(consredirfd[0]);
1266       close(consredirfd[1]);
1267       consredirfd[0] = consredirfd[1] = -1;
1268       evdeq(ev);
1269       return;
1270     }
1271   for (p = n = buf; l > 0; n++, l--)
1272     if (*n == '\n')
1273       {
1274         if (n > p)
1275           WriteString(console_window, p, n - p);
1276         WriteString(console_window, "\r\n", 2);
1277         p = n + 1;
1278       }
1279   if (n > p)
1280     WriteString(console_window, p, n - p);
1283 #endif
1285 /*ARGSUSED*/
1287 TtyGrabConsole(fd, on, rc_name)
1288 int fd, on;
1289 char *rc_name;
1291 #if defined(TIOCCONS) && !defined(linux)
1292   struct display *d;
1293   int ret = 0;
1294   int sfd = -1;
1296   if (on < 0)
1297     return 0;           /* pty close will ungrab */
1298   if (on)
1299     {
1300       if (displays == 0)
1301         {
1302           Msg(0, "I need a display");
1303           return -1;
1304         }
1305       for (d = displays; d; d = d->d_next)
1306         if (strcmp(d->d_usertty, "/dev/console") == 0)
1307           break;
1308       if (d)
1309         {
1310           Msg(0, "too dangerous - screen is running on /dev/console");
1311           return -1;
1312         }
1313     }
1315   if (!on)
1316     {
1317       char *slave;
1318       if ((fd = OpenPTY(&slave)) < 0)
1319         {
1320           Msg(errno, "%s: could not open detach pty master", rc_name);
1321           return -1;
1322         }
1323       if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0)
1324         {
1325           Msg(errno, "%s: could not open detach pty slave", rc_name);
1326           close(fd);
1327           return -1;
1328         }
1329     }
1330   if (UserContext() == 1)
1331     UserReturn(ioctl(fd, TIOCCONS, (char *)&on));
1332   ret = UserStatus();
1333   if (ret)
1334     Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1335   if (!on)
1336     {
1337       close(sfd);
1338       close(fd);
1339     }
1340   return ret;
1342 #else
1343 # if defined(SRIOCSREDIR) || defined(linux)
1344   struct display *d;
1345 #  ifdef SRIOCSREDIR
1346   int cfd;
1347 #  else
1348   struct mode new1, new2;
1349   char *slave;
1350 #  endif
1352   if (on > 0)
1353     {
1354       if (displays == 0)
1355         {
1356           Msg(0, "I need a display");
1357           return -1;
1358         }
1359       for (d = displays; d; d = d->d_next)
1360         if (strcmp(d->d_usertty, "/dev/console") == 0)
1361           break;
1362       if (d)
1363         {
1364           Msg(0, "too dangerous - screen is running on /dev/console");
1365           return -1;
1366         }
1367     }
1368   if (consredirfd[0] >= 0)
1369     {
1370       evdeq(&consredir_ev);
1371       close(consredirfd[0]);
1372       close(consredirfd[1]);
1373       consredirfd[0] = consredirfd[1] = -1;
1374     }
1375   if (on <= 0)
1376     return 0;
1377 #  ifdef SRIOCSREDIR
1378   if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1)
1379     {
1380       Msg(errno, "/dev/console");
1381       return -1;
1382     }
1383   if (pipe(consredirfd))
1384     {
1385       Msg(errno, "pipe");
1386       close(cfd);
1387       consredirfd[0] = consredirfd[1] = -1;
1388       return -1;
1389     }
1390   if (ioctl(cfd, SRIOCSREDIR, consredirfd[1]))
1391     {
1392       Msg(errno, "SRIOCSREDIR ioctl");
1393       close(cfd);
1394       close(consredirfd[0]);
1395       close(consredirfd[1]);
1396       consredirfd[0] = consredirfd[1] = -1;
1397       return -1;
1398     }
1399   close(cfd);
1400 #  else
1401   /* special linux workaround for a too restrictive kernel */
1402   if ((consredirfd[0] = OpenPTY(&slave)) < 0)
1403     {
1404       Msg(errno, "%s: could not open detach pty master", rc_name);
1405       return -1;
1406     }
1407   if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0)
1408     {
1409       Msg(errno, "%s: could not open detach pty slave", rc_name);
1410       close(consredirfd[0]);
1411       return -1;
1412     }
1413   InitTTY(&new1, 0);
1414   SetMode(&new1, &new2, 0, 0);
1415   SetTTY(consredirfd[1], &new2);
1416   if (UserContext() == 1)
1417     UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on));
1418   if (UserStatus())
1419     {
1420       Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1421       close(consredirfd[0]);
1422       close(consredirfd[1]);
1423       return -1;
1424     }
1425 #  endif
1426   consredir_ev.fd = consredirfd[0];
1427   consredir_ev.type = EV_READ;
1428   consredir_ev.handler = consredir_readev_fn;
1429   evenq(&consredir_ev);
1430   return 0;
1431 # else
1432   if (on > 0)
1433     Msg(0, "%s: don't know how to grab the console", rc_name);
1434   return -1;
1435 # endif
1436 #endif
1440  * Read modem control lines of a physical tty and write them to buf
1441  * in a readable format.
1442  * Will not write more than 256 characters to buf.
1443  * Returns buf;
1444  */
1445 char *
1446 TtyGetModemStatus(fd, buf)
1447 int fd;
1448 char *buf;
1450   char *p = buf;
1451 #ifdef TIOCGSOFTCAR
1452   unsigned int softcar;
1453 #endif
1454 #if defined(TIOCMGET) || defined(TIOCMODG)
1455   unsigned int mflags;
1456 #else
1457 # ifdef MCGETA
1458   /* this is yet another interface, found on hpux. grrr */
1459   mflag mflags;
1460 #if defined(MDTR)
1461 #  define TIOCM_DTR MDTR
1462 #endif /* MDTR */
1463 #if defined(MRTS)
1464 #  define TIOCM_RTS MRTS
1465 #endif /* MRTS */
1466 #if defined(MDSR)
1467 #  define TIOCM_DSR MDSR
1468 #endif /* MDSR */
1469 #if defined(MDCD)
1470 #  define TIOCM_CAR MDCD
1471 #endif /* MDCD */
1472 #if defined(MRI)
1473 #  define TIOCM_RNG MRI
1474 #endif /* MRI */
1475 #if defined(MCTS)
1476 #  define TIOCM_CTS MCTS
1477 #endif /* MCTS */
1478 # endif
1479 #endif
1480 #if defined(CLOCAL) || defined(CRTSCTS)
1481   struct mode mtio;     /* screen.h */
1482 #endif
1483 #if defined(CRTSCTS) || defined(TIOCM_CTS)
1484   int rtscts;
1485 #endif
1486   int clocal;
1488 #if defined(CLOCAL) || defined(CRTSCTS)
1489   GetTTY(fd, &mtio);
1490 #endif
1491   clocal = 0;
1492 #ifdef CLOCAL
1493   if (mtio.tio.c_cflag & CLOCAL)
1494     {
1495       clocal = 1;
1496       *p++ = '{';
1497     }
1498 #endif
1500 #ifdef TIOCM_CTS
1501 # ifdef CRTSCTS
1502   if (!(mtio.tio.c_cflag & CRTSCTS))
1503     rtscts = 0;
1504   else
1505 # endif /* CRTSCTS */
1506     rtscts = 1;
1507 #endif /* TIOCM_CTS */
1509 #ifdef TIOCGSOFTCAR
1510   if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0)
1511     softcar = 0;
1512 #endif
1514 #if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA)
1515 # ifdef TIOCMGET
1516   if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0)
1517 # else
1518 #  ifdef TIOCMODG
1519   if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0)
1520 #  else
1521   if (ioctl(fd, MCGETA, &mflags) < 0)
1522 #  endif
1523 # endif
1524     {
1525 #ifdef TIOCGSOFTCAR
1526       sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD");
1527 #else
1528       sprintf(p, "NO-TTY?");
1529 #endif
1530       p += strlen(p);
1531     }
1532   else
1533     {
1534       char *s;
1535 # ifdef FANCY_MODEM
1536 #  ifdef TIOCM_LE
1537       if (!(mflags & TIOCM_LE))
1538         for (s = "!LE "; *s; *p++ = *s++);
1539 #  endif
1540 # endif /* FANCY_MODEM */
1542 # ifdef TIOCM_RTS
1543       s = "!RTS "; if (mflags & TIOCM_RTS) s++;
1544       while (*s) *p++ = *s++;
1545 # endif
1546 # ifdef TIOCM_CTS
1547       s = "!CTS "; 
1548       if (!rtscts)
1549         {
1550           *p++ = '(';
1551           s = "!CTS) "; 
1552         }
1553       if (mflags & TIOCM_CTS) s++;
1554       while (*s) *p++ = *s++;
1555 # endif
1557 # ifdef TIOCM_DTR
1558       s = "!DTR "; if (mflags & TIOCM_DTR) s++;
1559       while (*s) *p++ = *s++;
1560 # endif
1561 # ifdef TIOCM_DSR
1562       s = "!DSR "; if (mflags & TIOCM_DSR) s++;
1563       while (*s) *p++ = *s++;
1564 # endif
1565 # if defined(TIOCM_CD) || defined(TIOCM_CAR)
1566       s = "!CD "; 
1567 #  ifdef TIOCGSOFTCAR
1568       if (softcar)
1569          {
1570           *p++ = '(';
1571           s = "!CD) ";
1572          }
1573 #  endif
1574 #  ifdef TIOCM_CD
1575       if (mflags & TIOCM_CD) s++;
1576 #  else
1577       if (mflags & TIOCM_CAR) s++;
1578 #  endif
1579       while (*s) *p++ = *s++;
1580 # endif
1581 # if defined(TIOCM_RI) || defined(TIOCM_RNG)
1582 #  ifdef TIOCM_RI
1583       if (mflags & TIOCM_RI)
1584 #  else
1585       if (mflags & TIOCM_RNG)
1586 #  endif
1587         for (s = "RI "; *s; *p++ = *s++);
1588 # endif
1589 # ifdef FANCY_MODEM
1590 #  ifdef TIOCM_ST
1591       s = "!ST "; if (mflags & TIOCM_ST) s++;
1592       while (*s) *p++ = *s++;
1593 #  endif
1594 #  ifdef TIOCM_SR
1595       s = "!SR "; if (mflags & TIOCM_SR) s++;
1596       while (*s) *p++ = *s++;
1597 #  endif
1598 # endif /* FANCY_MODEM */
1599       if (p > buf && p[-1] == ' ')
1600         p--;
1601       *p = '\0';
1602     }
1603 #else
1604 # ifdef TIOCGSOFTCAR
1605   sprintf(p, " %s", softcar ? "(CD)", "CD");
1606   p += strlen(p);
1607 # endif
1608 #endif
1609   if (clocal)
1610     *p++ = '}';
1611   *p = '\0';
1612   return buf;
1616  * Old bsd-ish machines may not have any of the baudrate B... symbols.
1617  * We hope to detect them here, so that the btable[] below always has
1618  * many entries.
1619  */
1620 #ifndef POSIX
1621 # ifndef TERMIO
1622 #  if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300)
1623 #if !defined(B0)
1624 #define         B0      0
1625 #endif /* B0 */
1626 #if !defined(B50)
1627 #define         B50     1
1628 #endif /* B50 */
1629 #if !defined(B75)
1630 #define         B75     2
1631 #endif /* B75 */
1632 #if !defined(B110)
1633 #define         B110    3
1634 #endif /* B110 */
1635 #if !defined(B134)
1636 #define         B134    4
1637 #endif /* B134 */
1638 #if !defined(B150)
1639 #define         B150    5
1640 #endif /* B150 */
1641 #if !defined(B200)
1642 #define         B200    6
1643 #endif /* B200 */
1644 #if !defined(B300)
1645 #define         B300    7
1646 #endif /* B300 */
1647 #if !defined(B600)
1648 #define         B600    8
1649 #endif /* B600 */
1650 #if !defined(B1200)
1651 #define B1200   9
1652 #endif /* B1200 */
1653 #if !defined(B1800)
1654 #define B1800   10
1655 #endif /* B1800 */
1656 #if !defined(B2400)
1657 #define B2400   11
1658 #endif /* B2400 */
1659 #if !defined(B4800)
1660 #define B4800   12
1661 #endif /* B4800 */
1662 #if !defined(B9600)
1663 #define B9600   13
1664 #endif /* B9600 */
1665 #if !defined(EXTA)
1666 #define EXTA    14
1667 #endif /* EXTA */
1668 #if !defined(EXTB)
1669 #define EXTB    15
1670 #endif /* EXTB */
1671 #  endif
1672 # endif
1673 #endif
1676  * On hpux, idx and sym will be different. 
1677  * Rumor has it that, we need idx in D_dospeed to make tputs
1678  * padding correct. 
1679  * Frequently used entries come first.
1680  */
1681 static struct baud_values btable[] =
1683 #if defined(B9600)
1684         {       13,     9600,   B9600   },
1685 #endif /* B9600 */
1686 #if defined(B19200)
1687         {       14,     19200,  B19200  },
1688 #endif /* B19200 */
1689 #if defined(EXTA)
1690         {       14,     19200,  EXTA    },
1691 #endif /* EXTA */
1692 #if defined(B38400)
1693         {       15,     38400,  B38400  },
1694 #endif /* B38400 */
1695 #if defined(EXTB)
1696         {       15,     38400,  EXTB    },
1697 #endif /* EXTB */
1698 #if defined(B57600)
1699         {       16,     57600,  B57600  },
1700 #endif /* B57600 */
1701 #if defined(B115200)
1702         {       17,     115200, B115200 },
1703 #endif /* B115200 */
1704 #if defined(B230400)
1705         {       18,     230400, B230400 },
1706 #endif /* B230400 */
1707 #if defined(B460800)
1708         {       19,     460800, B460800 },
1709 #endif /* B460800 */
1710 #if defined(B7200)
1711         {       13,     7200,   B7200   },
1712 #endif /* B7200 */
1713 #if defined(B4800)
1714         {       12,     4800,   B4800   },
1715 #endif /* B4800 */
1716 #if defined(B3600)
1717         {       12,     3600,   B3600   },
1718 #endif /* B3600 */
1719 #if defined(B2400)
1720         {       11,     2400,   B2400   },
1721 #endif /* B2400 */
1722 #if defined(B1800)
1723         {       10,     1800,   B1800   },
1724 #endif /* B1800 */
1725 #if defined(B1200)
1726         {       9,      1200,   B1200   },
1727 #endif /* B1200 */
1728 #if defined(B900)
1729         {       9,      900,    B900    },
1730 #endif /* B900 */
1731 #if defined(B600)
1732         {       8,      600,    B600    },
1733 #endif /* B600 */
1734 #if defined(B300)
1735         {       7,      300,    B300    },
1736 #endif /* B300 */
1737 #if defined(B200)
1738         {       6,      200,    B200    },
1739 #endif /* B200 */
1740 #if defined(B150)
1741         {       5,      150,    B150    },
1742 #endif /* B150 */
1743 #if defined(B134)
1744         {       4,      134,    B134    },
1745 #endif /* B134 */
1746 #if defined(B110)
1747         {       3,      110,    B110    },
1748 #endif /* B110 */
1749 #if defined(B75)
1750         {       2,      75,     B75     },
1751 #endif /* B75 */
1752 #if defined(B50)
1753         {       1,      50,     B50     },
1754 #endif /* B50 */
1755 #if defined(B0)
1756         {       0,      0,      B0      },
1757 #endif /* B0 */
1758                 {       -1,     -1,     -1      }
1762  * baud may either be a bits-per-second value or a symbolic
1763  * value as returned by cfget?speed() 
1764  */
1765 struct baud_values *
1766 lookup_baud(baud)
1767 int baud;
1769   struct baud_values *p;
1771   for (p = btable; p->idx >= 0; p++)
1772     if (baud == p->bps || baud == p->sym)
1773       return p;
1774   return NULL;
1778  * change the baud rate in a mode structure.
1779  * ibaud and obaud are given in bit/second, or at your option as
1780  * termio B... symbols as defined in e.g. suns sys/ttydev.h
1781  * -1 means don't change.
1782  */
1784 SetBaud(m, ibaud, obaud)
1785 struct mode *m;
1786 int ibaud, obaud;
1788   struct baud_values *ip, *op;
1790   if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) ||
1791       (!(op = lookup_baud(obaud)) && obaud != -1))
1792     return -1;
1794 #ifdef POSIX
1795   if (ip) cfsetispeed(&m->tio, ip->sym);
1796   if (op) cfsetospeed(&m->tio, op->sym);
1797 #else /* POSIX */
1798 # ifdef TERMIO
1799   if (ip)
1800     {
1801 #  ifdef IBSHIFT
1802       m->tio.c_cflag &= ~(CBAUD << IBSHIFT);
1803       m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT;
1804 #  else /* IBSHIFT */
1805       if (ibaud != obaud)
1806         return -1;
1807 #  endif /* IBSHIFT */
1808     }
1809   if (op)
1810     {
1811       m->tio.c_cflag &= ~CBAUD;
1812       m->tio.c_cflag |= op->sym & CBAUD;
1813     }
1814 # else /* TERMIO */
1815   if (ip) m->m_ttyb.sg_ispeed = ip->idx;
1816   if (op) m->m_ttyb.sg_ospeed = op->idx;
1817 # endif /* TERMIO */
1818 #endif /* POSIX */
1819   return 0;
1823  *  Write out the mode struct in a readable form
1824  */
1826 #ifdef DEBUG
1827 void
1828 DebugTTY(m)
1829 struct mode *m;
1831   int i;
1833 #ifdef POSIX
1834   debug("struct termios tio:\n");
1835   debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag);
1836   debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag);
1837   debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag);
1838   debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag);
1839   debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio));
1840   debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio));
1841   for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1842     {
1843       debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]);
1844     }
1845 # ifdef HPUX_LTCHARS_HACK
1846   debug1("suspc     = %#02x\n", m->m_ltchars.t_suspc);
1847   debug1("dsuspc    = %#02x\n", m->m_ltchars.t_dsuspc);
1848   debug1("rprntc    = %#02x\n", m->m_ltchars.t_rprntc);
1849   debug1("flushc    = %#02x\n", m->m_ltchars.t_flushc);
1850   debug1("werasc    = %#02x\n", m->m_ltchars.t_werasc);
1851   debug1("lnextc    = %#02x\n", m->m_ltchars.t_lnextc);
1852 # endif /* HPUX_LTCHARS_HACK */
1853 #else /* POSIX */
1854 # ifdef TERMIO
1855   debug("struct termio tio:\n");
1856   debug1("c_iflag = %04o\n", m->tio.c_iflag);
1857   debug1("c_oflag = %04o\n", m->tio.c_oflag);
1858   debug1("c_cflag = %04o\n", m->tio.c_cflag);
1859   debug1("c_lflag = %04o\n", m->tio.c_lflag);
1860   for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1861     {
1862       debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]);
1863     }
1864 # else /* TERMIO */
1865   debug1("sg_ispeed = %d\n",    m->m_ttyb.sg_ispeed);
1866   debug1("sg_ospeed = %d\n",    m->m_ttyb.sg_ospeed);
1867   debug1("sg_erase  = %#02x\n", m->m_ttyb.sg_erase);
1868   debug1("sg_kill   = %#02x\n", m->m_ttyb.sg_kill);
1869   debug1("sg_flags  = %#04x\n", (unsigned short)m->m_ttyb.sg_flags);
1870   debug1("intrc     = %#02x\n", m->m_tchars.t_intrc);
1871   debug1("quitc     = %#02x\n", m->m_tchars.t_quitc);
1872   debug1("startc    = %#02x\n", m->m_tchars.t_startc);
1873   debug1("stopc     = %#02x\n", m->m_tchars.t_stopc);
1874   debug1("eofc      = %#02x\n", m->m_tchars.t_eofc);
1875   debug1("brkc      = %#02x\n", m->m_tchars.t_brkc);
1876   debug1("suspc     = %#02x\n", m->m_ltchars.t_suspc);
1877   debug1("dsuspc    = %#02x\n", m->m_ltchars.t_dsuspc);
1878   debug1("rprntc    = %#02x\n", m->m_ltchars.t_rprntc);
1879   debug1("flushc    = %#02x\n", m->m_ltchars.t_flushc);
1880   debug1("werasc    = %#02x\n", m->m_ltchars.t_werasc);
1881   debug1("lnextc    = %#02x\n", m->m_ltchars.t_lnextc);
1882   debug1("ldisc     = %d\n",    m->m_ldisc);
1883   debug1("lmode     = %#x\n",   m->m_lmode);
1884 # endif /* TERMIO */
1885 #endif /* POSIX */
1887 #endif /* DEBUG */