//===-- 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; }