#include #include #include #include #include #include #include #include std::string getStdin() { char buffer[1024]; std::ostringstream str; do { std::cin.read(buffer, 1024); str.write(buffer, std::cin.gcount()); } while (std::cin.gcount() > 0); return str.str(); } int main(int argc, char** argv) { if (argc < 2) { return -1; } std::string command = argv[1]; if (command == "echo") { std::this_thread::sleep_for(std::chrono::milliseconds(3000)); std::cout << "HELLO world!" << std::flush; std::cerr << "1" << std::flush; return 0; } if (command == "capitalize") { std::this_thread::sleep_for(std::chrono::milliseconds(9000)); std::string input = getStdin(); for (auto& c : input) { c = static_cast(std::toupper(c)); } std::cout << input << std::flush; std::cerr << "2" << std::flush; return 1; } if (command == "dedup") { // Use a nested scope to free all resources before aborting below. { std::string input = getStdin(); std::set seen; std::string output; for (auto c : input) { if (!seen.count(c)) { seen.insert(c); output += c; } } std::cout << output << std::flush; std::cerr << "3" << std::flush; } // On Windows, the exit code of abort() is different between debug and // release builds, and does not yield a term_signal in libuv in either // case. For the sake of simplicity, we just return another non-zero code. #ifdef _WIN32 return 2; #else std::abort(); #endif } return -1; }