The following commit has been merged in the master branch:
commit 9d81008a303b5510601063363a40c8961b769339
Author: Guillem Jover <[email protected]>
Date:   Fri Aug 21 07:00:17 2009 +0200

    dpkg: Add new invoke hooks support
    
    Call pre-invoke and post-invoke hooks before and after unpack,
    configure, install, triggers-only, remove and purge actions.
    Set the DPKG_HOOK_ACTION environment variable to the current dpkg
    action.

diff --git a/debian/changelog b/debian/changelog
index 01f0215..1778368 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -43,6 +43,7 @@ dpkg (1.15.4) UNRELEASED; urgency=low
     Suggested by Christian Perrier <[email protected]>.
   * On configuration error print file name and line number.
   * Allow quoting values in configuration file options.
+  * Add new --pre-invoke and --post-invoke hooks in dpkg.
 
   [ Raphael Hertzog ]
   * Replace install-info by a wrapper around GNU's install-info. The wrapper
diff --git a/man/dpkg.1 b/man/dpkg.1
index d22d802..7168165 100644
--- a/man/dpkg.1
+++ b/man/dpkg.1
@@ -505,6 +505,20 @@ be marked selected for deinstallation.
 .BR \-E ", " \-\-skip\-same\-version
 Don't install the package if the same version of the package is already
 installed.
+.P
+.BI \-\-pre\-invoke= command
+.br
+.BI \-\-post\-invoke= command
+.RS
+Set an invoke hook \fIcommand\fP to be run via \*(lqsh \-c\*(rq before or
+after the dpkg run for the \fIunpack\fP, \fIconfigure\fP, \fIinstall\fP,
+\fItriggers\-only\fP, \fIremove\fP and \fIpurge\fP dpkg actions. This
+option can be specified multiple times. The order the options are specified
+is preserved, with the ones from the configuration files taking precedence.
+The environment variable \fBDPKG_HOOK_ACTION\fP is set for the hooks to the
+current dpkg action. Note: front-ends might call dpkg several times per
+invokation, which might run the hooks more times than expected.
+.RE
 .TP
 \fB\-\-status\-fd \fR\fIn\fR
 Send machine-readable package status and progress information to file
diff --git a/src/main.c b/src/main.c
index d237054..46ad658 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3,6 +3,7 @@
  * main.c - main program
  *
  * Copyright © 1994,1995 Ian Jackson <[email protected]>
+ * Copyright © 2006-2009 Guillem Jover <[email protected]>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
@@ -315,6 +316,62 @@ static void setpipe(const struct cmdinfo *cip, const char 
*value) {
   *pipe_head = pipe_new;
 }
 
+static int
+is_invoke_action(enum action action)
+{
+  switch (action) {
+  case act_unpack:
+  case act_configure:
+  case act_install:
+  case act_triggers:
+  case act_remove:
+  case act_purge:
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+struct invoke_hook *pre_invoke_hooks = NULL;
+struct invoke_hook **pre_invoke_hooks_tail = &pre_invoke_hooks;
+struct invoke_hook *post_invoke_hooks = NULL;
+struct invoke_hook **post_invoke_hooks_tail = &post_invoke_hooks;
+
+static void
+set_invoke_hook(const struct cmdinfo *cip, const char *value)
+{
+  struct invoke_hook ***hook_tail = cip->parg;
+  struct invoke_hook *hook_new;
+
+  hook_new = nfmalloc(sizeof(struct invoke_hook));
+  hook_new->command = nfstrsave(value);
+  hook_new->next = NULL;
+
+  /* Add the new hook at the tail of the list to preserve the order. */
+  **hook_tail = hook_new;
+  *hook_tail = &hook_new->next;
+}
+
+static void
+run_invoke_hooks(const char *action, struct invoke_hook *hook_head)
+{
+  struct invoke_hook *hook;
+
+  setenv("DPKG_HOOK_ACTION", action, 1);
+
+  for (hook = hook_head; hook; hook = hook->next) {
+    int status;
+
+    /* XXX: As an optimization, use exec instead if no shell metachar are
+     * used “!$=&|\\`'"^~;<>{}[]()?*#”. */
+    status = system(hook->command);
+    if (status != 0)
+      ohshit("error executing hook '%s', exit code %d", hook->command, status);
+  }
+
+  unsetenv("DPKG_HOOK_ACTION");
+}
+
 static void setforce(const struct cmdinfo *cip, const char *value) {
   const char *comma;
   size_t l;
@@ -430,6 +487,8 @@ static const struct cmdinfo cmdinfos[]= {
   ACTION( "command-fd",                   'c', act_commandfd,   commandfd     
),
 */
   
+  { "pre-invoke",        0,   1, NULL,          NULL,      set_invoke_hook, 0, 
&pre_invoke_hooks_tail },
+  { "post-invoke",       0,   1, NULL,          NULL,      set_invoke_hook, 0, 
&post_invoke_hooks_tail },
   { "status-fd",         0,   1, NULL,          NULL,      setpipe, 0, 
&status_pipes },
   { "log",               0,   1, NULL,          &log_file, NULL,    0 },
   { "pending",           'a', 0, &f_pending,    NULL,      NULL,    1 },
@@ -646,6 +705,10 @@ int main(int argc, const char *const *argv) {
     f_triggers = (cipaction->arg == act_triggers && *argv) ? -1 : 1;
 
   setvbuf(stdout, NULL, _IONBF, 0);
+
+  if (is_invoke_action(cipaction->arg))
+    run_invoke_hooks(cipaction->olong, pre_invoke_hooks);
+
   filesdbinit();
 
   actionfunction= (void (*)(const char* const*))cipaction->farg;
@@ -654,5 +717,8 @@ int main(int argc, const char *const *argv) {
 
   standard_shutdown();
 
+  if (is_invoke_action(cipaction->arg))
+    run_invoke_hooks(cipaction->olong, post_invoke_hooks);
+
   return reportbroken_retexitstatus();
 }
diff --git a/src/main.h b/src/main.h
index c9d8af4..3333d4e 100644
--- a/src/main.h
+++ b/src/main.h
@@ -101,6 +101,11 @@ extern const char *instdir;
 extern struct pkginqueue *ignoredependss;
 extern const char architecture[];
 
+struct invoke_hook {
+       struct invoke_hook *next;
+       const char *command;
+};
+
 /* from archives.c */
 
 void archivefiles(const char *const *argv);

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to