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