dpkgpm.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: dpkgpm.cc,v 1.1 1998/11/13 04:23:39 jgg Exp $
  4. /* ######################################################################
  5. DPKG Package Manager - Provide an interface to dpkg
  6. ##################################################################### */
  7. /*}}}*/
  8. // Includes /*{{{*/
  9. #ifdef __GNUG__
  10. #pragma implementation "apt-pkg/dpkgpm.h"
  11. #endif
  12. #include <apt-pkg/dpkgpm.h>
  13. #include <apt-pkg/error.h>
  14. #include <apt-pkg/configuration.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <fcntl.h>
  18. #include <sys/types.h>
  19. #include <sys/wait.h>
  20. #include <signal.h>
  21. #include <errno.h>
  22. /*}}}*/
  23. // DPkgPM::pkgDPkgPM - Constructor /*{{{*/
  24. // ---------------------------------------------------------------------
  25. /* */
  26. pkgDPkgPM::pkgDPkgPM(pkgDepCache &Cache) : pkgPackageManager(Cache)
  27. {
  28. }
  29. /*}}}*/
  30. // DPkgPM::pkgDPkgPM - Destructor /*{{{*/
  31. // ---------------------------------------------------------------------
  32. /* */
  33. pkgDPkgPM::~pkgDPkgPM()
  34. {
  35. }
  36. /*}}}*/
  37. // DPkgPM::Install - Install a package /*{{{*/
  38. // ---------------------------------------------------------------------
  39. /* Add an install operation to the sequence list */
  40. bool pkgDPkgPM::Install(PkgIterator Pkg,string File)
  41. {
  42. if (File.empty() == true || Pkg.end() == true)
  43. return _error->Error("Internal Error, No file name for %s",Pkg.Name());
  44. List.push_back(Item(Item::Install,Pkg,File));
  45. return true;
  46. }
  47. /*}}}*/
  48. // DPkgPM::Configure - Configure a package /*{{{*/
  49. // ---------------------------------------------------------------------
  50. /* Add a configure operation to the sequence list */
  51. bool pkgDPkgPM::Configure(PkgIterator Pkg)
  52. {
  53. if (Pkg.end() == true)
  54. return false;
  55. List.push_back(Item(Item::Configure,Pkg));
  56. return true;
  57. }
  58. /*}}}*/
  59. // DPkgPM::Remove - Remove a package /*{{{*/
  60. // ---------------------------------------------------------------------
  61. /* Add a remove operation to the sequence list */
  62. bool pkgDPkgPM::Remove(PkgIterator Pkg)
  63. {
  64. if (Pkg.end() == true)
  65. return false;
  66. List.push_back(Item(Item::Remove,Pkg));
  67. return true;
  68. }
  69. /*}}}*/
  70. // DPkgPM::Go - Run the sequence /*{{{*/
  71. // ---------------------------------------------------------------------
  72. /* This globs the operations and calls dpkg */
  73. bool pkgDPkgPM::Go()
  74. {
  75. for (vector<Item>::iterator I = List.begin(); I != List.end();)
  76. {
  77. vector<Item>::iterator J = I;
  78. for (; J != List.end() && J->Op == I->Op; J++);
  79. // Generate the argument list
  80. const char *Args[400];
  81. if (J - I > 350)
  82. J = I + 350;
  83. int n= 0;
  84. Args[n++] = "dpkg";
  85. switch (I->Op)
  86. {
  87. case Item::Remove:
  88. Args[n++] = "--force-depends";
  89. Args[n++] = "--force-remove-essential";
  90. Args[n++] = "--remove";
  91. break;
  92. case Item::Configure:
  93. Args[n++] = "--configure";
  94. break;
  95. case Item::Install:
  96. Args[n++] = "--unpack";
  97. break;
  98. }
  99. // Write in the file or package names
  100. if (I->Op == Item::Install)
  101. for (;I != J; I++)
  102. Args[n++] = I->File.c_str();
  103. else
  104. for (;I != J; I++)
  105. Args[n++] = I->Pkg.Name();
  106. Args[n] = 0;
  107. /* for (int k = 0; k != n; k++)
  108. cout << Args[k] << ' ';
  109. cout << endl;*/
  110. cout << flush;
  111. clog << flush;
  112. cerr << flush;
  113. /* Mask off sig int/quit. We do this because dpkg also does when
  114. it forks scripts. What happens is that when you hit ctrl-c it sends
  115. it to all processes in the group. Since dpkg ignores the signal
  116. it doesn't die but we do! So we must also ignore it */
  117. signal(SIGQUIT,SIG_IGN);
  118. signal(SIGINT,SIG_IGN);
  119. // Fork dpkg
  120. pid_t Child = fork();
  121. if (Child < 0)
  122. return _error->Errno("fork","Could't fork");
  123. // This is the child
  124. if (Child == 0)
  125. {
  126. signal(SIGQUIT,SIG_DFL);
  127. signal(SIGINT,SIG_DFL);
  128. signal(SIGWINCH,SIG_DFL);
  129. signal(SIGCONT,SIG_DFL);
  130. signal(SIGTSTP,SIG_DFL);
  131. if (chdir(_config->FindDir("Dir::Cache::Archives").c_str()) != 0)
  132. exit(100);
  133. // Close all of our FDs - just in case
  134. for (int K = 3; K != 40; K++)
  135. fcntl(K,F_SETFD,FD_CLOEXEC);
  136. int Flags,dummy;
  137. if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
  138. exit(100);
  139. // Discard everything in stdin before forking dpkg
  140. if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
  141. exit(100);
  142. while (read(STDIN_FILENO,&dummy,1) == 1);
  143. if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
  144. exit(100);
  145. /* No Job Control Stop Env is a magic dpkg var that prevents it
  146. from using sigstop */
  147. setenv("DPKG_NO_TSTP","yes",1);
  148. execvp("dpkg",(char **)Args);
  149. cerr << "Could not exec dpkg!" << endl;
  150. exit(100);
  151. }
  152. // Wait for dpkg
  153. int Status = 0;
  154. while (waitpid(Child,&Status,0) != Child)
  155. {
  156. if (errno == EINTR)
  157. continue;
  158. return _error->Errno("waitpid","Couldn't wait for subprocess");
  159. }
  160. // Check for an error code.
  161. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
  162. return _error->Error("Sub-process returned an error code");
  163. // Restore sig int/quit
  164. signal(SIGQUIT,SIG_DFL);
  165. signal(SIGINT,SIG_DFL);
  166. }
  167. return true;
  168. }
  169. /*}}}*/