# Write out the perl5i wrapper C program making sure it uses # the Perl its built with. use strict; use warnings; use File::Spec; my $file = shift; # Its going inside double quotes. my $perl_path = $^X; $perl_path =~ s{ ([\\"]) }{\\$1}gx; my $tempdir = File::Spec->tmpdir || "/tmp"; open my $fh, ">", $file or die $!; printf $fh <<'END', $0, $perl_path, $tempdir; /* THIS FILE IS GENERATED BY %s * Any changes here will be wiped out. Edit it there instead. */ #define DEBUG 0 #include #include #include #include /* * Meant to mimic the shell command * exec perl -Mperl5i::latest "$@" * * This is a C program so it works in a #! line. */ int main (int argc, char* argv[]) { int i; int j; const char* perl_cmd = "%s"; char* perl_args[argc+1]; char* dash_m = (char *)malloc(sizeof(char) * (strlen(argv[0]) + 20)); char* program; int saw_dash_e = 0; strcat(dash_m, "-Mperl5i::cmd="); strcat(dash_m, argv[0]); perl_args[0] = (char *)perl_cmd; perl_args[1] = dash_m; for( i = 1, j = 2; i < argc; i++ ) { char *dash_e = strchr(argv[i], 'e'); /* Its a one liner */ if( dash_e && strcmp(dash_e, "e") == 0 && (strchr(argv[i], '-') == argv[i]) && (strchr(argv[i], 'M') != argv[i]+1) ) { saw_dash_e = 1; /* Chop out the -e */ dash_e[0] = '\0'; /* If all that's left is a dash, ignore it */ if( strcmp(argv[i], "-") != 0 ) { perl_args[j] = argv[i]; j++; } /* Skip the next argument, its the program */ program = argv[i+1]; i++; continue; } perl_args[j] = argv[i]; j++; } /* Turn one liners into real programs to work around a Devel::Declare bug */ if( saw_dash_e ) { char tempfile[] = "%s/perl5i.XXXXXX"; int fd = mkstemp(tempfile); if( fd == -1 ) { perror("Could not open temporary file 'tempfile'"); exit(1); } FILE *fh = fdopen(fd, "w"); fprintf( fh, "$0 = '-e';\n" ); fprintf( fh, "#line 1 \"-e\"\n" ); fprintf( fh, "%%s", program ); fclose(fh); perl_args[j++] = tempfile; } /* Argument array must be terminated by a null */ perl_args[j] = (char *)NULL; #if DEBUG for( i = 0; i <= j; i++ ) { printf("perl_args[%%d]: %%s\n", i, perl_args[i]); } if( saw_dash_e ) printf("program: %%s\n", program); #endif return execv( perl_cmd, perl_args ); } END