| //===-- TTYState.cpp --------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Created by Greg Clayton on 3/26/07. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "TTYState.h" |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <sys/signal.h> |
| |
| TTYState::TTYState() : |
| m_fd(-1), |
| m_tflags(-1), |
| m_ttystateErr(-1), |
| m_processGroup(-1) |
| { |
| } |
| |
| TTYState::~TTYState() |
| { |
| } |
| |
| bool |
| TTYState::GetTTYState (int fd, bool saveProcessGroup) |
| { |
| if (fd >= 0 && ::isatty (fd)) |
| { |
| m_fd = fd; |
| m_tflags = fcntl (fd, F_GETFL, 0); |
| m_ttystateErr = tcgetattr (fd, &m_ttystate); |
| if (saveProcessGroup) |
| m_processGroup = tcgetpgrp (0); |
| else |
| m_processGroup = -1; |
| } |
| else |
| { |
| m_fd = -1; |
| m_tflags = -1; |
| m_ttystateErr = -1; |
| m_processGroup = -1; |
| } |
| return m_ttystateErr == 0; |
| } |
| |
| bool |
| TTYState::SetTTYState () const |
| { |
| int result = 0; |
| if (IsValid()) |
| { |
| if (TFlagsValid()) |
| result = fcntl (m_fd, F_SETFL, m_tflags); |
| |
| if (TTYStateValid()) |
| result = tcsetattr (m_fd, TCSANOW, &m_ttystate); |
| |
| if (ProcessGroupValid()) |
| { |
| // Save the original signal handler. |
| void (*saved_sigttou_callback) (int) = NULL; |
| saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN); |
| // Set the process group |
| result = tcsetpgrp (m_fd, m_processGroup); |
| // Restore the original signal handler. |
| signal (SIGTTOU, saved_sigttou_callback); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| |
| |
| TTYStateSwitcher::TTYStateSwitcher() : |
| m_currentState(~0) |
| { |
| } |
| |
| TTYStateSwitcher::~TTYStateSwitcher() |
| { |
| } |
| |
| bool |
| TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) |
| { |
| if (ValidStateIndex(idx)) |
| return m_ttystates[idx].GetTTYState(fd, saveProcessGroup); |
| return false; |
| } |
| |
| bool |
| TTYStateSwitcher::SetState(uint32_t idx) const |
| { |
| if (!ValidStateIndex(idx)) |
| return false; |
| |
| // See if we already are in this state? |
| if (ValidStateIndex(m_currentState) && (idx == m_currentState) && m_ttystates[idx].IsValid()) |
| return true; |
| |
| // Set the state to match the index passed in and only update the |
| // current state if there are no errors. |
| if (m_ttystates[idx].SetTTYState()) |
| { |
| m_currentState = idx; |
| return true; |
| } |
| |
| // We failed to set the state. The tty state was invalid or not |
| // initialized. |
| return false; |
| } |
| |