diff --git a/.circleci/config.yml b/.circleci/config.yml index acbbc0712..263d2f031 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,13 +25,13 @@ jobs: command: mkdir build; cd build; cmake ../; make -j4 - run: name: Connect new -> old - command: ../root_version/build/etserver --daemon; cp ../root_version/build/etterminal /usr/bin/etterminal; sleep 1; build/et -c "ls" localhost --logtostdout --v=9 + command: ../root_version/build/etserver --daemon; cp ../root_version/build/etterminal /usr/bin/etterminal; sleep 1; build/et -c "ls" localhost --logtostdout --verbose=9 - run: name: Kill server command: pkill etserver - run: name: Connect old -> new - command: export TERM=xterm-256color; build/etserver --daemon; cp build/etterminal /usr/bin/etterminal; sleep 1; ../root_version/build/et -c "ls" localhost --logtostdout --v=9 + command: export TERM=xterm-256color; build/etserver --daemon; cp build/etterminal /usr/bin/etterminal; sleep 1; ../root_version/build/et -c "ls" localhost --logtostdout --verbose=9 - run: name: Kill server command: pkill etserver diff --git a/CMakeLists.txt b/CMakeLists.txt index 199efdb53..773512b46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,6 @@ LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # Required packages find_package(Threads REQUIRED) -find_package(GFlags REQUIRED) find_package(Protobuf REQUIRED) find_package(Sodium REQUIRED) @@ -101,7 +100,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CURSES_INCLUDE_DIR} ${sodium_INCLUDE_DIR} - ${GFLAGS_INCLUDE_DIRS} ${SELINUX_INCLUDE_DIR} ${UTEMPTER_INCLUDE_DIR} ) @@ -168,7 +166,6 @@ target_link_libraries ( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${SELINUX_LIBRARIES} ${UTEMPTER_LIBRARIES} @@ -187,7 +184,6 @@ target_link_libraries ( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${SELINUX_LIBRARIES} ${UTEMPTER_LIBRARIES} @@ -206,7 +202,6 @@ target_link_libraries ( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${UTEMPTER_LIBRARIES} ${CORE_LIBRARIES} @@ -243,8 +238,6 @@ target_link_libraries ( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GLOG_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${SELINUX_LIBRARIES} ${UTEMPTER_LIBRARIES} @@ -265,8 +258,6 @@ target_link_libraries ( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GLOG_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${SELINUX_LIBRARIES} ${UTEMPTER_LIBRARIES} @@ -294,7 +285,6 @@ target_link_libraries( et-lib ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES} - ${GFLAGS_LIBRARIES} ${sodium_LIBRARY_RELEASE} ${SELINUX_LIBRARIES} ${UTEMPTER_LIBRARIES} diff --git a/src/base/Headers.hpp b/src/base/Headers.hpp index 406f30c3a..81b4448be 100644 --- a/src/base/Headers.hpp +++ b/src/base/Headers.hpp @@ -55,12 +55,11 @@ #include #include -#include - #include #include "ET.pb.h" #include "easylogging++.h" +#include #include "base64.hpp" #include "json.hpp" #include "sole.hpp" diff --git a/src/htm/HtmClientMain.cpp b/src/htm/HtmClientMain.cpp index 93382c5ac..c1b43bbe6 100644 --- a/src/htm/HtmClientMain.cpp +++ b/src/htm/HtmClientMain.cpp @@ -10,8 +10,6 @@ using namespace et; -DEFINE_bool(x, false, "flag to kill all old sessions belonging to the user"); - termios terminal_backup; void term(int signum) { @@ -25,11 +23,25 @@ void term(int signum) { } int main(int argc, char** argv) { - // Version string need to be set before GFLAGS parse arguments - SetVersionString(string(ET_VERSION)); GOOGLE_PROTOBUF_VERIFY_VERSION; srand(1); + // Parse command line arguments + cxxopts::Options options("htm", "Headless terminal multiplexer"); + options.allow_unrecognised_options(); + + options.add_options() // + ("help", "Print help") // + ("x,kill-other-sessions", + "kill all old sessions belonging to the user") // + ; + + auto result = options.parse(argc, argv); + if (result.count("help")) { + cout << options.help({}) << endl; + exit(0); + } + setvbuf(stdin, NULL, _IONBF, 0); // turn off buffering setvbuf(stdout, NULL, _IONBF, 0); // turn off buffering @@ -59,11 +71,8 @@ int main(int argc, char** argv) { // Reconfigure default logger to apply settings above el::Loggers::reconfigureLogger("default", defaultConf); - // GFLAGS parse command line arguments - gflags::ParseCommandLineFlags(&argc, &argv, true); - uid_t myuid = getuid(); - if (FLAGS_x) { + if (result.count("x")) { LOG(INFO) << "Killing previous htmd"; // Kill previous htm daemon string command = diff --git a/src/htm/HtmServerMain.cpp b/src/htm/HtmServerMain.cpp index 75d3f53f0..73d93588b 100644 --- a/src/htm/HtmServerMain.cpp +++ b/src/htm/HtmServerMain.cpp @@ -8,7 +8,6 @@ using namespace et; int main(int argc, char **argv) { // Version string need to be set before GFLAGS parse arguments - SetVersionString(string(ET_VERSION)); GOOGLE_PROTOBUF_VERIFY_VERSION; srand(1); @@ -26,9 +25,6 @@ int main(int argc, char **argv) { // Reconfigure default logger to apply settings above el::Loggers::reconfigureLogger("default", defaultConf); - // GFLAGS parse command line arguments - gflags::ParseCommandLineFlags(&argc, &argv, true); - shared_ptr socketHandler(new PipeSocketHandler()); HtmServer htm(socketHandler, SocketEndpoint(HtmServer::getPipeName())); htm.run(); diff --git a/src/terminal/TerminalClientMain.cpp b/src/terminal/TerminalClientMain.cpp index 743f9a7d8..93eeaf237 100644 --- a/src/terminal/TerminalClientMain.cpp +++ b/src/terminal/TerminalClientMain.cpp @@ -3,38 +3,6 @@ #include "ParseConfigFile.hpp" #include "PsuedoTerminalConsole.hpp" -using namespace et; -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -DEFINE_string(u, "", "username to login"); -DEFINE_string(host, "localhost", "host to join"); -DEFINE_int32(port, 2022, "port to connect on"); -DEFINE_string(c, "", "Command to run immediately after connecting"); -DEFINE_string( - prefix, "", - "Command prefix to launch etserver/etterminal on the server side"); -DEFINE_string(t, "", - "Array of source:destination ports or " - "srcStart-srcEnd:dstStart-dstEnd (inclusive) port ranges (e.g. " - "10080:80,10443:443, 10090-10092:8000-8002)"); -DEFINE_string(rt, "", - "Array of source:destination ports or " - "srcStart-srcEnd:dstStart-dstEnd (inclusive) port ranges (e.g. " - "10080:80,10443:443, 10090-10092:8000-8002)"); -DEFINE_string(jumphost, "", "jumphost between localhost and destination"); -DEFINE_int32(jport, 2022, "port to connect on jumphost"); -DEFINE_bool(x, false, "flag to kill all old sessions belonging to the user"); -DEFINE_int32(v, 0, "verbose level"); -DEFINE_bool(logtostdout, false, "log to stdout"); -DEFINE_bool(silent, false, "If enabled, disable logging"); -DEFINE_bool(noratelimit, false, - "There's 1024 lines/second limit, which can be " - "disabled based on different use case."); -DEFINE_bool(N, false, "Do not create a terminal"); - using namespace et; bool ping(SocketEndpoint socketEndpoint, @@ -50,16 +18,61 @@ bool ping(SocketEndpoint socketEndpoint, } int main(int argc, char** argv) { - // Version string need to be set before GFLAGS parse arguments - SetVersionString(string(ET_VERSION)); - // Setup easylogging configurations el::Configurations defaultConf = LogHandler::setupLogHandler(&argc, &argv); - // GFLAGS parse command line arguments - gflags::ParseCommandLineFlags(&argc, &argv, true); + // Parse command line arguments + cxxopts::Options options("et", "Remote shell for the busy and impatient"); + options.positional_help("[user@]hostname[:port]").show_positional_help(); + options.allow_unrecognised_options(); + + options.add_options() // + ("help", "Print help") // + ("version", "Print version") // + ("u,username", "Username") // + ("host", "Remote host name", + cxxopts::value()) // + ("p,port", "Remote machine port", + cxxopts::value()->default_value("2022")) // + ("c,command", "Run command on connect", + cxxopts::value()) // + ("prefix", "Add prefix when launching etterminal on server side", + cxxopts::value()) // + ("t,tunnel", + "Tunnel: Array of source:destination ports or " + "srcStart-srcEnd:dstStart-dstEnd (inclusive) port ranges (e.g. " + "10080:80,10443:443, 10090-10092:8000-8002)", + cxxopts::value()) // + ("r,reversetunnel", + "Reverse Tunnel: Array of source:destination ports or " + "srcStart-srcEnd:dstStart-dstEnd (inclusive) port ranges", + cxxopts::value()) // + ("jumphost", "jumphost between localhost and destination", + cxxopts::value()) // + ("jport", "Jumphost machine port", + cxxopts::value()->default_value("2022")) // + ("x,kill-other-sessions", + "kill all old sessions belonging to the user") // + ("v,verbose", "Enable verbose logging", + cxxopts::value()->default_value("0")) // + ("logtostdout", "Write log to stdout") // + ("silent", "Disable logging") // + ("N,no-terminal", "Do not create a terminal") // + ; + + options.parse_positional({"host", "positional"}); + + auto result = options.parse(argc, argv); + if (result.count("help")) { + cout << options.help({}) << endl; + exit(0); + } + if (result.count("version")) { + cout << "et version " << ET_VERSION << endl; + exit(0); + } - if (FLAGS_logtostdout) { + if (result.count("logtostdout")) { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "true"); } else { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "false"); @@ -68,7 +81,7 @@ int main(int argc, char** argv) { } // silent Flag, since etclient doesn't read /etc/et.cfg file - if (FLAGS_silent) { + if (result.count("silent")) { defaultConf.setGlobally(el::ConfigurationType::Enabled, "false"); } @@ -82,55 +95,37 @@ int main(int argc, char** argv) { // Install log rotation callback el::Helpers::installPreRollOutCallback(LogHandler::rolloutHandler); - // Override -h & --help - for (int i = 1; i < argc; i++) { - string s(argv[i]); - if (s == "-h" || s == "--help") { - cout << "et (options) [user@]hostname[:port]\n" - "Options:\n" - "-h Basic usage\n" - "-p Port for etserver to run on. Default: 2022\n" - "-u Username to connect to ssh & ET\n" - "-v=9 verbose log files\n" - "-c Initial command to execute upon connecting\n" - "-prefix Command prefix to launch etserver/etterminal on the " - "server side\n" - "-t Map local to remote TCP port (TCP Tunneling)\n" - " example: et -t=\"18000:8000\" hostname maps localhost:18000\n" - "-rt Map remote to local TCP port (TCP Reverse Tunneling)\n" - " example: et -rt=\"18000:8000\" hostname maps hostname:18000\n" - "to localhost:8000\n" - "-jumphost Jumphost between localhost and destination\n" - "-jport Port to connect on jumphost\n" - "-x Flag to kill all sessions belongs to the user\n" - "-logtostdout Sent log message to stdout\n" - "-silent Disable all logs\n" - "-noratelimit Disable rate limit" - << endl; - exit(1); - } - } - GOOGLE_PROTOBUF_VERIFY_VERSION; srand(1); + string username = ""; + if (result.count("username")) { + username = result["username"].as(); + } + int port = result["port"].as(); + LOG(INFO) << "Port initially set to " << port; + string host; + // Parse command-line argument - if (argc > 1) { - string arg = string(argv[1]); - if (arg.find('@') != string::npos) { - int i = arg.find('@'); - FLAGS_u = arg.substr(0, i); - arg = arg.substr(i + 1); - } - if (arg.find(':') != string::npos) { - int i = arg.find(':'); - FLAGS_port = stoi(arg.substr(i + 1)); - arg = arg.substr(0, i); - } - FLAGS_host = arg; + if (!result.count("host")) { + cout << "Missing host to connect to" << endl; + cout << options.help({}) << endl; + exit(0); + } + string arg = result["host"].as(); + if (arg.find('@') != string::npos) { + int i = arg.find('@'); + username = arg.substr(0, i); + arg = arg.substr(i + 1); + } + if (arg.find(':') != string::npos) { + int i = arg.find(':'); + port = stoi(arg.substr(i + 1)); + arg = arg.substr(0, i); } + host = arg; - Options options = { + Options sshConfigOptions = { NULL, // username NULL, // host NULL, // sshdir @@ -148,58 +143,63 @@ int main(int argc, char** argv) { }; char* home_dir = ssh_get_user_home_dir(); - string host_alias = FLAGS_host; - ssh_options_set(&options, SSH_OPTIONS_HOST, FLAGS_host.c_str()); + string host_alias = host; + ssh_options_set(&sshConfigOptions, SSH_OPTIONS_HOST, host.c_str()); // First parse user-specific ssh config, then system-wide config. - parse_ssh_config_file(&options, string(home_dir) + USER_SSH_CONFIG_PATH); - parse_ssh_config_file(&options, SYSTEM_SSH_CONFIG_PATH); - LOG(INFO) << "Parsed ssh config file, connecting to " << options.host; - FLAGS_host = string(options.host); + parse_ssh_config_file(&sshConfigOptions, + string(home_dir) + USER_SSH_CONFIG_PATH); + parse_ssh_config_file(&sshConfigOptions, SYSTEM_SSH_CONFIG_PATH); + LOG(INFO) << "Parsed ssh config file, connecting to " + << sshConfigOptions.host; + host = string(sshConfigOptions.host); // Parse username: cmdline > sshconfig > localuser - if (FLAGS_u.empty()) { - if (options.username) { - FLAGS_u = string(options.username); + if (username.empty()) { + if (sshConfigOptions.username) { + username = string(sshConfigOptions.username); } else { - FLAGS_u = string(ssh_get_local_username()); + username = string(ssh_get_local_username()); } } // Parse jumphost: cmd > sshconfig - if (options.ProxyJump && FLAGS_jumphost.length() == 0) { - string proxyjump = string(options.ProxyJump); + string jumphost = + result.count("jumphost") ? result["jumphost"].as() : ""; + if (sshConfigOptions.ProxyJump && jumphost.length() == 0) { + string proxyjump = string(sshConfigOptions.ProxyJump); size_t colonIndex = proxyjump.find(":"); if (colonIndex != string::npos) { string userhostpair = proxyjump.substr(0, colonIndex); size_t atIndex = userhostpair.find("@"); if (atIndex != string::npos) { - FLAGS_jumphost = userhostpair.substr(atIndex + 1); + jumphost = userhostpair.substr(atIndex + 1); } } else { - FLAGS_jumphost = proxyjump; + jumphost = proxyjump; } LOG(INFO) << "ProxyJump found for dst in ssh config: " << proxyjump; } bool is_jumphost = false; - if (!FLAGS_jumphost.empty()) { + if (!jumphost.empty()) { is_jumphost = true; - FLAGS_host = FLAGS_jumphost; - FLAGS_port = FLAGS_jport; + host = jumphost; + port = result["jport"].as(); + LOG(INFO) << "Setting port to jumphost port"; } - SocketEndpoint socketEndpoint = - SocketEndpoint(FLAGS_host, FLAGS_port, is_jumphost); + SocketEndpoint socketEndpoint = SocketEndpoint(host, port, is_jumphost); shared_ptr clientSocket(new TcpSocketHandler()); if (!ping(socketEndpoint, clientSocket)) { - cout << "Could not reach the ET server: " << FLAGS_host << ":" << FLAGS_port - << endl; + cout << "Could not reach the ET server: " << host << ":" << port << endl; exit(1); } + int jport = result["jport"].as(); string idpasskeypair = SshSetupHandler::SetupSsh( - FLAGS_u, FLAGS_host, host_alias, FLAGS_port, FLAGS_jumphost, FLAGS_jport, - FLAGS_x, FLAGS_v, FLAGS_prefix, FLAGS_noratelimit); + username, host, host_alias, port, jumphost, jport, result.count("x") > 0, + result["v"].as(), + result.count("prefix") ? result["prefix"].as() : "", true); string id = "", passkey = ""; // Trim whitespace @@ -217,13 +217,16 @@ int main(int argc, char** argv) { << passkey.length(); } shared_ptr console; - if (!FLAGS_N) { + if (!result.count("N")) { console.reset(new PsuedoTerminalConsole()); } TerminalClient terminalClient = TerminalClient(clientSocket, socketEndpoint, id, passkey, console); - terminalClient.run(FLAGS_c, FLAGS_t, FLAGS_rt); + terminalClient.run( + result.count("command") ? result["command"].as() : "", + result.count("t") ? result["t"].as() : "", + result.count("rt") ? result["rt"].as() : ""); // Uninstall log rotation callback el::Helpers::uninstallPreRollOutCallback(); diff --git a/src/terminal/TerminalMain.cpp b/src/terminal/TerminalMain.cpp index 6dc85c1e5..3c9b938d0 100644 --- a/src/terminal/TerminalMain.cpp +++ b/src/terminal/TerminalMain.cpp @@ -10,62 +10,51 @@ #include "simpleini/SimpleIni.h" using namespace et; -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -DEFINE_string(idpasskey, "", - "If set, uses IPC to send a client id/key to the server daemon"); -DEFINE_string(idpasskeyfile, "", - "If set, uses IPC to send a client id/key to the server daemon " - "from a file"); -DEFINE_bool(jump, false, - "If set, forward all packets between client and dst terminal"); -DEFINE_string(dsthost, "", "Must be set if jump is set to true"); -DEFINE_int32(dstport, 2022, "Must be set if jump is set to true"); -DEFINE_int32(v, 0, "verbose level"); -DEFINE_bool(logtostdout, false, "log to stdout"); -DEFINE_string(cfgfile, "", "Location of the config file"); -DEFINE_bool(noratelimit, false, "Disable rate limit"); - -string getIdpasskey() { - string idpasskey = FLAGS_idpasskey; - if (FLAGS_idpasskeyfile.length() > 0) { - // Check for passkey file - std::ifstream t(FLAGS_idpasskeyfile.c_str()); - std::stringstream buffer; - buffer << t.rdbuf(); - idpasskey = buffer.str(); - // Trim whitespace - idpasskey.erase(idpasskey.find_last_not_of(" \n\r\t") + 1); - // Delete the file with the passkey - remove(FLAGS_idpasskeyfile.c_str()); - } - return idpasskey; -} void setDaemonLogFile(string idpasskey, string daemonType) { - if (!FLAGS_logtostdout) { - string first_idpass_chars = idpasskey.substr(0, 10); - string logFile = - string("/tmp/etterminal_") + daemonType + "_" + first_idpass_chars; - // Redirect std streams to a file - LogHandler::stderrToFile(logFile); - } + string first_idpass_chars = idpasskey.substr(0, 10); + string logFile = + string("/tmp/etterminal_") + daemonType + "_" + first_idpass_chars; } int main(int argc, char **argv) { - // Version string need to be set before GFLAGS parse arguments - SetVersionString(string(ET_VERSION)); - // Setup easylogging configurations el::Configurations defaultConf = LogHandler::setupLogHandler(&argc, &argv); - // GFLAGS parse command line arguments - gflags::ParseCommandLineFlags(&argc, &argv, true); + // Parse command line arguments + cxxopts::Options options("et", "Remote shell for the busy and impatient"); + options.positional_help("[user@]hostname[:port]").show_positional_help(); + options.allow_unrecognised_options(); + + options.add_options() // + ("help", "Print help") // + ("idpasskey", + "If set, uses IPC to send a client id/key to the server daemon", + cxxopts::value()->default_value("")) // + ("idpasskeyfile", + "If set, uses IPC to send a client id/key to the server daemon from a " + "file", + cxxopts::value()->default_value("")) // + ("jump", + "If set, forward all packets between client and dst terminal") // + ("dsthost", "Must be set if jump is set to true", + cxxopts::value()->default_value("")) // + ("dstport", "Must be set if jump is set to true", + cxxopts::value()->default_value("2022")) // + ("v,verbose", "Enable verbose logging", + cxxopts::value()->default_value("0")) // + ("logtostdout", "Write log to stdout") // + ; + + options.parse_positional({"host", "positional"}); + + auto result = options.parse(argc, argv); + if (result.count("help")) { + cout << options.help({}) << endl; + exit(0); + } - if (FLAGS_logtostdout) { + if (result.count("logtostdout")) { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "true"); } else { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "false"); @@ -74,40 +63,14 @@ int main(int argc, char **argv) { // default max log file size is 20MB for etserver string maxlogsize = "20971520"; - if (FLAGS_cfgfile.length()) { - // Load the config file - CSimpleIniA ini(true, true, true); - SI_Error rc = ini.LoadFile(FLAGS_cfgfile.c_str()); - if (rc == 0) { - // read verbose level - const char *vlevel = ini.GetValue("Debug", "verbose", NULL); - if (vlevel) { - el::Loggers::setVerboseLevel(atoi(vlevel)); - } - // read silent setting - const char *silent = ini.GetValue("Debug", "silent", NULL); - if (silent && atoi(silent) != 0) { - defaultConf.setGlobally(el::ConfigurationType::Enabled, "false"); - } - // read log file size limit - const char *logsize = ini.GetValue("Debug", "logsize", NULL); - if (logsize && atoi(logsize) != 0) { - // make sure maxlogsize is a string of int value - maxlogsize = string(logsize); - } - - } else { - LOG(FATAL) << "Invalid config file: " << FLAGS_cfgfile; - } - } - GOOGLE_PROTOBUF_VERIFY_VERSION; srand(1); shared_ptr ipcSocketHandler(new PipeSocketHandler()); shared_ptr term(new PsuedoUserTerminal()); - if (FLAGS_idpasskey.length() == 0 && FLAGS_idpasskeyfile.length() == 0) { + string idpasskey; + if (result.count("idpasskey") == 0 && result.count("idpasskeyfile") == 0) { // Try to read from stdin struct timeval timeout; timeout.tv_sec = 1; @@ -134,14 +97,24 @@ int main(int argc, char **argv) { exit(1); } auto tokens = split(stdinData, '_'); - FLAGS_idpasskey = tokens[0]; + idpasskey = tokens[0]; FATAL_FAIL(setenv("TERM", tokens[1].c_str(), 1)); + } else { + string idpasskey = result["idpasskey"].as(); + if (result.count("idpasskeyfile")) { + // Check for passkey file + std::ifstream t(result["idpasskeyfile"].as().c_str()); + std::stringstream buffer; + buffer << t.rdbuf(); + idpasskey = buffer.str(); + // Trim whitespace + idpasskey.erase(idpasskey.find_last_not_of(" \n\r\t") + 1); + } } - string idpasskey = getIdpasskey(); string id = split(idpasskey, '/')[0]; string username = string(ssh_get_local_username()); - if (FLAGS_jump) { + if (result.count("jump")) { setDaemonLogFile(idpasskey, "jumphost"); // etserver with --jump cannot write to the default log file(root) @@ -161,7 +134,8 @@ int main(int argc, char **argv) { } shared_ptr jumpClientSocketHandler(new TcpSocketHandler()); UserJumphostHandler ujh(jumpClientSocketHandler, idpasskey, - SocketEndpoint(FLAGS_dsthost, FLAGS_dstport), + SocketEndpoint(result["dsthost"].as(), + result["dstport"].as()), ipcSocketHandler, SocketEndpoint(ROUTER_FIFO_NAME)); ujh.run(); @@ -183,7 +157,7 @@ int main(int argc, char **argv) { // Install log rotation callback el::Helpers::installPreRollOutCallback(LogHandler::rolloutHandler); - UserTerminalHandler uth(ipcSocketHandler, term, FLAGS_noratelimit, + UserTerminalHandler uth(ipcSocketHandler, term, true, SocketEndpoint(ROUTER_FIFO_NAME), idpasskey); cout << "IDPASSKEY:" << idpasskey << endl; if (DaemonCreator::create(true) == -1) { diff --git a/src/terminal/TerminalServerMain.cpp b/src/terminal/TerminalServerMain.cpp index a8abc4994..596366b4a 100644 --- a/src/terminal/TerminalServerMain.cpp +++ b/src/terminal/TerminalServerMain.cpp @@ -6,29 +6,45 @@ namespace gflags {} using namespace google; using namespace gflags; -DEFINE_int32(port, 0, "Port to listen on"); -DEFINE_bool(daemon, false, "Daemonize the server"); -DEFINE_string(cfgfile, "", "Location of the config file"); -DEFINE_int32(v, 0, "verbose level"); -DEFINE_bool(logtostdout, false, "log to stdout"); - int main(int argc, char **argv) { - // Version string need to be set before GFLAGS parse arguments - SetVersionString(string(ET_VERSION)); - // Setup easylogging configurations el::Configurations defaultConf = LogHandler::setupLogHandler(&argc, &argv); - // GFLAGS parse command line arguments - gflags::ParseCommandLineFlags(&argc, &argv, true); + // Parse command line arguments + cxxopts::Options options("etserver", + "Remote shell for the busy and impatient"); + options.allow_unrecognised_options(); + + options.add_options() // + ("help", "Print help") // + ("version", "Print version") // + ("port", "Port to listen on", + cxxopts::value()->default_value("0")) // + ("daemon", "Daemonize the server") // + ("cfgfile", "Location of the config file", + cxxopts::value()->default_value("")) // + ("logtostdout", "log to stdout") // + ("v,verbose", "Enable verbose logging", + cxxopts::value()->default_value("0")) // + ; + + auto result = options.parse(argc, argv); + if (result.count("help")) { + cout << options.help({}) << endl; + exit(0); + } + if (result.count("version")) { + cout << "et version " << ET_VERSION << endl; + exit(0); + } - if (FLAGS_daemon) { + if (result.count("daemon")) { if (DaemonCreator::create(true) == -1) { LOG(FATAL) << "Error creating daemon: " << strerror(errno); } } - if (FLAGS_logtostdout) { + if (result.count("logtostdout")) { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "true"); } else { defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "false"); @@ -39,15 +55,16 @@ int main(int argc, char **argv) { // default max log file size is 20MB for etserver string maxlogsize = "20971520"; - if (FLAGS_cfgfile.length()) { + int port = 0; + if (result.count("cfgfile")) { // Load the config file CSimpleIniA ini(true, true, true); - SI_Error rc = ini.LoadFile(FLAGS_cfgfile.c_str()); + SI_Error rc = ini.LoadFile(result["cfgfile"].as().c_str()); if (rc == 0) { - if (FLAGS_port == 0) { + if (!result.count("port")) { const char *portString = ini.GetValue("Networking", "Port", NULL); if (portString) { - FLAGS_port = stoi(portString); + port = stoi(portString); } } // read verbose level @@ -68,15 +85,15 @@ int main(int argc, char **argv) { } } else { - LOG(FATAL) << "Invalid config file: " << FLAGS_cfgfile; + LOG(FATAL) << "Invalid config file: " << result["cfgfile"].as(); } } GOOGLE_PROTOBUF_VERIFY_VERSION; srand(1); - if (FLAGS_port == 0) { - FLAGS_port = 2022; + if (port == 0) { + port = 2022; } // Set log file for etserver process here. @@ -91,7 +108,7 @@ int main(int argc, char **argv) { std::shared_ptr tcpSocketHandler(new TcpSocketHandler()); std::shared_ptr pipeSocketHandler(new PipeSocketHandler()); - TerminalServer terminalServer(tcpSocketHandler, SocketEndpoint(FLAGS_port), + TerminalServer terminalServer(tcpSocketHandler, SocketEndpoint(port), pipeSocketHandler, SocketEndpoint(ROUTER_FIFO_NAME)); terminalServer.run();