~ubuntu-branches/debian/experimental/apt/experimental

« back to all changes in this revision

Viewing changes to apt-pkg/deb/dpkgpm.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2010-02-18 22:07:23 UTC
  • mfrom: (9.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100218220723-zb7zdh6fmsmp30tr
Tags: 0.7.26~exp2
fix crash when LANGUAGE is not set

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
   ##################################################################### */
9
9
                                                                        /*}}}*/
10
10
// Includes                                                             /*{{{*/
11
 
#include <apt-pkg/deb/dpkgpm.h>
12
 
#include <apt-pkg/contrib/error.h>
13
 
#include <apt-pkg/contrib/configuration.h>
 
11
#include <apt-pkg/dpkgpm.h>
 
12
#include <apt-pkg/error.h>
 
13
#include <apt-pkg/configuration.h>
14
14
#include <apt-pkg/depcache.h>
15
 
#include <apt-pkg/contrib/strutl.h>
 
15
#include <apt-pkg/strutl.h>
16
16
#include <apti18n.h>
17
 
#include <apt-pkg/contrib/fileutl.h>
 
17
#include <apt-pkg/fileutl.h>
18
18
 
19
19
#include <unistd.h>
20
20
#include <stdlib.h>
49
49
    std::make_pair("install",   N_("Installing %s")),
50
50
    std::make_pair("configure", N_("Configuring %s")),
51
51
    std::make_pair("remove",    N_("Removing %s")),
 
52
    std::make_pair("purge",    N_("Completely removing %s")),
52
53
    std::make_pair("trigproc",  N_("Running post-installation trigger %s"))
53
54
  };
54
55
 
74
75
  };
75
76
}
76
77
 
 
78
/* helper function to ionice the given PID 
 
79
 
 
80
 there is no C header for ionice yet - just the syscall interface
 
81
 so we use the binary from util-linux
 
82
*/
 
83
static bool
 
84
ionice(int PID)
 
85
{
 
86
   if (!FileExists("/usr/bin/ionice"))
 
87
      return false;
 
88
   pid_t Process = ExecFork();      
 
89
   if (Process == 0)
 
90
   {
 
91
      char buf[32];
 
92
      snprintf(buf, sizeof(buf), "-p%d", PID);
 
93
      const char *Args[4];
 
94
      Args[0] = "/usr/bin/ionice";
 
95
      Args[1] = "-c3";
 
96
      Args[2] = buf;
 
97
      Args[3] = 0;
 
98
      execv(Args[0], (char **)Args);
 
99
   }
 
100
   return ExecWait(Process, "ionice");
 
101
}
 
102
 
77
103
// DPkgPM::pkgDPkgPM - Constructor                                      /*{{{*/
78
104
// ---------------------------------------------------------------------
79
105
/* */
109
135
{
110
136
   if (Pkg.end() == true)
111
137
      return false;
112
 
   
113
 
   List.push_back(Item(Item::Configure,Pkg));
 
138
 
 
139
   List.push_back(Item(Item::Configure, Pkg));
 
140
 
 
141
   // Use triggers for config calls if we configure "smart"
 
142
   // as otherwise Pre-Depends will not be satisfied, see #526774
 
143
   if (_config->FindB("DPkg::TriggersPending", false) == true)
 
144
      List.push_back(Item(Item::TriggersPending, PkgIterator()));
 
145
 
114
146
   return true;
115
147
}
116
148
                                                                        /*}}}*/
165
197
   // Write out the package actions in order.
166
198
   for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
