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 19TTYState::TTYState() : 20 m_fd(-1), 21 m_tflags(-1), 22 m_ttystateErr(-1), 23 m_processGroup(-1) 24{ 25} 26 27TTYState::~TTYState() 28{ 29} 30 31bool 32TTYState::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 54bool 55TTYState::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 83TTYStateSwitcher::TTYStateSwitcher() : 84 m_currentState(~0) 85{ 86} 87 88TTYStateSwitcher::~TTYStateSwitcher() 89{ 90} 91 92bool 93TTYStateSwitcher::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 100bool 101TTYStateSwitcher::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