]> git.saurik.com Git - apt.git/commitdiff
move pty stuff into its own function
authorMichael Vogt <mvo@debian.org>
Thu, 31 Oct 2013 06:36:47 +0000 (07:36 +0100)
committerMichael Vogt <mvo@debian.org>
Thu, 31 Oct 2013 06:36:47 +0000 (07:36 +0100)
apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h

index 0ebd9f28b9d32466a0d9e41572fad2b4d6ad5ff2..ddfc7c04e34f6e024e2c0e3da2c37c23bd763033 100644 (file)
@@ -55,7 +55,7 @@ public:
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
                        term_out(NULL), history_out(NULL), 
                         last_reported_progress(0.0), nr_terminal_rows(0),
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
                        term_out(NULL), history_out(NULL), 
                         last_reported_progress(0.0), nr_terminal_rows(0),
-                        fancy_progress_output(false)
+                        fancy_progress_output(false), master(-1), slave(-1)
    {
       dpkgbuf[0] = '\0';
       if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
    {
       dpkgbuf[0] = '\0';
       if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
@@ -63,6 +63,7 @@ public:
          fancy_progress_output = true;
          _config->Set("DpkgPM::Progress", true);
       }
          fancy_progress_output = true;
          _config->Set("DpkgPM::Progress", true);
       }
+
    }
    bool stdin_is_dev_null;
    // the buffer we use for the dpkg status-fd reading
    }
    bool stdin_is_dev_null;
    // the buffer we use for the dpkg status-fd reading
@@ -75,6 +76,16 @@ public:
    float last_reported_progress;
    int nr_terminal_rows;
    bool fancy_progress_output;
    float last_reported_progress;
    int nr_terminal_rows;
    bool fancy_progress_output;
+
+   // pty stuff
+   struct      termios tt;
+   int master;
+   int slave;
+
+   // signals
+   sigset_t sigmask;
+   sigset_t original_sigmask;
+
 };
 
 namespace
 };
 
 namespace
@@ -1055,6 +1066,61 @@ void pkgDPkgPM::CleanupTerminal()
    }
 }
 
    }
 }
 
+void pkgDPkgPM::StartPtyMagic()
+{
+   // setup the pty and stuff
+   struct      winsize win;
+
+   // if tcgetattr does not return zero there was a error
+   // and we do not do any pty magic
+   _error->PushToStack();
+   if (tcgetattr(STDOUT_FILENO, &d->tt) == 0)
+   {
+       ioctl(1, TIOCGWINSZ, (char *)&win);
+       d->nr_terminal_rows = win.ws_row;
+       if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0)
+       {
+           _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+           d->master = d->slave = -1;
+        } else {
+           struct termios rtt;
+           rtt = d->tt;
+           cfmakeraw(&rtt);
+           rtt.c_lflag &= ~ECHO;
+           rtt.c_lflag |= ISIG;
+           // block SIGTTOU during tcsetattr to prevent a hang if
+           // the process is a member of the background process group
+           // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
+           sigemptyset(&d->sigmask);
+           sigaddset(&d->sigmask, SIGTTOU);
+           sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
+           tcsetattr(0, TCSAFLUSH, &rtt);
+           sigprocmask(SIG_SETMASK, &d->original_sigmask, 0);
+        }
+      }
+   // complain only if stdout is either a terminal (but still failed) or is an invalid
+      // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
+      else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
+         _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+
+      if (_error->PendingError() == true)
+        _error->DumpErrors(std::cerr);
+      _error->RevertToStack();
+
+      // setup terminal
+      SetupTerminalScrollArea(d->nr_terminal_rows);
+}
+
+void pkgDPkgPM::StopPtyMagic()
+{
+   if(d->slave > 0)
+      close(d->slave);
+   if(d->master >= 0) 
+   {
+      tcsetattr(0, TCSAFLUSH, &d->tt);
+      close(d->master);
+   }
+}
 
 // DPkgPM::Go - Run the sequence                                       /*{{{*/
 // ---------------------------------------------------------------------
 
 // DPkgPM::Go - Run the sequence                                       /*{{{*/
 // ---------------------------------------------------------------------
