diff options
Diffstat (limited to 'tools/debugserver/source/TTYState.cpp')
-rw-r--r-- | tools/debugserver/source/TTYState.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/tools/debugserver/source/TTYState.cpp b/tools/debugserver/source/TTYState.cpp new file mode 100644 index 0000000000000..28bc956dc28b6 --- /dev/null +++ b/tools/debugserver/source/TTYState.cpp @@ -0,0 +1,122 @@ +//===-- 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; +} + |