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