Commit a9ec30d3e792b2bfaf2cd6b54c4ccb74b3e2dada
1 parent
b95148b4
Handle ~ sequences in gammalib::expand_env (#1580).
gammalib::expand_env replaces ~ or ~user by the user's home directory, ~+ by the value of the PWD environment variable and ~- by the value of the OLDPWD variable. If the user or the PWD or OLDPWD variable are not found, no replacement is done. Update change-log.
Showing
4 changed files
with
73 additions
and
19 deletions
ChangeLog
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | * Version 1.0.0 released |
| 4 | 4 | ========================= |
| 5 | 5 | |
| 6 | + Handle ~ in filenames (#1580) | |
| 6 | 7 | Perform __init__.py creation only in build step (#1569) |
| 7 | 8 | Remove access by name methods from GSkyRegions (#1564) |
| 8 | 9 | Resolve Python test problem on El Capitan (#1563) | ... | ... |
NEWS
| ... | ... | @@ -2,7 +2,7 @@ New Features and Important Changes in GammaLib 1.0.0 |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -19 November 2015 | |
| 5 | +22 November 2015 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -82,7 +82,8 @@ where this access is needed (#1564): |
| 82 | 82 | |
| 83 | 83 | 13. Support module |
| 84 | 84 | ------------------ |
| 85 | -None | |
| 85 | +The gammalib::expand_env() function now handles ~, ~user, ~+ and ~- following the | |
| 86 | +logic implemented for the bash shell. | |
| 86 | 87 | |
| 87 | 88 | |
| 88 | 89 | 14. XML module | ... | ... |
src/support/GTools.cpp
| ... | ... | @@ -35,6 +35,7 @@ |
| 35 | 35 | #include <sys/select.h> // select() function |
| 36 | 36 | #include <sys/types.h> |
| 37 | 37 | #include <sys/socket.h> // recv() function |
| 38 | +#include <pwd.h> | |
| 38 | 39 | #include <cmath> |
| 39 | 40 | #include <cfloat> |
| 40 | 41 | #include <cctype> |
| ... | ... | @@ -114,6 +115,12 @@ std::string gammalib::strip_chars(const std::string& arg, |
| 114 | 115 | * ${\<name\>}, $(\<name\>) and $\<name\> (in the last case the terminating |
| 115 | 116 | * delimiter is either a / or a blank character or the end of the string). |
| 116 | 117 | * Environment variables occuring within single quotes (') are ignored. |
| 118 | + * Environment variables that do not exist will be kept as specified. | |
| 119 | + * | |
| 120 | + * The method also replaces ~ or ~user by the user's home directory, ~+ | |
| 121 | + * by the value of the PWD environment variable and ~- by the value of the | |
| 122 | + * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found, | |
| 123 | + * no replacement is done. | |
| 117 | 124 | * |
| 118 | 125 | * This function has been inspired by the function ape_util_expand_env_var |
| 119 | 126 | * from ape_util.c in the ape software developed at HEASARC. |
| ... | ... | @@ -121,9 +128,9 @@ std::string gammalib::strip_chars(const std::string& arg, |
| 121 | 128 | std::string gammalib::expand_env(const std::string& arg) |
| 122 | 129 | { |
| 123 | 130 | // Set environment variable delimiters |
| 124 | - static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$" }; | |
| 125 | - static const char* end_delim[] = { "}", ")", "}", ")", "/" }; | |
| 126 | - static const int num_delim = 5; | |
| 131 | + static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" }; | |
| 132 | + static const char* end_delim[] = { "}", ")", "}", ")", "/", "/" }; | |
| 133 | + static const int num_delim = 6; | |
| 127 | 134 | |
| 128 | 135 | // Initialise result with argument |
| 129 | 136 | std::string result = arg; |
| ... | ... | @@ -171,7 +178,7 @@ std::string gammalib::expand_env(const std::string& arg) |
| 171 | 178 | if (begin_length > 0) { |
| 172 | 179 | |
| 173 | 180 | // Search for the termination delimiter of the environment |
| 174 | - // variable. There is a special case for delimiter 4: | |
| 181 | + // variable. There is a special case for delimiters 4 and 5: | |
| 175 | 182 | // It has always an end_length of zero as the / is not a real |
| 176 | 183 | // delimiter, but just an indicator that the environment variable |
| 177 | 184 | // ends. Another indicator is a blank. If the end of the |
| ... | ... | @@ -179,7 +186,7 @@ std::string gammalib::expand_env(const std::string& arg) |
| 179 | 186 | size_t i_start = index + begin_length; |
| 180 | 187 | size_t i_end = i_start; |
| 181 | 188 | size_t end_length = 0; |
| 182 | - if (delim_idx == 4) { | |
| 189 | + if (delim_idx == 4 || delim_idx == 5) { | |
| 183 | 190 | while (i_end < result.length() && |
| 184 | 191 | result.compare(i_end, 1, "/") != 0 && |
| 185 | 192 | result.compare(i_end, 1, " ") != 0) { |
| ... | ... | @@ -196,22 +203,53 @@ std::string gammalib::expand_env(const std::string& arg) |
| 196 | 203 | |
| 197 | 204 | // If termination delimiter has been found then expand the |
| 198 | 205 | // environment variable |
| 199 | - if (i_end < result.length() || delim_idx == 4) { | |
| 206 | + if (i_end < result.length() || delim_idx == 4 || delim_idx == 5) { | |
| 200 | 207 | |
| 201 | 208 | // Extract environment variable name |
| 202 | 209 | std::string name = result.substr(i_start, i_end-i_start); |
| 203 | 210 | size_t name_length = name.length(); |
| 204 | 211 | |
| 205 | - // Erase delimiters and environment variable | |
| 206 | - result.erase(index, begin_length+name_length+end_length); | |
| 212 | + // Initialise pointer on environment variable | |
| 213 | + const char* env = NULL; | |
| 214 | + | |
| 215 | + // Handle ~ | |
| 216 | + if (delim_idx == 5) { | |
| 217 | + if (name_length == 0) { | |
| 218 | + if ((env = std::getenv("HOME")) == NULL) { | |
| 219 | + struct passwd *pw = getpwuid(getuid()); | |
| 220 | + if (pw != NULL) { | |
| 221 | + env = pw->pw_dir; | |
| 222 | + } | |
| 223 | + } | |
| 224 | + } | |
| 225 | + else { | |
| 226 | + if (name == "+") { | |
| 227 | + env = std::getenv("PWD"); | |
| 228 | + } | |
| 229 | + else if (name == "-") { | |
| 230 | + env = std::getenv("OLDPWD"); | |
| 231 | + } | |
| 232 | + else { | |
| 233 | + struct passwd *pw = getpwnam(name.c_str()); | |
| 234 | + if (pw != NULL) { | |
| 235 | + env = pw->pw_dir; | |
| 236 | + } | |
| 237 | + } | |
| 238 | + } | |
| 239 | + } | |
| 207 | 240 | |
| 208 | - // Get the environment variable from the operating system | |
| 209 | - const char* env = std::getenv(name.c_str()); | |
| 241 | + // ... otherwise get the environment variable | |
| 242 | + else { | |
| 243 | + env = std::getenv(name.c_str()); | |
| 244 | + } | |
| 210 | 245 | |
| 211 | 246 | // If the environment variable has been found then replace |
| 212 | 247 | // it by its value |
| 213 | 248 | if (env != NULL) { |
| 214 | 249 | |
| 250 | + // Erase delimiters and environment variable | |
| 251 | + result.erase(index, begin_length+name_length+end_length); | |
| 252 | + | |
| 215 | 253 | // Set replacement string and its length |
| 216 | 254 | std::string replace(env); |
| 217 | 255 | size_t replace_length = replace.length(); |
| ... | ... | @@ -224,6 +262,12 @@ std::string gammalib::expand_env(const std::string& arg) |
| 224 | 262 | |
| 225 | 263 | } // endif: environment variable has been found |
| 226 | 264 | |
| 265 | + // If no environment variable has been found then set | |
| 266 | + // index=i_end+1 | |
| 267 | + else { | |
| 268 | + index = i_end + 1; | |
| 269 | + } | |
| 270 | + | |
| 227 | 271 | } // endif: termination delimiter found |
| 228 | 272 | |
| 229 | 273 | // If no environment variable has been found then set index=i_end+1 | ... | ... |
test/test_GSupport.cpp
| ... | ... | @@ -170,14 +170,14 @@ void TestGSupport::test_expand_env(void) |
| 170 | 170 | |
| 171 | 171 | // Non existing environment variable within string |
| 172 | 172 | s_in = "My $(HOMEIXYZ) is my castle."; |
| 173 | - s_ref = "My is my castle."; | |
| 173 | + s_ref = "My $(HOMEIXYZ) is my castle."; | |
| 174 | 174 | s_out = gammalib::expand_env(s_in); |
| 175 | 175 | test_assert(s_out == s_ref,"Non existing environment variable within string", |
| 176 | 176 | "Unexpected string \""+s_out+"\" (expected \""+s_ref+"\")"); |
| 177 | 177 | |
| 178 | 178 | // Empty environment variable within string |
| 179 | 179 | s_in = "My $() is my castle."; |
| 180 | - s_ref = "My is my castle."; | |
| 180 | + s_ref = "My $() is my castle."; | |
| 181 | 181 | s_out = gammalib::expand_env(s_in); |
| 182 | 182 | test_assert(s_out == s_ref,"Empty environment variable within string", |
| 183 | 183 | "Unexpected string \""+s_out+"\" (expected \""+s_ref+"\")"); |
| ... | ... | @@ -217,11 +217,19 @@ void TestGSupport::test_expand_env(void) |
| 217 | 217 | test_assert(s_out == s_ref,"$ENV{HOME}${HOME}$ENV(HOME)$(HOME) only string", |
| 218 | 218 | "Unexpected string \""+s_out+"\" (expected \""+s_ref+"\")"); |
| 219 | 219 | |
| 220 | - // Debugging | |
| 221 | - //std::cout << std::endl; | |
| 222 | - //std::cout << s_in << std::endl; | |
| 223 | - //std::cout << s_ref << std::endl; | |
| 224 | - //std::cout << s_out << std::endl; | |
| 220 | + // Test ~ | |
| 221 | + s_in = "My castle is ~"; | |
| 222 | + s_ref = gammalib::expand_env("My castle is $(HOME)"); | |
| 223 | + s_out = gammalib::expand_env(s_in); | |
| 224 | + test_assert(s_out == s_ref,"String with ~", | |
| 225 | + "Unexpected string \""+s_out+"\" (expected \""+s_ref+"\")"); | |
| 226 | + | |
| 227 | + // Test ~+ | |
| 228 | + s_in = "My castle is ~+"; | |
| 229 | + s_ref = gammalib::expand_env("My castle is $(PWD)"); | |
| 230 | + s_out = gammalib::expand_env(s_in); | |
| 231 | + test_assert(s_out == s_ref,"String with ~+", | |
| 232 | + "Unexpected string \""+s_out+"\" (expected \""+s_ref+"\")"); | |
| 225 | 233 | |
| 226 | 234 | // Exit test |
| 227 | 235 | return; | ... | ... |