retitle 546528 dash's preinst shouldn't rely on /bin/sh
tag 546528 +patch
thanks

* Matthias Klose <d...@debian.org> [2009-10-22 20:08]:
> changing that to a pre-dependency, but dash's preinst shouldn't rely
> on /bin/sh. bash's preinst is a C binary for that reason.

Here's a patch that makes dash's preinst a C binary too.

Regards
David


---
 debian/dash.preinst   |   32 ----------
 debian/dash.preinst.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++++
 debian/rules          |    7 ++-
 3 files changed, 157 insertions(+), 33 deletions(-)
 delete mode 100644 debian/dash.preinst
 create mode 100644 debian/dash.preinst.c

diff --git a/debian/dash.preinst b/debian/dash.preinst
deleted file mode 100644
index 6be584d..0000000
--- a/debian/dash.preinst
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-set -e
-
-divert() {
-       div=$(dpkg-divert --list $1)
-       distrib=${3:-$1.distrib}
-       if [ -z "$div" ]; then
-               dpkg-divert --package dash --divert $distrib --add $1
-               cp -dp $1 $distrib
-               ln -sf $2 $1
-       fi
-}
-
-divert /bin/sh dash
-divert /usr/share/man/man1/sh.1.gz dash.1.gz \
-       /usr/share/man/man1/sh.distrib.1.gz
-#!/bin/sh
-set -e
-
-divert() {
-       div=$(dpkg-divert --list $1)
-       distrib=${3:-$1.distrib}
-       if [ -z "$div" ]; then
-               dpkg-divert --package dash --divert $distrib --add $1
-               cp -dp $1 $distrib
-               ln -sf $2 $1
-       fi
-}
-
-divert /bin/sh dash
-divert /usr/share/man/man1/sh.1.gz dash.1.gz \
-       /usr/share/man/man1/sh.distrib.1.gz
diff --git a/debian/dash.preinst.c b/debian/dash.preinst.c
new file mode 100644
index 0000000..cf32596
--- /dev/null
+++ b/debian/dash.preinst.c
@@ -0,0 +1,151 @@
+/* Copyright (c) 2009 David Riebenbuaer <davr...@liegesta.at>
+ *
+ * You may freely use, distribute, and modify this program.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <errno.h>
+#include <error.h>
+
+#define DPKG_DIVERT "/usr/bin/dpkg-divert"
+#define LINE_LEN 1024
+
+void run_op(const char *const op[])
+{
+  pid_t child;
+
+  switch (child = fork()) {
+    case -1:
+      // fork failed
+      {
+        err(EXIT_FAILURE, "fork failed");
+      }
+
+
+    case 0:
+      // child
+      {
+        execvp(op[0], (char *const *)(op));
+
+        err(EXIT_FAILURE, "failed to exec %s", op[0]);
+      }
+
+
+    default:
+      // parent
+      {
+        int status;
+        pid_t pid;
+
+        pid = waitpid(child, &status, 0);
+
+        if (pid != -1) {
+          if (WIFEXITED(status)) {
+            if (WEXITSTATUS(status) == 0) {
+              return;
+            }
+            else {
+              exit(WEXITSTATUS(status));
+            }
+          }
+          else {
+            fprintf(stderr, "child didn't exit normally");
+            exit(EXIT_FAILURE);
+          }
+        }
+        else {
+          err(EXIT_FAILURE, "wait failed");
+        }
+
+        break;
+      }
+  }
+}
+
+void divert(const char *target, const char *source, const char *distrib)
+{
+  pid_t child;
+  int pipedes[2];
+  static char line[LINE_LEN];
+
+  memset(line, '\0', LINE_LEN);
+
+  if (pipe(pipedes)) {
+    err(EXIT_FAILURE, "pipe creation failed");
+  }
+
+  switch(child = fork()) {
+    case -1:
+      // fork failed
+      {
+        int errnum = errno;
+
+        close(pipedes[0]);
+        close(pipedes[1]);
+        error(EXIT_FAILURE, errnum, "fork failed");
+      }
+
+
+    case 0:
+      // child
+      {
+        if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) {
+          err(EXIT_FAILURE, "replacing stdout with pipe failed");
+        }
+
+        close(pipedes[STDIN_FILENO]);
+        close(pipedes[STDOUT_FILENO]);
+
+        execlp(DPKG_DIVERT, DPKG_DIVERT, "--list", target, NULL);
+
+        err(EXIT_FAILURE, "dpkg-divert exec failed");
+      }
+
+
+    default:
+      // parent
+      {
+        FILE *fd;
+
+        close(pipedes[STDOUT_FILENO]);
+        fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
+        fd = fdopen(pipedes[STDIN_FILENO], "r");
+
+        while (fgets(line, LINE_LEN, fd) != NULL) {
+          line[strlen(line)-1] = '\0';
+          break;
+        }
+        fclose(fd);
+
+        break;
+      }
+  }
+
+  if (strlen(line) == 0) {
+    const char *const dpkg_divert_op[] = {DPKG_DIVERT, "--package", "dash",
+      "--divert", distrib, "--add", target, NULL};
+    const char *const cp_op[] = {"cp", "-pd", target, distrib, NULL};
+    const char *const ln_op[] = {"ln", "-fs", source, target, NULL};
+
+    run_op(dpkg_divert_op);
+    run_op(cp_op);
+    run_op(ln_op);
+  }
+}
+
+int main(void)
+{
+  divert("/bin/sh", "dash", "/bin/sh.distrib");
+  divert("/usr/share/man/man1/sh.1.gz", "dash.1.gz",
+      "/usr/share/man/man1/sh.distrib.1.gz");
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/debian/rules b/debian/rules
index b5f6d7f..c67b3e2 100755
--- a/debian/rules
+++ b/debian/rules
@@ -36,7 +36,7 @@ configure-stamp: patch-stamp
          exec ../configure --host='$(DEB_HOST_GNU_TYPE)')
        touch configure-stamp
 
-build: deb-checkdir build-stamp
+build: preinst-build deb-checkdir build-stamp
 build-stamp: configure-stamp
        -$(CC) -v
        (cd build-tmp && exec $(MAKE) CFLAGS='$(CFLAGS)') || \
@@ -55,6 +55,11 @@ clean: deb-checkdir deb-checkuid
        rm -f configure-stamp patch-stamp build-stamp po-templates-stamp
        rm -rf '$(DIR)' '$(DIRA)'
        rm -f debian/files debian/substvars debian/dash.templates changelog
+       rm -f debian/dash.preinst
+
+preinst-build: debian/dash.preinst
+debian/dash.preinst: debian/dash.preinst.c
+       $(CC) -O2 -s -o debian/dash.preinst debian/dash.preinst.c
 
 install: install-indep install-arch
 install-indep: deb-checkdir deb-checkuid



-- 
To UNSUBSCRIBE, email to debian-bugs-rc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to