167
199
   {
 
200
      if(I->Pkg.end() == true)
 
201
         continue;
 
202
 
168
203
      pkgDepCache::StateCache &S = Cache[I->Pkg];
169
204
      
170
205
      fprintf(F,"%s ",I->Pkg.Name());
353
388
 */
354
389
void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
355
390
{
 
391
   bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false);
356
392
   // the status we output
357
393
   ostringstream status;
358
394
 
359
 
   if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
395
   if (Debug == true)
360
396
      std::clog << "got from dpkg '" << line << "'" << std::endl;
361
397
 
362
398
 
371
407
      'processing: install: pkg'
372
408
      'processing: configure: pkg'
373
409
      'processing: remove: pkg'
 
410
      'processing: purge: pkg' - but for apt is it a ignored "unknown" action
374
411
      'processing: trigproc: trigger'
375
412
            
376
413
   */
383
420
   TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
384
421
   if( list[0] == NULL || list[1] == NULL || list[2] == NULL) 
385
422
   {
386
 
      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
423
      if (Debug == true)
387
424
         std::clog << "ignoring line: not enough ':'" << std::endl;
388
425
      return;
389
426
   }
390
 
   char *pkg = list[1];
391
 
   char *action = _strstrip(list[2]);
 
427
   const char* const pkg = list[1];
 
428
   const char* action = _strstrip(list[2]);
392
429
 
393
430
   // 'processing' from dpkg looks like
394
431
   // 'processing: action: pkg'
395
432
   if(strncmp(list[0], "processing", strlen("processing")) == 0)
396
433
   {
397
434
      char s[200];
398
 
      char *pkg_or_trigger = _strstrip(list[2]);
399
 
      action =_strstrip( list[1]);
 
435
      const char* const pkg_or_trigger = _strstrip(list[2]);
 
436
      action = _strstrip( list[1]);
400
437
      const std::pair<const char *, const char *> * const iter =
401
438
        std::find_if(PackageProcessingOpsBegin,
402
439
                     PackageProcessingOpsEnd,
403
440
                     MatchProcessingOp(action));
404
441
      if(iter == PackageProcessingOpsEnd)
405
442
      {
406
 
         if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
407
 
            std::clog << "ignoring unknwon action: " << action << std::endl;
 
443
         if (Debug == true)
 
444
            std::clog << "ignoring unknown action: " << action << std::endl;
408
445
         return;
409
446
      }
410
447
      snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
415
452
             << endl;
416
453
      if(OutStatusFd > 0)
417
454
         write(OutStatusFd, status.str().c_str(), status.str().size());
418
 
      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
455
      if (Debug == true)
419
456
         std::clog << "send: '" << status.str() << "'" << endl;
420
457
      return;
421
458
   }
428
465
             << endl;
429
466
      if(OutStatusFd > 0)
430
467
         write(OutStatusFd, status.str().c_str(), status.str().size());
431
 
      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
468
      if (Debug == true)
432
469
         std::clog << "send: '" << status.str() << "'" << endl;
433
470
      return;
434
471
   }
435
 
   if(strncmp(action,"conffile",strlen("conffile")) == 0)
 
472
   else if(strncmp(action,"conffile",strlen("conffile")) == 0)
436
473
   {
437
474
      status << "pmconffile:" << list[1]
438
475
             << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
440
477
             << endl;
441
478
      if(OutStatusFd > 0)
442
479
         write(OutStatusFd, status.str().c_str(), status.str().size());
443
 
      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
480
      if (Debug == true)
444
481
         std::clog << "send: '" << status.str() << "'" << endl;
445
482
      return;
446
483
   }
447
484
 
448
 
   vector<struct DpkgState> &states = PackageOps[pkg];
 
485
   vector<struct DpkgState> const &states = PackageOps[pkg];
449
486
   const char *next_action = NULL;
450
487
   if(PackageOpsDone[pkg] < states.size())
451
488
      next_action = states[PackageOpsDone[pkg]].state;
468
505
             << endl;
469
506
      if(OutStatusFd > 0)
470
507
         write(OutStatusFd, status.str().c_str(), status.str().size());
471
 
      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
 
508
      if (Debug == true)
472
509
         std::clog << "send: '" << status.str() << "'" << endl;
473
510
   }
474
 
   if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) 
 
511
   if (Debug == true) 
475
512
      std::clog << "(parsed from dpkg) pkg: " << pkg 
476
513
                << " action: " << action << endl;
477
514
}
478
 
 
479
 
// DPkgPM::DoDpkgStatusFd                                               /*{{{*/
 
515
                                                                        /*}}}*/
 
516
// DPkgPM::DoDpkgStatusFd                                               /*{{{*/
480
517
// ---------------------------------------------------------------------
481
518
/*
482
519
 */
513
550
   dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
514
551
}
515
552
                                                                        /*}}}*/
516
 
 
 
553
// DPkgPM::WriteHistoryTag                                              /*{{{*/
 
554
void pkgDPkgPM::WriteHistoryTag(string tag, string value)
 
555
{
 
556
   if (value.size() > 0)
 
557
   {
 
558
      // poor mans rstrip(", ")
 
559
      if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
 
560
         value.erase(value.size() - 2, 2);
 
561
      fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
 
562
   }
 
563
}                                                                       /*}}}*/
 
