blog dds

2010.01.12

Useful Polyglot Code

Four years ago I blogged about an incantation that would allow the Windows command interpreter (cmd) to execute Unix shell scripts written inside plain batch files. Time for an update.

The original trick I posted involved starting the shell script with the line

@#!sh %0.bat %* 2>nul
However release 1.7 of Cygwin no longer supports DOS device names (such as NUL, PRN, CON), and therefore when the file is executed under the Unix shell the redirection creates a file named nul. Here is the rationale behind the year 2010 incantation update.

What we need in order to have a Windows command interpreter batch file (a file with a .BAT suffix) executed through the Unix shell is a Windows command that pass the file as an argument to the Unix shell. The following code will do this trick for its first argument.

@echo off
if "%~$PATH:1"=="" (
	rem Not found in PATH; try to run it as specified using the current
	rem directory or an absolute path
	sh %1 %2 %3 %4 %5 %6 %7 %8 %9
) else (
	rem Run the script from the path
	sh %~$PATH:1 %2 %3 %4 %5 %6 %7 %8 %9
)

We then need a polyglot command to invoke the above code: a line that will be valid both in the Windows command interpreter and the Unix shell, because both will execute our file's first line. A polyglot program is one that is simultaneously valid in more than one programming language. Such programs have a long history as interesting curiosities. For instance, the following code by Jack Applin, which won in the 1986 International Obfuscated C Code Contest, is portable to the C and Fortran 77 compilers as well as executable by the Unix Bourne shell.

cat =13 /*/ >/dev/null 2>&1; echo "Hello, world!"; exit
*
*  This program works under cc, f77, and /bin/sh.
*
*/; main() {
      write(
cat-~-cat
     /*,'(
*/
     ,"Hello, world!"
     ,
cat); putchar(~-~-~-cat); } /*
     ,)')
      end
*/
A more recent example is valid COBOL, Pascal, Fortran, C, Postscript, Unix shell, and machine code!

In our case starting a batch / shell script file with the following polyglot line does the trick.

@#!sh %0.bat %*
For the system to work we must also create in our path the following two files.
  1. A batch file named #!sh.bat with these contents. (Download the file by right-clicking on the link; note that the file name starts with #!).
  2. An empty file named @#!sh.
When the Windows command interpreter reads the polyglot line it will strip the leading @ (which in the DOS/Windows world means don't echo the executed command) and will execute the batch file #!sh.bat passing to it as an argument the location of the script and the remaining arguments. When the Unix shell reads the line, it will invoke the command @#!sh, which, as an empty file, does nothing. The rest of the file will then be executed as a shell script. Because Windows batch files don't nest the batch file #!sh.bat will never return to execute the rest of the shell script.

Read and post comments, or share through   


Creative Commons License Last modified: Tuesday, January 12, 2010 7:52 pm
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.