Paul Eggert wrote: > <https://perlbrew.pl/Dealing-with-shebangs.html> suggests something like the > following instead. This would avoid having separate shell scripts and .pl > files, > which would be a plus: > > #!/bin/sh > #! −*−perl−*− > eval 'exec perl −x −wS $0 ${1+"$@"}' > if 0;
This does not work for me (with perl 5.22.1), unfortunately: $ build-aux/useless-if-before-free Can't open perl script "−x": No such file or directory Ah, it's because it contains a non-ASCII '−' character! This one works: #!/bin/sh #! -*-perl-*- eval 'exec perl -x -wS $0 ${1+"$@"}' if 0; This one as well: #!/bin/sh #! -*-perl-*- eval 'exec perl -wS -x $0 ${1+"$@"}' if 0; Or this one: #!/bin/sh #! -*-perl-*- eval 'exec perl -wSx $0 ${1+"$@"}' if 0; ${1+"$@"} is the same as "$@". Haven't seen a platform that needs ${1+"$@"} in 20 years. See also the discussion in <https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Shell-Substitutions.html> . And $0 needs to be double-quoted (in case the file name contains a space). So, I'll use this prologue: #!/bin/sh #! -*-perl-*- eval 'exec perl -wSx "$0" "$@"' if 0; 2019-06-15 Bruno Haible <br...@clisp.org> Fix scripts to have valid executable format on Alpine Linux. Reported by Tim Rühsen <tim.rueh...@gmx.de>. Idea by Paul Eggert. * build-aux/useless-if-before-free: Use a prologue that starts with '#!/bin/sh'. * build-aux/announce-gen: Likewise. * build-aux/gitlog-to-changelog: Likewise. * build-aux/prefix-gnulib-mk: Likewise. * build-aux/update-copyright: Likewise. * tests/test-update-copyright.sh: Update test program accordingly. diff --git a/build-aux/announce-gen b/build-aux/announce-gen index 0174f5c..b572833 100755 --- a/build-aux/announce-gen +++ b/build-aux/announce-gen @@ -1,6 +1,20 @@ -eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"' - & eval 'exec perl -wS "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + # Generate a release announcement message. my $VERSION = '2018-03-07 03:46'; # UTC diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog index deddef2..a616b82 100755 --- a/build-aux/gitlog-to-changelog +++ b/build-aux/gitlog-to-changelog @@ -1,6 +1,20 @@ -eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"' - & eval 'exec perl -wS "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + # Convert git log output to ChangeLog format. my $VERSION = '2018-03-07 03:47'; # UTC diff --git a/build-aux/prefix-gnulib-mk b/build-aux/prefix-gnulib-mk index bef726f..66e138b 100755 --- a/build-aux/prefix-gnulib-mk +++ b/build-aux/prefix-gnulib-mk @@ -1,6 +1,19 @@ -eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"' - & eval 'exec perl -wS "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; use strict; use IO::File; diff --git a/build-aux/update-copyright b/build-aux/update-copyright index d80549e..fa9d427 100755 --- a/build-aux/update-copyright +++ b/build-aux/update-copyright @@ -1,6 +1,20 @@ -eval '(exit $?0)' && eval 'exec perl -wS -0777 -pi "$0" "$@"' - & eval 'exec perl -wS -0777 -pi "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + # Update an FSF copyright year list to include the current year. my $VERSION = '2018-03-07.03:47'; # UTC diff --git a/build-aux/useless-if-before-free b/build-aux/useless-if-before-free index 6d6b8d4..0701e7b 100755 --- a/build-aux/useless-if-before-free +++ b/build-aux/useless-if-before-free @@ -1,6 +1,20 @@ -eval '(exit $?0)' && eval 'exec perl -wST "$0" "$@"' - & eval 'exec perl -wST "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + # Detect instances of "if (p) free (p);". # Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces. diff --git a/tests/test-update-copyright.sh b/tests/test-update-copyright.sh index f270db5..9ef5344 100755 --- a/tests/test-update-copyright.sh +++ b/tests/test-update-copyright.sh @@ -37,9 +37,23 @@ trap 'rm -f $TMP_BASE*' 0 1 2 3 15 TMP=$TMP_BASE s=$TMP-script cat <<\EOF > $s -eval '(exit $?0)' && eval 'exec perl -wS -0777 -pi "$0" "$@"' - & eval 'exec perl -wS -0777 -pi "$0" $argv:q' - if 0; +#!/bin/sh +#! -*-perl-*- +# This is a prologue that allows to run a perl script as an executable +# on systems that are compliant to a POSIX version before POSIX:2017. +# On such systems, the usual invocation of an executable through execlp() +# or execvp() fails with ENOEXEC if it is a script that does not start +# with a #! line. The script interpreter mentioned in the #! line has +# to be /bin/sh, because on GuixSD systems that is the only program that +# has a fixed file name. The second line is for editing this file in +# Emacs. The next two lines below are valid code in both sh and perl. +# When executed by sh, they re-execute the script through the perl +# program found in $PATH. The '-x' option is essential; without it, +# perl would re-execute the script through /bin/sh. When executed by +# perl, the next two lines are a no-op. +eval 'exec perl -wSx "$0" "$@"' + if 0; + s/a/b/ EOF chmod a+x $s