564
// DPkgPM::OpenLog                                                      /*{{{*/
517
565
bool pkgDPkgPM::OpenLog()
518
566
{
519
567
   string logdir = _config->FindDir("Dir::Log");
520
568
   if(not FileExists(logdir))
521
569
      return _error->Error(_("Directory '%s' missing"), logdir.c_str());
 
570
 
 
571
   // get current time
 
572
   char timestr[200];
 
573
   time_t t = time(NULL);
 
574
   struct tm *tmp = localtime(&t);
 
575
   strftime(timestr, sizeof(timestr), "%F  %T", tmp);
 
576
 
 
577
   // open terminal log
522
578
   string logfile_name = flCombine(logdir,
523
579
                                   _config->Find("Dir::Log::Terminal"));
524
580
   if (!logfile_name.empty())
525
581
   {
526
582
      term_out = fopen(logfile_name.c_str(),"a");
 
583
      if (term_out == NULL)
 
584
         return _error->WarningE(_("Could not open file '%s'"), logfile_name.c_str());
 
585
 
527
586
      chmod(logfile_name.c_str(), 0600);
528
 
      // output current time
529
 
      char outstr[200];
530
 
      time_t t = time(NULL);
531
 
      struct tm *tmp = localtime(&t);
532
 
      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
533
 
      fprintf(term_out, "\nLog started: ");
534
 
      fprintf(term_out, "%s", outstr);
535
 
      fprintf(term_out, "\n");
536
 
   }
 
587
      fprintf(term_out, "\nLog started: %s\n", timestr);
 
588
   }
 
589
 
 
590
   // write 
 
591
   string history_name = flCombine(logdir,
 
592
                                   _config->Find("Dir::Log::History"));
 
593
   if (!history_name.empty())
 
594
   {
 
595
      history_out = fopen(history_name.c_str(),"a");
 
596
      chmod(history_name.c_str(), 0644);
 
597
      fprintf(history_out, "\nStart-Date: %s\n", timestr);
 
598
      string remove, purge, install, upgrade, downgrade;
 
599
      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
 
600
      {
 
601
         if (Cache[I].NewInstall())
 
602
            install += I.Name() + string(" (") + Cache[I].CandVersion + string("), ");
 
603
         else if (Cache[I].Upgrade())
 
604
            upgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
 
605
         else if (Cache[I].Downgrade())
 
606
            downgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
 
607
         else if (Cache[I].Delete())
 
608
         {
 
609
            if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
 
610
               purge += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");      
 
611
            else
 
612
               remove += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");     
 
613
         }
 
614
      }
 
615
      WriteHistoryTag("Install", install);
 
616
      WriteHistoryTag("Upgrade", upgrade);
 
617
      WriteHistoryTag("Downgrade",downgrade);
 
618
      WriteHistoryTag("Remove",remove);
 
619
      WriteHistoryTag("Purge",purge);
 
620
      fflush(history_out);
 
621
   }
 
622
   
537
623
   return true;
538
624
}
539
 
 
 
625
                                                                        /*}}}*/
 
626
// DPkg::CloseLog                                                       /*{{{*/
540
627
bool pkgDPkgPM::CloseLog()
541
628
{
 
629
   char timestr[200];
 
630
   time_t t = time(NULL);
 
631
   struct tm *tmp = localtime(&t);
 
632
   strftime(timestr, sizeof(timestr), "%F  %T", tmp);
 
633
 
542
634
   if(term_out)
543
635
   {
544
 
      char outstr[200];
545
 
      time_t t = time(NULL);
546
 
      struct tm *tmp = localtime(&t);
547
 
      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
548
636
      fprintf(term_out, "Log ended: ");
549
 
      fprintf(term_out, "%s", outstr);
 
637
      fprintf(term_out, "%s", timestr);
550
638
      fprintf(term_out, "\n");
551
639
      fclose(term_out);
552
640
   }
553
641
   term_out = NULL;
 
642
 
 
643
   if(history_out)
 
644
   {
 
645
      if (dpkg_error.size() > 0)
 
646
         fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
 
647
      fprintf(history_out, "End-Date: %s\n", timestr);
 
648
      fclose(history_out);
 
649
   }
 
650
 
554
651
   return true;
555
652
}
556
 
 
 
653
                                                                        /*}}}*/
557
654
/*{{{*/
558
655
// This implements a racy version of pselect for those architectures
559
656
// that don't have a working implementation.
575
672
   return retval;
