summaryrefslogtreecommitdiffstats
path: root/dselect/method.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dselect/method.cc')
-rw-r--r--dselect/method.cc256
1 files changed, 256 insertions, 0 deletions
diff --git a/dselect/method.cc b/dselect/method.cc
new file mode 100644
index 0000000..5e7972f
--- /dev/null
+++ b/dselect/method.cc
@@ -0,0 +1,256 @@
+/*
+ * dselect - Debian package maintenance user interface
+ * method.cc - access method handling
+ *
+ * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
+ * Copyright © 2001,2002 Wichert Akkerman <wakkerma@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <dpkg/i18n.h>
+#include <dpkg/dpkg.h>
+#include <dpkg/dpkg-db.h>
+#include <dpkg/subproc.h>
+#include <dpkg/command.h>
+
+#include "dselect.h"
+#include "method.h"
+
+static const char *const methoddirectories[]= {
+ LIBDIR "/" METHODSDIR,
+ LOCALLIBDIR "/" METHODSDIR,
+ nullptr
+};
+
+static char *methodlockfile = nullptr;
+static int methlockfd= -1;
+
+static void
+sthfailed(const char * reasoning)
+{
+ curseson();
+ clear();
+ printw("\n\n%s: %s\n", DSELECT, reasoning);
+ attrset(A_BOLD);
+ addstr(_("\nPress <enter> to continue."));
+ attrset(A_NORMAL);
+ refresh(); getch();
+}
+
+static void cu_unlockmethod(int, void**) {
+ struct flock fl;
+
+ if (methodlockfile == nullptr)
+ internerr("method lock file is nullptr");
+ if (methlockfd < 0)
+ internerr("method lock fd is %d < 0", methlockfd);
+ fl.l_type=F_UNLCK; fl.l_whence= SEEK_SET; fl.l_start=fl.l_len=0;
+ if (fcntl(methlockfd,F_SETLK,&fl) == -1)
+ sthfailed(_("cannot unlock access method area"));
+}
+
+static enum urqresult ensureoptions(void) {
+ dselect_option *newoptions;
+ int nread;
+
+ if (!options) {
+ newoptions = nullptr;
+ nread= 0;
+ for (const char *const *ccpp = methoddirectories; *ccpp; ccpp++)
+ readmethods(*ccpp, &newoptions, &nread);
+ if (!newoptions) {
+ sthfailed(_("no access methods are available"));
+ return urqr_fail;
+ }
+ options= newoptions;
+ noptions= nread;
+ }
+ return urqr_normal;
+}
+
+static enum urqresult lockmethod(void) {
+ struct flock fl;
+
+ if (methodlockfile == nullptr)
+ methodlockfile = dpkg_db_get_path(METHLOCKFILE);
+
+ if (methlockfd == -1) {
+ methlockfd= open(methodlockfile, O_RDWR|O_CREAT|O_TRUNC, 0660);
+ if (methlockfd == -1) {
+ if ((errno == EPERM) || (errno == EACCES)) {
+ sthfailed(_("requested operation requires superuser privilege"));
+ return urqr_fail;
+ }
+ sthfailed(_("cannot open or create access method lockfile"));
+ return urqr_fail;
+ }
+ }
+ fl.l_type=F_WRLCK; fl.l_whence=SEEK_SET; fl.l_start=fl.l_len=0;
+ if (fcntl(methlockfd,F_SETLK,&fl) == -1) {
+ if (errno == EACCES || errno == EAGAIN) {
+ sthfailed(_("the access method area is already locked"));
+ return urqr_fail;
+ }
+ sthfailed(_("cannot lock access method area"));
+ return urqr_fail;
+ }
+ push_cleanup(cu_unlockmethod, ~0, 0);
+ return urqr_normal;
+}
+
+static urqresult
+falliblesubprocess(struct command *cmd)
+{
+ pid_t pid;
+ int i, c;
+
+ cursesoff();
+
+ subproc_signals_ignore(cmd->name);
+
+ pid = subproc_fork();
+ if (pid == 0) {
+ subproc_signals_cleanup(0, nullptr);
+ command_exec(cmd);
+ }
+
+ fprintf(stderr, "\n");
+
+ i = subproc_reap(pid, cmd->name, SUBPROC_WARN);
+
+ subproc_signals_restore();
+
+ if (i == 0) {
+ sleep(1);
+ return urqr_normal;
+ }
+ fprintf(stderr,_("Press <enter> to continue.\n"));
+ m_output(stderr, _("<standard error>"));
+ do {
+ c = fgetc(stdin);
+ } while ((c == EOF && errno == EINTR) || (c != '\n' && c != EOF));
+ if (c == EOF)
+ ohshite(_("error reading acknowledgement of program failure message"));
+ return urqr_fail;
+}
+
+static urqresult runscript(const char *exepath, const char *name) {
+ urqresult ur;
+
+ ur= ensureoptions(); if (ur != urqr_normal) return ur;
+ ur=lockmethod(); if (ur != urqr_normal) return ur;
+ getcurrentopt();
+
+ if (coption) {
+ struct command cmd;
+
+ strcpy(coption->meth->pathinmeth,exepath);
+
+ command_init(&cmd, coption->meth->path, name);
+ command_add_args(&cmd, exepath, dpkg_db_get_dir(),
+ coption->meth->name, coption->name, nullptr);
+ ur = falliblesubprocess(&cmd);
+ command_destroy(&cmd);
+ } else {
+ sthfailed(_("no access method is selected or configured"));
+ ur= urqr_fail;
+ }
+ pop_cleanup(ehflag_normaltidy);
+
+ return ur;
+}
+
+urqresult urq_update(void) {
+ return runscript(METHODUPDATESCRIPT,_("update available list script"));
+}
+
+urqresult urq_install(void) {
+ return runscript(METHODINSTALLSCRIPT,_("installation script"));
+}
+
+static urqresult rundpkgauto(const char *name, const char *dpkgmode) {
+ urqresult ur;
+ struct command cmd;
+
+ command_init(&cmd, DPKG, name);
+ command_add_args(&cmd, DPKG, "--admindir", dpkg_db_get_dir(), "--pending",
+ dpkgmode, nullptr);
+
+ cursesoff();
+ printf(_("running %s %s ...\n"), "dpkg --pending", dpkgmode);
+ fflush(stdout);
+ ur = falliblesubprocess(&cmd);
+ command_destroy(&cmd);
+
+ return ur;
+}
+
+urqresult urq_remove(void) {
+ return rundpkgauto("dpkg --remove","--remove");
+}
+
+urqresult urq_config(void) {
+ return rundpkgauto("dpkg --configure","--configure");
+}
+
+urqresult urq_setup(void) {
+ quitaction qa;
+ urqresult ur;
+
+ ur= ensureoptions(); if (ur != urqr_normal) return ur;
+ ur=lockmethod(); if (ur != urqr_normal) return ur;
+ getcurrentopt();
+
+ curseson();
+ methodlist *l= new methodlist();
+ qa= l->display();
+ delete l;
+
+ if (qa == qa_quitchecksave) {
+ struct command cmd;
+
+ strcpy(coption->meth->pathinmeth,METHODSETUPSCRIPT);
+
+ command_init(&cmd, coption->meth->path, _("query/setup script"));
+ command_add_args(&cmd, METHODSETUPSCRIPT, dpkg_db_get_dir(),
+ coption->meth->name, coption->name, nullptr);
+ ur = falliblesubprocess(&cmd);
+ command_destroy(&cmd);
+ if (ur == urqr_normal) writecurrentopt();
+ } else {
+ ur= urqr_fail;
+ }
+
+ pop_cleanup(ehflag_normaltidy);
+ return ur;
+}