From e6b7445788131ec6320faa1fd3530771ae546641 Mon Sep 17 00:00:00 2001 From: Haitham Gad Date: Sun, 17 Mar 2013 14:10:17 -0400 Subject: [PATCH] - Changed FindReadline.cmake to search for Readline in macports paths before system paths. - Fixed CTRL-D. Now it exits tasksh. - Fixed a crash when a task description had any special characters. --- cmake/Modules/FindReadline.cmake | 88 +++++++++++++++++++++++++++++--- src/shell/Readline.cpp | 32 ++++++++++-- src/shell/Readline.h | 7 ++- src/shell/main.cpp | 19 ++++--- 4 files changed, 124 insertions(+), 22 deletions(-) diff --git a/cmake/Modules/FindReadline.cmake b/cmake/Modules/FindReadline.cmake index 8180dd0c3..83fe7bca0 100644 --- a/cmake/Modules/FindReadline.cmake +++ b/cmake/Modules/FindReadline.cmake @@ -1,8 +1,80 @@ -# GNU Readline library finder -if (READLINE_INCLUDE_DIR AND READLINE_LIBRARIES) - set (READLINE_FOUND TRUE) -else (READLINE_INCLUDE_DIR AND READLINE_LIBRARIES) - find_path (READLINE_INCLUDE_DIR readline/readline.h) - find_library (READLINE_LIBRARIES readline) - mark_as_advanced (READLINE_INCLUDE_DIR READLINE_LIBRARIES) -endif (READLINE_INCLUDE_DIR AND READLINE_LIBRARIES) +# - Find the readline library +# This module defines +# READLINE_INCLUDE_DIR, path to readline/readline.h, etc. +# READLINE_LIBRARIES, the libraries required to use READLINE. +# READLINE_FOUND, If false, do not try to use READLINE. +# also defined, but not for general use are +# READLINE_readline_LIBRARY, where to find the READLINE library. +# READLINE_ncurses_LIBRARY, where to find the ncurses library [might not be defined] + +# Apple readline does not support readline hooks +# So we look for another one by default +IF (APPLE) + FIND_PATH (READLINE_INCLUDE_DIR NAMES readline/readline.h PATHS + /sw/include + /opt/local/include + /opt/include + /usr/local/include + /usr/include/ + NO_DEFAULT_PATH + ) +ENDIF (APPLE) +FIND_PATH (READLINE_INCLUDE_DIR NAMES readline/readline.h) + + +# Apple readline does not support readline hooks +# So we look for another one by default +IF (APPLE) + FIND_LIBRARY (READLINE_readline_LIBRARY NAMES readline PATHS + /sw/lib + /opt/local/lib + /opt/lib + /usr/local/lib + /usr/lib + NO_DEFAULT_PATH + ) +ENDIF (APPLE) +FIND_LIBRARY (READLINE_readline_LIBRARY NAMES readline) + +# Sometimes readline really needs ncurses +IF (APPLE) + FIND_LIBRARY (READLINE_ncurses_LIBRARY NAMES ncurses PATHS + /sw/lib + /opt/local/lib + /opt/lib + /usr/local/lib + /usr/lib + NO_DEFAULT_PATH + ) +ENDIF (APPLE) +FIND_LIBRARY (READLINE_ncurses_LIBRARY NAMES ncurses) + +MARK_AS_ADVANCED ( + READLINE_INCLUDE_DIR + READLINE_readline_LIBRARY + READLINE_ncurses_LIBRARY + ) + +SET (READLINE_FOUND "NO" ) +IF (READLINE_INCLUDE_DIR) + IF (READLINE_readline_LIBRARY) + SET (READLINE_FOUND "YES" ) + SET (READLINE_LIBRARIES + ${READLINE_readline_LIBRARY} + ) + + # some readline libraries depend on ncurses + IF (READLINE_ncurses_LIBRARY) + SET (READLINE_LIBRARIES ${READLINE_LIBRARIES} ${READLINE_ncurses_LIBRARY}) + ENDIF (READLINE_ncurses_LIBRARY) + + ENDIF (READLINE_readline_LIBRARY) +ENDIF (READLINE_INCLUDE_DIR) + +IF (READLINE_FOUND) + MESSAGE (STATUS "Found readline library") +ELSE (READLINE_FOUND) + IF (READLINE_FIND_REQUIRED) + MESSAGE (FATAL_ERROR "Could not find readline -- please give some paths to CMake") + ENDIF (READLINE_FIND_REQUIRED) +ENDIF (READLINE_FOUND) diff --git a/src/shell/Readline.cpp b/src/shell/Readline.cpp index eaddafd10..de003cd4a 100644 --- a/src/shell/Readline.cpp +++ b/src/shell/Readline.cpp @@ -44,6 +44,11 @@ std::string Readline::gets (const std::string& prompt) #ifdef HAVE_READLINE // Get a line from the user. char *line_read = readline (prompt.c_str ()); + if (!line_read) // Exit when CTRL-D is pressed + { + std::cout << "exit\n"; + return "exit"; + } #else std::string line_read; std::cout << prompt; @@ -52,11 +57,11 @@ std::string Readline::gets (const std::string& prompt) #ifdef HAVE_READLINE // If the line has any text in it, save it on the history. - if (line_read && *line_read) + if (*line_read) add_history (line_read); #endif - std::string ret (line_read); + std::string ret(line_read); #ifdef HAVE_READLINE free (line_read); @@ -66,7 +71,7 @@ std::string Readline::gets (const std::string& prompt) } //////////////////////////////////////////////////////////////////////////////// -bool Readline::interactive_mode (const std::istream& in) +bool Readline::interactiveMode (const std::istream& in) { return (&in == &std::cin && isatty (0) == 1); } @@ -74,7 +79,9 @@ bool Readline::interactive_mode (const std::istream& in) //////////////////////////////////////////////////////////////////////////////// Wordexp::Wordexp (const std::string &str) { - wordexp (str.c_str (), &_p, 0); + std::string tmpStr(str); + escapeSpecialChars(tmpStr); + wordexp (tmpStr.c_str (), &_p, 0); } //////////////////////////////////////////////////////////////////////////////// @@ -96,3 +103,20 @@ char** Wordexp::argv () } //////////////////////////////////////////////////////////////////////////////// +char* Wordexp::argv (int i) +{ + return _p.we_wordv[i]; +} + +//////////////////////////////////////////////////////////////////////////////// +void Wordexp::escapeSpecialChars(std::string& str) +{ + size_t i = 0; + while ((i = str.find_first_of ("$*?!|&;<>(){}~#@", i)) != std::string::npos) + { + str.insert(i, 1, '\\'); + i += 2; + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/shell/Readline.h b/src/shell/Readline.h index 648022e79..ff634cbb6 100644 --- a/src/shell/Readline.h +++ b/src/shell/Readline.h @@ -38,7 +38,7 @@ class Readline { public: static std::string gets (const std::string& prompt); - static bool interactive_mode (const std::istream& in); + static bool interactiveMode (const std::istream& in); private: // No construction or destruction. @@ -52,11 +52,14 @@ private: class Wordexp { public: - Wordexp (const std::string &str); + Wordexp (const std::string& str); ~Wordexp (); int argc (); char** argv (); + char* argv (int i); + + void escapeSpecialChars(std::string& str); private: wordexp_t _p; diff --git a/src/shell/main.cpp b/src/shell/main.cpp index 5d554c30e..340da8a3b 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #ifdef CYGWIN #include @@ -115,8 +114,8 @@ int main (int argc, const char** argv) std::cout << (context.color () ? bold.colorize (PACKAGE_STRING) : PACKAGE_STRING) << " shell\n\n" - << STRING_CMD_SHELL_HELP1 << "\n" - << STRING_CMD_SHELL_HELP2 << "\n" + << STRING_CMD_SHELL_HELP1 << '\n' + << STRING_CMD_SHELL_HELP2 << '\n' << STRING_CMD_SHELL_HELP3 << "\n\n"; // Make a copy because context.clear will delete them. @@ -147,9 +146,13 @@ int main (int argc, const char** argv) std::string prompt (context.config.get ("shell.prompt") + " "); context.clear (); - if (Readline::interactive_mode (in)) + if (Readline::interactiveMode (in)) { input = Readline::gets (prompt); + + // if a string has nothing but whitespaces, ignore it + if (input.find_first_not_of (" \t") == std::string::npos) + continue; } else { @@ -159,7 +162,7 @@ int main (int argc, const char** argv) if (input.find_first_not_of (" \t") == std::string::npos) continue; - std::cout << prompt << input << "\n"; + std::cout << prompt << input << '\n'; } try @@ -169,7 +172,7 @@ int main (int argc, const char** argv) for (int i = 0; i < w.argc (); ++i) { if (std::find (quit_commands.begin (), quit_commands.end (), - lowerCase (w.argv ()[i])) != quit_commands.end ()) + lowerCase (w.argv (i))) != quit_commands.end ()) { context.clearMessages (); return 0; @@ -183,13 +186,13 @@ int main (int argc, const char** argv) catch (const std::string& error) { - std::cerr << error << "\n"; + std::cerr << error << '\n'; return -1; } catch (...) { - std::cerr << STRING_UNKNOWN_ERROR << "\n"; + std::cerr << STRING_UNKNOWN_ERROR << '\n'; return -2; } }