576
673
}
577
674
/*}}}*/
578
 
 
579
675
// DPkgPM::Go - Run the sequence                                        /*{{{*/
580
676
// ---------------------------------------------------------------------
581
677
/* This globs the operations and calls dpkg 
587
683
*/
588
684
bool pkgDPkgPM::Go(int OutStatusFd)
589
685
{
590
 
   unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);   
591
 
   unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
592
 
   bool NoTriggers = _config->FindB("DPkg::NoTriggers",false);
 
686
   fd_set rfds;
 
687
   struct timespec tv;
 
688
   sigset_t sigmask;
 
689
   sigset_t original_sigmask;
 
690
 
 
691
   unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
 
692
   unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
 
693
   bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false);
593
694
 
594
695
   if (RunScripts("DPkg::Pre-Invoke") == false)
595
696
      return false;
597
698
   if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
598
699
      return false;
599
700
 
 
701
   // support subpressing of triggers processing for special
 
702
   // cases like d-i that runs the triggers handling manually
 
703
   bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all");
 
704
   bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);
 
705
   if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true)
 
706
      List.push_back(Item(Item::ConfigurePending, PkgIterator()));
 
707
 
600
708
   // map the dpkg states to the operations that are performed
601
709
   // (this is sorted in the same way as Item::Ops)
602
710
   static const struct DpkgState DpkgStatesOpMap[][7] = {
610
718
      { 
611
719
         {"unpacked",N_("Preparing to configure %s") },
612
720
         {"half-configured", N_("Configuring %s") },
613
 
#if 0
614
 
         {"triggers-awaited", N_("Processing triggers for %s") },
615
 
         {"triggers-pending", N_("Processing triggers for %s") },
616
 
#endif
617
721
         { "installed", N_("Installed %s")},
618
722
         {NULL, NULL}
619
723
      },
620
724
      // Remove operation
621
725
      { 
622
726
         {"half-configured", N_("Preparing for removal of %s")},
623
 
#if 0
624
 
         {"triggers-awaited", N_("Preparing for removal of %s")},
625
 
         {"triggers-pending", N_("Preparing for removal of %s")},
626
 
#endif
627
727
         {"half-installed", N_("Removing %s")},
628
728
         {"config-files",  N_("Removed %s")},
629
729
         {NULL, NULL}
640
740
   // that will be [installed|configured|removed|purged] and add
641
741
   // them to the PackageOps map (the dpkg states it goes through)
642
742
   // and the PackageOpsTranslations (human readable strings)
643
 
   for (vector<Item>::iterator I = List.begin(); I != List.end();I++)
 
743
   for (vector<Item>::const_iterator I = List.begin(); I != List.end();I++)
644
744
   {
645
 
      string name = (*I).Pkg.Name();
 
745
      if((*I).Pkg.end() == true)
 
746
         continue;
 
747
 
 
748
      string const name = (*I).Pkg.Name();
646
749
      PackageOpsDone[name] = 0;
647
750
      for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL;  i++) 
648
751
      {
649
752
         PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
650
753
         PackagesTotal++;
651
754
      }
652
 
   }   
 
755
   }
653
756
 
654
757
   stdin_is_dev_null = false;
655
758
 
657
760
   OpenLog();
658
761
 
659
762
   // this loop is runs once per operation
660
 
   for (vector<Item>::iterator I = List.begin(); I != List.end();)
 
763
   for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
