Blame SOURCES/0002-Implement-as-a-command-separator.patch

28453c
From f5bf4407d7801d5add15b786a7425b6135dfb7e2 Mon Sep 17 00:00:00 2001
28453c
From: Jan Zeleny <jzeleny@redhat.com>
28453c
Date: Thu, 21 Nov 2013 12:18:46 +0100
28453c
Subject: [PATCH] Implement "--" as a command separator
28453c
28453c
Whatever comes after the first "--" will be considered a command. If there
28453c
are multiple arguments after the first "--", they will all be concatenated by
28453c
spaces and treated as a single command afterwards.
28453c
---
28453c
 scl.1 |  9 ++++++-
28453c
 scl.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++----------------
28453c
 2 files changed, 76 insertions(+), 21 deletions(-)
28453c
28453c
diff --git a/scl.1 b/scl.1
28453c
index aa797739b1faafe8760e9fc7c5ddaa6ef5da5f4f..f552653f82e97e6503e81f5f75d63b8ca0429bfa 100644
28453c
--- a/scl.1
28453c
+++ b/scl.1
28453c
@@ -5,6 +5,8 @@ scl \- Setup and run software from Software Collection environment
28453c
 .PP
28453c
 \fBscl\fP \fI<action>\fR \fI<collection1>\fR [\fI<collection2> ...\fR] \fI<command>\fR
28453c
 .PP
28453c
+\fBscl\fP \fI<action>\fR \fI<collection1>\fR [\fI<collection2> ...\fR] -- \fI<command>\fR
28453c
+.PP
28453c
 \fBscl\fP {\fB-l|--list\fP} [\fI<collection1> <collection2> ...\fR]
28453c
 .SH "DESCRIPTION"
28453c
 .PP
28453c
@@ -27,6 +29,10 @@ collections which are enabled by the left-right order as present on \fBscl\fP co
28453c
 Collection environment enabled. Control is returned back to the caller with the original
28453c
 environment as soon as the command finishes. It \fI<command>\fR is '-' (dash) then it is
28453c
 read from the standard input.
28453c
+.PP
28453c
+Note that if you use \fI<command>\fR consisting of multiple arguments, you either need to
28453c
+use quotes or the \fB--\fP command separator. Everything that follows the
28453c
+separator will be considered a command or its argument.
28453c
 .SH "OPTIONS"
28453c
 .PP
28453c
 .IP "\fB-l, --list\fP"
28453c
@@ -52,4 +58,5 @@ scl -l example
28453c
 list all packages within example collection
28453c
 .SH "AUTHOR"
28453c
 .PP
28453c
-\fBscl\fP was written by Jindrich Novy <jnovy@redhat.com>.
28453c
+\fBscl\fP was written by Jindrich Novy <jnovy@redhat.com> and Jan Zeleny
28453c
+<jzeleny@redhat.com>
28453c
diff --git a/scl.c b/scl.c
28453c
index 81fdf5d94a9e011d697cd422cd581d21364d7eca..cf3ff5bfa7fce0b95705b0aa09946524d06801c5 100644
28453c
--- a/scl.c
28453c
+++ b/scl.c
28453c
@@ -31,6 +31,7 @@
28453c
 #include <fcntl.h>
28453c
 
28453c
 #define SCL_CONF_DIR "/etc/scl/conf/"
28453c
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
28453c
 