@@ -1121,8 +1187,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
    fd_set rfds;
    struct timespec tv;
 
    fd_set rfds;
    struct timespec tv;
-   sigset_t sigmask;
-   sigset_t original_sigmask;
 
    unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
    unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
 
    unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
    unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
@@ -1210,8 +1274,12 @@ bool pkgDPkgPM::Go(int OutStatusFd)
         dpkgMultiArch = true;
    }
 
         dpkgMultiArch = true;
    }
 
-   // this loop is runs once per operation
-   for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
+   // start pty magic before the loop
+   StartPtyMagic();
+
+   // this loop is runs once per dpkg operation
+   vector<Item>::const_iterator I = List.begin();
+   while (I != List.end())
    {
       // Do all actions with the same Op in one run
       vector<Item>::const_iterator J = I;
    {
       // Do all actions with the same Op in one run
       vector<Item>::const_iterator J = I;
@@ -1402,47 +1470,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       // ignore SIGHUP as well (debian #463030)
       sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
 
       // ignore SIGHUP as well (debian #463030)
       sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
 
-      struct   termios tt;
-      struct   winsize win;
-      int      master = -1;
-      int      slave = -1;
-
-      // if tcgetattr does not return zero there was a error
-      // and we do not do any pty magic
-      _error->PushToStack();
-      if (tcgetattr(STDOUT_FILENO, &tt) == 0)
-      {
-        ioctl(1, TIOCGWINSZ, (char *)&win);
-         d->nr_terminal_rows = win.ws_row;
-        if (openpty(&master, &slave, NULL, &tt, &win) < 0)
-        {
-           _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
-           master = slave = -1;
-        }  else {
-           struct termios rtt;
-           rtt = tt;
-           cfmakeraw(&rtt);
-           rtt.c_lflag &= ~ECHO;
-           rtt.c_lflag |= ISIG;
-           // block SIGTTOU during tcsetattr to prevent a hang if
-           // the process is a member of the background process group
-           // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
-           sigemptyset(&sigmask);
-           sigaddset(&sigmask, SIGTTOU);
-           sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
-           tcsetattr(0, TCSAFLUSH, &rtt);
-           sigprocmask(SIG_SETMASK, &original_sigmask, 0);
-        }
-      }
-      // complain only if stdout is either a terminal (but still failed) or is an invalid
-      // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
-      else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
-         _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
-
-      if (_error->PendingError() == true)
-        _error->DumpErrors(std::cerr);
-      _error->RevertToStack();
-
        // Fork dpkg
       pid_t Child;
       _config->Set("APT::Keep-Fds::",fd[1]);
        // Fork dpkg
       pid_t Child;
       _config->Set("APT::Keep-Fds::",fd[1]);
@@ -1461,15 +1488,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       if (Child == 0)
       {
 
       if (Child == 0)
       {
 
-        if(slave >= 0 && master >= 0) 
+        if(d->slave >= 0 && d->master >= 0) 
         {
            setsid();
         {
            setsid();
-           ioctl(slave, TIOCSCTTY, 0);
-           close(master);
-           dup2(slave, 0);
-           dup2(slave, 1);
-           dup2(slave, 2);
-           close(slave);
+           ioctl(d->slave, TIOCSCTTY, 0);
+           close(d->master);
+           dup2(d->slave, 0);
+           dup2(d->slave, 1);
+           dup2(d->slave, 2);
+           close(d->slave);
         }
         close(fd[0]); // close the read end of the pipe
 
         }
         close(fd[0]); // close the read end of the pipe
 
@@ -1493,9 +1520,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
            if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
               _exit(100);
         }
            if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
               _exit(100);
         }
-         // setup terminal
-         SetupTerminalScrollArea(d->nr_terminal_rows);
-         SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0);
 
         /* No Job Control Stop Env is a magic dpkg var that prevents it
            from using sigstop */
 
         /* No Job Control Stop Env is a magic dpkg var that prevents it
            from using sigstop */
@@ -1519,12 +1543,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       int const _dpkgin = fd[0];
       close(fd[1]);                        // close the write end of the pipe
 
       int const _dpkgin = fd[0];
       close(fd[1]);                        // close the write end of the pipe
 
-      if(slave > 0)
-        close(slave);
-
       // setups fds
       // setups fds
-      sigemptyset(&sigmask);
-      sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
+      sigemptyset(&d->sigmask);
+      sigprocmask(SIG_BLOCK,&d->sigmask,&d->original_sigmask);
 
       /* free vectors (and therefore memory) as we don't need the included data anymore */
       for (std::vector<char *>::const_iterator p = Packages.begin();
 
       /* free vectors (and therefore memory) as we don't need the included data anymore */
       for (std::vector<char *>::const_iterator p = Packages.begin();
@@ -1553,18 +1574,18 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
         // wait for input or output here
         FD_ZERO(&rfds);
 
         // wait for input or output here
         FD_ZERO(&rfds);
-        if (master >= 0 && !d->stdin_is_dev_null)
+        if (d->master >= 0 && !d->stdin_is_dev_null)
            FD_SET(0, &rfds); 
         FD_SET(_dpkgin, &rfds);
            FD_SET(0, &rfds); 
         FD_SET(_dpkgin, &rfds);
-        if(master >= 0)
-           FD_SET(master, &rfds);
+        if(d->master >= 0)
+           FD_SET(d->master, &rfds);
         tv.tv_sec = 1;
         tv.tv_nsec = 0;
         tv.tv_sec = 1;
         tv.tv_nsec = 0;
-        select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, 
-                             &tv, &original_sigmask);
+        select_ret = pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, 
+                             &tv, &d->original_sigmask);
         if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS))
         if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS))