661
764
   {
662
 
      vector<Item>::iterator J = I;
663
 
      for (; J != List.end() && J->Op == I->Op; J++);
 
765
      // Do all actions with the same Op in one run
 
766
      vector<Item>::const_iterator J = I;
 
767
      if (TriggersPending == true)
 
768
         for (; J != List.end(); J++)
 
769
         {
 
770
            if (J->Op == I->Op)
 
771
               continue;
 
772
            if (J->Op != Item::TriggersPending)
 
773
               break;
 
774
            vector<Item>::const_iterator T = J + 1;
 
775
            if (T != List.end() && T->Op == I->Op)
 
776
               continue;
 
777
            break;
 
778
         }
 
779
      else
 
780
         for (; J != List.end() && J->Op == I->Op; J++)
 
781
            /* nothing */;
664
782
 
665
783
      // Generate the argument list
666
784
      const char *Args[MaxArgs + 50];
 
785
      
 
786
      // Now check if we are within the MaxArgs limit
 
787
      //
 
788
      // this code below is problematic, because it may happen that
 
789
      // the argument list is split in a way that A depends on B
 
790
      // and they are in the same "--configure A B" run
 
791
      // - with the split they may now be configured in different
 
792
      //   runs 
667
793
      if (J - I > (signed)MaxArgs)
668
794
         J = I + MaxArgs;
669
795
      
670
796
      unsigned int n = 0;
671
797
      unsigned long Size = 0;
672
 
      string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
 
798
      string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
673
799
      Args[n++] = Tmp.c_str();
674
800
      Size += strlen(Args[n-1]);
675
801
      
719
845
         
720
846
         case Item::Configure:
721
847
         Args[n++] = "--configure";
722
 
         if (NoTriggers)
723
 
            Args[n++] = "--no-triggers";
724
 
         Size += strlen(Args[n-1]);
725
 
         break;
726
 
         
 
848
         Size += strlen(Args[n-1]);
 
849
         break;
 
850
 
 
851
         case Item::ConfigurePending:
 
852
         Args[n++] = "--configure";
 
853
         Size += strlen(Args[n-1]);
 
854
         Args[n++] = "--pending";
 
855
         Size += strlen(Args[n-1]);
 
856
         break;
 
857
 
 
858
         case Item::TriggersPending:
 
859
         Args[n++] = "--triggers-only";
 
860
         Size += strlen(Args[n-1]);
 
861
         Args[n++] = "--pending";
 
862
         Size += strlen(Args[n-1]);
 
863
         break;
 
864
 
727
865
         case Item::Install:
728
866
         Args[n++] = "--unpack";
729
867
         Size += strlen(Args[n-1]);
731
869
         Size += strlen(Args[n-1]);
732
870
         break;
733
871
      }
734
 
      
 
872
 
 
873
      if (NoTriggers == true && I->Op != Item::TriggersPending &&
 
874
          I->Op != Item::ConfigurePending)
 
875
      {
 
876
         Args[n++] = "--no-triggers";
 
877
         Size += strlen(Args[n-1]);
 
878
      }
 
879
 
735
880
      // Write in the file or package names
736
881
      if (I->Op == Item::Install)
737
882
      {
747
892
      {
748
893
         for (;I != J && Size < MaxArgBytes; I++)
749
894
         {
 
895
            if((*I).Pkg.end() == true)
 
896
               continue;
750
897
            Args[n++] = I->Pkg.Name();
751
898
            Size += strlen(Args[n-1]);
752
899
         }       
777
924
      sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
778
925
 
779
926
      struct    termios tt;
780
 
      struct    termios tt_out;
781
927
      struct    winsize win;
782
 
      int       master;
783
 
      int       slave;
 
928
      int       master = -1;
 
929
      int       slave = -1;
784
930
 
785
 
      // FIXME: setup sensible signal handling (*ick*)
786
 
      tcgetattr(0, &tt);
787
 
      tcgetattr(1, &tt_out);
788
 
      ioctl(0, TIOCGWINSZ, (char *)&win);
789
 
      if (openpty(&master, &slave, NULL, &tt_out, &win) < 0) 
 
931
      // if tcgetattr does not return zero there was a error
 
932
      // and we do not do any pty magic
 
933
      if (tcgetattr(0, &tt) == 0)
790
934
      {
791
 
         const char *s = _("Can not write log, openpty() "
792
 
                           "failed (/dev/pts not mounted?)\n");
793
 
         fprintf(stderr, "%s",s);
794
 
         fprintf(term_out, "%s",s);
795
 
         master = slave = -1;
796
 
      }  else {
797
 
         struct termios rtt;
798
 
         rtt = tt;
799
 
         cfmakeraw(&rtt);
800
 
         rtt.c_lflag &= ~ECHO;
801
 
         tcsetattr(0, TCSAFLUSH, &rtt);
 
935
         ioctl(0, TIOCGWINSZ, (char *)&win);
 
936
         if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
 
937
         {
 
938
            const char *s = _("Can not write log, openpty() "
 
939
                              "failed (/dev/pts not mounted?)\n");
 
940
            fprintf(stderr, "%s",s);
 
941
            if(term_out)
 
942
              fprintf(term_out, "%s",s);
 
943
            master = slave = -1;
 
944
         }  else {
 
945
            struct termios rtt;
 
946
            rtt = tt;
 
947
            cfmakeraw(&rtt);
 
948
            rtt.c_lflag &= ~ECHO;
 
949
            // block SIGTTOU during tcsetattr to prevent a hang if
 
950
            // the process is a member of the background process group
 
951
            // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 
952
            sigemptyset(&sigmask);
 
953
            sigaddset(&sigmask, SIGTTOU);
 
954
            sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
 
955
            tcsetattr(0, TCSAFLUSH, &rtt);
 
956
            sigprocmask(SIG_SETMASK, &original_sigmask, 0);
 
957
         }
802
958
      }
803
959
 
804
960
       // Fork dpkg
805
961
      pid_t Child;
806
962
      _config->Set("APT::Keep-Fds::",fd[1]);
 
963
      // send status information that we are about to fork dpkg
 
964
      if(OutStatusFd > 0) {
 
965
         ostringstream status;
 
966
         status << "pmstatus:dpkg-exec:" 
 
967
                << (PackagesDone/float(PackagesTotal)*100.0) 
 
968
                << ":" << _("Running dpkg")
 
969
                << endl;
 
970
         write(OutStatusFd, status.str().c_str(), status.str().size());
 
971
      }
807
972
      Child = ExecFork();
808
973
            
809
974
      // This is the child
821
986
         }
822
987
         close(fd[0]); // close the read end of the pipe
823
988
 
 
989
         if (_config->FindDir("DPkg::Chroot-Directory","/") != "/") 
 
990
         {
 
991
            std::cerr << "Chrooting into " 
 
992
                      << _config->FindDir("DPkg::Chroot-Directory") 
 
993
                      << std::endl;
 
994
            if (chroot(_config->FindDir("DPkg::Chroot-Directory","/").c_str()) != 0)
 
995
               _exit(100);
 
996
         }
 
997
 
824
998
         if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
825
999
            _exit(100);
826
1000
         
840
1014
               _exit(100);
841
1015
         }