28453c
 static void check_asprintf( char **strp, const char *fmt, ... ) {
28453c
 	va_list args;
28453c
@@ -245,8 +246,10 @@ int main(int argc, char **argv) {
28453c
 	struct stat st;
28453c
 	char *path, *enablepath;
28453c
 	char tmp[] = "/var/tmp/sclXXXXXX";
28453c
-	char *cmd = NULL, *bash_cmd, *echo, *enabled;
28453c
-	int i, tfd, ffd, stdin_read = 0;
28453c
+	char *bash_cmd, *echo, *enabled;
28453c
+	int i, tfd, ffd;
28453c
+	int separator_pos = 0;
28453c
+	char *command = NULL;
28453c
 
28453c
 	if (argc == 2 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h"))) {
28453c
 		print_usage(argv[0]);
28453c
@@ -263,25 +266,58 @@ int main(int argc, char **argv) {
28453c
 		exit(EXIT_SUCCESS);
28453c
 	}
28453c
 
28453c
-	if (!strcmp(argv[argc-1], "-")) {	/* reading command from stdin */
28453c
-		size_t r;
28453c
+	for (i = 0; i < argc; i++) {
28453c
+		if (strcmp(argv[i], "--") == 0) {
28453c
+			break;
28453c
+		}
28453c
+	}
28453c
+	separator_pos = i;
28453c
 
28453c
+	if (separator_pos == argc) {
28453c
+		/* Separator not found */
28453c
 		if (argc < 4) {
28453c
-			fprintf(stderr, "Need at least 3 arguments.\nRun %s without arguments to get help.\n", argv[0]);
28453c
+			fprintf(stderr, "Need at least 3 arguments.\nRun %s --help to get help.\n", argv[0]);
28453c
 			exit(EXIT_FAILURE);
28453c
 		}
28453c
 
28453c
-		cmd = malloc(BUFSIZ);
28453c
+		command = strdup(argv[argc-1]);
28453c
+		if (command == NULL) {
28453c
+			fprintf(stderr, "Can't duplicate string.\n");
28453c
+		}
28453c
+	} else if (separator_pos == argc-1) {
28453c
+		command = "-";
28453c
+	} else if (separator_pos <= 2) {
28453c
+		fprintf(stderr, "Need at least 2 arguments before command is specified.\nRun %s --help to get help.\n", argv[0]);
28453c
+		exit(EXIT_FAILURE);
28453c
+	} else {
28453c
+		command = NULL;
28453c
+	}
28453c
 
28453c
-		if (!cmd) {
28453c
+	if ((command == NULL && !strcmp(argv[separator_pos+1], "-")) ||
28453c
+	    (command != NULL && !strcmp(command, "-"))) {	/* reading command from stdin */
28453c
+		size_t r;
28453c
+
28453c
+
28453c
+		command = malloc(BUFSIZ+1);
28453c
+		if (!command) {
28453c
 			fprintf(stderr, "Can't allocate memory.\n");
28453c
 			exit(EXIT_FAILURE);
28453c
 		}
28453c
 
28453c
-		for (r=0; (r += fread(cmd+r, 1, BUFSIZ, stdin));) {
28453c
-			if (feof(stdin)) break;
28453c
-			cmd = realloc(cmd, r+BUFSIZ);
28453c
-			if (!cmd) {
28453c
+		for (r=0; (r += fread(command+r, 1, BUFSIZ, stdin));) {
28453c
+			if (feof(stdin)) {
28453c
+				if (r % BUFSIZ == 0) {
28453c
+					command = realloc(command, r+1);
28453c
+					if (!command) {
28453c
+						fprintf(stderr, "Can't reallocate memory.\n");
28453c
+						exit(EXIT_FAILURE);
28453c
+					}
28453c
+				}
28453c
+				command[r] = '\0';
28453c
+				break;
28453c
+			}
28453c
+			command = realloc(command, r+BUFSIZ+1);
28453c
+			if (!command) {
28453c
 				fprintf(stderr, "Can't reallocate memory.\n");
28453c
 				exit(EXIT_FAILURE);
28453c
 			}
28453c
@@ -290,15 +326,27 @@ int main(int argc, char **argv) {
28453c
 			fprintf(stderr, "Error reading command from stdin.\n");
28453c
 			exit(EXIT_FAILURE);
28453c
 		}
28453c
-		stdin_read = 1;
28453c
-	}
28453c
+	} else if (command == NULL) {
28453c
+		int len = 0;
28453c
+		for (i = separator_pos+1; i < argc; i++) {
28453c
+			len += strlen(argv[i])+3; /* +1 for additional space, +2 for additional quotes */
28453c
+		}
28453c
 
28453c
-	if (!stdin_read) {
28453c
-		if (argc < 4) {
28453c
-			print_usage(argv[0]);
28453c
+		command = malloc((len+1)*sizeof(char));
28453c
+		if (command == NULL) {
28453c
+			fprintf(stderr, "Can't allocate memory.\n");
28453c
 			exit(EXIT_FAILURE);
28453c
 		}
28453c
-		cmd = strdup(argv[argc-1]);
28453c
+
28453c
+		len = 0;
28453c
+		for (i = separator_pos+1; i < argc; i++) {
28453c
+			command[len++] = '"';
28453c
+			strcpy(command+len, argv[i]);
28453c
+			len += strlen(argv[i]);
28453c
+			command[len++] = '"';
28453c
+			command[len++] = ' ';
28453c
+		}
28453c
+		command[len] = '\0';
28453c
 	}
28453c
 
28453c
 	tfd = mkstemp(tmp);
28453c
@@ -307,7 +355,7 @@ int main(int argc, char **argv) {
28453c
 	write_script(tfd, enabled);
28453c
 	free(enabled);
28453c
 
28453c
-	for (i=2; i
28453c
+	for (i=2; i
28453c
 		FILE *f;
28453c
 		size_t r;
28453c
 		char scl_dir[BUFSIZ];
28453c
@@ -367,9 +415,9 @@ int main(int argc, char **argv) {
28453c
 		free(path);
28453c
 	}
28453c
 
28453c
-	write_script(tfd, cmd);
28453c
+	write_script(tfd, command);
28453c
 	write_script(tfd, "\n");
28453c
-	free(cmd);
28453c
+	free(command);
28453c
 	close(tfd);
28453c
 
28453c
 	check_asprintf(&bash_cmd, "/bin/bash %s", tmp);
28453c
-- 
28453c
1.8.3.1
28453c