| 618 | } |
| 619 | |
| 620 | void EmbeddedShell::run() { |
| 621 | char* line = nullptr; |
| 622 | const char ctrl_c = '\3'; |
| 623 | int numCtrlC = 0; |
| 624 | // `true` when a multiline query is incomplete. See `EmbeddedShell::processInput`. |
| 625 | continueLine = false; |
| 626 | currLine = ""; |
| 627 | |
| 628 | #ifndef _WIN32 |
| 629 | termios raw{}; |
| 630 | if (isatty(STDIN_FILENO)) { |
| 631 | if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) { |
| 632 | errno = ENOTTY; |
| 633 | return; |
| 634 | } |
| 635 | raw = orig_termios; |
| 636 | raw.c_lflag &= ~ECHO; |
| 637 | |
| 638 | if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) < 0) { |
| 639 | errno = ENOTTY; |
| 640 | return; |
| 641 | } |
| 642 | noEcho = true; |
| 643 | } |
| 644 | #else |
| 645 | oldOutputCP = GetConsoleOutputCP(); |
| 646 | SetConsoleOutputCP(CP_UTF8); |
| 647 | #endif |
| 648 | |
| 649 | while (true) { |
| 650 | line = linenoise(continueLine ? ALTPROMPT : PROMPT, CONPROMPT, SCONPROMPT); |
| 651 | |
| 652 | if (line == nullptr && !continueLine) { |
| 653 | // EOF is reached and there is no input left to process. Exit loop. |
| 654 | break; |
| 655 | } |
| 656 | |
| 657 | std::string lineStr; |
| 658 | if (line == nullptr) { |
| 659 | // EOF is reached, but there is an incomplete query (`continueLine` == true). |
| 660 | // Mark as complete with a semicolon and attempt to process the query. |
| 661 | lineStr = ";"; |
| 662 | } else { |
| 663 | // Not EOF. We take the input as is. |
| 664 | lineStr = std::string(line); |
| 665 | } |
| 666 | lineStr = lineStr.erase(lineStr.find_last_not_of(" \t\n\r\f\v") + 1); |
| 667 | if (!lineStr.empty() && lineStr[0] == ctrl_c) { |
| 668 | if (!continueLine && lineStr[1] == '\0') { |
| 669 | numCtrlC++; |
| 670 | if (numCtrlC >= 2) { |
| 671 | free(line); |
| 672 | break; |
| 673 | } |
| 674 | } |
| 675 | currLine = ""; |
| 676 | continueLine = false; |
| 677 | free(line); |
no test coverage detected