]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/TTYState.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / TTYState.cpp
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 <sys/signal.h>
17 #include <unistd.h>
18
19 TTYState::TTYState()
20     : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {}
21
22 TTYState::~TTYState() {}
23
24 bool TTYState::GetTTYState(int fd, bool saveProcessGroup) {
25   if (fd >= 0 && ::isatty(fd)) {
26     m_fd = fd;
27     m_tflags = fcntl(fd, F_GETFL, 0);
28     m_ttystateErr = tcgetattr(fd, &m_ttystate);
29     if (saveProcessGroup)
30       m_processGroup = tcgetpgrp(0);
31     else
32       m_processGroup = -1;
33   } else {
34     m_fd = -1;
35     m_tflags = -1;
36     m_ttystateErr = -1;
37     m_processGroup = -1;
38   }
39   return m_ttystateErr == 0;
40 }
41
42 bool TTYState::SetTTYState() const {
43   int result = 0;
44   if (IsValid()) {
45     if (TFlagsValid())
46       result = fcntl(m_fd, F_SETFL, m_tflags);
47
48     if (TTYStateValid())
49       result = tcsetattr(m_fd, TCSANOW, &m_ttystate);
50
51     if (ProcessGroupValid()) {
52       // Save the original signal handler.
53       void (*saved_sigttou_callback)(int) = NULL;
54       saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN);
55       // Set the process group
56       result = tcsetpgrp(m_fd, m_processGroup);
57       // Restore the original signal handler.
58       signal(SIGTTOU, saved_sigttou_callback);
59     }
60     return true;
61   }
62   return false;
63 }
64
65 TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {}
66
67 TTYStateSwitcher::~TTYStateSwitcher() {}
68
69 bool TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) {
70   if (ValidStateIndex(idx))
71     return m_ttystates[idx].GetTTYState(fd, saveProcessGroup);
72   return false;
73 }
74
75 bool TTYStateSwitcher::SetState(uint32_t idx) const {
76   if (!ValidStateIndex(idx))
77     return false;
78
79   // See if we already are in this state?
80   if (ValidStateIndex(m_currentState) && (idx == m_currentState) &&
81       m_ttystates[idx].IsValid())
82     return true;
83
84   // Set the state to match the index passed in and only update the
85   // current state if there are no errors.
86   if (m_ttystates[idx].SetTTYState()) {
87     m_currentState = idx;
88     return true;
89   }
90
91   // We failed to set the state. The tty state was invalid or not
92   // initialized.
93   return false;
94 }