[pacman-dev] [PATCH 4/4] pacman: implement signature check callback using an external command

Rémy Oudompheng remyoudompheng at gmail.com
Sun Apr 10 07:40:20 EDT 2011


Signed-off-by: Rémy Oudompheng <remy at archlinux.org>
---
 src/pacman/callback.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 74 insertions(+), 1 deletions(-)

diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 1ff9a47..06f161c 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <sys/time.h>
 #include <sys/types.h> /* off_t */
+#include <sys/wait.h>  /* waitpid */
 #include <unistd.h>
 #include <wchar.h>
 
@@ -689,7 +690,79 @@ void cb_log(pmloglevel_t level, const char *fmt, va_list args)
 
 /* Callback to check signatures with an external command */
 int cb_checksig(const char *path, const pmpgpsig_t *sig) {
-	return 0;
+	int ret = 0;
+	int retval;
+	int childpid;
+	char *parsedcmd;
+	int pipefd[2];
+
+	if(!config->checksigcommand) {
+		return -1;
+	}
+
+	parsedcmd = strdup(config->checksigcommand);
+	/* replace all occurrences of %f with the filename */
+	if(strstr(parsedcmd, "%f")) {
+		char *tempcmd = strreplace(parsedcmd, "%f", path);
+		free(parsedcmd);
+		parsedcmd = tempcmd;
+	}
+
+	/* execute the parsed command via /bin/sh -c */
+	pipe(pipefd);
+	childpid = fork();
+
+	if (childpid < 0) {
+		pm_printf(PM_LOG_ERROR, _("running ChecksigCommand: fork failed!\n"));
+		ret = -1;
+		goto cleanup;
+	} else if (childpid == 0) {
+		/* we are in the child */
+		close(pipefd[1]);
+		/* read from the pipe */
+		dup2(pipefd[0], 0);
+		pm_printf(PM_LOG_DEBUG, "child: running command: %s\n", parsedcmd);
+		if (execl("/bin/sh", "/bin/sh", "-c", parsedcmd, NULL) == -1)
+			exit(127);
+	} else {
+		/* we are still in pacman */
+		close(pipefd[0]);
+		size_t remaining;
+		const char *signature = alpm_pgpsig_get_raw(sig, &remaining);
+		if (! signature) {
+			close(pipefd[1]);
+			ret = -1;
+			goto wait;
+		}
+		while(remaining > 0) {
+			/* write signature into pipe */
+			ssize_t written = write(pipefd[1], signature, remaining);
+			if (written < 0) {
+				pm_printf(PM_LOG_ERROR, _("running ChecksigCommand: broken pipe!\n"));
+				ret = -1;
+			  break;
+			}
+			signature += written;
+			remaining -= written;
+		}
+		close(pipefd[1]);
+	}
+
+wait:
+	waitpid(childpid, &retval, 0);
+
+	if(!WIFEXITED(retval)) {
+		/* exited abnormally */
+		pm_printf(PM_LOG_DEBUG, "ChecksigCommand exited abnormally "
+				"status (%d,%d)\n", retval >> 8, retval & 0xff);
+		ret = -1;
+	} else {
+		ret = (WEXITSTATUS(retval) == 0) ? 0 : 1;
+	}
+
+cleanup:
+	free(parsedcmd);
+	return ret;
 }
 
 /* vim: set ts=2 sw=2 noet: */
-- 
1.7.4.4



More information about the pacman-dev mailing list