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-reinstreq";
776 Size
+= strlen(Args
[n
-1]);
777 Args
[n
++] = "--force-remove-essential";
778 Size
+= strlen(Args
[n
-1]);
779 Args
[n
++] = "--remove";
780 Size
+= strlen(Args
[n
-1]);
784 Args
[n
++] = "--force-depends";
785 Size
+= strlen(Args
[n
-1]);
786 Args
[n
++] = "--force-remove-reinstreq";
787 Size
+= strlen(Args
[n
-1]);
788 Args
[n
++] = "--force-remove-essential";
789 Size
+= strlen(Args
[n
-1]);
790 Args
[n
++] = "--purge";
791 Size
+= strlen(Args
[n
-1]);
794 case Item::Configure
:
795 Args
[n
++] = "--configure";
796 Size
+= strlen(Args
[n
-1]);
799 case Item::ConfigurePending
:
800 Args
[n
++] = "--configure";
801 Size
+= strlen(Args
[n
-1]);
802 Args
[n
++] = "--pending";
803 Size
+= strlen(Args
[n
-1]);
806 case Item::TriggersPending
:
807 Args
[n
++] = "--triggers-only";
808 Size
+= strlen(Args
[n
-1]);
809 Args
[n
++] = "--pending";
810 Size
+= strlen(Args
[n
-1]);
814 Args
[n
++] = "--unpack";
815 Size
+= strlen(Args
[n
-1]);
816 Args
[n
++] = "--auto-deconfigure";
817 Size
+= strlen(Args
[n
-1]);
821 if (NoTriggers
== true && I
->Op
!= Item::TriggersPending
&&
822 I
->Op
!= Item::ConfigurePending
)
824 Args
[n
++] = "--no-triggers";
825 Size
+= strlen(Args
[n
-1]);
828 // Write in the file or package names
829 if (I
->Op
== Item::Install
)
831 for (;I
!= J
&& Size
< MaxArgBytes
; I
++)
833 if (I
->File
[0] != '/')
834 return _error
->Error("Internal Error, Pathname to install is not absolute '%s'",I
->File
.c_str());
835 Args
[n
++] = I
->File
.c_str();
836 Size
+= strlen(Args
[n
-1]);
841 for (;I
!= J
&& Size
< MaxArgBytes
; I
++)
843 if((*I
).Pkg
.end() == true)
845 Args
[n
++] = I
->Pkg
.Name();
846 Size
+= strlen(Args
[n
-1]);
852 if (_config
->FindB("Debug::pkgDPkgPM",false) == true)
854 for (unsigned int k
= 0; k
!= n
; k
++)
855 clog
<< Args
[k
] << ' ';
864 typedef void (*sighandler_t
)(int);
866 /* Mask off sig int/quit. We do this because dpkg also does when
867 it forks scripts. What happens is that when you hit ctrl-c it sends
868 it to all processes in the group. Since dpkg ignores the signal
869 it doesn't die but we do! So we must also ignore it */
870 sighandler_t old_SIGQUIT
= signal(SIGQUIT
,SIG_IGN
);
871 sighandler_t old_SIGINT
= signal(SIGINT
,SIG_IGN
);
873 // ignore SIGHUP as well (debian #463030)
874 sighandler_t old_SIGHUP
= signal(SIGHUP
,SIG_IGN
);
881 // if tcgetattr does not return zero there was a error
882 // and we do not do any pty magic
883 if (tcgetattr(0, &tt
) == 0)
885 ioctl(0, TIOCGWINSZ
, (char *)&win
);
886 if (openpty(&master
, &slave
, NULL
, &tt
, &win
) < 0)
888 const char *s
= _("Can not write log, openpty() "
889 "failed (/dev/pts not mounted?)\n");
890 fprintf(stderr
, "%s",s
);
892 fprintf(term_out
, "%s",s
);
898 rtt
.c_lflag
&= ~ECHO
;
899 // block SIGTTOU during tcsetattr to prevent a hang if
900 // the process is a member of the background process group
901 // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
902 sigemptyset(&sigmask
);
903 sigaddset(&sigmask
, SIGTTOU
);
904 sigprocmask(SIG_BLOCK
,&sigmask
, &original_sigmask
);
905 tcsetattr(0, TCSAFLUSH
, &rtt
);
906 sigprocmask(SIG_SETMASK
, &original_sigmask
, 0);
912 _config
->Set("APT::Keep-Fds::",fd
[1]);
913 // send status information that we are about to fork dpkg
914 if(OutStatusFd
> 0) {
915 ostringstream status
;
916 status
<< "pmstatus:dpkg-exec:"
917 << (PackagesDone
/float(PackagesTotal
)*100.0)
918 << ":" << _("Running dpkg")
920 write(OutStatusFd
, status
.str().c_str(), status
.str().size());
927 if(slave
>= 0 && master
>= 0)
930 ioctl(slave
, TIOCSCTTY
, 0);
937 close(fd
[0]); // close the read end of the pipe
939 if (_config
->FindDir("DPkg::Chroot-Directory","/") != "/")
941 std::cerr
<< "Chrooting into "
942 << _config
->FindDir("DPkg::Chroot-Directory")
944 if (chroot(_config
->FindDir("DPkg::Chroot-Directory","/").c_str()) != 0)
948 if (chdir(_config
->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
951 if (_config
->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO
))
954 if ((Flags
= fcntl(STDIN_FILENO
,F_GETFL
,dummy
)) < 0)
957 // Discard everything in stdin before forking dpkg
958 if (fcntl(STDIN_FILENO
,F_SETFL
,Flags
| O_NONBLOCK
) < 0)
961 while (read(STDIN_FILENO
,&dummy
,1) == 1);
963 if (fcntl(STDIN_FILENO
,F_SETFL
,Flags
& (~(long)O_NONBLOCK
)) < 0)
967 /* No Job Control Stop Env is a magic dpkg var that prevents it
968 from using sigstop */
969 putenv((char *)"DPKG_NO_TSTP=yes");
970 execvp(Args
[0],(char **)Args
);
971 cerr
<< "Could not exec dpkg!" << endl
;
976 if (_config
->FindB("DPkg::UseIoNice", false) == true)
979 // clear the Keep-Fd again
980 _config
->Clear("APT::Keep-Fds",fd
[1]);
985 // we read from dpkg here
986 int const _dpkgin
= fd
[0];
987 close(fd
[1]); // close the write end of the pipe
993 sigemptyset(&sigmask
);
994 sigprocmask(SIG_BLOCK
,&sigmask
,&original_sigmask
);
996 // the result of the waitpid call
999 while ((res
=waitpid(Child
,&Status
, WNOHANG
)) != Child
) {
1001 // FIXME: move this to a function or something, looks ugly here
1002 // error handling, waitpid returned -1
1005 RunScripts("DPkg::Post-Invoke");
1007 // Restore sig int/quit
1008 signal(SIGQUIT
,old_SIGQUIT
);
1009 signal(SIGINT
,old_SIGINT
);
1010 signal(SIGHUP
,old_SIGHUP
);
1011 return _error
->Errno("waitpid","Couldn't wait for subprocess");
1014 // wait for input or output here
1016 if (!stdin_is_dev_null
)
1018 FD_SET(_dpkgin
, &rfds
);
1020 FD_SET(master
, &rfds
);
1023 select_ret
= pselect(max(master
, _dpkgin
)+1, &rfds
, NULL
, NULL
,
1024 &tv
, &original_sigmask
);
1025 if (select_ret
< 0 && (errno
== EINVAL
|| errno
== ENOSYS
))
1026 select_ret
= racy_pselect(max(master
, _dpkgin
)+1, &rfds
, NULL
,
1027 NULL
, &tv
, &original_sigmask
);
1028 if (select_ret
== 0)
1030 else if (select_ret
< 0 && errno
== EINTR
)
1032 else if (select_ret
< 0)
1034 perror("select() returned error");
1038 if(master
>= 0 && FD_ISSET(master
, &rfds
))
1039 DoTerminalPty(master
);
1040 if(master
>= 0 && FD_ISSET(0, &rfds
))
1042 if(FD_ISSET(_dpkgin
, &rfds
))
1043 DoDpkgStatusFd(_dpkgin
, OutStatusFd
);
1047 // Restore sig int/quit
1048 signal(SIGQUIT
,old_SIGQUIT
);
1049 signal(SIGINT
,old_SIGINT
);
1050 signal(SIGHUP
,old_SIGHUP
);
1054 tcsetattr(0, TCSAFLUSH
, &tt
);
1058 // Check for an error code.
1059 if (WIFEXITED(Status
) == 0 || WEXITSTATUS(Status
) != 0)
1061 // if it was set to "keep-dpkg-runing" then we won't return
1062 // here but keep the loop going and just report it as a error
1064 bool const stopOnError
= _config
->FindB("Dpkg::StopOnError",true);
1067 RunScripts("DPkg::Post-Invoke");
1069 if (WIFSIGNALED(Status
) != 0 && WTERMSIG(Status
) == SIGSEGV
)
1070 _error
->Error("Sub-process %s received a segmentation fault.",Args
[0]);
1071 else if (WIFEXITED(Status
) != 0)
1072 _error
->Error("Sub-process %s returned an error code (%u)",Args
[0],WEXITSTATUS(Status
));
1074 _error
->Error("Sub-process %s exited unexpectedly",Args
[0]);
1085 if (RunScripts("DPkg::Post-Invoke") == false)
1088 Cache
.writeStateFile(NULL
);
1092 // pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/
1093 // ---------------------------------------------------------------------
1095 void pkgDPkgPM::Reset()
1097 List
.erase(List
.begin(),List
.end());
1101 /* memrchr -- find the last occurrence of a byte in a memory block
1103 Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2005,
1104 2006, 2007, 2008 Free Software Foundation, Inc.
1106 Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
1107 with help from Dan Sahlin (dan@sics.se) and
1108 commentary by Jim Blandy (jimb@ai.mit.edu);
1109 adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
1110 and implemented by Roland McGrath (roland@ai.mit.edu).
1112 This program is free software: you can redistribute it and/or modify
1113 it under the terms of the GNU General Public License as published by
1114 the Free Software Foundation; either version 3 of the License, or
1115 (at your option) any later version.
1117 This program is distributed in the hope that it will be useful,
1118 but WITHOUT ANY WARRANTY; without even the implied warranty of
1119 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1120 GNU General Public License for more details.
1122 You should have received a copy of the GNU General Public License
1123 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1126 # include <memcopy.h>
1128 # include <config.h>
1129 # define reg_char char
1141 # define __memrchr memrchr
1144 /* Search no more than N bytes of S for C. */
1146 __memrchr (void const *s
, int c_in
, size_t n
)
1148 /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
1149 long instead of a 64-bit uintmax_t tends to give better
1150 performance. On 64-bit hardware, unsigned long is generally 64
1151 bits already. Change this typedef to experiment with
1153 typedef unsigned long int longword
;
1155 const unsigned char *char_ptr
;
1156 const longword
*longword_ptr
;
1157 longword repeated_one
;
1158 longword repeated_c
;
1159 unsigned reg_char c
;
1161 c
= (unsigned char) c_in
;
1163 /* Handle the last few bytes by reading one byte at a time.
1164 Do this until CHAR_PTR is aligned on a longword boundary. */
1165 for (char_ptr
= (const unsigned char *) s
+ n
;
1166 n
> 0 && (size_t) char_ptr
% sizeof (longword
) != 0;
1168 if (*--char_ptr
== c
)
1169 return (void *) char_ptr
;
1171 longword_ptr
= (const longword
*) char_ptr
;
1173 /* All these elucidatory comments refer to 4-byte longwords,
1174 but the theory applies equally well to any size longwords. */
1176 /* Compute auxiliary longword values:
1177 repeated_one is a value which has a 1 in every byte.
1178 repeated_c has c in every byte. */
1179 repeated_one
= 0x01010101;
1180 repeated_c
= c
| (c
<< 8);
1181 repeated_c
|= repeated_c
<< 16;
1182 if (0xffffffffU
< (longword
) -1)
1184 repeated_one
|= repeated_one
<< 31 << 1;
1185 repeated_c
|= repeated_c
<< 31 << 1;
1186 if (8 < sizeof (longword
))
1190 for (i
= 64; i
< sizeof (longword
) * 8; i
*= 2)
1192 repeated_one
|= repeated_one
<< i
;
1193 repeated_c
|= repeated_c
<< i
;
1198 /* Instead of the traditional loop which tests each byte, we will test a
1199 longword at a time. The tricky part is testing if *any of the four*
1200 bytes in the longword in question are equal to c. We first use an xor
1201 with repeated_c. This reduces the task to testing whether *any of the
1202 four* bytes in longword1 is zero.
1205 ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
1206 That is, we perform the following operations:
1207 1. Subtract repeated_one.
1209 3. & a mask consisting of 0x80 in every byte.
1210 Consider what happens in each byte:
1211 - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
1212 and step 3 transforms it into 0x80. A carry can also be propagated
1213 to more significant bytes.
1214 - If a byte of longword1 is nonzero, let its lowest 1 bit be at
1215 position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
1216 the byte ends in a single bit of value 0 and k bits of value 1.
1217 After step 2, the result is just k bits of value 1: 2^k - 1. After
1218 step 3, the result is 0. And no carry is produced.
1219 So, if longword1 has only non-zero bytes, tmp is zero.
1220 Whereas if longword1 has a zero byte, call j the position of the least
1221 significant zero byte. Then the result has a zero at positions 0, ...,
1222 j-1 and a 0x80 at position j. We cannot predict the result at the more
1223 significant bytes (positions j+1..3), but it does not matter since we
1224 already have a non-zero bit at position 8*j+7.
1226 So, the test whether any byte in longword1 is zero is equivalent to
1227 testing whether tmp is nonzero. */
1229 while (n
>= sizeof (longword
))
1231 longword longword1
= *--longword_ptr
^ repeated_c
;
1233 if ((((longword1
- repeated_one
) & ~longword1
)
1234 & (repeated_one
<< 7)) != 0)
1239 n
-= sizeof (longword
);
1242 char_ptr
= (const unsigned char *) longword_ptr
;
1244 /* At this point, we know that either n < sizeof (longword), or one of the
1245 sizeof (longword) bytes starting at char_ptr is == c. On little-endian
1246 machines, we could determine the first such byte without any further
1247 memory accesses, just by looking at the tmp result from the last loop
1248 iteration. But this does not work on big-endian machines. Choose code
1249 that works in both cases. */
1253 if (*--char_ptr
== c
)
1254 return (void *) char_ptr
;
1260 weak_alias (__memrchr
, memrchr
)