Home | History | Annotate | Download | only in source
      1 //===-- TTYState.cpp --------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  Created by Greg Clayton on 3/26/07.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "TTYState.h"
     15 #include <fcntl.h>
     16 #include <unistd.h>
     17 #include <sys/signal.h>
     18 
     19 TTYState::TTYState() :
     20     m_fd(-1),
     21     m_tflags(-1),
     22     m_ttystateErr(-1),
     23     m_processGroup(-1)
     24 {
     25 }
     26 
     27 TTYState::~TTYState()
     28 {
     29 }
     30 
     31 bool
     32 TTYState::GetTTYState (int fd, bool saveProcessGroup)
     33 {
     34     if (fd >= 0 && ::isatty (fd))
     35     {
     36         m_fd = fd;
     37         m_tflags = fcntl (fd, F_GETFL, 0);
     38         m_ttystateErr = tcgetattr (fd, &m_ttystate);
     39         if (saveProcessGroup)
     40             m_processGroup = tcgetpgrp (0);
     41         else
     42             m_processGroup = -1;
     43     }
     44     else
     45     {
     46         m_fd = -1;
     47         m_tflags = -1;
     48         m_ttystateErr = -1;
     49         m_processGroup = -1;
     50     }
     51     return m_ttystateErr == 0;
     52 }
     53 
     54 bool
     55 TTYState::SetTTYState () const
     56 {
     57     int result = 0;
     58     if (IsValid())
     59     {
     60         if (TFlagsValid())
     61             result = fcntl (m_fd, F_SETFL, m_tflags);
     62 
     63         if (TTYStateValid())
     64             result = tcsetattr (m_fd, TCSANOW, &m_ttystate);
     65 
     66         if (ProcessGroupValid())
     67         {
     68             // Save the original signal handler.
     69             void (*saved_sigttou_callback) (int) = NULL;
     70             saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN);
     71             // Set the process group
     72             result = tcsetpgrp (m_fd, m_processGroup);
     73             // Restore the original signal handler.
     74             signal (SIGTTOU, saved_sigttou_callback);
     75         }
     76         return true;
     77     }
     78     return false;
     79 }
     80 
     81 
     82 
     83 TTYStateSwitcher::TTYStateSwitcher() :
     84     m_currentState(~0)
     85 {
     86 }
     87 
     88 TTYStateSwitcher::~TTYStateSwitcher()
     89 {
     90 }
     91 
     92 bool
     93 TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup)
     94 {
     95     if (ValidStateIndex(idx))
     96         return m_ttystates[idx].GetTTYState(fd, saveProcessGroup);
     97     return false;
     98 }
     99 
    100 bool
    101 TTYStateSwitcher::SetState(uint32_t idx) const
    102 {
    103     if (!ValidStateIndex(idx))
    104         return false;
    105 
    106     // See if we already are in this state?
    107     if (ValidStateIndex(m_currentState) && (idx == m_currentState) && m_ttystates[idx].IsValid())
    108         return true;
    109 
    110     // Set the state to match the index passed in and only update the
    111     // current state if there are no errors.
    112     if (m_ttystates[idx].SetTTYState())
    113     {
    114         m_currentState = idx;
    115         return true;
    116     }
    117 
    118     // We failed to set the state. The tty state was invalid or not
    119     // initialized.
    120     return false;
    121 }
    122 
    123