842
1016
 
843
 
 
844
1017
         /* No Job Control Stop Env is a magic dpkg var that prevents it
845
1018
            from using sigstop */
846
1019
         putenv((char *)"DPKG_NO_TSTP=yes");
849
1022
         _exit(100);
850
1023
      }      
851
1024
 
 
1025
      // apply ionice
 
1026
      if (_config->FindB("DPkg::UseIoNice", false) == true)
 
1027
         ionice(Child);
 
1028
 
852
1029
      // clear the Keep-Fd again
853
1030
      _config->Clear("APT::Keep-Fds",fd[1]);
854
1031
 
856
1033
      int Status = 0;
857
1034
 
858
1035
      // we read from dpkg here
859
 
      int _dpkgin = fd[0];
 
1036
      int const _dpkgin = fd[0];
860
1037
      close(fd[1]);                        // close the write end of the pipe
861
1038
 
862
 
      // the result of the waitpid call
863
 
      int res;
864
1039
      if(slave > 0)
865
1040
         close(slave);
866
1041
 
867
1042
      // setups fds
868
 
      fd_set rfds;
869
 
      struct timespec tv;
870
 
      sigset_t sigmask;
871
 
      sigset_t original_sigmask;
872
1043
      sigemptyset(&sigmask);
873
1044
      sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
874
1045
 
 
1046
      // the result of the waitpid call
 
1047
      int res;
875
1048
      int select_ret;
876
1049
      while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
877
1050
         if(res < 0) {
890
1063
 
891
1064
         // wait for input or output here
892
1065
         FD_ZERO(&rfds);
893
 
         if (!stdin_is_dev_null)
 
1066
         if (master >= 0 && !stdin_is_dev_null)
894
1067
            FD_SET(0, &rfds); 
895
1068
         FD_SET(_dpkgin, &rfds);
896
1069
         if(master >= 0)
938
1111
         // if it was set to "keep-dpkg-runing" then we won't return
939
1112
         // here but keep the loop going and just report it as a error
940
1113
         // for later
941
 
         bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
 
1114
         bool const stopOnError = _config->FindB("Dpkg::StopOnError",true);
942
1115
         
943
1116
         if(stopOnError)
944
1117
            RunScripts("DPkg::Post-Invoke");
945
1118
 
946
1119
         if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) 
947
 
            _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
 
1120
            strprintf(dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
948
1121
         else if (WIFEXITED(Status) != 0)
949
 
            _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
 
1122
            strprintf(dpkg_error, "Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
950
1123
         else 
951
 
            _error->Error("Sub-process %s exited unexpectedly",Args[0]);
 
1124
            strprintf(dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
 
1125
 
 
1126
         if(dpkg_error.size() > 0)
 
1127
            _error->Error(dpkg_error.c_str());
952
1128
 
953
1129
         if(stopOnError) 
954
1130
         {