apt/apt-0.5.15cnc6-alt-apt-pipe.patch

604 lines
13 KiB
Diff
Raw Normal View History

--- 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 <argz.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <setproctitle.h>
+
+/* ----------------------------------------------------------------------------
+*/
+
+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 <query>\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 <regex.h>
#include <sys/wait.h>
+#ifndef APT_PIPE
#include <readline/readline.h>
#include <readline/history.h>
+#endif
#include <fnmatch.h>
/*}}}*/
@@ -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