Browse Source

* first (raw and ineffient) implementation

debian/1.8.y
Michael Vogt 15 years ago
parent
commit
d8cb4aa445
  1. 77
      apt-pkg/deb/dpkgpm.cc
  2. 2
      apt-pkg/makefile
  3. 2
      cmdline/makefile

77
apt-pkg/deb/dpkgpm.cc

@ -25,6 +25,11 @@
#include <sstream>
#include <map>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <pty.h>
#include <config.h>
#include <apti18n.h>
/*}}}*/
@ -516,7 +521,24 @@ bool pkgDPkgPM::Go(int OutStatusFd)
it doesn't die but we do! So we must also ignore it */
sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
struct termios tt;
struct winsize win;
int master;
int slave;
tcgetattr(0, &tt);
ioctl(0, TIOCGWINSZ, (char *)&win);
if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
fprintf(stderr, _("openpty failed\n"));
}
struct termios rtt;
rtt = tt;
cfmakeraw(&rtt);
rtt.c_lflag &= ~ECHO;
tcsetattr(0, TCSAFLUSH, &rtt);
// Fork dpkg
pid_t Child;
_config->Set("APT::Keep-Fds::",fd[1]);
@ -525,8 +547,16 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// This is the child
if (Child == 0)
{
setsid();
ioctl(slave, TIOCSCTTY, 0);
close(master);
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
close(slave);
close(fd[0]); // close the read end of the pipe
if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
_exit(100);
@ -545,7 +575,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
_exit(100);
}
/* No Job Control Stop Env is a magic dpkg var that prevents it
from using sigstop */
putenv("DPKG_NO_TSTP=yes");
@ -567,11 +598,19 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// the read buffers for the communication with dpkg
char line[1024] = {0,};
char buf[2] = {0,0};
char term_buf[2] = {0,0};
char input_buf[2] = {0,0};
// the result of the waitpid call
int res;
close(slave);
fcntl(0, F_SETFL, O_NONBLOCK);
fcntl(master, F_SETFL, O_NONBLOCK);
FILE *term_out = fopen("/var/log/dpkg-out.log","a");
chmod("/var/log/dpkg-out.log", 0600);
while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
if(res < 0) {
// FIXME: move this to a function or something, looks ugly here
@ -585,18 +624,41 @@ bool pkgDPkgPM::Go(int OutStatusFd)
signal(SIGINT,old_SIGINT);
return _error->Errno("waitpid","Couldn't wait for subprocess");
}
// wait for input or output here
// FIXME: use select() instead of the rubish below
// read a single char, make sure that the read can't block
// (otherwise we may leave zombies)
int term_len = read(master, term_buf, 1);
int input_len = read(0, input_buf, 1);
int len = read(_dpkgin, buf, 1);
// nothing to read, wait a bit for more
// see if we have any input that needs to go to the
// master pty
if(input_len > 0)
write(master, input_buf, 1);
// see if we have any output that needs to be echoed
// and written to the log
if(term_len > 0)
{
do
{
fwrite(term_buf, 1, 1, term_out);
write(1, term_buf, 1);
} while(read(master, term_buf, 1) > 0);
term_buf[0] = 0;
}
// nothing to read from dpkg , wait a bit for more
if(len <= 0)
{
usleep(1000);
continue;
}
// sanity check (should never happen)
if(strlen(line) >= sizeof(line)-10)
{
@ -702,10 +764,13 @@ bool pkgDPkgPM::Go(int OutStatusFd)
line[0]=0;
}
close(_dpkgin);
fclose(term_out);
// Restore sig int/quit
signal(SIGQUIT,old_SIGQUIT);
signal(SIGINT,old_SIGINT);
tcsetattr(0, TCSAFLUSH, &tt);
// Check for an error code.
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)

2
apt-pkg/makefile

@ -15,7 +15,7 @@ LIBRARY=apt-pkg
LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
MAJOR=4.4
MINOR=0
SLIBS=$(PTHREADLIB) $(INTLLIBS)
SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil
APT_DOMAIN:=libapt-pkg$(MAJOR)
# Source code for the contributed non-core things

2
cmdline/makefile

@ -14,7 +14,7 @@ include $(PROGRAM_H)
# The apt-get program
PROGRAM=apt-get
SLIBS = -lapt-pkg
SLIBS = -lapt-pkg -lutil
LIB_MAKES = apt-pkg/makefile
SOURCE = apt-get.cc acqprogress.cc
include $(PROGRAM_H)

Loading…
Cancel
Save