diff options
author | harti <harti@FreeBSD.org> | 2005-01-26 18:19:39 +0000 |
---|---|---|
committer | harti <harti@FreeBSD.org> | 2005-01-26 18:19:39 +0000 |
commit | 17159f0f8beae09feea301a55dff93895b79399b (patch) | |
tree | c321afb0d87aa82ef737eee5faca7f2adc43af9e /usr.bin | |
parent | 2898737c63ae261843285bb83cce473fc8bf7948 (diff) | |
download | FreeBSD-src-17159f0f8beae09feea301a55dff93895b79399b.zip FreeBSD-src-17159f0f8beae09feea301a55dff93895b79399b.tar.gz |
Fix quoting of the MAKEFLAGS environment variable by only quoting spaces
and tabs. This is still not correct for command line variable values
ending in a backslash because this would require a larger effort.
Document this limitation in the BUGS section of the man page. The
quoting is mostly compatible with that of gmake and smake.
Tested by: Max Okumoto and Joerg Sonnenberger from DragonFly BSD
Reviewed by: ru (man page, partly)
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/make/main.c | 27 | ||||
-rw-r--r-- | usr.bin/make/make.1 | 25 | ||||
-rw-r--r-- | usr.bin/make/nonints.h | 4 | ||||
-rw-r--r-- | usr.bin/make/parse.c | 2 | ||||
-rw-r--r-- | usr.bin/make/str.c | 99 |
5 files changed, 146 insertions, 11 deletions
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 2c3ba65..e29df4a 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -144,14 +144,21 @@ static char *objdir; /* where we chdir'ed to */ static void MFLAGS_append(char *flag, char *arg) { + char *str; Var_Append(MAKEFLAGS, flag, VAR_GLOBAL); - if (arg != NULL) - Var_Append(MAKEFLAGS, arg, VAR_GLOBAL); + if (arg != NULL) { + str = MAKEFLAGS_quote(arg); + Var_Append(MAKEFLAGS, str, VAR_GLOBAL); + free(str); + } Var_Append("MFLAGS", flag, VAR_GLOBAL); - if (arg != NULL) - Var_Append("MFLAGS", arg, VAR_GLOBAL); + if (arg != NULL) { + str = MAKEFLAGS_quote(arg); + Var_Append("MFLAGS", str, VAR_GLOBAL); + free(str); + } } /*- @@ -340,7 +347,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { */ for (argv += optind, argc -= optind; *argv; ++argv, --argc) if (Parse_IsVar(*argv)) { - char *ptr = Var_Quote(*argv); + char *ptr = MAKEFLAGS_quote(*argv); Var_Append(MAKEFLAGS, ptr, VAR_GLOBAL); free(ptr); @@ -376,7 +383,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { * Only those that come from the various arguments. */ void -Main_ParseArgLine(char *line) +Main_ParseArgLine(char *line, int mflags) { char **argv; /* Manufactured argument vector */ int argc; /* Number of arguments in argv */ @@ -388,7 +395,11 @@ Main_ParseArgLine(char *line) if (!*line) return; - argv = brk_string(line, &argc, TRUE); + if (mflags) + argv = MAKEFLAGS_break(line, &argc); + else + argv = brk_string(line, &argc, TRUE); + MainParseArgs(argc, argv); } @@ -622,7 +633,7 @@ main(int argc, char **argv) * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's * in a different format). */ - Main_ParseArgLine(getenv("MAKEFLAGS")); + Main_ParseArgLine(getenv("MAKEFLAGS"), 1); MainParseArgs(argc, argv); diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1 index a846121..b931a97 100644 --- a/usr.bin/make/make.1 +++ b/usr.bin/make/make.1 @@ -32,7 +32,7 @@ .\" @(#)make.1 8.8 (Berkeley) 6/13/95 .\" $FreeBSD$ .\" -.Dd December 2, 2004 +.Dd January 26, 2005 .Dt MAKE 1 .Os .Sh NAME @@ -590,6 +590,20 @@ environment variable made available for all programs which executes; compare with the .Ic .MAKEFLAGS special target below. +.Pp +When passing macro definitions and flag arguments in the +.Ev MAKEFLAGS +environment variable, +space and tab characters are quoted by preceding them with a backslash. +When reading the +.Ev MAKEFLAGS +variable from the environment, +all sequences of a backslash and one of space or tab +are replaced just with their second character +without causing a word break. +Any other occurences of a backslash are retained. +Groups of unquoted space, tab and newline characters cause word +breaking. .It Va MFLAGS This variable is provided for backward compatibility and contains all the options from the @@ -1467,3 +1481,12 @@ all: ... \&.endfor .Ed +.Pp +A trailing backslash in a variable value defined on the command line causes +the delimiting space in the +.Ev MAKEFLAGS +environment variable to be preceeded by that backslash. +That causes a submake to not treat that space as a word delimiter. +Fixing this requires a larger rewrite of the code handling command line +macros and assignments to +.Va .MAKEFLAGS . diff --git a/usr.bin/make/nonints.h b/usr.bin/make/nonints.h index cc64313..561b24c 100644 --- a/usr.bin/make/nonints.h +++ b/usr.bin/make/nonints.h @@ -62,7 +62,7 @@ int For_Eval(char *); void For_Run(int); /* main.c */ -void Main_ParseArgLine(char *); +void Main_ParseArgLine(char *, int); char *Cmd_Exec(char *, char **); void Debug(const char *, ...); void Error(const char *, ...); @@ -92,6 +92,8 @@ void Parse_MainName(Lst *); void str_init(void); char *str_concat(const char *, const char *, int); char **brk_string(char *, int *, Boolean); +char *MAKEFLAGS_quote(const char *); +char **MAKEFLAGS_break(const char *, int *); int Str_Match(const char *, const char *); const char *Str_SYSVMatch(const char *, const char *, int *); void Str_SYSVSubst(Buffer, const char *, const char *, int); diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index b9c8c05..eb1a5d0 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1033,7 +1033,7 @@ ParseDoDependency (char *line) * set the initial character to a null-character so the loop to * get sources won't get anything */ - Main_ParseArgLine(line); + Main_ParseArgLine(line, 0); *line = '\0'; } else if (specType == ExShell) { if (Job_ParseShell(line) != SUCCESS) { diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c index 2979906..9903980 100644 --- a/usr.bin/make/str.c +++ b/usr.bin/make/str.c @@ -223,6 +223,105 @@ done: argv[argc] = NULL; } /* + * Quote a string for appending it to MAKEFLAGS. According to Posix the + * kind of quoting here is implementation-defined. This quoting must ensure + * that the parsing of MAKEFLAGS's contents in a sub-shell yields the same + * options, option arguments and macro definitions as in the calling make. + * We simply quote all blanks, which according to Posix are space and tab + * in the POSIX locale. Don't use isblank because in that case makes with + * different locale settings could not communicate. We must also quote + * backslashes obviously. + */ +char * +MAKEFLAGS_quote(const char *str) +{ + char *ret, *q; + const char *p; + + /* assume worst case - everything has to be quoted */ + ret = emalloc(strlen(str) * 2 + 1); + + p = str; + q = ret; + while (*p != '\0') { + switch (*p) { + + case ' ': + case '\t': + *q++ = '\\'; + break; + + default: + break; + } + *q++ = *p++; + } + *q++ = '\0'; + return (ret); +} + +char ** +MAKEFLAGS_break(const char *str, int *pargc) +{ + char *q, *start; + int len; + + /* allocate room for a copy of the string */ + if ((len = strlen(str) + 1) > curlen) + buffer = erealloc(buffer, curlen = len); + + start = NULL; + *pargc = 1; + + for (q = buffer;;) { + switch (*str) { + case ' ': + case '\t': + /* word separator */ + if (start == NULL) { + /* not in a word */ + str++; + continue; + } + /* FALLTHRU */ + case '\0': + if (start == NULL) + goto done; + + /* finish word */ + *q++ = '\0'; + if (argmax == *pargc) { + argmax *= 2; + argv = erealloc(argv, + sizeof(*argv) * (argmax + 1)); + } + argv[(*pargc)++] = start; + start = NULL; + + if (*str++ == '\0') + goto done; + continue; + + case '\\': + if (str[1] == ' ' || str[1] == '\t') + /* was a quote */ + str++; + break; + + default: + break; + } + if (start == NULL) + /* start of new word */ + start = q; + *q++ = *str++; + } + done: + argv[(*pargc)] = NULL; + return (argv); +} + +/* * Str_Match -- * * See if a particular string matches a particular pattern. |