[pacman-dev] [PATCH] Support reading package args from stdin

Dave Reisner d at falconindy.com
Fri Nov 5 04:54:18 CET 2010


Only occurs if no arguments were provided directly. Arguments can be
separated by any amount of valid whitespace. This allows for piping into
pacman from other programs or from itself, e.g.:

  pacman -Qdtq | pacman -Rs

This is better than using xargs, as xargs will not reconnect stdin to
the terminal. The above operation performed using xargs would require
the --noconfirm flag to be passed to pacman.

Signed-off-by: Dave Reisner <d at falconindy.com>
---
Additional cleanup at Dan's request, and added documentation to man page wrt to
this feature. Woo, documentation.

 doc/pacman.8.txt    |    5 +++++
 src/pacman/pacman.c |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 4bdb3f9..418ddfc 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -25,6 +25,11 @@ Since version 3.0.0, pacman has been the frontend to linkman:libalpm[3], the
 ``Arch Linux Package Management'' library. This library allows alternative
 front ends to be written (for instance, a GUI front end).
 
+Invoking pacman involves specifying an operation with any potential options
+and targets to operate on. A 'target' is usually a package name, filename, URL,
+or a search string. Targets can be provided as arguments to pacman and/or
+passed through standard input.
+
 
 Operations
 ----------
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 15abecc..39390a5 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -26,6 +26,7 @@
 #define PACKAGE_VERSION GIT_VERSION
 #endif
 
+#include <ctype.h> /* isspace */
 #include <stdlib.h> /* atoi */
 #include <stdio.h>
 #include <limits.h>
@@ -1305,6 +1306,39 @@ int main(int argc, char *argv[])
 		cleanup(ret);
 	}
 
+	/* we also support reading targets from stdin */
+	if(!isatty(fileno(stdin))) {
+		char line[PATH_MAX];
+		int i = 0;
+		while(i < PATH_MAX && (line[i] = fgetc(stdin)) != EOF) {
+			if(isspace((unsigned char)line[i])) {
+				/* avoid adding zero length arg when multiple spaces separate args */
+				if(i > 0) {
+					line[i] = '\0';
+					pm_targets = alpm_list_add(pm_targets, strdup(line));
+					i = 0;
+				}
+			} else {
+				i++;
+			}
+		}
+		/* check for buffer overflow */
+		if (i >= PATH_MAX) {
+			pm_printf(PM_LOG_ERROR, _("buffer overflow detected in arg parsing\n"));
+			cleanup(EXIT_FAILURE);
+		}
+
+		/* end of stream -- check for data still in line buffer */
+		if(i > 0) {
+			line[i] = '\0';
+			pm_targets = alpm_list_add(pm_targets, strdup(line));
+		}
+		if (!freopen(ctermid(NULL), "r", stdin)) {
+			pm_printf(PM_LOG_ERROR, _("failed to reopen stdin for reading: (%s)\n"),
+					strerror(errno));
+		}
+	}
+
 	/* parse the config file */
 	ret = parseconfig(config->configfile);
 	if(ret != 0) {
-- 
1.7.3.2



More information about the pacman-dev mailing list