--- apt-0.5.15cnc6/cmdline/apt-pipe.c..pipe 2005-06-27 22:09:57 +0400 +++ apt-0.5.15cnc6/cmdline/apt-pipe.c 2005-06-27 22:29:45 +0400 @@ -0,0 +1,387 @@ +/* ---------------------------------------------------------------------------- + $Id: apt-pipe.c,v 1.3 2005/03/20 20:56:03 me Exp $ + */ + +#ifndef APT_PIPE_PATH +#define APT_PIPE_PATH "/var/lib/apt/pipe" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* ---------------------------------------------------------------------------- +*/ + +extern int aptpipe_init(void); +extern int aptpipe_main(int, const char **); +extern int aptpipe_fini(void); + +/* ---------------------------------------------------------------------------- + */ + +static volatile sig_atomic_t signalled = 0; + +/* ---------------------------------------------------------------------------- + server +*/ +static void sighandler(int sig) +{ + ++signalled; +} + +static void set_sighandler(int flags) +{ + struct sigaction sa; + + sa.sa_handler = sighandler; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGINT); + sigaddset(&sa.sa_mask, SIGTERM); + sigaddset(&sa.sa_mask, SIGHUP); + sa.sa_flags = flags; + + (void) sigaction(SIGINT, &sa, NULL); + (void) sigaction(SIGTERM, &sa, NULL); + (void) sigaction(SIGHUP, &sa, NULL); +} + +static int do_listen() +{ + int servsock; + struct sockaddr_un sockaddr; + + if ((servsock = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) + return -1; + + unlink(APT_PIPE_PATH); + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sun_family = AF_LOCAL; + strncpy(sockaddr.sun_path, APT_PIPE_PATH, sizeof(sockaddr.sun_path)); + if (bind(servsock, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) + return -1; + + return ((listen(servsock, 1)) < 0 ? -1 : servsock); +} + +static ssize_t recv_query(int sock, void *buf, size_t bufsize, int *fd) +{ + struct msghdr msg; + struct iovec iov[1]; + ssize_t received = 0; + + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + struct cmsghdr *cmsg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = buf; + iov[0].iov_len = bufsize; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + if ((received = recvmsg(sock, &msg, MSG_WAITALL)) > 0 && + (cmsg = CMSG_FIRSTHDR(&msg)) != NULL && + cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && + cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) + *fd = *((int *) CMSG_DATA(cmsg)); + + return(received); +} + +static int send_reply(int sock, char *buf, ssize_t bufsize, int fd) +{ + int i, ac; + char **av = NULL; + + /* minimal sanity check */ + if (0 != *(buf + bufsize - 1)) + return -1; + + /* make fd passed by client our stdout/stderr */ + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + + /* apt's .Parse skips av[0], so fake it */ + ac = argz_count(buf, bufsize) + 1; + av = (char **)calloc(ac + 1, sizeof(char *)); + *av = ""; + + argz_extract(buf, bufsize, ++av); + + ac = i = aptpipe_main(ac, (const char **)--av); + fflush(stdout); + fflush(stderr); + + free(av); + + if ((fd = open("/dev/null", O_RDWR)) < 0) + return 1; + + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + + i = (i < 0); + ac = (ac > 0); + + /* send last reply later */ + if (!ac) + write(sock, &i, sizeof(int)); + + return(ac); +} + +static int mainloop(int servsock) { + int cl; + int done = 0; + char buf[65536]; + + while(!signalled && !done) { + int fd = -1; + size_t received; + + /* TODO check for pending errors on socket */ + + /* enable EINTR while in accept */ + set_sighandler(0); + if((cl = accept(servsock, NULL, 0)) < 0) continue; + + set_sighandler(SA_RESTART); + if ((received = recv_query(cl, buf, sizeof(buf), &fd)) > 0 && fd != -1) + done = send_reply(cl, buf, received, fd); + if (!done) + close(cl); + } + + close(servsock); + return(cl); +} + +static int daemonize() +{ + pid_t pid; + int i, fd; + int fds[2] = {-1, -1}; + + if (pipe(fds) < 0) + return -1; + + if ((pid = fork()) < 0) + return -1; + + if (pid) { + /* parent */ + close(fds[1]); + /* get child's status */ + if (read(fds[0], &i, (sizeof(int))) != sizeof(int)) + return -1; + return i; + } + + /* child */ + close(fds[0]); + setsid(); + chdir("/"); + while (fds[1] <= 2) { + fds[1] = dup(fds[1]); + if (fds[1] < 0) + exit(1); + } + + if ((fd = open("/dev/null", O_RDWR)) < 0) + exit(1); + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + /* closeall */ + i = sysconf (_SC_OPEN_MAX); + for (fd = 3; fd < i; fd++) + if (fd != fds[1]) + close (fd); + + /* ignore some signals */ + signal(SIGHUP, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGUSR2, SIG_IGN); + /* no EINTR please */ + set_sighandler(SA_RESTART); + + /* open listening socket */ + if ((fd = do_listen()) < 0) + exit(1); + + /* init apt */ + if (aptpipe_init() < 0) + exit(1); + + /* clean up proc title */ + setproctitle("%s", "ready"); + + /* we're still alive, notify parent */ + i = 0; + write(fds[1], &i, sizeof(int)); + close(fds[1]); + + /* enter main loop */ + fd = mainloop(fd); + + /* cleanup */ + aptpipe_fini(); + unlink(APT_PIPE_PATH); + if (fd) + write(fd, &i, sizeof(int)); + exit(EXIT_SUCCESS); +} + +/* ---------------------------------------------------------------------------- + client +*/ +static int do_connect() +{ + int sock; + struct sockaddr_un servaddr; + + if ((sock = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) + return sock; + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sun_family = AF_LOCAL; + strncpy(servaddr.sun_path, APT_PIPE_PATH, sizeof(servaddr.sun_path)); + for(;;) { + if (connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { + /* ENOENT ECONNREFUSED : (re)spawn daemon */ + if (errno == ENOENT || errno == ECONNREFUSED) { + if (daemonize() < 0) { + fprintf(stderr, "daemonize(): %s\n", strerror(errno)); + exit(1); + } + continue; + } else { + /* EACCESS etc -- just die */ + fprintf(stderr, "connect(): %s\n", strerror(errno)); + exit(1); + } + } + break; + } + + return sock; +} + +static ssize_t send_query(int fd, int ac, char *av[]) +{ + int i; + struct msghdr msg; + struct iovec *iov = NULL; + + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + struct cmsghdr *cmsg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + if ((iov = (struct iovec *)calloc(ac, sizeof(struct iovec))) == NULL) + return -1; + + msg.msg_iov = iov; + msg.msg_iovlen = ac; + + for (i=0; i < ac; iov++, i++) { + iov->iov_base = (void *)av[i]; + iov->iov_len = strlen(av[i]) + 1; + } + + /* keep final 0 for a while */ + (--iov)->iov_len--; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + + if (sendmsg(fd, &msg, 0) < 0) + return -1; + + /* pass fd and final 0 */ + i = 0; + iov = msg.msg_iov; + iov->iov_base = &i; + iov->iov_len = 1; + msg.msg_iovlen = 1; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *((int *) CMSG_DATA(cmsg)) = STDOUT_FILENO; + + return (sendmsg(fd, &msg, 0)); +} + +static int recv_reply(int fd) +{ + int i; + + if (read(fd, &i, (sizeof(int))) != sizeof(int)) + return -1; + return i; +} + +/*----------------------------------------------------------------------------*/ +int main(int ac, char *av[]) +{ + int i, fd; + + if (ac < 2) { + fprintf(stderr, "usage: %s \n", av[0]); + exit(EXIT_FAILURE); + } + + if ((fd = do_connect()) < 0) { + fprintf(stderr, "do_connect: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* pass our query in av[] and stdout fd to server */ + if (send_query(fd, --ac, ++av) < 0) { + fprintf(stderr, "send_query: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* wait for status responce + actual server reply will be passed via passed stdout */ + if ((i = recv_reply(fd)) < 0) { + fprintf(stderr, "recv_reply\n"); + exit(EXIT_FAILURE); + } + + return i; +} --- apt-0.5.15cnc6/cmdline/apt-shell.cc..pipe 2005-06-27 22:09:57 +0400 +++ apt-0.5.15cnc6/cmdline/apt-shell.cc 2005-06-27 22:09:57 +0400 @@ -1,4 +1,4 @@ -// -*- mode: cpp; mode: fold -*- +// -*- mode: c++; mode: folding -*- // Description /*{{{*/ // $Id: apt-get.cc,v 1.126 2003/02/12 16:14:08 doogie Exp $ /* ###################################################################### @@ -65,8 +65,10 @@ #include #include +#ifndef APT_PIPE #include #include +#endif #include /*}}}*/ @@ -3724,9 +3726,7 @@ return true; return _error->Error(_("No packages found")); } - /*}}}*/ -// --- End of stuff from apt-cache. - +/*}}}*/ // ShowHelp - Show a help screen /*{{{*/ // --------------------------------------------------------------------- @@ -4105,6 +4105,7 @@ } /*}}}*/ +#ifndef APT_PIPE // ReadLine* - readline library stuff /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -4272,6 +4273,7 @@ write_history(History.c_str()); } /*}}}*/ +#endif CommandLine::Args *CommandArgs(const char *Name) { @@ -4392,6 +4394,138 @@ } } /*}}}*/ + +#ifdef APT_PIPE +bool DumpConfig(CommandLine &CmdL) +{ + _config->Dump(cout); + return true; +} + +bool DoErrors(CommandLine &CmdL) +{ + if (_error->empty() == false) { + _error->DumpErrors(); + } + + return true; +} + +extern "C" { + int aptpipe_init(void); + int aptpipe_main(int ac, const char *av[]); + int aptpipe_fini(void); +} + +int aptpipe_init(void) +{ + // initialize config + CommandLine CmdL(CommandArgs(""), _config); + + // Setup the output streams + c0out.rdbuf(devnull.rdbuf()); + c1out.rdbuf(cout.rdbuf()); + c2out.rdbuf(cout.rdbuf()); + + // Initialize the package library + if (pkgInitConfig(*_config) == false || + pkgInitSystem(*_config, _system) == false) { + _error->DumpErrors(); + return 100; + } + + // add our nasty defaults + _config->Set("Acquire::CDROM::Copy", "false"); + _config->Set("Acquire::CDROM::Copy-All", "false"); + + // Prepare the cache + GCache = new CacheFile(); + GCache->Open(); + + if (_error->empty() == false) { + bool Errors = _error->PendingError(); + _error->DumpErrors(); + return Errors == true?100:0; + } + + // TODO check for unmets + +#ifdef WITH_LUA + _lua->SetDepCache(*GCache); + _lua->RunScripts("Scripts::AptShell::Init"); + _lua->ResetCaches(); + bool HasCmdScripts = (_lua->HasScripts("Scripts::AptGet::Command") || + _lua->HasScripts("Scripts::AptCache::Command")); +#endif + + return 0; +} + +int aptpipe_main(int ac, const char *av[]) +{ + int rc; + CommandLine::Dispatch Cmds[] = { + {"update", &DoUpdate}, + {"upgrade", &DoUpgrade}, + {"install", &DoInstall}, + {"remove", &DoInstall}, + {"keep", &DoInstall}, + {"dist-upgrade", &DoDistUpgrade}, + {"dselect-upgrade", &DoDSelectUpgrade}, + {"build-dep", &DoBuildDep}, + {"clean", &DoClean}, + {"autoclean", &DoAutoClean}, + {"check", &DoCheck}, + {"help", &ShowHelp}, + {"commit", &DoCommit}, + {"quit", &DoQuit}, + {"exit", &DoQuit}, + {"status", &DoStatus}, + {"script", &DoScript}, + {"errors", &DoErrors}, + // apt-cache + {"showpkg", &DumpPackage}, + {"unmet", &UnMet}, + {"search", &Search}, + {"list", &DoList}, + {"ls", &DoList}, + {"depends", &Depends}, + {"whatdepends", &WhatDepends}, + {"rdepends", &RDepends}, + {"show", &ShowPackage}, + // apt-config + {"dumpconfig", &DumpConfig}, + {0, 0} + }; + + // Make our own copy of the configuration. + Configuration _Config(*_config); + + delete _config; + _config = new Configuration(_Config); + + // Parse skips av[0] + CommandLine CmdL(CommandArgs(av[1]), _config); + CmdL.Parse(ac, av); + CmdL.DispatchArg(Cmds); + + rc = (_error->PendingError() == false ? + ((_config->FindB("quit") == true) ? 1 : 0) : -1); + + // restore saved config + delete _config; + _config = new Configuration(_Config); + + return rc; +} + +int aptpipe_fini() +{ + delete GCache; + return 0; +} + +#else int main(int argc,const char *argv[]) { CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, @@ -4610,5 +4744,5 @@ return 0; } - +#endif // vim:sts=3:sw=3 --- apt-0.5.15cnc6/cmdline/Makefile.am..pipe 2005-06-27 22:09:57 +0400 +++ apt-0.5.15cnc6/cmdline/Makefile.am 2005-06-27 22:09:57 +0400 @@ -4,7 +4,7 @@ bin_PROGRAMS = apt-get apt-cache apt-cdrom apt-config if COMPILE_APTSHELL -bin_PROGRAMS += apt-shell +bin_PROGRAMS += apt-shell apt-pipe endif if COMPILE_STATIC bin_PROGRAMS += apt-get-static apt-cache-static apt-cdrom-static @@ -16,6 +16,9 @@ apt_cache_SOURCES = apt-cache.cc apt_shell_SOURCES = apt-shell.cc acqprogress.cc acqprogress.h apt_shell_LDADD = $(LDADD) -lreadline +apt_pipe_SOURCES = $(apt_shell_SOURCES) apt-pipe.c +apt_pipe_CPPFLAGS = -DAPT_PIPE +apt_pipe_LDADD = $(LDADD) -lsetproctitle apt_config_SOURCES = apt-config.cc apt_cdrom_SOURCES = apt-cdrom.cc rpmindexcopy.cc rpmindexcopy.h