| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- // -*- mode: cpp; mode: fold -*-
- // Description /*{{{*/
- // $Id: dpkgpm.cc,v 1.9 1999/04/20 05:02:09 jgg Exp $
- /* ######################################################################
- DPKG Package Manager - Provide an interface to dpkg
-
- ##################################################################### */
- /*}}}*/
- // Includes /*{{{*/
- #ifdef __GNUG__
- #pragma implementation "apt-pkg/dpkgpm.h"
- #endif
- #include <apt-pkg/dpkgpm.h>
- #include <apt-pkg/error.h>
- #include <apt-pkg/configuration.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <errno.h>
- /*}}}*/
- // DPkgPM::pkgDPkgPM - Constructor /*{{{*/
- // ---------------------------------------------------------------------
- /* */
- pkgDPkgPM::pkgDPkgPM(pkgDepCache &Cache) : pkgPackageManager(Cache)
- {
- }
- /*}}}*/
- // DPkgPM::pkgDPkgPM - Destructor /*{{{*/
- // ---------------------------------------------------------------------
- /* */
- pkgDPkgPM::~pkgDPkgPM()
- {
- }
- /*}}}*/
- // DPkgPM::Install - Install a package /*{{{*/
- // ---------------------------------------------------------------------
- /* Add an install operation to the sequence list */
- bool pkgDPkgPM::Install(PkgIterator Pkg,string File)
- {
- if (File.empty() == true || Pkg.end() == true)
- return _error->Error("Internal Error, No file name for %s",Pkg.Name());
- List.push_back(Item(Item::Install,Pkg,File));
- return true;
- }
- /*}}}*/
- // DPkgPM::Configure - Configure a package /*{{{*/
- // ---------------------------------------------------------------------
- /* Add a configure operation to the sequence list */
- bool pkgDPkgPM::Configure(PkgIterator Pkg)
- {
- if (Pkg.end() == true)
- return false;
-
- List.push_back(Item(Item::Configure,Pkg));
- return true;
- }
- /*}}}*/
- // DPkgPM::Remove - Remove a package /*{{{*/
- // ---------------------------------------------------------------------
- /* Add a remove operation to the sequence list */
- bool pkgDPkgPM::Remove(PkgIterator Pkg)
- {
- if (Pkg.end() == true)
- return false;
-
- List.push_back(Item(Item::Remove,Pkg));
- return true;
- }
- /*}}}*/
- // DPkgPM::RunScripts - Run a set of scripts /*{{{*/
- // ---------------------------------------------------------------------
- /* This looks for a list of script sto run from the configuration file,
- each one is run with system from a forked child. */
- bool pkgDPkgPM::RunScripts(const char *Cnf)
- {
- Configuration::Item const *Opts = _config->Tree(Cnf);
- if (Opts == 0 || Opts->Child == 0)
- return true;
- Opts = Opts->Child;
- // Fork for running the system calls
- pid_t Child = ExecFork();
-
- // This is the child
- if (Child == 0)
- {
- if (chdir("/tmp/") != 0)
- _exit(100);
-
- unsigned int Count = 1;
- for (; Opts != 0; Opts = Opts->Next, Count++)
- {
- if (Opts->Value.empty() == true)
- continue;
-
- if (system(Opts->Value.c_str()) != 0)
- _exit(100+Count);
- }
- _exit(0);
- }
- // Wait for the child
- int Status = 0;
- while (waitpid(Child,&Status,0) != Child)
- {
- if (errno == EINTR)
- continue;
- return _error->Errno("waitpid","Couldn't wait for subprocess");
- }
- // Restore sig int/quit
- signal(SIGQUIT,SIG_DFL);
- signal(SIGINT,SIG_DFL);
-
- // Check for an error code.
- if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
- {
- unsigned int Count = WEXITSTATUS(Status);
- if (Count > 100)
- {
- Count -= 100;
- for (; Opts != 0 && Count != 1; Opts = Opts->Next, Count--);
- _error->Error("Problem executing scripts %s '%s'",Cnf,Opts->Value.c_str());
- }
-
- return _error->Error("Sub-process returned an error code");
- }
-
- return true;
- }
- /*}}}*/
- // DPkgPM::Go - Run the sequence /*{{{*/
- // ---------------------------------------------------------------------
- /* This globs the operations and calls dpkg */
- bool pkgDPkgPM::Go()
- {
- if (RunScripts("DPkg::Pre-Invoke") == false)
- return false;
-
- for (vector<Item>::iterator I = List.begin(); I != List.end();)
- {
- vector<Item>::iterator J = I;
- for (; J != List.end() && J->Op == I->Op; J++);
- // Generate the argument list
- const char *Args[400];
- if (J - I > 350)
- J = I + 350;
-
- unsigned int n = 0;
- unsigned long Size = 0;
- Args[n++] = _config->Find("Dir::Bin::dpkg","dpkg").c_str();
- Size += strlen(Args[n-1]);
-
- // Stick in any custom dpkg options
- Configuration::Item const *Opts = _config->Tree("DPkg::Options");
- if (Opts != 0)
- {
- Opts = Opts->Child;
- for (; Opts != 0; Opts = Opts->Next)
- {
- if (Opts->Value.empty() == true)
- continue;
- Args[n++] = Opts->Value.c_str();
- Size += Opts->Value.length();
- }
- }
-
- switch (I->Op)
- {
- case Item::Remove:
- Args[n++] = "--force-depends";
- Size += strlen(Args[n-1]);
- Args[n++] = "--force-remove-essential";
- Size += strlen(Args[n-1]);
- Args[n++] = "--remove";
- Size += strlen(Args[n-1]);
- break;
-
- case Item::Configure:
- Args[n++] = "--configure";
- Size += strlen(Args[n-1]);
- break;
-
- case Item::Install:
- Args[n++] = "--unpack";
- Size += strlen(Args[n-1]);
- break;
- }
-
- // Write in the file or package names
- if (I->Op == Item::Install)
- {
- 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]);
- }
- }
- else
- {
- for (;I != J && Size < 1024; I++)
- {
- Args[n++] = I->Pkg.Name();
- Size += strlen(Args[n-1]);
- }
- }
- Args[n] = 0;
- J = I;
-
- if (_config->FindB("Debug::pkgDPkgPM",false) == true)
- {
- for (unsigned int k = 0; k != n; k++)
- clog << Args[k] << ' ';
- clog << endl;
- continue;
- }
-
- cout << flush;
- clog << flush;
- cerr << flush;
- /* Mask off sig int/quit. We do this because dpkg also does when
- it forks scripts. What happens is that when you hit ctrl-c it sends
- it to all processes in the group. Since dpkg ignores the signal
- it doesn't die but we do! So we must also ignore it */
- signal(SIGQUIT,SIG_IGN);
- signal(SIGINT,SIG_IGN);
-
- // Fork dpkg
- pid_t Child = ExecFork();
-
- // This is the child
- if (Child == 0)
- {
- if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
- _exit(100);
-
- int Flags,dummy;
- if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
- _exit(100);
-
- // Discard everything in stdin before forking dpkg
- if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
- _exit(100);
-
- while (read(STDIN_FILENO,&dummy,1) == 1);
-
- if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
- _exit(100);
- /* No Job Control Stop Env is a magic dpkg var that prevents it
- from using sigstop */
- setenv("DPKG_NO_TSTP","yes",1);
- execvp(Args[0],(char **)Args);
- cerr << "Could not exec dpkg!" << endl;
- _exit(100);
- }
- // Wait for dpkg
- int Status = 0;
- while (waitpid(Child,&Status,0) != Child)
- {
- if (errno == EINTR)
- continue;
- RunScripts("DPkg::Post-Invoke");
- return _error->Errno("waitpid","Couldn't wait for subprocess");
- }
- // Restore sig int/quit
- signal(SIGQUIT,SIG_DFL);
- signal(SIGINT,SIG_DFL);
-
- // Check for an error code.
- if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
- {
- RunScripts("DPkg::Post-Invoke");
- if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
- return _error->Error("Sub-process recieved a segmentation fault.");
-
- if (WIFEXITED(Status) != 0)
- return _error->Error("Sub-process returned an error code (%u)",WEXITSTATUS(Status));
-
- return _error->Error("Sub-process exited unexpectedly");
- }
- }
- if (RunScripts("DPkg::Post-Invoke") == false)
- return false;
- return true;
- }
- /*}}}*/
|