From 6d9026c4b4620b4f65d172522b7b3a7aed4a94df Mon Sep 17 00:00:00 2001 From: Yaniv Kamay Date: Sat, 9 Jan 2010 23:06:00 +0200 Subject: client: add Platform::term_printf Platform::term_printf is a variant of printf that on windows dynamically opens console in order to have visible output during command line processing. --- client/application.cpp | 67 ++++++++++++++++++++++++++------------------- client/application.h | 7 +++-- client/cmd_line_parser.cpp | 29 ++++++++++---------- client/platform.h | 1 + client/windows/main.cpp | 28 ++----------------- client/windows/platform.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++ client/x11/platform.cpp | 8 ++++++ 7 files changed, 133 insertions(+), 71 deletions(-) (limited to 'client') diff --git a/client/application.cpp b/client/application.cpp index 1405c705..33cc9477 100644 --- a/client/application.cpp +++ b/client/application.cpp @@ -1448,7 +1448,8 @@ static inline int str_to_port(const char *str) return port; } -bool Application::set_channels_security(CmdLineParser& parser, bool on, char *val) +bool Application::set_channels_security(CmdLineParser& parser, bool on, char *val, + const char* arg0) { RedPeer::ConnectionOptions::Type option; option = (on) ? RedPeer::ConnectionOptions::CON_OP_SECURE : @@ -1465,7 +1466,8 @@ bool Application::set_channels_security(CmdLineParser& parser, bool on, char *va if (!strcmp(val, "all")) { if ((val = parser.next_argument())) { - std::cout << "\"all\" is exclusive in secure-channels\n"; + Platform::term_printf("%s: \"all\" is exclusive in secure-channels\n", arg0); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; return false; } PeerConnectionOptMap::iterator iter = _peer_con_opt.begin(); @@ -1478,7 +1480,8 @@ bool Application::set_channels_security(CmdLineParser& parser, bool on, char *va do { ChannelsNamesMap::iterator iter = channels_names.find(val); if (iter == channels_names.end()) { - std::cout << "bad channel name \"" << val << "\" in secure-channels\n"; + Platform::term_printf("%s: bad channel name \"%s\" in secure-channels\n", arg0, val); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; return false; } _peer_con_opt[(*iter).second] = option; @@ -1486,7 +1489,7 @@ bool Application::set_channels_security(CmdLineParser& parser, bool on, char *va return true; } -bool Application::set_canvas_option(CmdLineParser& parser, char *val) +bool Application::set_canvas_option(CmdLineParser& parser, char *val, const char* arg0) { typedef std::map< std::string, CanvasOption> CanvasNamesMap; CanvasNamesMap canvas_types; @@ -1500,19 +1503,23 @@ bool Application::set_canvas_option(CmdLineParser& parser, char *val) canvas_types["gl_pbuff"] = CANVAS_OPTION_OGL_PBUFF; #endif _canvas_types.clear(); + do { CanvasNamesMap::iterator iter = canvas_types.find(val); if (iter == canvas_types.end()) { - std::cout << "bad canvas type \"" << val << "\"\n"; + Platform::term_printf("%s: bad canvas type \"%s\"\n", arg0, val); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; return false; } _canvas_types.resize(_canvas_types.size() + 1); _canvas_types[_canvas_types.size() - 1] = (*iter).second; } while ((val = parser.next_argument())); + return true; } -bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char *val) +bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char *val, + const char* arg0) { typedef std::map< std::string, int> ChannelsNamesMap; ChannelsNamesMap channels_names; @@ -1524,7 +1531,8 @@ bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char * if (!strcmp(val, "all")) { if ((val = parser.next_argument())) { - std::cout << "\"all\" is exclusive\n"; + Platform::term_printf("%s: \"all\" is exclusive\n", arg0); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; return false; } for (unsigned int i = 0; i < _enabled_channels.size(); i++) { @@ -1536,14 +1544,22 @@ bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char * do { ChannelsNamesMap::iterator iter = channels_names.find(val); if (iter == channels_names.end()) { - std::cout << "bad channel name \"" << val << "\"\n"; + Platform::term_printf("%s: bad channel name \"%s\"\n", arg0, val); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; return false; } _enabled_channels[(*iter).second] = enable; } while ((val = parser.next_argument())); + return true; } +void Application::on_cmd_line_invalid_arg(const char* arg0, const char* what, const char* val) +{ + Platform::term_printf("%s: invalid %s value %s\n", arg0, what, val); + _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; +} + bool Application::process_cmd_line(int argc, char** argv) { std::string host; @@ -1616,16 +1632,14 @@ bool Application::process_cmd_line(int argc, char** argv) break; case SPICE_OPT_PORT: { if ((port = str_to_port(val)) == -1) { - std::cout << "invalid port " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + on_cmd_line_invalid_arg(argv[0], "port", val); return false; } break; } case SPICE_OPT_SPORT: { if ((sport = str_to_port(val)) == -1) { - std::cout << "invalid secure port " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + on_cmd_line_invalid_arg(argv[0], "secure port", val); return false; } break; @@ -1633,8 +1647,7 @@ bool Application::process_cmd_line(int argc, char** argv) case SPICE_OPT_FULL_SCREEN: if (val) { if (strcmp(val, "auto-conf")) { - std::cout << "invalid full screen mode " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + on_cmd_line_invalid_arg(argv[0], "full screen mode", val); return false; } auto_display_res = true; @@ -1645,33 +1658,27 @@ bool Application::process_cmd_line(int argc, char** argv) password = val; break; case SPICE_OPT_SECURE_CHANNELS: - if (!set_channels_security(parser, true, val)) { + if (!set_channels_security(parser, true, val, argv[0])) { return false; } break; case SPICE_OPT_UNSECURE_CHANNELS: - if (!set_channels_security(parser, false, val)) { + if (!set_channels_security(parser, false, val, argv[0])) { return false; } break; case SPICE_OPT_ENABLE_CHANNELS: - if (!set_enable_channels(parser, true, val)) { - std::cout << "invalid channels " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + if (!set_enable_channels(parser, true, val, argv[0])) { return false; } break; case SPICE_OPT_DISABLE_CHANNELS: - if (!set_enable_channels(parser, false, val)) { - std::cout << "invalid channels " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + if (!set_enable_channels(parser, false, val, argv[0])) { return false; } break; case SPICE_OPT_CANVAS_TYPE: - if (!set_canvas_option(parser, val)) { - std::cout << "invalid canvas option " << val << "\n"; - _exit_code = SPICEC_ERROR_CODE_INVALID_ARG; + if (!set_canvas_option(parser, val, argv[0])) { return false; } break; @@ -1679,14 +1686,16 @@ bool Application::process_cmd_line(int argc, char** argv) parser.show_help(); return false; case CmdLineParser::OPTION_ERROR: + _exit_code = SPICEC_ERROR_CODE_CMD_LINE_ERROR; return false; default: - throw Exception("cmd line error"); + throw Exception("cmd line error", SPICEC_ERROR_CODE_CMD_LINE_ERROR); } } if (parser.is_set(SPICE_OPT_SECURE_CHANNELS) && !parser.is_set(SPICE_OPT_SPORT)) { - std::cout << "missing --secure-port\n"; + Platform::term_printf("%s: missing --secure-port\n", argv[0]); + _exit_code = SPICEC_ERROR_CODE_CMD_LINE_ERROR; return false; } @@ -1714,7 +1723,9 @@ bool Application::process_cmd_line(int argc, char** argv) (*iter).second = RedPeer::ConnectionOptions::CON_OP_SECURE; continue; } - std::cout << "missing --port or --sport\n"; + + Platform::term_printf("%s: missing --port or --sport\n", argv[0]); + _exit_code = SPICEC_ERROR_CODE_CMD_LINE_ERROR; return false; } diff --git a/client/application.h b/client/application.h index 3c0297ff..27701eb0 100644 --- a/client/application.h +++ b/client/application.h @@ -165,9 +165,10 @@ public: static int main(int argc, char** argv, const char* version_str); private: - bool set_channels_security(CmdLineParser& parser, bool on, char *val); - bool set_enable_channels(CmdLineParser& parser, bool enable, char *val); - bool set_canvas_option(CmdLineParser& parser, char *val); + bool set_channels_security(CmdLineParser& parser, bool on, char *val, const char* arg0); + bool set_enable_channels(CmdLineParser& parser, bool enable, char *val, const char* arg0); + bool set_canvas_option(CmdLineParser& parser, char *val, const char* arg0); + void on_cmd_line_invalid_arg(const char* arg0, const char* what, const char* val); bool process_cmd_line(int argc, char** argv); void abort(); void init_scan_code(int index); diff --git a/client/cmd_line_parser.cpp b/client/cmd_line_parser.cpp index 65ae404a..caa4b034 100644 --- a/client/cmd_line_parser.cpp +++ b/client/cmd_line_parser.cpp @@ -344,7 +344,7 @@ int CmdLineParser::get_option(char** val) int name_pos = (opt_obj->type == REQUIRED_ARGUMENT) ? optind - 2 : optind - 1; std::string cmd_name(_argv[name_pos] + 2); if (cmd_name.find(opt_obj->name) != 0) { - std::cout << _argv[0] << ": invalid option '--" << cmd_name << "'\n"; + Platform::term_printf("%s: invalid option '--%s'\n", _argv[0], cmd_name.c_str()); return OPTION_ERROR; } #endif @@ -360,11 +360,11 @@ int CmdLineParser::get_option(char** val) case -1: { *val = NULL; if (!_positional_args && optind != _argc) { - std::cout << _argv[0] << ": unexpected positional arguments\n"; + Platform::term_printf("%s: unexpected positional arguments\n", _argv[0]); return OPTION_ERROR; } if ((opt_obj = find_missing_opt())) { - std::cout << _argv[0] << ": option --" << opt_obj->name << " is required\n"; + Platform::term_printf("%s: option --%s is required\n", _argv[0], opt_obj->name.c_str()); return OPTION_ERROR; } _done = true; @@ -378,18 +378,19 @@ int CmdLineParser::get_option(char** val) #ifdef DISABLE_ABBREVIATE std::string cmd_name(_argv[optind - 1] + 2); if (cmd_name.find(opt_obj->name) != 0) { - std::cout << _argv[0] << ": invalid option '--" << cmd_name << "'\n"; + Platform::term_printf("%s: invalid option '--%s'\n", _argv[0], cmd_name.c_str()); return OPTION_ERROR; } #endif - std::cout << _argv[0] << ": option --" << opt_obj->name << " requires an argument\n"; + Platform::term_printf("%s: option --%s requires an argument\n", + _argv[0], opt_obj->name.c_str()); } else if (optopt == 0) { - std::cout << _argv[0] << ": invalid option '" << _argv[optind - 1] << "'\n"; + Platform::term_printf("%s: invalid option '%s'\n", _argv[0], _argv[optind - 1]); } else if ((opt_obj = find((char)optopt))) { - std::cout << _argv[0] << ": option '-" << opt_obj->short_name << - "' requires an argument\n"; + Platform::term_printf("%s: option '-%c' requires an argument\n", + _argv[0], opt_obj->short_name); } else { - std::cout << _argv[0] << ": invalid option '-" << char(optopt) << "'\n"; + Platform::term_printf("%s: invalid option '-%c'\n", _argv[0], char(optopt)); } return OPTION_ERROR; default: @@ -447,13 +448,13 @@ void CmdLineParser::show_help() { static const int HELP_START_POS = 30; static const int HELP_WIDTH = 80 - HELP_START_POS; + std::ostringstream os; - std::cout << basename(_argv[0]) << " - " << _description.c_str() << "\n\noptions:\n\n"; + os << basename(_argv[0]) << " - " << _description.c_str() << "\n\noptions:\n\n"; Options::iterator iter = _options.begin(); for (; iter != _options.end(); ++iter) { CmdLineParser::Option* opt = *iter; - std::ostringstream os; if (opt->short_name) { os << " -" << opt->short_name << ", "; @@ -516,9 +517,9 @@ void CmdLineParser::show_help() line.clear(); } } while (line.size() || std::getline(is, line)); - - std::cout << os.str(); } - std::cout << "\n"; + + os << "\n"; + Platform::term_printf(os.str().c_str()); } diff --git a/client/platform.h b/client/platform.h index a36cdc50..50db1534 100644 --- a/client/platform.h +++ b/client/platform.h @@ -42,6 +42,7 @@ public: static void path_append(std::string& path, const std::string& partial_path); static uint64_t get_process_id(); static uint64_t get_thread_id(); + static void term_printf(const char* format, ...); static const MonitorsList& init_monitors(); static void destroy_monitors(); diff --git a/client/windows/main.cpp b/client/windows/main.cpp index a1575e90..afc98c97 100644 --- a/client/windows/main.cpp +++ b/client/windows/main.cpp @@ -22,12 +22,6 @@ extern "C" { #include "pthread.h" } -//#define OPEN_CONSOLE -#ifdef OPEN_CONSOLE -#include -#include -#endif - #include "application.h" #include "debug.h" #include "utils.h" @@ -83,23 +77,6 @@ int WINAPI WinMain(HINSTANCE hInstance, try { init_version_string(); -#ifdef OPEN_CONSOLE - AllocConsole(); - HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); - int hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); - FILE * fp = _fdopen(hConHandle, "w"); - *stdout = *fp; - - h = GetStdHandle(STD_INPUT_HANDLE); - hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); - fp = _fdopen(hConHandle, "r"); - *stdin = *fp; - - h = GetStdHandle(STD_ERROR_HANDLE); - hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); - fp = _fdopen(hConHandle, "w"); - *stderr = *fp; -#endif pthread_win32_process_attach_np(); init_winsock(); exit_val = Application::main(__argc, __argv, version_string); @@ -114,11 +91,10 @@ int WINAPI WinMain(HINSTANCE hInstance, LOG_ERROR("unhandled exception"); exit_val = SPICEC_ERROR_CODE_ERROR; } + log4cpp::Category::shutdown(); -#ifdef OPEN_CONSOLE - _getch(); -#endif pthread_win32_process_detach_np(); + return exit_val; } diff --git a/client/windows/platform.cpp b/client/windows/platform.cpp index dcdb84e3..d5ff0f09 100644 --- a/client/windows/platform.cpp +++ b/client/windows/platform.cpp @@ -18,6 +18,8 @@ #include "common.h" #include +#include +#include #include "platform.h" #include "win_platform.h" @@ -740,3 +742,65 @@ void WinPlatform::exit_modal_loop() KillTimer(paltform_win, MODAL_LOOP_TIMER_ID); modal_loop_active = false; } + +static bool has_console = false; + +static void create_console() +{ + static Mutex console_mutex; + + Lock lock(console_mutex); + + if (has_console) { + return; + } + + AllocConsole(); + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + int hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); + FILE * fp = _fdopen(hConHandle, "w"); + *stdout = *fp; + + h = GetStdHandle(STD_INPUT_HANDLE); + hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); + fp = _fdopen(hConHandle, "r"); + *stdin = *fp; + + h = GetStdHandle(STD_ERROR_HANDLE); + hConHandle = _open_osfhandle((intptr_t)h, _O_TEXT); + fp = _fdopen(hConHandle, "w"); + *stderr = *fp; + + has_console = true; + + HWND consol_window = GetConsoleWindow(); + + if (consol_window) { + SetForegroundWindow(consol_window); + } +} + +class ConsoleWait { +public: + ~ConsoleWait() + { + if (has_console) { + Platform::term_printf("\n\nPress any key to exit..."); + _getch(); + } + } + +} console_wait; + + +void Platform::term_printf(const char* format, ...) +{ + if (!has_console) { + create_console(); + } + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp index 1bedb225..bceae05a 100644 --- a/client/x11/platform.cpp +++ b/client/x11/platform.cpp @@ -252,6 +252,14 @@ void Platform::yield() pthread_yield(); } +void Platform::term_printf(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + void Platform::set_thread_priority(void* thread, Platform::ThreadPriority in_priority) { ASSERT(thread == NULL); -- cgit