From 91a5ccf011c569dabc6cc79997ddd5f4e04592b1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 21 Aug 2016 13:23:14 +0200 Subject: Add support for process fallback search directory --- butl/process | 8 ++++++-- butl/process.cxx | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/butl/process b/butl/process index 75f3c66..c967c44 100644 --- a/butl/process +++ b/butl/process @@ -208,8 +208,12 @@ namespace butl // // process p (pp, args); // - process_path - path_search (const char*& args0); + // You can also specify the fallback directory which will be tried last. + // This, for example, can be used to implement the Windows "search in the + // parent executable's directory" semantics across platforms. + // + static process_path + path_search (const char*& args0, const dir_path& fallback = dir_path ()); public: #ifndef _WIN32 diff --git a/butl/process.cxx b/butl/process.cxx index cceceed..dcb4bc9 100644 --- a/butl/process.cxx +++ b/butl/process.cxx @@ -93,7 +93,7 @@ namespace butl #ifndef _WIN32 process_path process:: - path_search (const char*& args0) + path_search (const char*& args0, const dir_path& fb) { // Note that there is a similar version for Win32. @@ -161,6 +161,20 @@ namespace butl break; } + // If we were given a fallback, try that. + // + if (!fb.empty ()) + { + if (search (fb.string ().c_str (), fb.string ().size ())) + { + // In this case we have to set the recall path. + // + rp = fb; + rp /= f; + break; + } + } + // Did not find anything. // throw process_error (ENOENT, false); @@ -347,7 +361,7 @@ namespace butl #else // _WIN32 process_path process:: - path_search (const char*& args0) + path_search (const char*& args0, const dir_path& fb) { // Note that there is a similar version for Win32. @@ -460,7 +474,7 @@ namespace butl if (search ("", 0)) break; - // Finally, search in PATH. Recall is unchanged. + // Now search in PATH. Recall is unchanged. // { const char* b (getenv ("PATH")); @@ -480,6 +494,26 @@ namespace butl break; } + // Finally, if we were given a fallback, try that. This case is similar + // to searching in the parent executable's directory. + // + if (!fb.empty ()) + { + // I would have been nice to preserve trailing slash (by using + // representation() instead of string()), but that would involve + // a copy. Oh, well, can't always win. + // + if (search (fb.string ().c_str (), fb.string ().size ())) + { + // In this case we have to set the recall path. At least here we + // got to keep the original slash. + // + rp = fb; + rp /= f; + break; + } + } + // Did not find anything. // throw process_error (ENOENT); -- cgit v1.1