-           select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL,
-                                     NULL, &tv, &original_sigmask);
+           select_ret = racy_pselect(max(d->master, _dpkgin)+1, &rfds, NULL,
+                                     NULL, &tv, &d->original_sigmask);
         if (select_ret == 0) 
            continue;
         else if (select_ret < 0 && errno == EINTR)
         if (select_ret == 0) 
            continue;
         else if (select_ret < 0 && errno == EINTR)
@@ -1575,10 +1596,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
            continue;
         } 
         
            continue;
         } 
         
-        if(master >= 0 && FD_ISSET(master, &rfds))
-           DoTerminalPty(master);
-        if(master >= 0 && FD_ISSET(0, &rfds))
-           DoStdin(master);
+        if(d->master >= 0 && FD_ISSET(d->master, &rfds))
+           DoTerminalPty(d->master);
+        if(d->master >= 0 && FD_ISSET(0, &rfds))
+           DoStdin(d->master);
         if(FD_ISSET(_dpkgin, &rfds))
            DoDpkgStatusFd(_dpkgin, OutStatusFd);
       }
         if(FD_ISSET(_dpkgin, &rfds))
            DoDpkgStatusFd(_dpkgin, OutStatusFd);
       }
@@ -1589,13 +1610,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       signal(SIGINT,old_SIGINT);
       
       signal(SIGHUP,old_SIGHUP);
       signal(SIGINT,old_SIGINT);
       
       signal(SIGHUP,old_SIGHUP);
-
-      if(master >= 0) 
-      {
-        tcsetattr(0, TCSAFLUSH, &tt);
-        close(master);
-      }
-
       // Check for an error code.
       if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
       {
       // Check for an error code.
       if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
       {
@@ -1632,6 +1646,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       SendTerminalProgress(100);
 
    CleanupTerminal();
       SendTerminalProgress(100);
 
    CleanupTerminal();
+   StopPtyMagic();
 
    if (pkgPackageManager::SigINTStop)
        _error->Warning(_("Operation was interrupted before it could finish"));
 
    if (pkgPackageManager::SigINTStop)
        _error->Warning(_("Operation was interrupted before it could finish"));
index 1a58e1af5959fb07e515cb45aa020d227ba9e00f..5551b43832ec6933aa708af970087b72be63d9e0 100644 (file)
@@ -95,6 +95,9 @@ class pkgDPkgPM : public pkgPackageManager
    // dpkg log
    bool OpenLog();
    bool CloseLog();
    // dpkg log
    bool OpenLog();
    bool CloseLog();
+
+   void StartPtyMagic();
+   void StopPtyMagic();
    
    // input processing
    void DoStdin(int master);
    
    // input processing
    void DoStdin(int master);