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]