1 // -*- mode: cpp; mode: fold -*-
3 // $Id: dpkgpm.cc,v 1.28 2004/01/27 02:25:01 mdz Exp $
4 /* ######################################################################
6 DPKG Package Manager - Provide an interface to dpkg
8 ##################################################################### */
11 #include <apt-pkg/dpkgpm.h>
12 #include <apt-pkg/error.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/depcache.h>
15 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/fileutl.h>
22 #include <sys/select.h>
23 #include <sys/types.h>
35 #include <sys/ioctl.h>
47 // Maps the dpkg "processing" info to human readable names. Entry 0
48 // of each array is the key, entry 1 is the value.
49 const std::pair<const char *, const char *> PackageProcessingOps[] = {
50 std::make_pair("install", N_("Installing %s")),
51 std::make_pair("configure", N_("Configuring %s")),
52 std::make_pair("remove", N_("Removing %s")),
53 std::make_pair("purge", N_("Completely removing %s")),
54 std::make_pair("trigproc", N_("Running post-installation trigger %s"))
57 const std::pair<const char *, const char *> * const PackageProcessingOpsBegin = PackageProcessingOps;
58 const std::pair<const char *, const char *> * const PackageProcessingOpsEnd = PackageProcessingOps + sizeof(PackageProcessingOps) / sizeof(PackageProcessingOps[0]);
60 // Predicate to test whether an entry in the PackageProcessingOps
61 // array matches a string.
62 class MatchProcessingOp
67 MatchProcessingOp(const char *the_target)
72 bool operator()(const std::pair<const char *, const char *> &pair) const
74 return strcmp(pair.first, target) == 0;
79 /* helper function to ionice the given PID
81 there is no C header for ionice yet - just the syscall interface
82 so we use the binary from util-linux
87 if (!FileExists("/usr/bin/ionice"))
89 pid_t Process = ExecFork();
93 snprintf(buf, sizeof(buf), "-p%d", PID);
95 Args[0] = "/usr/bin/ionice";
99 execv(Args[0], (char **)Args);
101 return ExecWait(Process, "ionice");
104 // DPkgPM::pkgDPkgPM - Constructor /*{{{*/
105 // ---------------------------------------------------------------------
107 pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
108 : pkgPackageManager(Cache), dpkgbuf_pos(0),
109 term_out(NULL), PackagesDone(0), PackagesTotal(0)
113 // DPkgPM::pkgDPkgPM - Destructor /*{{{*/
114 // ---------------------------------------------------------------------
116 pkgDPkgPM::~pkgDPkgPM()
120 // DPkgPM::Install - Install a package /*{{{*/
121 // ---------------------------------------------------------------------
122 /* Add an install operation to the sequence list */
123 bool pkgDPkgPM::Install(PkgIterator Pkg,string File)
125 if (File.empty() == true || Pkg.end() == true)
126 return _error->Error("Internal Error, No file name for %s",Pkg.Name());
128 List.push_back(Item(Item::Install,Pkg,File));
132 // DPkgPM::Configure - Configure a package /*{{{*/
133 // ---------------------------------------------------------------------
134 /* Add a configure operation to the sequence list */
135 bool pkgDPkgPM::Configure(PkgIterator Pkg)
137 if (Pkg.end() == true)
140 List.push_back(Item(Item::Configure, Pkg));
142 // Use triggers for config calls if we configure "smart"
143 // as otherwise Pre-Depends will not be satisfied, see #526774
144 if (_config->FindB("DPkg::TriggersPending", false) == true)
145 List.push_back(Item(Item::TriggersPending, PkgIterator()));
150 // DPkgPM::Remove - Remove a package /*{{{*/
151 // ---------------------------------------------------------------------
152 /* Add a remove operation to the sequence list */
153 bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge)
155 if (Pkg.end() == true)
159 List.push_back(Item(Item::Purge,Pkg));
161 List.push_back(Item(Item::Remove,Pkg));
165 // DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/
166 // ---------------------------------------------------------------------
167 /* This is part of the helper script communication interface, it sends
168 very complete information down to the other end of the pipe.*/
169 bool pkgDPkgPM::SendV2Pkgs(FILE *F)
171 fprintf(F,"VERSION 2\n");
173 /* Write out all of the configuration directives by walking the
174 configuration tree */
175 const Configuration::Item *Top = _config->Tree(0);
178 if (Top->Value.empty() == false)
181 QuoteString(Top->FullTag(),"=\"\n").c_str(),
182 QuoteString(Top->Value,"\n").c_str());
191 while (Top != 0 && Top->Next == 0)
198 // Write out the package actions in order.
199 for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
201 if(I->Pkg.end() == true)
204 pkgDepCache::StateCache &S = Cache[I->Pkg];
206 fprintf(F,"%s ",I->Pkg.Name());
208 if (I->Pkg->CurrentVer == 0)
211 fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr());
213 // Show the compare operator
215 if (S.InstallVer != 0)
218 if (I->Pkg->CurrentVer != 0)
219 Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer());
226 fprintf(F,"%s ",S.InstVerIter(Cache).VerStr());
231 // Show the filename/operation
232 if (I->Op == Item::Install)
235 if (I->File[0] != '/')
236 fprintf(F,"**ERROR**\n");
238 fprintf(F,"%s\n",I->File.c_str());
240 if (I->Op == Item::Configure)
241 fprintf(F,"**CONFIGURE**\n");
242 if (I->Op == Item::Remove ||
243 I->Op == Item::Purge)
244 fprintf(F,"**REMOVE**\n");
252 // DPkgPM::RunScriptsWithPkgs - Run scripts with package names on stdin /*{{{*/
253 // ---------------------------------------------------------------------
254 /* This looks for a list of scripts to run from the configuration file
255 each one is run and is fed on standard input a list of all .deb files
256 that are due to be installed. */
257 bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
259 Configuration::Item const *Opts = _config->Tree(Cnf);
260 if (Opts == 0 || Opts->Child == 0)
264 unsigned int Count = 1;
265 for (; Opts != 0; Opts = Opts->Next, Count++)
267 if (Opts->Value.empty() == true)
270 // Determine the protocol version
271 string OptSec = Opts->Value;
272 string::size_type Pos;
273 if ((Pos = OptSec.find(' ')) == string::npos || Pos == 0)
274 Pos = OptSec.length();
275 OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos);
277 unsigned int Version = _config->FindI(OptSec+"::Version",1);
281 if (pipe(Pipes) != 0)
282 return _error->Errno("pipe","Failed to create IPC pipe to subprocess");
283 SetCloseExec(Pipes[0],true);
284 SetCloseExec(Pipes[1],true);
286 // Purified Fork for running the script
287 pid_t Process = ExecFork();
291 dup2(Pipes[0],STDIN_FILENO);
292 SetCloseExec(STDOUT_FILENO,false);
293 SetCloseExec(STDIN_FILENO,false);
294 SetCloseExec(STDERR_FILENO,false);
299 Args[2] = Opts->Value.c_str();
301 execv(Args[0],(char **)Args);
305 FILE *F = fdopen(Pipes[1],"w");
307 return _error->Errno("fdopen","Faild to open new FD");
309 // Feed it the filenames.
313 for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
315 // Only deal with packages to be installed from .deb
316 if (I->Op != Item::Install)
320 if (I->File[0] != '/')
323 /* Feed the filename of each package that is pending install
325 fprintf(F,"%s\n",I->File.c_str());
334 Die = !SendV2Pkgs(F);
338 // Clean up the sub process
339 if (ExecWait(Process,Opts->Value.c_str()) == false)
340 return _error->Error("Failure running script %s",Opts->Value.c_str());
347 // DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
348 // ---------------------------------------------------------------------
351 void pkgDPkgPM::DoStdin(int master)
353 unsigned char input_buf[256] = {0,};
354 ssize_t len = read(0, input_buf, sizeof(input_buf));
356 write(master, input_buf, len);
358 stdin_is_dev_null = true;
361 // DPkgPM::DoTerminalPty - Read the terminal pty and write log /*{{{*/
362 // ---------------------------------------------------------------------
364 * read the terminal pty and write log
366 void pkgDPkgPM::DoTerminalPty(int master)
368 unsigned char term_buf[1024] = {0,0, };
370 ssize_t len=read(master, term_buf, sizeof(term_buf));
371 if(len == -1 && errno == EIO)
373 // this happens when the child is about to exit, we
374 // give it time to actually exit, otherwise we run
381 write(1, term_buf, len);
383 fwrite(term_buf, len, sizeof(char), term_out);
386 // DPkgPM::ProcessDpkgStatusBuf /*{{{*/
387 // ---------------------------------------------------------------------
390 void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
392 bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false);
393 // the status we output
394 ostringstream status;
397 std::clog << "got from dpkg '" << line << "'" << std::endl;
400 /* dpkg sends strings like this:
401 'status: <pkg>: <pkg qstate>'
402 errors look like this:
403 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data
404 and conffile-prompt like this
405 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited
407 Newer versions of dpkg sent also:
408 'processing: install: pkg'
409 'processing: configure: pkg'
410 'processing: remove: pkg'
411 'processing: purge: pkg' - but for apt is it a ignored "unknown" action
412 'processing: trigproc: trigger'
416 // dpkg sends multiline error messages sometimes (see
417 // #374195 for a example. we should support this by
418 // either patching dpkg to not send multiline over the
419 // statusfd or by rewriting the code here to deal with
420 // it. for now we just ignore it and not crash
421 TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
422 if( list[0] == NULL || list[1] == NULL || list[2] == NULL)
425 std::clog << "ignoring line: not enough ':'" << std::endl;
428 const char* const pkg = list[1];
429 const char* action = _strstrip(list[2]);
431 // 'processing' from dpkg looks like
432 // 'processing: action: pkg'
433 if(strncmp(list[0], "processing", strlen("processing")) == 0)
436 const char* const pkg_or_trigger = _strstrip(list[2]);
437 action = _strstrip( list[1]);
438 const std::pair<const char *, const char *> * const iter =
439 std::find_if(PackageProcessingOpsBegin,
440 PackageProcessingOpsEnd,
441 MatchProcessingOp(action));
442 if(iter == PackageProcessingOpsEnd)
445 std::clog << "ignoring unknown action: " << action << std::endl;
448 snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
450 status << "pmstatus:" << pkg_or_trigger
451 << ":" << (PackagesDone/float(PackagesTotal)*100.0)
455 write(OutStatusFd, status.str().c_str(), status.str().size());
457 std::clog << "send: '" << status.str() << "'" << endl;
461 if(strncmp(action,"error",strlen("error")) == 0)
463 status << "pmerror:" << list[1]
464 << ":" << (PackagesDone/float(PackagesTotal)*100.0)
468 write(OutStatusFd, status.str().c_str(), status.str().size());
470 std::clog << "send: '" << status.str() << "'" << endl;
473 else if(strncmp(action,"conffile",strlen("conffile")) == 0)
475 status << "pmconffile:" << list[1]
476 << ":" << (PackagesDone/float(PackagesTotal)*100.0)
480 write(OutStatusFd, status.str().c_str(), status.str().size());
482 std::clog << "send: '" << status.str() << "'" << endl;
486 vector<struct DpkgState> const &states = PackageOps[pkg];
487 const char *next_action = NULL;
488 if(PackageOpsDone[pkg] < states.size())
489 next_action = states[PackageOpsDone[pkg]].state;
490 // check if the package moved to the next dpkg state
491 if(next_action && (strcmp(action, next_action) == 0))
493 // only read the translation if there is actually a next
495 const char *translation = _(states[PackageOpsDone[pkg]].str);
497 snprintf(s, sizeof(s), translation, pkg);
499 // we moved from one dpkg state to a new one, report that
500 PackageOpsDone[pkg]++;
502 // build the status str
503 status << "pmstatus:" << pkg
504 << ":" << (PackagesDone/float(PackagesTotal)*100.0)
508 write(OutStatusFd, status.str().c_str(), status.str().size());
510 std::clog << "send: '" << status.str() << "'" << endl;
513 std::clog << "(parsed from dpkg) pkg: " << pkg
514 << " action: " << action << endl;
517 // DPkgPM::DoDpkgStatusFd /*{{{*/
518 // ---------------------------------------------------------------------
521 void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
526 len=read(statusfd, &dpkgbuf[dpkgbuf_pos], sizeof(dpkgbuf)-dpkgbuf_pos);
531 // process line by line if we have a buffer
533 while((q=(char*)memchr(p, '\n', dpkgbuf+dpkgbuf_pos-p)) != NULL)
536 ProcessDpkgStatusLine(OutStatusFd, p);
537 p=q+1; // continue with next line
540 // now move the unprocessed bits (after the final \n that is now a 0x0)
541 // to the start and update dpkgbuf_pos
542 void *memrchr(void const *, int, size_t);
543 p = (char*)memrchr(dpkgbuf, 0, dpkgbuf_pos);
547 // we are interessted in the first char *after* 0x0
550 // move the unprocessed tail to the start and update pos
551 memmove(dpkgbuf, p, p-dpkgbuf);
552 dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
555 // DPkgPM::OpenLog /*{{{*/
556 bool pkgDPkgPM::OpenLog()
558 string logdir = _config->FindDir("Dir::Log");
559 if(not FileExists(logdir))
560 return _error->Error(_("Directory '%s' missing"), logdir.c_str());
561 string logfile_name = flCombine(logdir,
562 _config->Find("Dir::Log::Terminal"));
563 if (!logfile_name.empty())
565 term_out = fopen(logfile_name.c_str(),"a");
566 if (term_out == NULL)
567 return _error->WarningE(_("Could not open file '%s'"), logfile_name.c_str());
569 chmod(logfile_name.c_str(), 0600);
570 // output current time
572 time_t t = time(NULL);
573 struct tm *tmp = localtime(&t);
574 strftime(outstr, sizeof(outstr), "%F %T", tmp);
575 fprintf(term_out, "\nLog started: %s\n", outstr);
580 // DPkg::CloseLog /*{{{*/
581 bool pkgDPkgPM::CloseLog()
586 time_t t = time(NULL);
587 struct tm *tmp = localtime(&t);
588 strftime(outstr, sizeof(outstr), "%F %T", tmp);
589 fprintf(term_out, "Log ended: ");
590 fprintf(term_out, "%s", outstr);
591 fprintf(term_out, "\n");
599 // This implements a racy version of pselect for those architectures
600 // that don't have a working implementation.
601 // FIXME: Probably can be removed on Lenny+1
602 static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
603 fd_set *exceptfds, const struct timespec *timeout,
604 const sigset_t *sigmask)
610 tv.tv_sec = timeout->tv_sec;
611 tv.tv_usec = timeout->tv_nsec/1000;
613 sigprocmask(SIG_SETMASK, sigmask, &origmask);
614 retval = select(nfds, readfds, writefds, exceptfds, &tv);
615 sigprocmask(SIG_SETMASK, &origmask, 0);
619 // DPkgPM::Go - Run the sequence /*{{{*/
620 // ---------------------------------------------------------------------
621 /* This globs the operations and calls dpkg
623 * If it is called with "OutStatusFd" set to a valid file descriptor
624 * apt will report the install progress over this fd. It maps the
625 * dpkg states a package goes through to human readable (and i10n-able)
626 * names and calculates a percentage for each step.
628 bool pkgDPkgPM::Go(int OutStatusFd)
633 sigset_t original_sigmask;
635 unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
636 unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
637 bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false);
639 if (RunScripts("DPkg::Pre-Invoke") == false)
642 if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
645 // support subpressing of triggers processing for special
646 // cases like d-i that runs the triggers handling manually
647 bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all");
648 bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);
649 if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true)
650 List.push_back(Item(Item::ConfigurePending, PkgIterator()));
652 // map the dpkg states to the operations that are performed
653 // (this is sorted in the same way as Item::Ops)
654 static const struct DpkgState DpkgStatesOpMap[][7] = {
657 {"half-installed", N_("Preparing %s")},
658 {"unpacked", N_("Unpacking %s") },
661 // Configure operation
663 {"unpacked",N_("Preparing to configure %s") },
664 {"half-configured", N_("Configuring %s") },
665 { "installed", N_("Installed %s")},
670 {"half-configured", N_("Preparing for removal of %s")},
671 {"half-installed", N_("Removing %s")},
672 {"config-files", N_("Removed %s")},
677 {"config-files", N_("Preparing to completely remove %s")},
678 {"not-installed", N_("Completely removed %s")},
683 // init the PackageOps map, go over the list of packages that
684 // that will be [installed|configured|removed|purged] and add
685 // them to the PackageOps map (the dpkg states it goes through)
686 // and the PackageOpsTranslations (human readable strings)
687 for (vector<Item>::const_iterator I = List.begin(); I != List.end();I++)
689 if((*I).Pkg.end() == true)
692 string const name = (*I).Pkg.Name();
693 PackageOpsDone[name] = 0;
694 for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; i++)
696 PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
701 stdin_is_dev_null = false;
706 // this loop is runs once per operation
707 for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
709 // Do all actions with the same Op in one run
710 vector<Item>::const_iterator J = I;
711 if (TriggersPending == true)
712 for (; J != List.end(); J++)
716 if (J->Op != Item::TriggersPending)
718 vector<Item>::const_iterator T = J + 1;
719 if (T != List.end() && T->Op == I->Op)
724 for (; J != List.end() && J->Op == I->Op; J++)
727 // Generate the argument list
728 const char *Args[MaxArgs + 50];
730 // Now check if we are within the MaxArgs limit
732 // this code below is problematic, because it may happen that
733 // the argument list is split in a way that A depends on B
734 // and they are in the same "--configure A B" run
735 // - with the split they may now be configured in different
737 if (J - I > (signed)MaxArgs)
741 unsigned long Size = 0;
742 string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
743 Args[n++] = Tmp.c_str();
744 Size += strlen(Args[n-1]);
746 // Stick in any custom dpkg options
747 Configuration::Item const *Opts = _config->Tree("DPkg::Options");
751 for (; Opts != 0; Opts = Opts->Next)
753 if (Opts->Value.empty() == true)
755 Args[n++] = Opts->Value.c_str();
756 Size += Opts->Value.length();
760 char status_fd_buf[20];
764 Args[n++] = "--status-fd";
765 Size += strlen(Args[n-1]);
766 snprintf(status_fd_buf,sizeof(status_fd_buf),"%i", fd[1]);
767 Args[n++] = status_fd_buf;
768 Size += strlen(Args[n-1]);
773 Args[n++] = "--force-depends";
774 Size += strlen(Args[n-1]);
775 Args[n++] = "--force-remove-essential";
776 Size += strlen(Args[n-1]);
777 Args[n++] = "--remove";
778 Size += strlen(Args[n-1]);
782 Args[n++] = "--force-depends";
783 Size += strlen(Args[n-1]);
784 Args[n++] = "--force-remove-essential";
785 Size += strlen(Args[n-1]);
786 Args[n++] = "--purge";
787 Size += strlen(Args[n-1]);
790 case Item::Configure:
791 Args[n++] = "--configure";
792 Size += strlen(Args[n-1]);
795 case Item::ConfigurePending:
796 Args[n++] = "--configure";
797 Size += strlen(Args[n-1]);
798 Args[n++] = "--pending";
799 Size += strlen(Args[n-1]);
802 case Item::TriggersPending:
803 Args[n++] = "--triggers-only";
804 Size += strlen(Args[n-1]);
805 Args[n++] = "--pending";
806 Size += strlen(Args[n-1]);
810 Args[n++] = "--unpack";
811 Size += strlen(Args[n-1]);
812 Args[n++] = "--auto-deconfigure";
813 Size += strlen(Args[n-1]);
817 if (NoTriggers == true && I->Op != Item::TriggersPending &&
818 I->Op != Item::ConfigurePending)
820 Args[n++] = "--no-triggers";
821 Size += strlen(Args[n-1]);
824 // Write in the file or package names
825 if (I->Op == Item::Install)
827 for (;I != J && Size < MaxArgBytes; I++)
829 if (I->File[0] != '/')
830 return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
831 Args[n++] = I->File.c_str();
832 Size += strlen(Args[n-1]);
837 for (;I != J && Size < MaxArgBytes; I++)
839 if((*I).Pkg.end() == true)
841 Args[n++] = I->Pkg.Name();
842 Size += strlen(Args[n-1]);
848 if (_config->FindB("Debug::pkgDPkgPM",false) == true)
850 for (unsigned int k = 0; k != n; k++)
851 clog << Args[k] << ' ';
860 typedef void (*sighandler_t)(int);
862 /* Mask off sig int/quit. We do this because dpkg also does when
863 it forks scripts. What happens is that when you hit ctrl-c it sends
864 it to all processes in the group. Since dpkg ignores the signal
865 it doesn't die but we do! So we must also ignore it */
866 sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
867 sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
869 // ignore SIGHUP as well (debian #463030)
870 sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
877 // if tcgetattr does not return zero there was a error
878 // and we do not do any pty magic
879 if (tcgetattr(0, &tt) == 0)
881 ioctl(0, TIOCGWINSZ, (char *)&win);
882 if (openpty(&master, &slave, NULL, &tt, &win) < 0)
884 const char *s = _("Can not write log, openpty() "
885 "failed (/dev/pts not mounted?)\n");
886 fprintf(stderr, "%s",s);
888 fprintf(term_out, "%s",s);
894 rtt.c_lflag &= ~ECHO;
895 // block SIGTTOU during tcsetattr to prevent a hang if
896 // the process is a member of the background process group
897 // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
898 sigemptyset(&sigmask);
899 sigaddset(&sigmask, SIGTTOU);
900 sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
901 tcsetattr(0, TCSAFLUSH, &rtt);
902 sigprocmask(SIG_SETMASK, &original_sigmask, 0);
908 _config->Set("APT::Keep-Fds::",fd[1]);
909 // send status information that we are about to fork dpkg
910 if(OutStatusFd > 0) {
911 ostringstream status;
912 status << "pmstatus:dpkg-exec:"
913 << (PackagesDone/float(PackagesTotal)*100.0)
914 << ":" << _("Running dpkg")
916 write(OutStatusFd, status.str().c_str(), status.str().size());
923 if(slave >= 0 && master >= 0)
926 ioctl(slave, TIOCSCTTY, 0);
933 close(fd[0]); // close the read end of the pipe
935 if (_config->FindDir("DPkg::Chroot-Directory","/") != "/")
937 std::cerr << "Chrooting into "
938 << _config->FindDir("DPkg::Chroot-Directory")
940 if (chroot(_config->FindDir("DPkg::Chroot-Directory","/").c_str()) != 0)
944 if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
947 if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
950 if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
953 // Discard everything in stdin before forking dpkg
954 if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
957 while (read(STDIN_FILENO,&dummy,1) == 1);
959 if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
963 /* No Job Control Stop Env is a magic dpkg var that prevents it
964 from using sigstop */
965 putenv((char *)"DPKG_NO_TSTP=yes");
966 execvp(Args[0],(char **)Args);
967 cerr << "Could not exec dpkg!" << endl;
972 if (_config->FindB("DPkg::UseIoNice", false) == true)
975 // clear the Keep-Fd again
976 _config->Clear("APT::Keep-Fds",fd[1]);
981 // we read from dpkg here
982 int const _dpkgin = fd[0];
983 close(fd[1]); // close the write end of the pipe
989 sigemptyset(&sigmask);
990 sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
992 // the result of the waitpid call
995 while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
997 // FIXME: move this to a function or something, looks ugly here
998 // error handling, waitpid returned -1
1001 RunScripts("DPkg::Post-Invoke");
1003 // Restore sig int/quit
1004 signal(SIGQUIT,old_SIGQUIT);
1005 signal(SIGINT,old_SIGINT);
1006 signal(SIGHUP,old_SIGHUP);
1007 return _error->Errno("waitpid","Couldn't wait for subprocess");
1010 // wait for input or output here
1012 if (!stdin_is_dev_null)
1014 FD_SET(_dpkgin, &rfds);
1016 FD_SET(master, &rfds);
1019 select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL,
1020 &tv, &original_sigmask);
1021 if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS))
1022 select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL,
1023 NULL, &tv, &original_sigmask);
1024 if (select_ret == 0)
1026 else if (select_ret < 0 && errno == EINTR)
1028 else if (select_ret < 0)
1030 perror("select() returned error");
1034 if(master >= 0 && FD_ISSET(master, &rfds))
1035 DoTerminalPty(master);
1036 if(master >= 0 && FD_ISSET(0, &rfds))
1038 if(FD_ISSET(_dpkgin, &rfds))
1039 DoDpkgStatusFd(_dpkgin, OutStatusFd);
1043 // Restore sig int/quit
1044 signal(SIGQUIT,old_SIGQUIT);
1045 signal(SIGINT,old_SIGINT);
1046 signal(SIGHUP,old_SIGHUP);
1050 tcsetattr(0, TCSAFLUSH, &tt);
1054 // Check for an error code.
1055 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1057 // if it was set to "keep-dpkg-runing" then we won't return
1058 // here but keep the loop going and just report it as a error
1060 bool const stopOnError = _config->FindB("Dpkg::StopOnError",true);
1063 RunScripts("DPkg::Post-Invoke");
1065 if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
1066 _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
1067 else if (WIFEXITED(Status) != 0)
1068 _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
1070 _error->Error("Sub-process %s exited unexpectedly",Args[0]);
1081 if (RunScripts("DPkg::Post-Invoke") == false)
1084 Cache.writeStateFile(NULL);
1088 // pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/
1089 // ---------------------------------------------------------------------
1091 void pkgDPkgPM::Reset()
1093 List.erase(List.begin(),List.end());
1097 /* memrchr -- find the last occurrence of a byte in a memory block
1099 Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2005,
1100 2006, 2007, 2008 Free Software Foundation, Inc.
1102 Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
1103 with help from Dan Sahlin (dan@sics.se) and
1104 commentary by Jim Blandy (jimb@ai.mit.edu);
1105 adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
1106 and implemented by Roland McGrath (roland@ai.mit.edu).
1108 This program is free software: you can redistribute it and/or modify
1109 it under the terms of the GNU General Public License as published by
1110 the Free Software Foundation; either version 3 of the License, or
1111 (at your option) any later version.
1113 This program is distributed in the hope that it will be useful,
1114 but WITHOUT ANY WARRANTY; without even the implied warranty of
1115 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1116 GNU General Public License for more details.
1118 You should have received a copy of the GNU General Public License
1119 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1122 # include <memcopy.h>
1124 # include <config.h>
1125 # define reg_char char
1137 # define __memrchr memrchr
1140 /* Search no more than N bytes of S for C. */
1142 __memrchr (void const *s, int c_in, size_t n)
1144 /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
1145 long instead of a 64-bit uintmax_t tends to give better
1146 performance. On 64-bit hardware, unsigned long is generally 64
1147 bits already. Change this typedef to experiment with
1149 typedef unsigned long int longword;
1151 const unsigned char *char_ptr;
1152 const longword *longword_ptr;
1153 longword repeated_one;
1154 longword repeated_c;
1155 unsigned reg_char c;
1157 c = (unsigned char) c_in;
1159 /* Handle the last few bytes by reading one byte at a time.
1160 Do this until CHAR_PTR is aligned on a longword boundary. */
1161 for (char_ptr = (const unsigned char *) s + n;
1162 n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
1164 if (*--char_ptr == c)
1165 return (void *) char_ptr;
1167 longword_ptr = (const longword *) char_ptr;
1169 /* All these elucidatory comments refer to 4-byte longwords,
1170 but the theory applies equally well to any size longwords. */
1172 /* Compute auxiliary longword values:
1173 repeated_one is a value which has a 1 in every byte.
1174 repeated_c has c in every byte. */
1175 repeated_one = 0x01010101;
1176 repeated_c = c | (c << 8);
1177 repeated_c |= repeated_c << 16;
1178 if (0xffffffffU < (longword) -1)
1180 repeated_one |= repeated_one << 31 << 1;
1181 repeated_c |= repeated_c << 31 << 1;
1182 if (8 < sizeof (longword))
1186 for (i = 64; i < sizeof (longword) * 8; i *= 2)
1188 repeated_one |= repeated_one << i;
1189 repeated_c |= repeated_c << i;
1194 /* Instead of the traditional loop which tests each byte, we will test a
1195 longword at a time. The tricky part is testing if *any of the four*
1196 bytes in the longword in question are equal to c. We first use an xor
1197 with repeated_c. This reduces the task to testing whether *any of the
1198 four* bytes in longword1 is zero.
1201 ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
1202 That is, we perform the following operations:
1203 1. Subtract repeated_one.
1205 3. & a mask consisting of 0x80 in every byte.
1206 Consider what happens in each byte:
1207 - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
1208 and step 3 transforms it into 0x80. A carry can also be propagated
1209 to more significant bytes.
1210 - If a byte of longword1 is nonzero, let its lowest 1 bit be at
1211 position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
1212 the byte ends in a single bit of value 0 and k bits of value 1.
1213 After step 2, the result is just k bits of value 1: 2^k - 1. After
1214 step 3, the result is 0. And no carry is produced.
1215 So, if longword1 has only non-zero bytes, tmp is zero.
1216 Whereas if longword1 has a zero byte, call j the position of the least
1217 significant zero byte. Then the result has a zero at positions 0, ...,
1218 j-1 and a 0x80 at position j. We cannot predict the result at the more
1219 significant bytes (positions j+1..3), but it does not matter since we
1220 already have a non-zero bit at position 8*j+7.
1222 So, the test whether any byte in longword1 is zero is equivalent to
1223 testing whether tmp is nonzero. */
1225 while (n >= sizeof (longword))
1227 longword longword1 = *--longword_ptr ^ repeated_c;
1229 if ((((longword1 - repeated_one) & ~longword1)
1230 & (repeated_one << 7)) != 0)
1235 n -= sizeof (longword);
1238 char_ptr = (const unsigned char *) longword_ptr;
1240 /* At this point, we know that either n < sizeof (longword), or one of the
1241 sizeof (longword) bytes starting at char_ptr is == c. On little-endian
1242 machines, we could determine the first such byte without any further
1243 memory accesses, just by looking at the tmp result from the last loop
1244 iteration. But this does not work on big-endian machines. Choose code
1245 that works in both cases. */
1249 if (*--char_ptr == c)
1250 return (void *) char_ptr;
1256 weak_alias (__memrchr, memrchr)