xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/TTYState.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick //===-- TTYState.cpp --------------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick //  Created by Greg Clayton on 3/26/07.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick 
13061da546Spatrick #include "TTYState.h"
14061da546Spatrick #include <fcntl.h>
15061da546Spatrick #include <sys/signal.h>
16061da546Spatrick #include <unistd.h>
17061da546Spatrick 
TTYState()18061da546Spatrick TTYState::TTYState()
19061da546Spatrick     : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {}
20061da546Spatrick 
21*f6aab3d8Srobert TTYState::~TTYState() = default;
22061da546Spatrick 
GetTTYState(int fd,bool saveProcessGroup)23061da546Spatrick bool TTYState::GetTTYState(int fd, bool saveProcessGroup) {
24061da546Spatrick   if (fd >= 0 && ::isatty(fd)) {
25061da546Spatrick     m_fd = fd;
26061da546Spatrick     m_tflags = fcntl(fd, F_GETFL, 0);
27061da546Spatrick     m_ttystateErr = tcgetattr(fd, &m_ttystate);
28061da546Spatrick     if (saveProcessGroup)
29061da546Spatrick       m_processGroup = tcgetpgrp(0);
30061da546Spatrick     else
31061da546Spatrick       m_processGroup = -1;
32061da546Spatrick   } else {
33061da546Spatrick     m_fd = -1;
34061da546Spatrick     m_tflags = -1;
35061da546Spatrick     m_ttystateErr = -1;
36061da546Spatrick     m_processGroup = -1;
37061da546Spatrick   }
38061da546Spatrick   return m_ttystateErr == 0;
39061da546Spatrick }
40061da546Spatrick 
SetTTYState() const41061da546Spatrick bool TTYState::SetTTYState() const {
42061da546Spatrick   if (IsValid()) {
43061da546Spatrick     if (TFlagsValid())
44*f6aab3d8Srobert       fcntl(m_fd, F_SETFL, m_tflags);
45061da546Spatrick 
46061da546Spatrick     if (TTYStateValid())
47*f6aab3d8Srobert       tcsetattr(m_fd, TCSANOW, &m_ttystate);
48061da546Spatrick 
49061da546Spatrick     if (ProcessGroupValid()) {
50061da546Spatrick       // Save the original signal handler.
51061da546Spatrick       void (*saved_sigttou_callback)(int) = NULL;
52061da546Spatrick       saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN);
53061da546Spatrick       // Set the process group
54*f6aab3d8Srobert       tcsetpgrp(m_fd, m_processGroup);
55061da546Spatrick       // Restore the original signal handler.
56061da546Spatrick       signal(SIGTTOU, saved_sigttou_callback);
57061da546Spatrick     }
58061da546Spatrick     return true;
59061da546Spatrick   }
60061da546Spatrick   return false;
61061da546Spatrick }
62061da546Spatrick 
TTYStateSwitcher()63061da546Spatrick TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {}
64061da546Spatrick 
65*f6aab3d8Srobert TTYStateSwitcher::~TTYStateSwitcher() = default;
66061da546Spatrick 
GetState(uint32_t idx,int fd,bool saveProcessGroup)67061da546Spatrick bool TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) {
68061da546Spatrick   if (ValidStateIndex(idx))
69061da546Spatrick     return m_ttystates[idx].GetTTYState(fd, saveProcessGroup);
70061da546Spatrick   return false;
71061da546Spatrick }
72061da546Spatrick 
SetState(uint32_t idx) const73061da546Spatrick bool TTYStateSwitcher::SetState(uint32_t idx) const {
74061da546Spatrick   if (!ValidStateIndex(idx))
75061da546Spatrick     return false;
76061da546Spatrick 
77061da546Spatrick   // See if we already are in this state?
78061da546Spatrick   if (ValidStateIndex(m_currentState) && (idx == m_currentState) &&
79061da546Spatrick       m_ttystates[idx].IsValid())
80061da546Spatrick     return true;
81061da546Spatrick 
82061da546Spatrick   // Set the state to match the index passed in and only update the
83061da546Spatrick   // current state if there are no errors.
84061da546Spatrick   if (m_ttystates[idx].SetTTYState()) {
85061da546Spatrick     m_currentState = idx;
86061da546Spatrick     return true;
87061da546Spatrick   }
88061da546Spatrick 
89061da546Spatrick   // We failed to set the state. The tty state was invalid or not
90061da546Spatrick   // initialized.
91061da546Spatrick   return false;
92061da546Spatrick }
93