X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/6dd55be709d9dffdd380467193e0256ded60beb8..7834cb579fe88a11bd3850363bbd4c77797581bb:/apt-pkg/deb/dpkgpm.cc diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 9322a868d..a9982bc34 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: dpkgpm.cc,v 1.6 1999/01/31 08:49:39 jgg Exp $ +// $Id: dpkgpm.cc,v 1.16 1999/12/12 03:48:36 jgg Exp $ /* ###################################################################### DPKG Package Manager - Provide an interface to dpkg @@ -22,6 +22,7 @@ #include #include #include +#include /*}}}*/ // DPkgPM::pkgDPkgPM - Constructor /*{{{*/ @@ -65,12 +66,15 @@ bool pkgDPkgPM::Configure(PkgIterator Pkg) // DPkgPM::Remove - Remove a package /*{{{*/ // --------------------------------------------------------------------- /* Add a remove operation to the sequence list */ -bool pkgDPkgPM::Remove(PkgIterator Pkg) +bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge) { if (Pkg.end() == true) return false; - List.push_back(Item(Item::Remove,Pkg)); + if (Purge == true) + List.push_back(Item(Item::Purge,Pkg)); + else + List.push_back(Item(Item::Remove,Pkg)); return true; } /*}}}*/ @@ -86,27 +90,14 @@ bool pkgDPkgPM::RunScripts(const char *Cnf) Opts = Opts->Child; // Fork for running the system calls - pid_t Child = fork(); - if (Child < 0) - return _error->Errno("fork","Could't fork"); + pid_t Child = ExecFork(); // This is the child if (Child == 0) { - signal(SIGPIPE,SIG_DFL); - signal(SIGQUIT,SIG_DFL); - signal(SIGINT,SIG_DFL); - signal(SIGWINCH,SIG_DFL); - signal(SIGCONT,SIG_DFL); - signal(SIGTSTP,SIG_DFL); - if (chdir("/tmp/") != 0) _exit(100); - // Close all of our FDs - just in case - for (int K = 3; K != 40; K++) - fcntl(K,F_SETFD,FD_CLOEXEC); - unsigned int Count = 1; for (; Opts != 0; Opts = Opts->Next, Count++) { @@ -131,7 +122,7 @@ bool pkgDPkgPM::RunScripts(const char *Cnf) // Restore sig int/quit signal(SIGQUIT,SIG_DFL); signal(SIGINT,SIG_DFL); - + // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { @@ -140,7 +131,7 @@ bool pkgDPkgPM::RunScripts(const char *Cnf) { Count -= 100; for (; Opts != 0 && Count != 1; Opts = Opts->Next, Count--); - _error->Error("Probablem executing scripts %s '%s'",Cnf,Opts->Value.c_str()); + _error->Error("Problem executing scripts %s '%s'",Cnf,Opts->Value.c_str()); } return _error->Error("Sub-process returned an error code"); @@ -148,6 +139,86 @@ bool pkgDPkgPM::RunScripts(const char *Cnf) return true; } + + /*}}}*/ +// DPkgPM::RunScriptsWithPkgs - Run scripts with package names on stdin /*{{{*/ +// --------------------------------------------------------------------- +/* This looks for a list of scripts to run from the configuration file + each one is run and is fed on standard input a list of all .deb files + that are due to be installed. */ +bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) +{ + Configuration::Item const *Opts = _config->Tree(Cnf); + if (Opts == 0 || Opts->Child == 0) + return true; + Opts = Opts->Child; + + unsigned int Count = 1; + for (; Opts != 0; Opts = Opts->Next, Count++) + { + if (Opts->Value.empty() == true) + continue; + + // Create the pipes + int Pipes[2]; + if (pipe(Pipes) != 0) + return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); + SetCloseExec(Pipes[0],true); + SetCloseExec(Pipes[1],true); + + // Purified Fork for running the script + pid_t Process = ExecFork(); + if (Process == 0) + { + // Setup the FDs + dup2(Pipes[0],STDIN_FILENO); + SetCloseExec(STDOUT_FILENO,false); + SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDERR_FILENO,false); + + const char *Args[4]; + Args[0] = "/bin/sh"; + Args[1] = "-c"; + Args[2] = Opts->Value.c_str(); + Args[3] = 0; + execv(Args[0],(char **)Args); + _exit(100); + } + close(Pipes[0]); + FileFd Fd(Pipes[1]); + + // Feed it the filenames. + for (vector::iterator I = List.begin(); I != List.end(); I++) + { + // Only deal with packages to be installed from .deb + if (I->Op != Item::Install) + continue; + + // No errors here.. + if (I->File[0] != '/') + continue; + + /* Feed the filename of each package that is pending install + into the pipe. */ + if (Fd.Write(I->File.begin(),I->File.length()) == false || + Fd.Write("\n",1) == false) + { + kill(Process,SIGINT); + Fd.Close(); + ExecWait(Process,Opts->Value.c_str(),true); + return _error->Error("Failure running script %s",Opts->Value.c_str()); + } + } + Fd.Close(); + + // Clean up the sub process + if (ExecWait(Process,Opts->Value.c_str()) == false) + return _error->Error("Failure running script %s",Opts->Value.c_str()); + } + + return true; +} + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -156,7 +227,10 @@ bool pkgDPkgPM::Go() { if (RunScripts("DPkg::Pre-Invoke") == false) return false; - + + if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false) + return false; + for (vector::iterator I = List.begin(); I != List.end();) { vector::iterator J = I; @@ -197,6 +271,15 @@ bool pkgDPkgPM::Go() Size += strlen(Args[n-1]); break; + case Item::Purge: + Args[n++] = "--force-depends"; + Size += strlen(Args[n-1]); + Args[n++] = "--force-remove-essential"; + Size += strlen(Args[n-1]); + Args[n++] = "--purge"; + Size += strlen(Args[n-1]); + break; + case Item::Configure: Args[n++] = "--configure"; Size += strlen(Args[n-1]); @@ -213,6 +296,8 @@ bool pkgDPkgPM::Go() { for (;I != J && Size < 1024; I++) { + if (I->File[0] != '/') + return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str()); Args[n++] = I->File.c_str(); Size += strlen(Args[n-1]); } @@ -248,27 +333,14 @@ bool pkgDPkgPM::Go() signal(SIGINT,SIG_IGN); // Fork dpkg - pid_t Child = fork(); - if (Child < 0) - return _error->Errno("fork","Could't fork"); + pid_t Child = ExecFork(); // This is the child if (Child == 0) { - signal(SIGPIPE,SIG_DFL); - signal(SIGQUIT,SIG_DFL); - signal(SIGINT,SIG_DFL); - signal(SIGWINCH,SIG_DFL); - signal(SIGCONT,SIG_DFL); - signal(SIGTSTP,SIG_DFL); - - if (chdir(_config->FindDir("Dir::Cache::Archives").c_str()) != 0) + if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0) _exit(100); - // Close all of our FDs - just in case - for (int K = 3; K != 40; K++) - fcntl(K,F_SETFD,FD_CLOEXEC); - int Flags,dummy; if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0) _exit(100); @@ -284,7 +356,7 @@ bool pkgDPkgPM::Go() /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ - setenv("DPKG_NO_TSTP","yes",1); + putenv("DPKG_NO_TSTP=yes"); execvp(Args[0],(char **)Args); cerr << "Could not exec dpkg!" << endl; _exit(100); @@ -308,7 +380,13 @@ bool pkgDPkgPM::Go() if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { RunScripts("DPkg::Post-Invoke"); - return _error->Error("Sub-process returned an error code"); + if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) + return _error->Error("Sub-process %s recieved a segmentation fault.",Args[0]); + + if (WIFEXITED(Status) != 0) + return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status)); + + return _error->Error("Sub-process %s exited unexpectedly",Args[0]); } } @@ -317,3 +395,11 @@ bool pkgDPkgPM::Go() return true; } /*}}}*/ +// pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgDPkgPM::Reset() +{ + List.erase(List.begin(),List.end()); +} + /*}}}*/