home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / screen-3.5 / part04 / tty.c.dist < prev    next >
Encoding:
Text File  |  1993-07-25  |  20.9 KB  |  914 lines

  1. /* Copyright (c) 1993
  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., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. /*
  24.  * NOTICE: tty.c is automatically generated from tty.sh
  25.  * Do not change anything here. If you then change tty.sh.
  26.  */
  27.  
  28. #include "rcs.h"
  29. RCS_ID("$Id: tty.sh,v 1.2 1993/06/17 17:32:23 mlschroe Exp $ FAU")
  30.  
  31. #include <stdio.h>
  32. #include <sys/types.h>
  33. #include <signal.h>
  34. #include <fcntl.h>
  35. #ifndef sun
  36. # include <sys/ioctl.h> /* collosions with termios.h */
  37. #else
  38. # include <sys/ttold.h>    /* needed for TIOCEXCL */
  39. #endif
  40.  
  41. #ifdef ISC
  42. # include <sys/tty.h>
  43. # include <sys/sioctl.h>
  44. # include <sys/pty.h>
  45. #endif
  46.  
  47. #include "config.h"
  48. #include "screen.h"
  49. #include "extern.h"
  50.  
  51. extern struct display *display, *displays;
  52. extern int iflag;
  53.  
  54.  
  55. /*
  56.  *  Carefully open a charcter device. Not used to open ttys.
  57.  */
  58.  
  59. int
  60. OpenTTY(line)
  61. char *line;
  62. {
  63.   int f;
  64.   sig_t (*sigalrm)__P(SIGPROTOARG);
  65.  
  66.   sigalrm = signal(SIGALRM, SIG_IGN);
  67.   alarm(2);
  68.   /* this open only succeeds, if real uid is allowed */
  69.   if ((f = secopen(line, O_RDWR | O_NDELAY, 0)) == -1)
  70.     {
  71.       Msg(errno, "Cannot open line '%s' for R/W", line);
  72.       alarm(0);
  73.       signal(SIGALRM, sigalrm);
  74.       return -1;
  75.     }
  76. #ifdef I_POP
  77.   debug("OpenTTY I_POP\n");
  78.   while (ioctl(f, I_POP) >= 0)
  79.     ;
  80. #endif
  81.   /*
  82.    * We come here exclusively. This is to stop all kermit and cu type things
  83.    * accessing the same tty line.
  84.    * Perhaps we should better create a lock in some /usr/spool/locks directory?
  85.    */
  86. #ifdef TIOCEXCL
  87.  errno = 0;
  88.  ioctl(f, TIOCEXCL, (char *) 0);
  89.  debug3("%d %d %d\n", getuid(), geteuid(), getpid());
  90.  debug2("%s TIOCEXCL errno %d\n", line, errno);
  91. #endif  /* TIOCEXCL */
  92.   /*
  93.    * We create a sane tty mode. We do not copy things from the display tty
  94.    */
  95. #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE
  96.   if (display)
  97.     {
  98.       debug1("OpenTTY: using mode of display for %s\n", line);
  99.       SetTTY(f, &d_NewMode);
  100. #ifdef DEBUG
  101.       DebugTTY(&d_NewMode);
  102. #endif
  103.     }
  104.   else
  105. #endif 
  106.     {
  107.       struct mode Mode;
  108.  
  109.       InitTTY(&Mode, TTY_FLAG_PLAIN);
  110. #ifdef DEBUG
  111.       DebugTTY(&Mode);
  112. #endif
  113.       SetTTY(f, &Mode);
  114.     }
  115.   brktty(f);
  116.   alarm(0);
  117.   signal(SIGALRM, sigalrm);
  118.   debug2("'%s' CONNECT fd=%d.\n", line, f);
  119.   return f;
  120. }
  121.  
  122.  
  123. /*
  124.  *  Tty mode handling
  125.  */
  126.  
  127. #if defined(TERMIO) || defined(POSIX)
  128. int intrc, origintrc = VDISABLE;        /* display? */
  129. #else
  130. int intrc, origintrc = -1;        /* display? */
  131. #endif
  132. static startc, stopc;                   /* display? */
  133.  
  134.  
  135. void
  136. InitTTY(m, ttyflag)
  137. struct mode *m;
  138. int ttyflag;
  139. {
  140.   bzero((char *)m, sizeof(*m));
  141. #ifdef POSIX
  142.   /* struct termios tio 
  143.    * defaults, as seen on SunOS 4.1.3
  144.    */
  145.   debug1("InitTTY: POSIX: termios defaults a la SunOS 4.1.3 (%d)\n", ttyflag);
  146. #if defined(BRKINT)
  147.       m->tio.c_iflag |= BRKINT;
  148. #endif /* BRKINT */
  149. #if defined(IGNPAR)
  150.       m->tio.c_iflag |= IGNPAR;
  151. #endif /* IGNPAR */
  152. #if defined(ISTRIP)
  153.       m->tio.c_iflag |= ISTRIP;
  154. #endif /* ISTRIP */
  155. #if defined(IXON)
  156.       m->tio.c_iflag |= IXON;
  157. #endif /* IXON */
  158. #if defined(IMAXBEL)
  159.       m->tio.c_iflag |= IMAXBEL; 
  160. #endif /* IMAXBEL */
  161.  
  162.   if (!ttyflag)    /* may not even be good for ptys.. */
  163.     {
  164. #if defined(ICRNL)
  165.       m->tio.c_iflag |= ICRNL;
  166. #endif /* ICRNL */
  167. #if defined(ONLCR)
  168.       m->tio.c_oflag |= ONLCR; 
  169. #endif /* ONLCR */
  170. #if defined(TAB3)
  171.       m->tio.c_oflag |= TAB3; 
  172. #endif /* TAB3 */
  173. #if defined(PARENB)
  174.       m->tio.c_cflag |= PARENB;
  175. #endif /* PARENB */
  176.     }
  177.  
  178. #if defined(OPOST)
  179.       m->tio.c_oflag |= OPOST;
  180. #endif /* OPOST */
  181.  
  182. #if defined(B9600)
  183.       m->tio.c_cflag |= B9600;
  184. #endif /* B9600 */
  185. #if defined(CS8)
  186.        m->tio.c_cflag |= CS8;
  187. #endif /* CS8 */
  188. #if defined(CREAD)
  189.       m->tio.c_cflag |= CREAD;
  190. #endif /* CREAD */
  191. #if defined(IBSHIFT) && defined(B9600)
  192.       m->tio.c_cflag |= B9600 << IBSHIFT;
  193. #endif /* IBSHIFT) && defined(B9600 */
  194. /* IF{CLOCAL}    m->tio.c_cflag |= CLOCAL; */
  195.  
  196. #if defined(ECHOCTL)
  197.       m->tio.c_lflag |= ECHOCTL;
  198. #endif /* ECHOCTL */
  199. #if defined(ECHOKE)
  200.       m->tio.c_lflag |= ECHOKE;
  201. #endif /* ECHOKE */
  202.  
  203.   if (!ttyflag)
  204.     {
  205. #if defined(ISIG)
  206.       m->tio.c_lflag |= ISIG;
  207. #endif /* ISIG */
  208. #if defined(ICANON)
  209.       m->tio.c_lflag |= ICANON;
  210. #endif /* ICANON */
  211. #if defined(ECHO)
  212.       m->tio.c_lflag |= ECHO;
  213. #endif /* ECHO */
  214.     }
  215. #if defined(ECHOE)
  216.       m->tio.c_lflag |= ECHOE;
  217. #endif /* ECHOE */
  218. #if defined(ECHOK)
  219.       m->tio.c_lflag |= ECHOK;
  220. #endif /* ECHOK */
  221. #if defined(IEXTEN)
  222.       m->tio.c_lflag |= IEXTEN;
  223. #endif /* IEXTEN */
  224.  
  225. #if defined(VINTR)
  226.       m->tio.c_cc[VINTR]    = Ctrl('C');
  227. #endif /* VINTR */
  228. #if defined(VQUIT)
  229.       m->tio.c_cc[VQUIT]    = Ctrl('\\');
  230. #endif /* VQUIT */
  231. #if defined(VERASE)
  232.       m->tio.c_cc[VERASE]   = 0x7f; /* DEL */
  233. #endif /* VERASE */
  234. #if defined(VKILL)
  235.       m->tio.c_cc[VKILL]    = Ctrl('H');
  236. #endif /* VKILL */
  237. #if defined(VEOF)
  238.       m->tio.c_cc[VEOF]     = Ctrl('D');
  239. #endif /* VEOF */
  240. #if defined(VEOL)
  241.       m->tio.c_cc[VEOL]     = 0000;
  242. #endif /* VEOL */
  243. #if defined(VEOL2)
  244.       m->tio.c_cc[VEOL2]    = 0000;
  245. #endif /* VEOL2 */
  246. #if defined(VSWTCH)
  247.       m->tio.c_cc[VSWTCH]   = 0000;
  248. #endif /* VSWTCH */
  249. #if defined(VSTART)
  250.       m->tio.c_cc[VSTART]   = Ctrl('Q');
  251. #endif /* VSTART */
  252. #if defined(VSTOP)
  253.       m->tio.c_cc[VSTOP]    = Ctrl('S');
  254. #endif /* VSTOP */
  255. #if defined(VSUSP)
  256.       m->tio.c_cc[VSUSP]    = Ctrl('Z');
  257. #endif /* VSUSP */
  258. #if defined(VDSUSP)
  259.       m->tio.c_cc[VDSUSP]   = Ctrl('Y');
  260. #endif /* VDSUSP */
  261. #if defined(VREPRINT)
  262.       m->tio.c_cc[VREPRINT] = Ctrl('R');
  263. #endif /* VREPRINT */
  264. #if defined(VDISCARD)
  265.       m->tio.c_cc[VDISCARD] = Ctrl('O');
  266. #endif /* VDISCARD */
  267. #if defined(VWERASE)
  268.       m->tio.c_cc[VWERASE]  = Ctrl('W');
  269. #endif /* VWERASE */
  270. #if defined(VLNEXT)
  271.       m->tio.c_cc[VLNEXT]   = Ctrl('V');
  272. #endif /* VLNEXT */
  273. #if defined(VSTATUS)
  274.       m->tio.c_cc[VSTATUS]  = Ctrl('T');
  275. #endif /* VSTATUS */
  276.  
  277. # ifdef hpux
  278.   m->m_ltchars.t_suspc =  Ctrl('Z');
  279.   m->m_ltchars.t_dsuspc = Ctrl('Y');
  280.   m->m_ltchars.t_rprntc = Ctrl('R');
  281.   m->m_ltchars.t_flushc = Ctrl('O');
  282.   m->m_ltchars.t_werasc = Ctrl('W');
  283.   m->m_ltchars.t_lnextc = Ctrl('V');
  284. # endif /* hpux */
  285.  
  286. #else /* POSIX */
  287.  
  288. # ifdef TERMIO
  289.   debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag);
  290.   /* struct termio tio 
  291.    * defaults, as seen on Mototola SYSV68:
  292.    * input: 7bit, CR->NL, ^S/^Q flow control 
  293.    * output: POSTprocessing: NL->NL-CR, Tabs to spaces
  294.    * control: 9600baud, 8bit CSIZE, enable input
  295.    * local: enable signals, erase/kill processing, echo on.
  296.    */
  297. #if defined(ISTRIP)
  298.       m->tio.c_iflag |= ISTRIP;
  299. #endif /* ISTRIP */
  300. #if defined(IXON)
  301.       m->tio.c_iflag |= IXON;
  302. #endif /* IXON */
  303.  
  304. #if defined(OPOST)
  305.       m->tio.c_oflag |= OPOST;
  306. #endif /* OPOST */
  307.  
  308.   if (!ttyflag)    /* may not even be good for ptys.. */
  309.     {
  310. #if defined(ICRNL)
  311.       m->tio.c_iflag |= ICRNL;
  312. #endif /* ICRNL */
  313. #if defined(ONLCR)
  314.       m->tio.c_oflag |= ONLCR;
  315. #endif /* ONLCR */
  316. #if defined(TAB3)
  317.       m->tio.c_oflag |= TAB3;
  318. #endif /* TAB3 */
  319.     }
  320.  
  321. #if defined(B9600)
  322.       m->tio.c_cflag  = B9600;
  323. #endif /* B9600 */
  324. #if defined(CS8)
  325.        m->tio.c_cflag |= CS8;
  326. #endif /* CS8 */
  327. #if defined(CREAD)
  328.       m->tio.c_cflag |= CREAD;
  329. #endif /* CREAD */
  330.  
  331.   if (!ttyflag)
  332.     {
  333. #if defined(ISIG)
  334.       m->tio.c_lflag |= ISIG;
  335. #endif /* ISIG */
  336. #if defined(ICANON)
  337.       m->tio.c_lflag |= ICANON;
  338. #endif /* ICANON */
  339. #if defined(ECHO)
  340.       m->tio.c_lflag |= ECHO;
  341. #endif /* ECHO */
  342.     }
  343. #if defined(ECHOE)
  344.       m->tio.c_lflag |= ECHOE;
  345. #endif /* ECHOE */
  346. #if defined(ECHOK)
  347.       m->tio.c_lflag |= ECHOK;
  348. #endif /* ECHOK */
  349.  
  350. #if defined(VINTR)
  351.       m->tio.c_cc[VINTR]  = Ctrl('C');
  352. #endif /* VINTR */
  353. #if defined(VQUIT)
  354.       m->tio.c_cc[VQUIT]  = Ctrl('\\');
  355. #endif /* VQUIT */
  356. #if defined(VERASE)
  357.       m->tio.c_cc[VERASE] = 0177; /* DEL */
  358. #endif /* VERASE */
  359. #if defined(VKILL)
  360.       m->tio.c_cc[VKILL]  = Ctrl('H');
  361. #endif /* VKILL */
  362. #if defined(VEOF)
  363.       m->tio.c_cc[VEOF]   = Ctrl('D');
  364. #endif /* VEOF */
  365. #if defined(VEOL)
  366.       m->tio.c_cc[VEOL]   = 0377;
  367. #endif /* VEOL */
  368. #if defined(VEOL2)
  369.       m->tio.c_cc[VEOL2]  = 0377;
  370. #endif /* VEOL2 */
  371. #if defined(VSWTCH)
  372.       m->tio.c_cc[VSWTCH] = 0000;
  373. #endif /* VSWTCH */
  374. # else /* TERMIO */
  375.   debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag);
  376.   m->m_ttyb.sg_ispeed = B9600;
  377.   m->m_ttyb.sg_ospeed = B9600;
  378.   m->m_ttyb.sg_erase  = 0177; /*DEL */
  379.   m->m_ttyb.sg_kill   = Ctrl('H');
  380.   if (!ttyflag)
  381.     m->m_ttyb.sg_flags = CRMOD | ECHO
  382. #if defined(ANYP)
  383.       | ANYP
  384. #endif /* ANYP */
  385.     ;
  386.   else
  387.     m->m_ttyb.sg_flags = CBREAK
  388. #if defined(ANYP)
  389.       | ANYP
  390. #endif /* ANYP */
  391.     ;
  392.  
  393.   m->m_tchars.t_intrc   = Ctrl('C');
  394.   m->m_tchars.t_quitc   = Ctrl('\\');
  395.   m->m_tchars.t_startc  = Ctrl('Q');
  396.   m->m_tchars.t_stopc   = Ctrl('S');
  397.   m->m_tchars.t_eofc    = Ctrl('D');
  398.   m->m_tchars.t_brkc    = -1;
  399.  
  400.   m->m_ltchars.t_suspc  = Ctrl('Z');
  401.   m->m_ltchars.t_dsuspc = Ctrl('Y');
  402.   m->m_ltchars.t_rprntc = Ctrl('R');
  403.   m->m_ltchars.t_flushc = Ctrl('O');
  404.   m->m_ltchars.t_werasc = Ctrl('W');
  405.   m->m_ltchars.t_lnextc = Ctrl('V');
  406.  
  407. #if defined(NTTYDISC)
  408.       m->m_ldisc = NTTYDISC;
  409. #endif /* NTTYDISC */
  410.  
  411.   m->m_lmode = 0
  412. #if defined(LDECCTQ)
  413.       | LDECCTQ
  414. #endif /* LDECCTQ */
  415. #if defined(LCTLECH)
  416.       | LCTLECH
  417. #endif /* LCTLECH */
  418. #if defined(LPASS8)
  419.       | LPASS8
  420. #endif /* LPASS8 */
  421. #if defined(LCRTKIL)
  422.       | LCRTKIL
  423. #endif /* LCRTKIL */
  424. #if defined(LCRTERA)
  425.       | LCRTERA
  426. #endif /* LCRTERA */
  427. #if defined(LCRTBS)
  428.       | LCRTBS
  429. #endif /* LCRTBS */
  430. ;
  431. # endif /* TERMIO */
  432. #endif /* POSIX */
  433. }
  434.  
  435. void 
  436. SetTTY(fd, mp)
  437. int fd;
  438. struct mode *mp;
  439. {
  440.   errno = 0;
  441. #ifdef POSIX
  442.   tcsetattr(fd, TCSADRAIN, &mp->tio);
  443. # ifdef hpux
  444.   ioctl(fd, TIOCSLTC, &mp->m_ltchars);
  445. # endif
  446. #else
  447. # ifdef TERMIO
  448.   ioctl(fd, TCSETAW, &mp->tio);
  449. # else
  450.   /* ioctl(fd, TIOCSETP, &mp->m_ttyb); */
  451.   ioctl(fd, TIOCSETC, &mp->m_tchars);
  452.   ioctl(fd, TIOCLSET, &mp->m_lmode);
  453.   ioctl(fd, TIOCSETD, &mp->m_ldisc);
  454.   ioctl(fd, TIOCSETP, &mp->m_ttyb);
  455.   ioctl(fd, TIOCSLTC, &mp->m_ltchars); /* moved here for apollo. jw */
  456. # endif
  457. #endif
  458.   if (errno)
  459.     Msg(errno, "SetTTY (fd %d): ioctl failed", fd);
  460. }
  461.  
  462. void
  463. GetTTY(fd, mp)
  464. int fd;
  465. struct mode *mp;
  466. {
  467.   errno = 0;
  468. #ifdef POSIX
  469.   tcgetattr(fd, &mp->tio);
  470. # ifdef hpux
  471.   ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  472. # endif
  473. #else
  474. # ifdef TERMIO
  475.   ioctl(fd, TCGETA, &mp->tio);
  476. # else
  477.   ioctl(fd, TIOCGETP, &mp->m_ttyb);
  478.   ioctl(fd, TIOCGETC, &mp->m_tchars);
  479.   ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  480.   ioctl(fd, TIOCLGET, &mp->m_lmode);
  481.   ioctl(fd, TIOCGETD, &mp->m_ldisc);
  482. # endif
  483. #endif
  484.   if (errno)
  485.     Msg(errno, "GetTTY (fd %d): ioctl failed", fd);
  486. }
  487.  
  488. void
  489. SetMode(op, np)
  490. struct mode *op, *np;
  491. {
  492.   *np = *op;
  493.  
  494. #if defined(TERMIO) || defined(POSIX)
  495.   np->tio.c_iflag &= ~ICRNL;
  496. # ifdef ONLCR
  497.   np->tio.c_oflag &= ~ONLCR;
  498. # endif
  499.   np->tio.c_lflag &= ~(ICANON | ECHO);
  500.  
  501.   /*
  502.    * Unfortunately, the master process never will get SIGINT if the real
  503.    * terminal is different from the one on which it was originaly started
  504.    * (process group membership has not been restored or the new tty could not
  505.    * be made controlling again). In my solution, it is the attacher who
  506.    * receives SIGINT (because it is always correctly associated with the real
  507.    * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. 
  508.    * Marc Boucher (marc@CAM.ORG)
  509.    */
  510.   if (iflag)
  511.     np->tio.c_lflag |= ISIG;
  512.   else
  513.     np->tio.c_lflag &= ~ISIG;
  514.   /* 
  515.    * careful, careful catche monkey..
  516.    * never set VMIN and VTIME to zero, if you want blocking io.
  517.    */
  518.   np->tio.c_cc[VMIN] = 1;
  519.   np->tio.c_cc[VTIME] = 0;
  520. #if defined(VSTART)
  521.       startc = op->tio.c_cc[VSTART];
  522. #endif /* VSTART */
  523. #if defined(VSTOP)
  524.       stopc = op->tio.c_cc[VSTOP];
  525. #endif /* VSTOP */
  526.   if (iflag)
  527.     origintrc = intrc = op->tio.c_cc[VINTR];
  528.   else
  529.     {
  530.       origintrc = op->tio.c_cc[VINTR];
  531.       intrc = np->tio.c_cc[VINTR] = VDISABLE;
  532.     }
  533.   np->tio.c_cc[VQUIT] = VDISABLE;
  534.   if (d_flow == 0)
  535.     {
  536.       np->tio.c_cc[VINTR] = VDISABLE;
  537. #if defined(VSTART)
  538.       np->tio.c_cc[VSTART] = VDISABLE;
  539. #endif /* VSTART */
  540. #if defined(VSTOP)
  541.       np->tio.c_cc[VSTOP] = VDISABLE;
  542. #endif /* VSTOP */
  543.       np->tio.c_iflag &= ~IXON;
  544.     }
  545. #if defined(VDISCARD)
  546.       np->tio.c_cc[VDISCARD] = VDISABLE;
  547. #endif /* VDISCARD */
  548. #if defined(VSUSP)
  549.       np->tio.c_cc[VSUSP] = VDISABLE;
  550. #endif /* VSUSP */
  551. # ifdef hpux
  552.   np->m_ltchars.t_suspc  = VDISABLE;
  553.   np->m_ltchars.t_dsuspc = VDISABLE;
  554.   np->m_ltchars.t_rprntc = VDISABLE;
  555.   np->m_ltchars.t_flushc = VDISABLE;
  556.   np->m_ltchars.t_werasc = VDISABLE;
  557.   np->m_ltchars.t_lnextc = VDISABLE;
  558. # else /* hpux */
  559. #if defined(VDSUSP)
  560.       np->tio.c_cc[VDSUSP] = VDISABLE;
  561. #endif /* VDSUSP */
  562. # endif /* hpux */
  563. #else /* TERMIO || POSIX */
  564.   startc = op->m_tchars.t_startc;
  565.   stopc = op->m_tchars.t_stopc;
  566.   if (iflag)
  567.     origintrc = intrc = op->m_tchars.t_intrc;
  568.   else
  569.     {
  570.       origintrc = op->m_tchars.t_intrc;
  571.       intrc = np->m_tchars.t_intrc = -1;
  572.     }
  573.   np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
  574.   np->m_ttyb.sg_flags |= CBREAK;
  575.   np->m_tchars.t_quitc = -1;
  576.   if (d_flow == 0)
  577.     {
  578.       np->m_tchars.t_intrc = -1;
  579.       np->m_tchars.t_startc = -1;
  580.       np->m_tchars.t_stopc = -1;
  581.     }
  582.   np->m_ltchars.t_suspc = -1;
  583.   np->m_ltchars.t_dsuspc = -1;
  584.   np->m_ltchars.t_flushc = -1;
  585.   np->m_ltchars.t_lnextc = -1;
  586. #endif /* defined(TERMIO) || defined(POSIX) */
  587. }
  588.  
  589. void
  590. SetFlow(on)
  591. int on;
  592. {
  593.   ASSERT(display);
  594.   if (d_flow == on)
  595.     return;
  596. #if defined(TERMIO) || defined(POSIX)
  597.   if (on)
  598.     {
  599.       d_NewMode.tio.c_cc[VINTR] = intrc;
  600. #if defined(VSTART)
  601.       d_NewMode.tio.c_cc[VSTART] = startc;
  602. #endif /* VSTART */
  603. #if defined(VSTOP)
  604.       d_NewMode.tio.c_cc[VSTOP] = stopc;
  605. #endif /* VSTOP */
  606.       d_NewMode.tio.c_iflag |= IXON;
  607.     }
  608.   else
  609.     {
  610.       d_NewMode.tio.c_cc[VINTR] = VDISABLE;
  611. #if defined(VSTART)
  612.       d_NewMode.tio.c_cc[VSTART] = VDISABLE;
  613. #endif /* VSTART */
  614. #if defined(VSTOP)
  615.       d_NewMode.tio.c_cc[VSTOP] = VDISABLE;
  616. #endif /* VSTOP */
  617.       d_NewMode.tio.c_iflag &= ~IXON;
  618.     }
  619. # ifdef POSIX
  620.   if (tcsetattr(d_userfd, TCSANOW, &d_NewMode.tio))
  621. # else
  622.   if (ioctl(d_userfd, TCSETAW, &d_NewMode.tio) != 0)
  623. # endif
  624.     debug1("SetFlow: ioctl errno %d\n", errno);
  625. #else /* POSIX || TERMIO */
  626.   if (on)
  627.     {
  628.       d_NewMode.m_tchars.t_intrc = intrc;
  629.       d_NewMode.m_tchars.t_startc = startc;
  630.       d_NewMode.m_tchars.t_stopc = stopc;
  631.     }
  632.   else
  633.     {
  634.       d_NewMode.m_tchars.t_intrc = -1;
  635.       d_NewMode.m_tchars.t_startc = -1;
  636.       d_NewMode.m_tchars.t_stopc = -1;
  637.     }
  638.   if (ioctl(d_userfd, TIOCSETC, &d_NewMode.m_tchars) != 0)
  639.     debug1("SetFlow: ioctl errno %d\n", errno);
  640. #endif /* POSIX || TERMIO */
  641.   d_flow = on;
  642. }
  643.  
  644.  
  645. /*
  646.  *  Job control handling
  647.  */
  648.  
  649. /*ARGSUSED*/
  650. void
  651. brktty(fd)
  652. int fd;
  653. {
  654. #ifdef POSIX
  655.   setsid();        /* will break terminal affiliation */
  656. # ifdef BSD
  657.   ioctl(fd, TIOCSCTTY, 0);
  658. # endif /* BSD */
  659. #else /* POSIX */
  660. # ifdef SYSV
  661.   setpgrp();        /* will break terminal affiliation */
  662. # else /* SYSV */
  663. #  ifdef BSDJOBS
  664.   int devtty;
  665.  
  666.   if ((devtty = open("/dev/tty", O_RDWR | O_NDELAY)) >= 0)
  667.     {
  668.       if (ioctl(devtty, TIOCNOTTY, (char *)0))
  669.         debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno);
  670.       close(devtty);
  671.     }
  672. #  endif /* BSDJOBS */
  673. # endif /* SYSV */
  674. #endif /* POSIX */
  675. }
  676.  
  677. int
  678. fgtty(fd)
  679. int fd;
  680. {
  681. #ifdef BSDJOBS
  682.   int mypid;
  683.  
  684.   mypid = getpid();
  685.  
  686. # if defined(BSDI) || defined(__386BSD__) || defined(__osf__)
  687.   setsid();    /* should be already done */
  688.   ioctl(fd, TIOCSCTTY, 0);
  689. # endif /* BSDI || __386BSD__ */
  690.  
  691. # ifdef POSIX
  692.   if (tcsetpgrp(fd, mypid))
  693.     {
  694.       debug1("fgtty: tcsetpgrp: %d\n", errno);
  695.       return -1;
  696.     }
  697. # else /* POSIX */
  698.   if (ioctl(fd, TIOCSPGRP, &mypid) != 0)
  699.     debug1("fgtty: TIOSETPGRP: %d\n", errno);
  700. #  ifndef SYSV    /* Already done in brktty():setpgrp() */
  701.   if (setpgrp(fd, mypid))
  702.     debug1("fgtty: setpgrp: %d\n", errno);
  703. #  endif
  704. # endif /* POSIX */
  705. #endif /* BSDJOBS */
  706.   return 0;
  707. }
  708.  
  709.  
  710. /* 
  711.  * Send a break for n * 0.25 seconds. Tty must be PLAIN.
  712.  */
  713.  
  714. void SendBreak(wp, n, closeopen)
  715. struct win *wp;
  716. int n, closeopen;
  717. {
  718.   if ((wp->w_t.flags & TTY_FLAG_PLAIN) == 0)
  719.     return;
  720.  
  721.   debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd);
  722. #ifdef POSIX
  723.   (void) tcflush(wp->w_ptyfd, TCIOFLUSH);
  724. #else
  725. # ifdef TIOCFLUSH
  726.   (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0);
  727. # endif /* TIOCFLUSH */
  728. #endif /* POSIX */
  729.   if (closeopen)
  730.     {
  731.       close(wp->w_ptyfd);
  732.       sleep((n + 3) / 4);
  733.       if ((wp->w_ptyfd = OpenTTY(wp->w_tty)) < 1)
  734.     {
  735.       Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty);
  736.       return;
  737.     }
  738.     }
  739.   else
  740.     {
  741. #ifdef POSIX 
  742.       debug("tcsendbreak\n");
  743.       if (tcsendbreak(wp->w_ptyfd, n) < 0)
  744.     {
  745.       Msg(errno, "cannot send BREAK");
  746.       return;
  747.     }
  748. #else
  749.       if (!n)
  750.     n++;
  751. # ifdef TCSBRK
  752.       debug("TCSBRK\n");
  753.     {
  754.       int i;
  755.       for (i = 0; i < n; i++)
  756.         if (ioctl(wp->w_ptyfd, TCSBRK, (char *)0) < 0)
  757.           {
  758.         Msg(errno, "Cannot send BREAK");
  759.         return;
  760.           }
  761.     }
  762. # else /* TCSBRK */
  763. #  if defined(TIOCSBRK) && defined(TIOCCBRK)
  764.       debug("TIOCSBRK TIOCCBRK\n");
  765.       if (ioctl(wp->w_ptyfd, TIOCSBRK, (char *)0) < 0)
  766.     {
  767.       Msg(errno, "Can't send BREAK");
  768.       return;
  769.     }
  770.       sleep((n + 3) / 4);
  771.       if (ioctl(wp->w_ptyfd, TIOCCBRK, (char *)0) < 0)
  772.     {
  773.       Msg(errno, "BREAK stuck!!! -- HELP!");
  774.       return;
  775.     }
  776. #  else /* TIOCSBRK && TIOCCBRK */
  777.       Msg(0, "Break not simulated yet"); 
  778.       return;
  779. #  endif /* TIOCSBRK && TIOCCBRK */
  780. # endif /* TCSBRK */
  781. #endif /* POSIX */
  782.       debug("            broken\n");
  783.     }
  784. }
  785.  
  786.  
  787. /*
  788.  *  Console grabbing
  789.  */
  790.  
  791. /*ARGSUSED*/
  792. int
  793. TtyGrabConsole(fd, on, rc_name)
  794. int fd, on;
  795. char *rc_name;
  796. {
  797. #ifdef TIOCCONS
  798.   char *slave;
  799.   int sfd = -1, ret = 0;
  800.   struct display *d;
  801.  
  802.   if (!on)
  803.     {
  804.       if ((fd = OpenPTY(&slave)) < 0)
  805.     {
  806.       Msg(errno, "%s: could not open detach pty master", rc_name);
  807.       return -1;
  808.     }
  809.       if ((sfd = open(slave, O_RDWR)) < 0)
  810.     {
  811.       Msg(errno, "%s: could not open detach pty slave", rc_name);
  812.       close(fd);
  813.       return -1;
  814.     }
  815.     }
  816.   else
  817.     {
  818.       if (displays == 0)
  819.     {
  820.       Msg(0, "I need a display");
  821.       return -1;
  822.     }
  823.       for (d = displays; d; d = d->_d_next)
  824.     if (strcmp(d->_d_usertty, "/dev/console") == 0)
  825.       break;
  826.       if (d)
  827.     {
  828.       Msg(0, "too dangerous - screen is running on /dev/console");
  829.       return -1;
  830.     }
  831.     }
  832.   if (UserContext() == 1)
  833.     UserReturn(ioctl(fd, TIOCCONS, &on));
  834.   ret = UserStatus();
  835.   if (ret)
  836.     Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
  837.   if (!on)
  838.     {
  839.       close(sfd);
  840.       close(fd);
  841.     }
  842.   return ret;
  843. #else /* TIOCCONS */
  844.   Msg(0, "%s: no TIOCCONS on this machine", rc_name);
  845.   return -1;
  846. #endif /* TIOCCONS */
  847. }
  848.  
  849.  
  850. /*
  851.  *  Write out the mode struct in a readable form
  852.  */
  853.  
  854. #ifdef DEBUG
  855. void
  856. DebugTTY(m)
  857. struct mode *m;
  858. {
  859.   int i;
  860.  
  861. #ifdef POSIX
  862.   debug("struct termios tio:\n");
  863.   debug1("c_iflag = %#x\n", m->tio.c_iflag);
  864.   debug1("c_oflag = %#x\n", m->tio.c_oflag);
  865.   debug1("c_cflag = %#x\n", m->tio.c_cflag);
  866.   debug1("c_lflag = %#x\n", m->tio.c_lflag);
  867.   for (i = 0; i < NCCS; i++)
  868.     {
  869.       debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]);
  870.     }
  871. # ifdef hpux
  872.   debug1("suspc     = %#02x\n", m->m_ltchars.t_suspc);
  873.   debug1("dsuspc    = %#02x\n", m->m_ltchars.t_dsuspc);
  874.   debug1("rprntc    = %#02x\n", m->m_ltchars.t_rprntc);
  875.   debug1("flushc    = %#02x\n", m->m_ltchars.t_flushc);
  876.   debug1("werasc    = %#02x\n", m->m_ltchars.t_werasc);
  877.   debug1("lnextc    = %#02x\n", m->m_ltchars.t_lnextc);
  878. # endif /* hpux */
  879. #else /* POSIX */
  880. # ifdef TERMIO
  881.   debug("struct termio tio:\n");
  882.   debug1("c_iflag = %04o\n", m->tio.c_iflag);
  883.   debug1("c_oflag = %04o\n", m->tio.c_oflag);
  884.   debug1("c_cflag = %04o\n", m->tio.c_cflag);
  885.   debug1("c_lflag = %04o\n", m->tio.c_lflag);
  886.   for (i = 0; i < NCC; i++)
  887.     {
  888.       debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]);
  889.     }
  890. # else /* TERMIO */
  891.   debug1("sg_ispeed = %d\n",    m->m_ttyb.sg_ispeed);
  892.   debug1("sg_ospeed = %d\n",    m->m_ttyb.sg_ospeed);
  893.   debug1("sg_erase  = %#02x\n", m->m_ttyb.sg_erase);
  894.   debug1("sg_kill   = %#02x\n", m->m_ttyb.sg_kill);
  895.   debug1("sg_flags  = %#04x\n", (unsigned short)m->m_ttyb.sg_flags);
  896.   debug1("intrc     = %#02x\n", m->m_tchars.t_intrc);
  897.   debug1("quitc     = %#02x\n", m->m_tchars.t_quitc);
  898.   debug1("startc    = %#02x\n", m->m_tchars.t_startc);
  899.   debug1("stopc     = %#02x\n", m->m_tchars.t_stopc);
  900.   debug1("eofc      = %#02x\n", m->m_tchars.t_eofc);
  901.   debug1("brkc      = %#02x\n", m->m_tchars.t_brkc);
  902.   debug1("suspc     = %#02x\n", m->m_ltchars.t_suspc);
  903.   debug1("dsuspc    = %#02x\n", m->m_ltchars.t_dsuspc);
  904.   debug1("rprntc    = %#02x\n", m->m_ltchars.t_rprntc);
  905.   debug1("flushc    = %#02x\n", m->m_ltchars.t_flushc);
  906.   debug1("werasc    = %#02x\n", m->m_ltchars.t_werasc);
  907.   debug1("lnextc    = %#02x\n", m->m_ltchars.t_lnextc);
  908.   debug1("ldisc     = %d\n",    m->m_ldisc);
  909.   debug1("lmode     = %#x\n",   m->m_lmode);
  910. # endif /* TERMIO */
  911. #endif /* POSIX */
  912. }
  913. #endif /* DEBUG */
  914.