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