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