+static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) {
+ if (Path == 0)
+ // Noop
+ return false;
+ std::string File;
+ if (Path->isEmpty())
+ // Redirect empty paths to /dev/null
+ File = "/dev/null";
+ else
+ File = Path->toString();
+
+ // Open the file
+ int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
+ if (InFD == -1) {
+ MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
+ + (FD == 0 ? "input" : "output"));
+ return true;
+ }
+
+ // Install it as the requested FD
+ if (-1 == dup2(InFD, FD)) {
+ MakeErrMsg(ErrMsg, "Cannot dup2");
+ return true;
+ }
+ close(InFD); // Close the original FD
+ return false;
+}
+
+static bool Timeout = false;
+static void TimeOutHandler(int Sig) {
+ Timeout = true;
+}
+
+static void SetMemoryLimits (unsigned size)
+{
+#if HAVE_SYS_RESOURCE_H
+ struct rlimit r;
+ __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
+
+ // Heap size
+ getrlimit (RLIMIT_DATA, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_DATA, &r);
+#ifdef RLIMIT_RSS
+ // Resident set size.
+ getrlimit (RLIMIT_RSS, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_RSS, &r);
+#endif
+#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it.
+ // Virtual memory.
+ getrlimit (RLIMIT_AS, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_AS, &r);
+#endif
+#endif
+}
+