<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>White screen</title>
	<atom:link href="http://whitescreen.nicolaas.net/feed" rel="self" type="application/rss+xml" />
	<link>http://whitescreen.nicolaas.net</link>
	<description>Assorted articles on... well, anything</description>
	<lastBuildDate>Thu, 26 Nov 2009 16:02:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Windows shebangs</title>
		<link>http://whitescreen.nicolaas.net/programming/windows-shebangs</link>
		<comments>http://whitescreen.nicolaas.net/programming/windows-shebangs#comments</comments>
		<pubDate>Thu, 26 Nov 2009 15:13:22 +0000</pubDate>
		<dc:creator>Dion Nicolaas</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://whitescreen.nicolaas.net/?p=27</guid>
		<description><![CDATA[Windows shebangs In Writing a PHP polyglot, I wrote about the Unix &#8216;shebang&#8217; mechanism. Any script, being shell script, Perl, PHP or any other language, will be started by the shell; and any script can have a very special line in the beginning, that looks e.g. like this: #! /usr/bin/perl -w The #! means so [...]]]></description>
			<content:encoded><![CDATA[<h1>Windows shebangs</h1>
<p>In <a href="http://whitescreen.nicolaas.net/programming/php-polyglot">Writing a PHP polyglot</a>, I wrote about the Unix &#8216;shebang&#8217; mechanism. Any script, being shell script, Perl, PHP or any other language, will be started by the shell; and any script can have a very special line in the beginning, that looks e.g. like this:</p>
<pre>#! /usr/bin/perl -w</pre>
<p>The #! means so much as: ‘use the following command to run this script’. And then the name of the program to use follows. Now the shell knows what to do with this program, and does that instead of trying to interpret the file itself.</p>
<p>Indeed, the rest of the article was about an amusing way to get something like that to work; read it if you want to know weird stuff about batch language.</p>
<h2>A more general approach</h2>
<p>Although writing a polyglot is fun, it hardly counts as a good solution. There is a much easier solution in Windows, via so-called &#8216;file type associations&#8217;. It can be done from your command line, and goes something like this: first, you tell Windows that a file ending in .pl is a Perl file:</p>
<pre>c:\&gt; assoc .pl=Perl</pre>
<p>And then you explain what Windows should do with a file of that new type:</p>
<pre>c:\&gt; ftype Perl="C:\Perl\bin\perl.exe" "%1" %*</pre>
<p>And now you run your Perl script:</p>
<pre>c:\&gt; pi.pl
3.14159265358979</pre>
<p>There you go. Windows will remember from now on what to do with Perl files, and you don&#8217;t need any special code. Exactly the same thing could be done for PHP files, or for any other file type your system supports.</p>
<p>(What strikes me as odd is that assoc is used to tell the system what <em>file type </em>a file with a certain extension is, and ftype then <em>associates </em>this file type to a command. But that&#8217;s probably just me.)</p>
<h2>This might actually be better than a shebang</h2>
<p>There is an interesting advantage to this mechanism above the polyglot way, or even the shebang concept: these are systems settings. That means that on a correctly configured system, it will always work. In the PHP polyglot, the full path name to PHP was specified, because it is not on your path by default. In a shebang, it is actually required that a full path is used. But what if your system doesn&#8217;t have PHP in /usr/bin/php, but in /home/dnicolaas/myownphp/php? Then the script doesn&#8217;t work and needs editing. Of course it could work if you could specify a command without a full path, but changing all version of Unix is outside the scope of this article.</p>
<h3>A clever workaround?</h3>
<p>The problem was recognised by Unix experts, and in some scripts you will see this instead:</p>
<pre>#! /usr/bin/env perl -w</pre>
<p>Here, the full path to perl isn&#8217;t specifed. So what is /usr/bin/env? It is not a program that knows how to interpret a language specified in its second parameter;  it just runs all its arguments as a command in a copy of the environment. In other words, it runs</p>
<pre>perl -w</pre>
<p>in a new shell. And since this new environment will just look up perl in the path, this gets around the requirement that perl gets specified with a full path. It exchanges it for the requirement that /usr/bin/env exists, of course, but that usually does. Except that on some systems it doesn&#8217;t, so this workaround is not perfect.</p>
<h2>&#8230; or maybe not?</h2>
<p>There are two things that are not so nice about the file type associations: they require your to give your scripts a unique extension, and they even require you to type that extension when you want to run the program. When I want to know the value of π, I don&#8217;t need to know which programming language I used; I&#8217;d rather type</p>
<pre>pi</pre>
<p>than</p>
<pre>pi.pl</pre>
<p>Another disadvantage is that if I get a script from a Unix user (or even a whole collection of scripts,) I have to rename them before I can use them. The first problem can be solved in Windows by setting the PATHEXT variable:</p>
<pre>set PATHEXT=%PATHEXT%;.pl</pre>
<p>This turns .pl into a so-called <em>executable extension</em>; Windows now knows that files with the .pl extension can be typed on the command line without the extension, much like files ending in .com, .exe and .bat.</p>
<p>The second problem cannot be solved so easily. Renaming files acquired from somewhere else is never nice: it is work, it requires thinking when upgrading to a new version, and it might break installers. Is there anything we can do about that?</p>
<h2>Running extensionless scripts</h2>
<p>So let&#8217;s assume a Unix programmer gave us a little Perl script that reads like this:</p>
<pre><span style="color: #a020f0;">#! /usr/bin/perl</span>
<span style="color: #a020f0;">use </span>Math::Trig;

<span style="color: #0000ff;"><strong>print</strong></span> <span style="color: #800000;">"</span><span style="color: #800000;">The trip around a planet with radius </span><span style="color: #008080;">$ARGV[</span><span style="color: #800000;">0</span><span style="color: #008080;">]</span><span style="color: #800000;"> is </span><span style="color: #800000;">"</span>;
<span style="color: #0000ff;"><strong>print</strong></span> pi * <span style="color: #800000;">2</span> * <span style="color: #008080;">$ARGV[</span><span style="color: #800000;">0</span><span style="color: #008080;">]</span>;
<span style="color: #0000ff;"><strong>print</strong></span> <span style="color: #800000;">"</span><span style="color: #6a5acd;">\n</span><span style="color: #800000;">"</span>;</pre>
<p>It&#8217;s called circ, and you can invoke it as follows:</p>
<pre>$ circ 6371
The trip around a planet with radius 6371 is 40030.1735920411</pre>
<p>At least, that is what your Unix friend said. But all you get is this:</p>
<pre>c:\&gt; circ 6371
'circ' is not recognized as an internal or external command,
operable program or batch file.</pre>
<p>But couldn&#8217;t we use ftype and assoc to associate the empty extension?</p>
<pre>c:\&gt; assoc .=Perl
.=Perl

c:\&gt; ftype Perl="C:\Perl\bin\perl.exe" "%1" %*
Perl="C:\Perl\bin\perl.exe" "%1" %*

c:\&gt; circ 6371
'circ' is not recognized as an internal or external command,
operable program or batch file.
</pre>
<p>Why didn&#8217;t this work? Because we didn&#8217;t specify the empty extension as an executable extension. Windows faithfully adds all executable extensions to &#8216;circ&#8217; to make it run, but it doesn&#8217;t add the empty extension if you don&#8217;t tell it to:</p>
<pre>c:\&gt; set PATHEXT=%PATHEXT%;.
c:\&gt; circ 6371
The trip around a planet with radius 6371 is 40030.1735920411</pre>
<p>So there we are! Now we can run any Perl script that we get from our Unix friends!</p>
<h2>Another extensionless script</h2>
<p>So let&#8217;s assume a Unix programmer gave us a little PHP script that reads like this:</p>
<pre>#! /usr/bin/php
<span style="color: #6a5acd;">&lt;?php</span>
<span style="color: #008080;">print</span> "<span style="color: #800000;">The volume </span><span style="color: #6a5acd;">of</span><span style="color: #800000;"> a planet </span><span style="color: #6a5acd;">with</span><span style="color: #800000;"> radius </span><span style="color: #0000ff;"><strong>$</strong></span><span style="color: #008080;">argv</span><span style="color: #800000;">[</span><span style="color: #800000;">1</span><span style="color: #800000;">] </span><span style="color: #6a5acd;">is</span><span style="color: #800000;"> </span>";
<span style="color: #008080;">print</span> <span style="color: #008080;">pi</span><span style="color: #6a5acd;">()</span> <span style="color: #0000ff;"><strong>*</strong></span> <span style="color: #800000;">4</span> <span style="color: #0000ff;"><strong>*</strong></span> <span style="color: #008080;">pow</span><span style="color: #6a5acd;">(</span><span style="color: #0000ff;"><strong>$</strong></span><span style="color: #008080;">argv</span><span style="color: #6a5acd;">[</span><span style="color: #800000;">1</span><span style="color: #6a5acd;">]</span>,<span style="color: #800000;">3</span><span style="color: #6a5acd;">)</span> <span style="color: #0000ff;"><strong>/</strong></span> <span style="color: #800000;">3</span>;
<span style="color: #008080;">print</span> "<span style="color: #6a5acd;">\n</span>";
<span style="color: #6a5acd;">?&gt;</span></pre>
<p>And it&#8217;s called volu, and meant to be run like this:</p>
<pre>$ volu 6371
The volume of a planet with radius 6371 is 1.08320691685E+012</pre>
<p>Ouch. That won&#8217;t work, will it? Since we associated the empty extension with Perl, Windows will insist on running Perl on this script. And it isn&#8217;t Perl.</p>
<p>Perl tries, I must admit. But Perl doesn&#8217;t know we&#8217;re running on Windows, so Perl tries to run the program specified in the shebang line:</p>
<pre>c:\&gt; volu 6371
Can't exec /usr/bin/php at volu line 1.</pre>
<p>But hey! That may be the solution. What if we associated the empty extension with a program that reads shebang lines, and runs the <em>Windows equivalent</em> of the command specified in the shebang line?</p>
<h2>A Windows shebang</h2>
<p>So let&#8217;s try this:</p>
<pre>c:\&gt; assoc .=shebangfile
.=shebangfile

c:\&gt; ftype shebangfile=shebang.bat "%1" %*
shebangfile=shebang.bat "%1" %*

c:\&gt; set PATHEXT=%PATHEXT%;.</pre>
<p>Now we have arranged that every extensionless file will be run with shebang.bat, so this:</p>
<pre>c:\&gt; volu 6371</pre>
<p>will turn into this:</p>
<pre>shebang.bat c:\volu 6371</pre>
<p>Now the only thing we need to do is create shebang.bat, and put it in your path (your c:\WINDOWS directory is fine.) What shebang.bat does is exactly the same as what the shell on Unix does: it reads the first line of the file, extracts the command from it, and runs it with the whole command line as arguments. Since we don&#8217;t want to know where on Windows Perl or PHP are installed, and we don&#8217;t mind being a little better than the original shebang solution, shebang.bat just extract the last bit (the command name) from the path and runs that, effectively assuming it&#8217;s on your path. So the above command translates to:</p>
<pre>php c:\volu 6371</pre>
<p>which works like a charm.</p>
<p>Here&#8217;s shebang.bat:</p>
<pre>
@<font color="#008080">echo</font><font color="#0000ff"><b> off</b></font>
<font color="#008080">rem</font><font color="#008000"><i> shebang.bat - Unix shell behaviour from windows.</i></font>
<font color="#008080">rem</font><font color="#008000"><i> Use</i></font>
<font color="#008080">rem</font><font color="#008000"><i>     assoc .=shebangfile</i></font>
<font color="#008080">rem</font><font color="#008000"><i>     ftype shebangfile=shebang.bat &quot;</i></font><font color="#008080">%1</font><font color="#008000"><i>&quot; </i></font><font color="#008080">%*</font>
<font color="#008080">rem</font><font color="#008000"><i>     set pathext=</i></font><font color="#008080">%pathext%</font><font color="#008000"><i>;.</i></font>
<font color="#008080">rem</font><font color="#008000"><i> and put this somewhere in your path.</i></font>
<font color="#008080">rem</font><font color="#008000"><i> Author: Dion Nicolaas &lt;dion@nicolaas.net&gt;</i></font>
<font color="#008080">rem</font><font color="#008000"><i> <a href="http://whitescreen.nicolaas.net/programming/windows-shebangs">http://whitescreen.nicolaas.net/programming/windows-shebangs</a></i></font>
<font color="#008080">rem</font><font color="#008000"><i> </i></font>
<font color="#008080">rem</font><font color="#008000"><i> Get the first line of the file</i></font>
<font color="#008080">set</font> <font color="#6a5acd">/p</font><font color="#008080"> line</font><font color="#0000ff"><b>=</b></font>&lt;<font color="#008080">%1</font>
<font color="#008080">rem</font><font color="#008000"><i> Remove all quotes from the string, they shouldn't be there anyway</i></font>
<font color="#008080">set</font><font color="#008080"> line</font><font color="#0000ff"><b>=</b></font><font color="#008080">%line:&quot;=%</font>
<font color="#008080">rem</font><font color="#008000"><i> turn each part of the path into a quoted string, separated by spaces</i></font>
<font color="#008080">set</font><font color="#008080"> line</font><font color="#0000ff"><b>=</b></font><font color="#800000">&quot;</font><font color="#008080">%line:/=&quot; &quot;%</font>&quot;
<font color="#008080">rem</font><font color="#008000"><i> set first to the first part (&quot;#!&quot;), last to the last part (e.g. perl -w)</i></font>
<font color="#0000ff"><b>for</b></font> <font color="#008080">%%i</font> in (<font color="#008080">%line%</font>) do <font color="#0000ff"><b>call</b></font><font color="#0000ff"><b> :firstlast</b></font> <font color="#008080">%%i</font>
<font color="#008080">rem</font><font color="#008000"><i> if it was a shebang line, set command accordingly, else use &quot;type&quot;</i></font>
<font color="#008080">set</font><font color="#008080"> command</font><font color="#0000ff"><b>=</b></font><font color="#008080">type</font>
<font color="#0000ff"><b>if</b></font><font color="#0000ff"><b> </b></font><font color="#800000">&quot;</font><font color="#008080">%first%</font><font color="#800000">&quot;</font><font color="#0000ff"><b>==</b></font><font color="#800000">&quot;#!&quot;</font> <font color="#008080">set</font><font color="#008080"> command</font><font color="#0000ff"><b>=</b></font><font color="#008080">%last%</font>
<font color="#0000ff"><b>if</b></font><font color="#0000ff"><b> </b></font><font color="#800000">&quot;</font><font color="#008080">%first%</font><font color="#800000">&quot;</font><font color="#0000ff"><b>==</b></font><font color="#800000">&quot;#! &quot;</font> <font color="#008080">set</font><font color="#008080"> command</font><font color="#0000ff"><b>=</b></font><font color="#008080">%last%</font>
<font color="#008080">rem</font><font color="#008000"><i> Run command on the command line</i></font>
<font color="#008080">%command%</font> <font color="#008080">%*</font>
<font color="#0000ff"><b>goto</b></font><font color="#0000ff"><b> :EOF</b></font>
<font color="#0000ff"><b>:firstlast</b></font>
<font color="#008080">rem</font><font color="#008000"><i> Get first and last token, unquote in the process (which will also strip </i></font>
<font color="#008080">rem</font><font color="#008000"><i> spaces). In Unix scripts 'perl -w' is much more likely than &quot;the language</i></font>
<font color="#008080">rem</font><font color="#008000"><i> processor&quot; (long file name with spaces)</i></font>
<font color="#0000ff"><b>if</b></font><font color="#0000ff"><b> </b></font><font color="#800000">&quot;</font><font color="#008080">%first%</font><font color="#800000">&quot;</font><font color="#0000ff"><b>==</b></font><font color="#800000">&quot;&quot;</font> <font color="#008080">set</font><font color="#008080"> first</font><font color="#0000ff"><b>=</b></font>%~1
<font color="#008080">set</font><font color="#008080"> last</font><font color="#0000ff"><b>=</b></font>%~1
</pre>
<p>There&#8217;s nothing very special about this batch file. It&#8217;s just that batch language is not very good at text processing.</p>
<p>There is one special case that wasn&#8217;t mentioned before: What if a file doesn&#8217;t have a shebang line? On Unix, a script without a shebang line is assumed to be a shell script, but only if it&#8217;s permissions show it is an executable file. On Windows that would be a bit dangerous, because we just designated <em>every</em> extensionless file executable: that includes README and TODO and other files that are probably just text. So if a file doesn&#8217;t start with &#8216;#!&#8217;, we just run it through &#8216;type&#8217;, which effectively displays it on the screen.</p>
<h2>Epilogue</h2>
<p>One more thing: changing PATHEXT from your command line is temporarily. If you want this to work permanently, you need to edit your environment differently: Click &#8216;Start&#8217; / &#8216;Control Panel&#8217; / Double-click &#8216;System&#8217; / &#8216;Advanced&#8217; tab / button &#8216;Environment Variables&#8217;. Then find &#8216;PATHEXT&#8217; in the &#8216;System Variables&#8217;, &#8216;Edit&#8217; it, click a few OKs and open a new CMD window. Your old, already open windows will NOT magically get the new version of PATHEXT, but all your new ones will.</p>
<p>This version of shebang.bat only support shebang lines like this:</p>
<pre>#!/usr/local/bin/php
#! /usr/local/bin/perl -w</pre>
<p>When run with a file that starts with</p>
<pre>#! /usr/bin/env perl</pre>
<p>it will fail:</p>
<pre>'env' is not recognized as an internal or external command,
operable program or batch file.</pre>
<p>But env.bat is very easy to implement on Windows. Just store it somewhere on your path as well:</p>
<pre>@<span style="color: #008080;">%*</span></pre>
<p>This looks like cursing, but it actually means: run %* (all parameters to this batch), but don&#8217;t echo it (the @ suppresses output.) This might not catch all subtleties of the Unix &#8216;env&#8217;, but for our purpose it will do just fine.</p>
]]></content:encoded>
			<wfw:commentRss>http://whitescreen.nicolaas.net/programming/windows-shebangs/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Writing a PHP polyglot</title>
		<link>http://whitescreen.nicolaas.net/programming/php-polyglot</link>
		<comments>http://whitescreen.nicolaas.net/programming/php-polyglot#comments</comments>
		<pubDate>Thu, 22 Oct 2009 08:57:30 +0000</pubDate>
		<dc:creator>Dion Nicolaas</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://whitescreen.nicolaas.net/?p=12</guid>
		<description><![CDATA[Introduction Sometimes, it is very useful to run a PHP program from the command line. When you want to try out a small feature; when batch language just doesn&#8217;t do it; or when some of PHP&#8217;s powerful library functions (like fopen()) come in handy. However, running a small program like that is always a bit [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Sometimes, it is very useful to run a PHP program from the command line. When you want to try out a small feature; when batch language just doesn&#8217;t do it; or when some of PHP&#8217;s powerful library functions (like fopen()) come in handy. However, running a small program like that is always a bit clumsy. First of all, PHP is usually not in your path; and wouldn&#8217;t be nice if you could just type the name of the program and run it?<br />
Take this simple PHP script:</p>
<pre>&lt;?php
print date('r', $argv[1]) . "\n";
?&gt;</pre>
<p>If you ever store dates as a time(), i.e. the number of seconds since 1 January, 1970, you know how useful this is. You can call it like this:</p>
<pre>c:\php\php.exe -q time2str.php 1234567890</pre>
<p>and it will answer with</p>
<pre>Sat, 14 Feb 2009 00:31:30 +0100</pre>
<p>Indeed, Valentine&#8217;s day in 2009.<br />
But the call you have to make is pretty cumbersome. So you write a batch file, time2str.bat, that looks like this:</p>
<pre>@c:\php\php.exe -q time2str.php %1</pre>
<p>and now you can just type</p>
<pre>time2str 1234567890</pre>
<p>to get your result. You stuff both files somewhere in your path, and when you remember about it a few days later, you type:</p>
<pre>time2str 1234567890
Could not open input file: time2str.php</pre>
<p>Hmm. Of course you are running from another directory now. So now you should hardcode time2str.php&#8217;s directory. Or time2str.bat should be smart enough to find out its own directory, and then find the PHP file in it. This batch file starts to become a nuisance.</p>
<h3>The Unix shell can do it</h3>
<p>In Unix and Linux, there is a good solution for this. Any script, being shell script, Perl, PHP or any other language, will be started by the shell; and any script can have a very special line in the beginning, that looks e.g. like this:</p>
<pre>#! /usr/bin/perl -w</pre>
<p>The #! means so much as: &#8216;use the following command to run this script&#8217;. And then the name of the program to use follows. Now the shell knows what to do with this program, and does that instead of trying to interpret the file itself.<br />
Now that would be nice on Windows! Unfortunately, it doesn&#8217;t exists. What does exist is the &#8216;executable extension&#8217;: if you double-click on a file called something.doc, the application handling DOC files is started. What not everyone knows, is that this also means that if you type something.doc at the command line, that application is started. But to enable this, you have to change global settings on your system, and in case of PHP, there is a clear drawback: if you now double-click a PHP file, it will be executed in a DOS window that disappears immediately after the program ends. It makes more sense to associate PHP files with your favourite editor!</p>
<h3>&#8230; but a polyglot can, too</h3>
<p>The solution presented here was inspired by Perl, for which a similar trick trick exists to make Perl scripts execute on Windows. The idea is to turn the PHP file into a batch file that runs PHP on itself. But that is easier said than done&#8230;<br />
Here&#8217;s an outline of the task. We want a PHP program to run from the command line. To achieve this, we turn it into a batch file. That batch file contains both instructions in batch file language to run PHP, and the actual PHP program that is being executed. The two problems are that PHP should completely ignore the batch instructions, whereas the batch interpreter, CMD, should ignore the PHP code. A program that runs in two languages is usually called a polyglot; strictly speaking, a polyglot should do the same in both languages, but this is a more practical example.</p>
<h3>Let&#8217;s just start somewhere</h3>
<p>Here&#8217;s the first take. Let&#8217;s create a batch file called str2time.bat that contains the following:</p>
<pre>@c:\php\php.exe -q %~f0 %*
@goto :EOF
&lt;?php
 print date('r', $argv[1]) . "\n";
?&gt;</pre>
<p>The first line runs PHP (or more precisely, c:\php\php.exe) on the file indicated by %~f0. This is batch-speak to point to the full path of %0, and %0 is the command itself. So %~f0 expands to the full path of the batch file time2str.bat itself. %* stands for all command line parameters except %0. They will be passed to PHP, which will handle them.<br />
The second line skips to the end of the file. the label :EOF is always implicitly present in batch files. This makes sure the rest of the file, in this case the PHP code, is completely skipped bij CMD. A feature of CMD that is in this case helpful is that it will not read the skipped lines at all. The batch file will run without error messages, even though these lines are not valid batch syntax.<br />
The @-characters in the first two lines make sure that those lines are not echoed by CMD before they are executed. The same can be achieved by starting the batch file with @echo off, but this is shorter.<br />
Then follows the PHP code, but the batch interpreter blindly ignores all that; it just jumps to the end of the file and exits. So half of the task is done!<br />
If you run this, you will see the following:</p>
<pre>@c:\php\php.exe -q %~f0 %*
@goto :EOF
Sat, 14 Feb 2009 00:31:30 +0100</pre>
<p>Here the burden of the polyglot programmer shows: who produced this output? PHP or CMD? In this case, it is pretty easy to sort out: it was PHP. In PHP, everything that appears outside &lt;?php and ?&gt; will be printed literally. So the first to lines of our PHP script are the first line of our output. The the rest is executed, and the correct answer is printed: Valentine&#8217;s day.</p>
<h3>&#8216;Shut up, PHP!&#8217;</h3>
<p>So now the task at hand is this: make sure the file starts with &lt;?php. How about:</p>
<pre>&lt;?php /*
@c:\php\php.exe -q %~f0 %*
@goto :EOF
*/ ?&gt;
&lt;?php
 print date('r', $argv[1]) . "\n";
?&gt;</pre>
<p>What is done here is twofold: first of all, we start the file with a PHP opening tag, to make sure the batch lines are not printed; and secondly, we place comment brackets around the batch lines, to make sure PHP doesn&#8217;t try to execute them! So we now have hidden the two lines of batch instructions from PHP. Let&#8217;s try; do you feel what&#8217;s coming?</p>
<pre>/*0&lt;?php
The filename, directory name, or volume label syntax is incorrect.
Sat, 14 Feb 2009 00:31:30 +0100</pre>
<p>Whoops. What is this? And again: Who produced this output?</p>
<h3>&#8216;&#8230; and you too, CMD!&#8217;</h3>
<p>This time, it&#8217;s the batch interpreter that is complaining. First of all, it echoes the first command it encounters in the file:</p>
<pre>/*0&lt;?php</pre>
<p>What it really wanted to say was this:</p>
<pre>/* 0&lt; ?php</pre>
<p>which is the long version of:</p>
<pre>/* &lt; ?php</pre>
<p>What you see here is a redirected input command, much like e.g.</p>
<pre>sort &lt; records.txt</pre>
<p>In CMD, you are allowed to reverse the order of the parts, and write</p>
<pre>&lt; records.txt sort</pre>
<p>To be helpful, when echoing the command, CMD will put it in the right order. In our polyglot, we see that CMD actually tries to execute the command /* and uses ?php as input.<br />
After executing this command, CMD produces an error message:</p>
<pre>The filename, directory name, or volume label syntax is incorrect.</pre>
<p>That&#8217;s the second line of the output. The reason for this error message is that the filename ?php is not valid for redirecting: it contains a wildcard (?), and CMD cannot handle that.<br />
The last line is our output from PHP, which is just how we want it. So now the PHP problems are solved, but we have two new, batch-related problems: the first line is now echoed by CMD, and produces an error when executing because the syntax is incorrect. How do we hide this line from CMD?<br />
Polyglot programming is a bit like running in circles; every time you solve a problem in one languages, you create a new problem in the other language. Luckily, the problems are becoming smaller in the process.</p>
<h3>Do nothing in two languages</h3>
<p>The fact that CMD reversed the order of the parts is the key. In batch files, you can make sure lines are not executed at all by starting them with a :-character. This is different from a rem-statement; the latter is executed, and echoed if echo is still on. In fact, : is a very powerful character, as you can see in the next version:</p>
<pre>&lt;?php/* :
@c:\php\php.exe -q %~f0 %*
@goto :EOF
*/ ?&gt;
&lt;?php
 print date('r', $argv[1]) . "\n";
?&gt;</pre>
<p>In this version, two things are changed in the first line: first of all, the PHP comment opening is placed directly after the PHP opening tag; and secondly, the :-character is added. Now here is a surprise; CMD will be smart enough to reverse the order of the parts, but after that, it will find out it has nothing to do! CMD will execute the following line:</p>
<pre>: &lt; ?php/*</pre>
<p>But since lines starting with a : are completely skipped, CMD doesn&#8217;t even look at the filename anymore. By concatenating the PHP opening tag and the comment opening, we created a longer, even more illegal filename ?php/*, which is ignored completely. But in the file, the :-character appears inside the PHP comment, so PHP doesn&#8217;t care about it at all.<br />
And this is it! If we run this batch file, we get:</p>
<pre>Sat, 14 Feb 2009 00:31:30 +0100</pre>
<p>And that is exactly the output of PHP we want.<br />
Voila! Four lines of polyglot that you can just prepend to every PHP program to make it run from the command line. Three lines more than Unix, but it makes for a much more interesting read.</p>
<h3>Appendix</h3>
<p>Below is the file with simple syntax highlighting, first the batch version, then the PHP version. Special words and characters are purple, comments are green, and functions and variables are blue. The grey part in the batch file is mostly invalid syntax, but is never reached.<br />
One more thing: since everything after the : in the first line is seen as a comment in both PHP and batch language, you can really write a comment there. I inserted some sort of small signature there.</p>
<h4>Batch</h4>
<pre><span style="color: #6a5acd;">&lt;</span>?php/* <span style="color: #008000;"><em>: http://whitescreen.nicolaas.net/php_polyglot.php</em></span>
<span style="color: #6a5acd;">@</span>c:\php\php.exe -q <span style="color: #0000ff;"><strong>%~f0</strong></span> <span style="color: #0000ff;"><strong>%*</strong></span>
<span style="color: #6a5acd;">@</span><span style="color: #0000ff;"><strong>goto</strong></span><span style="color: #0000ff;"><strong> :EOF</strong></span>
<span style="color: silver;"><em>*/ ?&gt;
&lt;?php
    print date('r', $argv[1]) . "\n";
?&gt;</em></span></pre>
<h4>PHP</h4>
<pre><span style="color: #6a5acd;">&lt;?php</span><span style="color: #008000;"><em>/* : http://whitescreen.nicolaas.net/php_polyglot.php</em></span>
<span style="color: #008000;"><em>@c:\php\php.exe -q %~f0 %*</em></span>
<span style="color: #008000;"><em>@goto :EOF</em></span>
<span style="color: #008000;"><em>*/</em></span> <span style="color: #6a5acd;">?&gt;</span>
<span style="color: #6a5acd;">&lt;?php</span>
    <span style="color: #0000ff;"><strong>print</strong></span> <span style="color: #0000ff;"><strong>date</strong></span><span style="color: #6a5acd;">(</span>'<span style="color: #800000;">r</span>', <span style="color: #0000ff;"><strong>$argv</strong></span><span style="color: #6a5acd;">[</span><span style="color: #800000;">1</span><span style="color: #6a5acd;">])</span> <span style="color: #0000ff;"><strong>.</strong></span> "<span style="color: #800000;">\n</span>";
<span style="color: #6a5acd;">?&gt;</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://whitescreen.nicolaas.net/programming/php-polyglot/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>White screen</title>
		<link>http://whitescreen.nicolaas.net/about/white-screen-wordpress</link>
		<comments>http://whitescreen.nicolaas.net/about/white-screen-wordpress#comments</comments>
		<pubDate>Thu, 22 Oct 2009 07:33:44 +0000</pubDate>
		<dc:creator>Dion Nicolaas</dc:creator>
				<category><![CDATA[About]]></category>

		<guid isPermaLink="false">http://whitescreen.nicolaas.net/?p=1</guid>
		<description><![CDATA[Some knowledge is there to be shared. Some observations may be worth knowing. The White Screen already exists for a while, but it was never easy to add to that&#8230; Which probably means that some knowledge remains unknown. Let&#8217;s try this way&#8230;]]></description>
			<content:encoded><![CDATA[<p>Some knowledge is there to be shared. Some observations may be worth knowing.</p>
<p>The White Screen already exists for a while, but it was never easy to add to that&#8230; Which probably means that some knowledge remains unknown. Let&#8217;s try this way&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://whitescreen.nicolaas.net/about/white-screen-wordpress/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
