|
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