While finding an external program, we should only split the shebang once since that is what Linux and BSD also do. This is also why everyone uses #!/usr/bin/env in their shebangs since that allows you to run an interpreter in a path with spaces in it. See `man execve` for more details, specifically the sections for interpreter scripts.pull/2708/head
parent
120f7a4c40
commit
abcace7ee1
5 changed files with 108 additions and 1 deletions
@ -0,0 +1 @@ |
||||
some stuff here |
@ -0,0 +1,79 @@ |
||||
#include <stdio.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <sys/types.h> |
||||
|
||||
#ifdef _WIN32 |
||||
#include <io.h> |
||||
#include <windows.h> |
||||
#else |
||||
#include <unistd.h> |
||||
#endif |
||||
|
||||
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 char* |
||||
parser_get_line (FILE * f) |
||||
{ |
||||
ssize_t size; |
||||
size_t n = 0; |
||||
char *line = NULL; |
||||
|
||||
size = getline (&line, &n, f); |
||||
if (size < 0) { |
||||
fprintf (stderr, "%s\n", strerror (errno)); |
||||
free (line); |
||||
return NULL; |
||||
} |
||||
return line; |
||||
} |
||||
|
||||
int |
||||
main (int argc, char * argv[]) |
||||
{ |
||||
FILE *f; |
||||
char *line = NULL; |
||||
|
||||
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; |
||||
} |
||||
|
||||
line = parser_get_line (f); |
||||
|
||||
if (!line || line[0] != '#' || line[1] != '!') { |
||||
fprintf (stderr, "Invalid script\n"); |
||||
goto err; |
||||
} |
||||
|
||||
free (line); |
||||
line = parser_get_line (f); |
||||
|
||||
if (!line || strncmp (line, "copy", 4) != 0) { |
||||
fprintf (stderr, "Syntax error\n"); |
||||
goto err; |
||||
} |
||||
|
||||
return intrp_copyfile (argv[2], argv[3]); |
||||
|
||||
err: |
||||
free (line); |
||||
return 1; |
||||
} |
@ -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) |
@ -0,0 +1,2 @@ |
||||
#!/usr/bin/env @INTRP@ |
||||
copy |
Loading…
Reference in new issue