diff --git a/src/exec.cc b/src/exec.cc
index e9ddb5ee14cad9e752a4e9ad074c8abc8cd83374..2e092b2e0dd6010d966048fa6258b9e6ebd98ead 100644
--- a/src/exec.cc
+++ b/src/exec.cc
@@ -54,11 +54,7 @@ void runProgram(const string & program,
 
     /* Create a temporary directory where the build will take
        place. */
-    static int counter = 0;
-    string tmpDir = (format("/tmp/nix-%1%-%2%") % getpid() % counter++).str();
-
-    if (mkdir(tmpDir.c_str(), 0777) == -1)
-        throw SysError(format("creating directory `%1%'") % tmpDir);
+    string tmpDir = createTempDir();
 
     AutoDelete delTmpDir(tmpDir);
 
diff --git a/src/util.cc b/src/util.cc
index bedd031def3d52bfe3f92a3498cf6ae213e11505..ed7562a29d735e6584e9d3e0e1b6575724cc1db1 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -171,6 +171,26 @@ void makePathReadOnly(const string & path)
 }
 
 
+static string tempName()
+{
+    static int counter = 0;
+    char * s = getenv("TMPDIR");
+    string tmpRoot = s ? canonPath(string(s)) : "/tmp";
+    return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
+}
+
+
+string createTempDir()
+{
+    while (1) {
+	string tmpDir = tempName();
+	if (mkdir(tmpDir.c_str(), 0777) == 0) return tmpDir;
+	if (errno != EEXIST)
+	    throw SysError(format("creating directory `%1%'") % tmpDir);
+    }
+}
+
+
 Verbosity verbosity = lvlError;
 
 static int nestingLevel = 0;
diff --git a/src/util.hh b/src/util.hh
index d0e42f3b1707db47d5dc927df60eee170b3543fc..31dba7fafedd96d146222805cca7f6c7cfffa109 100644
--- a/src/util.hh
+++ b/src/util.hh
@@ -72,6 +72,9 @@ void deletePath(const string & path);
 /* Make a path read-only recursively. */
 void makePathReadOnly(const string & path);
 
+/* Create a temporary directory. */
+string createTempDir();
+
 
 /* Messages. */