|
6 | 6 | #include "ConsoleColors.h" |
7 | 7 | #include "Lacewing/Lacewing.h" |
8 | 8 | #include <signal.h> |
| 9 | +#include <termios.h> |
| 10 | +#include <unistd.h> |
9 | 11 |
|
10 | 12 | using namespace std::string_view_literals; |
11 | 13 |
|
@@ -100,22 +102,20 @@ struct clientstats |
100 | 102 | }; |
101 | 103 | static std::vector<std::unique_ptr<clientstats>> clientdata; |
102 | 104 |
|
103 | | -int ExitWithError(const char * msg, int error) |
104 | | -{ |
105 | | - std::cout << red << msg << ", got error number "sv << error << ".\r\n"sv; |
106 | | - std::cout << "Press any key to exit.\r\n"sv; |
107 | | - |
108 | | - // Clear input for getchar() |
109 | | - std::cin.clear(); |
110 | | - std::cin.ignore(); |
111 | | - std::cin.ignore(); |
112 | | - |
113 | | - getchar(); // wait for user keypress |
114 | | - return 1; |
115 | | -} |
| 105 | +static termios oldt; |
116 | 106 |
|
117 | 107 | int main() |
118 | 108 | { |
| 109 | + // Disable console input |
| 110 | + if (tcgetattr(STDIN_FILENO, &oldt) == -1) |
| 111 | + { |
| 112 | + std::cout << "Couldn't read console mode (error "sv << errno << "). Aborting server startup.\r\n"sv; |
| 113 | + return errno; |
| 114 | + } |
| 115 | + termios newt = oldt; |
| 116 | + newt.c_lflag &= ~ECHO; |
| 117 | + tcsetattr(STDIN_FILENO, TCSANOW, &newt); |
| 118 | + |
119 | 119 | // Handle closing nicely |
120 | 120 | signal(SIGABRT, CloseHandler); |
121 | 121 | signal(SIGFPE, CloseHandler); |
@@ -193,6 +193,7 @@ int main() |
193 | 193 | std::cout << green << "Host started. Port "sv << port << ", build "sv << globalserver->buildnum << ". "sv << |
194 | 194 | (flashpolicypath.empty() ? "Flash not hosting"sv : "Flash policy hosting on TCP port 843"sv) << '.' << |
195 | 195 | std::string(flashpolicypath.empty() ? 30 : 5, ' ') << "\r\n"sv << yellow; |
| 196 | + std::cout.flush(); |
196 | 197 |
|
197 | 198 | globalserver->host((lw_ui16)port); |
198 | 199 |
|
@@ -239,20 +240,20 @@ int main() |
239 | 240 | lw_sync_delete(lw_trace_sync); |
240 | 241 | #endif |
241 | 242 |
|
242 | | - std::wcout << green << timeBuffer << L" | Program completed.\r\n"sv; |
243 | | - std::wcout << timeBuffer << L" | Total bytes: "sv << totalBytesIn << L" in, "sv << totalBytesOut << L" out.\r\n"sv; |
244 | | - std::wcout << timeBuffer << L" | Total msgs: "sv << totalNumMessagesIn << L" in, "sv << totalNumMessagesOut << L" out.\r\n"sv; |
245 | | - std::wcout << timeBuffer << L" | Max msgs in 1 sec: "sv << maxNumMessagesIn << L" in, "sv << maxNumMessagesOut << L" out.\r\n"sv; |
246 | | - std::wcout << timeBuffer << L" | Max bytes in 1 sec: "sv << maxBytesInInOneSec << L" in, "sv << maxBytesOutInOneSec << L" out.\r\n"sv; |
247 | | - std::wcout << timeBuffer << L" | Press any key to exit.\r\n"sv; |
| 243 | + std::cout << green << timeBuffer << " | Program completed.\r\n"sv; |
| 244 | + std::cout << timeBuffer << " | Total bytes: "sv << totalBytesIn << " in, "sv << totalBytesOut << " out.\r\n"sv; |
| 245 | + std::cout << timeBuffer << " | Total msgs: "sv << totalNumMessagesIn << " in, "sv << totalNumMessagesOut << " out.\r\n"sv; |
| 246 | + std::cout << timeBuffer << " | Max msgs in 1 sec: "sv << maxNumMessagesIn << " in, "sv << maxNumMessagesOut << " out.\r\n"sv; |
| 247 | + std::cout << timeBuffer << " | Max bytes in 1 sec: "sv << maxBytesInInOneSec << " in, "sv << maxBytesOutInOneSec << " out.\r\n"sv; |
| 248 | + std::cout << timeBuffer << " | Press any key to exit.\r\n"sv; |
248 | 249 |
|
249 | | - // Clear input for getchar() |
| 250 | + // Clear any keypress the user did before we waited |
250 | 251 | std::cin.clear(); |
251 | 252 | std::cin.ignore(); |
252 | | - std::cin.ignore(); |
253 | | - |
254 | | - getchar(); // wait for user keypress |
| 253 | + std::cin.get(); // wait for user keypress |
255 | 254 |
|
| 255 | + std::cout << "\x1B[0m"; // reset console color |
| 256 | + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore console input mode |
256 | 257 | return 0; |
257 | 258 | } |
258 | 259 |
|
@@ -611,39 +612,57 @@ void GenerateFlashPolicy(int port) |
611 | 612 |
|
612 | 613 | void CloseHandler(int sig) |
613 | 614 | { |
614 | | - std::cout << red << '\r' << timeBuffer; |
| 615 | + std::cout << red << '\r' << timeBuffer << " | "sv; |
615 | 616 |
|
616 | 617 | // Catch exceptions |
617 | 618 | switch (sig) |
618 | 619 | { |
619 | 620 | case SIGABRT: |
620 | | - std::cout << "Caught SIGABRT: usually caused by an abort() or assert()"; |
| 621 | + std::cout << "Caught SIGABRT: usually caused by an abort() or assert() \r\n"sv; |
621 | 622 | break; |
622 | 623 | case SIGFPE: |
623 | | - std::cout << "Caught SIGFPE: arithmetic exception, such as divide by zero\n"; |
| 624 | + std::cout << "Caught SIGFPE: arithmetic exception, such as divide by zero \r\n"sv; |
624 | 625 | break; |
625 | 626 | case SIGILL: |
626 | | - std::cout << "Caught SIGILL: illegal instruction\n"; |
| 627 | + std::cout << "Caught SIGILL: illegal instruction \r\n"sv; |
627 | 628 | break; |
628 | 629 | case SIGINT: |
629 | | - std::cout << "Caught SIGINT: interactive attention signal, probably a ctrl+c\n"; |
| 630 | + std::cout << "Caught SIGINT: interactive attention signal, probably a ctrl+c \r\n"sv; |
630 | 631 | break; |
631 | 632 | case SIGSEGV: |
632 | | - std::cout << "Caught SIGSEGV: segfault\n"; |
| 633 | + std::cout << "Caught SIGSEGV: segfault \r\n"sv; |
633 | 634 | break; |
634 | 635 | case SIGTERM: |
635 | 636 | default: |
636 | | - std::cout << "Caught SIGTERM: a termination request was sent to the program\n"; |
| 637 | + std::cout << "Caught SIGTERM: a termination request was sent to the program \r\n"sv; |
637 | 638 | break; |
638 | 639 | } |
639 | | - std::cout << std::string(40, ' ') << "\r\n" << yellow; |
640 | 640 |
|
641 | 641 | if (!shutdowned) |
642 | 642 | { |
643 | | - std::cout << red << '\r' << timeBuffer << " | Got Ctrl-C or Close, ending app."sv << std::string(70, ' ') << "\r\n"sv << yellow; |
| 643 | + std::cout << red << '\r' << timeBuffer << " | Got Ctrl-C or Close, ending the app."sv << std::string(30, ' ') << "\r\n"sv << yellow; |
644 | 644 | Shutdown(); |
645 | 645 | } |
646 | 646 |
|
| 647 | + // Every other command will likely kill the program after end of this handler |
647 | 648 | if (sig != SIGINT) |
648 | | - exit(sig); |
| 649 | + { |
| 650 | + std::cout << red << '\r' << timeBuffer << " | Aborting instantly from signal "sv << sig << '.' << std::string(40, ' ') << "\r\n"sv; |
| 651 | + std::cout << "\x1B[0m"; // reset console color |
| 652 | + |
| 653 | + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore console input mode |
| 654 | + |
| 655 | + if (!flashpolicypath.empty() && deleteFlashPolicyAtEndOfApp) |
| 656 | + remove(flashpolicypath.c_str()); |
| 657 | + |
| 658 | + // Cleanup time |
| 659 | + clientdata.clear(); |
| 660 | + lacewing::timer_delete(globalmsgrecvcounttimer); |
| 661 | + globalserver->unhost(); |
| 662 | + globalserver->flash->unhost(); |
| 663 | + delete globalserver; |
| 664 | + lacewing::pump_delete(globalpump); |
| 665 | + |
| 666 | + exit(EXIT_FAILURE); |
| 667 | + } |
649 | 668 | } |
0 commit comments