diff --git a/CMakeLists.txt b/CMakeLists.txt index f1718df39..a422f940d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required (VERSION 2.8) set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required -include (CheckIncludeFiles) include (CheckFunctionExists) include (CheckStructHasMember) @@ -90,10 +89,9 @@ if (READLINE_FOUND) set (TASK_LIBRARIES ${TASK_LIBRARIES} ${READLINE_LIBRARIES}) endif (READLINE_FOUND) -check_include_files (wordexp.h HAVE_WORDEXP_H) - check_function_exists (timegm HAVE_TIMEGM) check_function_exists (get_current_dir_name HAVE_GET_CURRENT_DIR_NAME) +check_function_exists (wordexp HAVE_WORDEXP) check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) check_struct_has_member ("struct stat" st_birthtime "sys/types.h;sys/stat.h" HAVE_ST_BIRTHTIME) diff --git a/cmake.h.in b/cmake.h.in index 984f920f8..3eaf04d77 100644 --- a/cmake.h.in +++ b/cmake.h.in @@ -67,8 +67,8 @@ /* Found uuid_unparse_lower in the uuid library */ #cmakedefine HAVE_UUID_UNPARSE_LOWER -/* Found wordexp.h in the libreadline library */ -#cmakedefine HAVE_WORDEXP_H +/* Found wordexp.h */ +#cmakedefine HAVE_WORDEXP /* Undefine this to eliminate the execute command */ #define HAVE_EXECUTE 1 diff --git a/src/shell/Readline.cpp b/src/shell/Readline.cpp index bbcca232b..ebd66c229 100644 --- a/src/shell/Readline.cpp +++ b/src/shell/Readline.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////////////// // taskwarrior - a command line task list manager. // -// Copyright 2006-2014, Paul Beckingham, Federico Hernandez. +// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -75,65 +75,3 @@ bool Readline::interactiveMode (const std::istream& in) } //////////////////////////////////////////////////////////////////////////////// -Wordexp::Wordexp (const std::string &str) -{ -#ifdef HAVE_WORDEXP_H - std::string strCopy (str); - escapeSpecialChars(strCopy); - wordexp (strCopy.c_str (), &_p, 0); -#else - _input = str; - escapeSpecialChars(_input); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -Wordexp::~Wordexp () -{ -#ifdef HAVE_WORDEXP_H - wordfree (&_p); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -int Wordexp::argc () -{ -#ifdef HAVE_WORDEXP_H - return _p.we_wordc; -#else - return 1; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -char** Wordexp::argv () -{ -#ifdef HAVE_WORDEXP_H - return _p.we_wordv; -#else - return (char**)_input.c_str (); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -char* Wordexp::argv (int i) -{ -#ifdef HAVE_WORDEXP_H - return _p.we_wordv[i]; -#else - return (char*)_input.c_str (); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -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 263a67f20..bac5a7e85 100644 --- a/src/shell/Readline.h +++ b/src/shell/Readline.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////////////// // taskwarrior - a command line task list manager. // -// Copyright 2006-2014, Paul Beckingham, Federico Hernandez. +// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -49,26 +49,5 @@ private: Readline& operator= (const Readline&); // Don't implement. }; -// RAII for wordexp_t -class Wordexp -{ -public: - Wordexp (const std::string& str); - ~Wordexp (); - - int argc (); - char** argv (); - char* argv (int i); - - void escapeSpecialChars(std::string& str); - -private: -#ifdef HAVE_WORDEXP_H - wordexp_t _p; -#else - std::string _input; -#endif -}; - #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/shell/main.cpp b/src/shell/main.cpp index fc1b98c95..69a65b9cd 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,8 @@ Context context; +#define MAX_ARGUMENTS 256 + //////////////////////////////////////////////////////////////////////////////// int main (int argc, const char** argv) { @@ -154,19 +157,59 @@ int main (int argc, const char** argv) try { - Wordexp w ("task " + trim (input + permanent_overrides)); +#ifdef HAVE_WORDEXP + std::string command = "task " + trim (input + permanent_overrides); - for (int i = 0; i < w.argc (); ++i) + // Escape special chars. + size_t i = 0; + while ((i = command.find_first_of ("$*?!|&;<>(){}~#@", i)) != std::string::npos) + { + command.insert(i, 1, '\\'); + i += 2; + } + + // Perform expansion. + wordexp_t p; + wordexp (command.c_str (), &p, 0); + char** w = p.we_wordv; + + for (int i = 0; i < p.we_wordc; ++i) { if (std::find (quit_commands.begin (), quit_commands.end (), - lowerCase (w.argv (i))) != quit_commands.end ()) + lowerCase (w[i])) != quit_commands.end ()) { context.clearMessages (); return 0; } } - int status = context.initialize (w.argc (), (const char**)w.argv ()); + int status = context.initialize (p.we_wordc, (const char**)p.we_wordv); + wordfree(&p); +#else + std::string command = "task " + trim (input + permanent_overrides); + int arg_count = 0; + char* arg_vector[MAX_ARGUMENTS]; + + char* arg = strtok ((char*)command.c_str (), " "); + while (arg && arg_count < MAX_ARGUMENTS) + { + arg_vector[arg_count++] = arg; + arg = strtok (0, " "); + } + + for (int i = 1; i < arg_count; ++i) + { + if (std::find (quit_commands.begin (), quit_commands.end (), + lowerCase (arg_vector[i])) != quit_commands.end ()) + { + context.clearMessages (); + return 0; + } + } + + int status = context.initialize (arg_count, (const char**) arg_vector); +#endif + if (status == 0) context.run (); }