diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 682182c69..a72023275 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -560,7 +560,11 @@ class ExternalProgram: with open(script) as f: first_line = f.readline().strip() if first_line.startswith('#!'): - commands = first_line[2:].split('#')[0].strip().split() + # In a shebang, everything before the first space is assumed to + # be the command to run and everything after the first space is + # the single argument to pass to that command. So we must split + # exactly once. + commands = first_line[2:].split('#')[0].strip().split(maxsplit=1) if mesonlib.is_windows(): # Windows does not have UNIX paths so remove them, # but don't remove Windows paths diff --git a/test cases/common/167 external program shebang parsing/input.txt b/test cases/common/167 external program shebang parsing/input.txt new file mode 100644 index 000000000..40e30d4b2 --- /dev/null +++ b/test cases/common/167 external program shebang parsing/input.txt @@ -0,0 +1 @@ +some stuff here diff --git a/test cases/common/167 external program shebang parsing/main.c b/test cases/common/167 external program shebang parsing/main.c new file mode 100644 index 000000000..a90206bc7 --- /dev/null +++ b/test cases/common/167 external program shebang parsing/main.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +/* Who cares about stack sizes in test programs anyway */ +#define LINE_LENGTH 4096 + +static int +intrp_copyfile (char * src, char * dest) +{ +#ifdef _WIN32 + if (!CopyFile (src, dest, FALSE)) + return 1; + return 0; +#else + return execlp ("cp", "copyfile", src, dest, NULL); +#endif +} + +static void +parser_get_line (FILE * f, char line[LINE_LENGTH]) +{ + if (!fgets (line, LINE_LENGTH, f)) + fprintf (stderr, "%s\n", strerror (errno)); +} + +int +main (int argc, char * argv[]) +{ + FILE *f = NULL; + char line[LINE_LENGTH]; + + if (argc != 4) { + fprintf (stderr, "Invalid number of arguments: %i\n", argc); + goto err; + } + + if ((f = fopen (argv[1], "r")) == NULL) { + fprintf (stderr, "%s\n", strerror (errno)); + goto err; + } + + parser_get_line (f, line); + + if (!line || line[0] != '#' || line[1] != '!') { + fprintf (stderr, "Invalid script\n"); + goto err; + } + + parser_get_line (f, line); + + if (!line || strncmp (line, "copy", 4) != 0) { + fprintf (stderr, "Syntax error: %s\n", line); + goto err; + } + + return intrp_copyfile (argv[2], argv[3]); + +err: + fclose (f); + return 1; +} diff --git a/test cases/common/167 external program shebang parsing/meson.build b/test cases/common/167 external program shebang parsing/meson.build new file mode 100644 index 000000000..c1cc5af9d --- /dev/null +++ b/test cases/common/167 external program shebang parsing/meson.build @@ -0,0 +1,21 @@ +project('shebang parsing', 'c') + +interpreter = executable('aninterp', 'main.c', native : true) + +cdata = configuration_data() +cdata.set('INTRP', interpreter.full_path()) + +f = configure_file(input : 'script.int.in', + output : 'script.int', + configuration : cdata) + +# Test that parsing a shebang with spaces works properly. See `man execve`, +# specifically the section on "Interpreter scripts" and the one under "NOTES". +script = find_program(f) + +custom_target('interpthis', + input : 'input.txt', + output : 'output.txt', + depends : interpreter, + command : [script, '@INPUT@', '@OUTPUT@'], + build_by_default : true) diff --git a/test cases/common/167 external program shebang parsing/script.int.in b/test cases/common/167 external program shebang parsing/script.int.in new file mode 100644 index 000000000..77ff90907 --- /dev/null +++ b/test cases/common/167 external program shebang parsing/script.int.in @@ -0,0 +1,2 @@ +#!/usr/bin/env @INTRP@ +copy