Simplify the getenv use and handle the empty $HOME case
authorThiago Macieira <thiago.macieira@intel.com>
Sat, 29 Dec 2012 23:37:01 +0000 (21:37 -0200)
committerThiago Macieira <thiago.macieira@intel.com>
Thu, 31 Jan 2013 23:49:18 +0000 (00:49 +0100)
getenv(3) can return NULL if the variable isn't set. Some Standard
Library implementations (like Clang's libc++) do not like a NULL as
the argument to std::string's constructor, which is why the code is so
convoluted as it is. Instead, simplify the code by having a getenv
wrapper that has a default value.

And handle the case of the empty $HOME: currently, if it isn't set,
the application would crash. Instead, use getpwuid as a fallback.

Change-Id: I0185dbc7b026a5978b678207b31de90cba531623
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
src/qtchooser/main.cpp

index 33b2f62..b05c1b6 100644 (file)
@@ -68,6 +68,7 @@
 #  include <sys/types.h>
 #  include <dirent.h>
 #  include <libgen.h>
+#  include <pwd.h>
 #  include <unistd.h>
 #  define PATH_SEP "/"
 #  define EXE_SUFFIX ""
@@ -195,22 +196,38 @@ static vector<string> stringSplit(const char *source)
     return result;
 }
 
+static string qgetenv(const char *env, const string &defaultValue = string())
+{
+    const char *value = getenv(env);
+    return value ? string(value) : defaultValue;
+}
+
+static string userHome()
+{
+    const char *value = getenv("HOME");
+    if (value)
+        return value;
+
+#if defined(_WIN32) || defined(__WIN32__)
+    // ### FIXME: some Windows-specific code to get the user's home directory
+    // using GetUserProfileDirectory (userenv.h / dll)
+    return "C:";
+#else
+    struct passwd *pwd = getpwuid(getuid());
+    if (pwd && pwd->pw_dir)
+        return pwd->pw_dir;
+    return string();
+#endif
+}
+
 vector<string> ToolWrapper::searchPaths() const
 {
     vector<string> paths;
 
     // search the XDG config location directories
-    const char *globalDirs = getenv("XDG_CONFIG_DIRS");
-    paths = stringSplit(!globalDirs || !*globalDirs ? "/etc/xdg" : globalDirs);
-
-    string localDir;
-    const char *localDirEnv = getenv("XDG_CONFIG_HOME");
-    if (localDirEnv && *localDirEnv) {
-        localDir = localDirEnv;
-    } else {
-        localDir = getenv("HOME"); // accept empty $HOME too
-        localDir += "/.config";
-    }
+    paths = stringSplit(qgetenv("XDG_CONFIG_DIRS", "/etc/xdg").c_str());
+
+    string localDir = qgetenv("XDG_CONFIG_HOME", userHome() + PATH_SEP ".config");
     paths.push_back(localDir);
 
     for (vector<string>::iterator it = paths.begin(); it != paths.end(); ++it)