1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "platform/globals.h" |
6 | #if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || \ |
7 | defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA) |
8 | |
9 | #include "bin/console.h" |
10 | |
11 | #include <errno.h> |
12 | #include <sys/ioctl.h> |
13 | #include <termios.h> |
14 | |
15 | #include "bin/fdutils.h" |
16 | #include "platform/signal_blocker.h" |
17 | |
18 | namespace dart { |
19 | namespace bin { |
20 | |
21 | class PosixConsole { |
22 | public: |
23 | static const tcflag_t kInvalidFlag = -1; |
24 | |
25 | static void Initialize() { |
26 | SaveMode(STDOUT_FILENO, &stdout_initial_c_lflag_); |
27 | SaveMode(STDERR_FILENO, &stderr_initial_c_lflag_); |
28 | SaveMode(STDIN_FILENO, &stdin_initial_c_lflag_); |
29 | } |
30 | |
31 | static void Cleanup() { |
32 | RestoreMode(STDOUT_FILENO, stdout_initial_c_lflag_); |
33 | RestoreMode(STDERR_FILENO, stderr_initial_c_lflag_); |
34 | RestoreMode(STDIN_FILENO, stdin_initial_c_lflag_); |
35 | ClearLFlags(); |
36 | } |
37 | |
38 | private: |
39 | static tcflag_t stdout_initial_c_lflag_; |
40 | static tcflag_t stderr_initial_c_lflag_; |
41 | static tcflag_t stdin_initial_c_lflag_; |
42 | |
43 | static void ClearLFlags() { |
44 | stdout_initial_c_lflag_ = kInvalidFlag; |
45 | stderr_initial_c_lflag_ = kInvalidFlag; |
46 | stdin_initial_c_lflag_ = kInvalidFlag; |
47 | } |
48 | |
49 | static void SaveMode(intptr_t fd, tcflag_t* flag) { |
50 | ASSERT(flag != NULL); |
51 | struct termios term; |
52 | int status = TEMP_FAILURE_RETRY(tcgetattr(fd, &term)); |
53 | if (status != 0) { |
54 | return; |
55 | } |
56 | *flag = term.c_lflag; |
57 | } |
58 | |
59 | static void RestoreMode(intptr_t fd, tcflag_t flag) { |
60 | if (flag == kInvalidFlag) { |
61 | return; |
62 | } |
63 | struct termios term; |
64 | int status = TEMP_FAILURE_RETRY(tcgetattr(fd, &term)); |
65 | if (status != 0) { |
66 | return; |
67 | } |
68 | term.c_lflag = flag; |
69 | VOID_TEMP_FAILURE_RETRY(tcsetattr(fd, TCSANOW, &term)); |
70 | } |
71 | |
72 | DISALLOW_ALLOCATION(); |
73 | DISALLOW_IMPLICIT_CONSTRUCTORS(PosixConsole); |
74 | }; |
75 | |
76 | tcflag_t PosixConsole::stdout_initial_c_lflag_ = PosixConsole::kInvalidFlag; |
77 | tcflag_t PosixConsole::stderr_initial_c_lflag_ = PosixConsole::kInvalidFlag; |
78 | tcflag_t PosixConsole::stdin_initial_c_lflag_ = PosixConsole::kInvalidFlag; |
79 | |
80 | void Console::SaveConfig() { |
81 | PosixConsole::Initialize(); |
82 | } |
83 | |
84 | void Console::RestoreConfig() { |
85 | PosixConsole::Cleanup(); |
86 | } |
87 | |
88 | } // namespace bin |
89 | } // namespace dart |
90 | |
91 | #endif // defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || |
92 | // defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA) |
93 | |