blob: 5f10050fcdde63a77ef5e8501dfe1006401bd71b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include <sys/signal.h>
Kate Stoneb9c1b512016-09-06 20:57:50 +000017#include <unistd.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018
Kate Stoneb9c1b512016-09-06 20:57:50 +000019TTYState::TTYState()
20 : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
Kate Stoneb9c1b512016-09-06 20:57:50 +000022TTYState::~TTYState() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023
Kate Stoneb9c1b512016-09-06 20:57:50 +000024bool 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);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 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
42bool 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);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 return true;
61 }
62 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063}
64
Kate Stoneb9c1b512016-09-06 20:57:50 +000065TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067TTYStateSwitcher::~TTYStateSwitcher() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069bool 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
75bool TTYStateSwitcher::SetState(uint32_t idx) const {
76 if (!ValidStateIndex(idx))
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +000078
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;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094}