+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (write == true)
+ {
+ int Res;
+ do
+ {
+ Res = select(Fd+1,0,&Set,0,(timeout != 0?&tv:0));
+ }
+ while (Res < 0 && errno == EINTR);
+
+ if (Res <= 0)
+ return false;
+ }
+ else
+ {
+ int Res;
+ do
+ {
+ Res = select(Fd+1,&Set,0,0,(timeout != 0?&tv:0));
+ }
+ while (Res < 0 && errno == EINTR);
+
+ if (Res <= 0)
+ return false;
+ }
+
+ return true;
+}
+ /*}}}*/
+// ExecFork - Magical fork that sanitizes the context before execing /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used if you want to cleanse the environment for the forked
+ child, it fixes up the important signals and nukes all of the fds,
+ otherwise acts like normal fork. */
+pid_t ExecFork()
+{
+ // Fork off the process
+ pid_t Process = fork();
+ if (Process < 0)
+ {
+ cerr << "FATAL -> Failed to fork." << endl;
+ exit(100);
+ }
+
+ // Spawn the subprocess
+ if (Process == 0)
+ {
+ // Setup the signals
+ signal(SIGPIPE,SIG_DFL);
+ signal(SIGQUIT,SIG_DFL);
+ signal(SIGINT,SIG_DFL);
+ signal(SIGWINCH,SIG_DFL);
+ signal(SIGCONT,SIG_DFL);
+ signal(SIGTSTP,SIG_DFL);
+
+ set<int> KeepFDs;
+ Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds");
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ int fd = atoi(Opts->Value.c_str());
+ KeepFDs.insert(fd);
+ }
+ }
+
+ // Close all of our FDs - just in case
+ for (int K = 3; K != 40; K++)
+ {
+ if(KeepFDs.find(K) == KeepFDs.end())
+ fcntl(K,F_SETFD,FD_CLOEXEC);
+ }
+ }
+
+ return Process;
+}
+ /*}}}*/
+// ExecWait - Fancy waitpid /*{{{*/
+// ---------------------------------------------------------------------
+/* Waits for the given sub process. If Reap is set then no errors are
+ generated. Otherwise a failed subprocess will generate a proper descriptive
+ message */
+bool ExecWait(pid_t Pid,const char *Name,bool Reap)
+{
+ if (Pid <= 1)
+ return true;
+
+ // Wait and collect the error code
+ int Status;
+ while (waitpid(Pid,&Status,0) != Pid)
+ {
+ if (errno == EINTR)
+ continue;
+
+ if (Reap == true)
+ return false;
+
+ return _error->Error(_("Waited for %s but it wasn't there"),Name);
+ }
+
+
+ // Check for an error code.
+ if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
+ {
+ if (Reap == true)
+ return false;
+ if (WIFSIGNALED(Status) != 0)
+ {
+ if( WTERMSIG(Status) == SIGSEGV)
+ return _error->Error(_("Sub-process %s received a segmentation fault."),Name);
+ else
+ return _error->Error(_("Sub-process %s received signal %u."),Name, WTERMSIG(Status));
+ }
+
+ if (WIFEXITED(Status) != 0)
+ return _error->Error(_("Sub-process %s returned an error code (%u)"),Name,WEXITSTATUS(Status));
+
+ return _error->Error(_("Sub-process %s exited unexpectedly"),Name);
+ }
+