Worst Abuse of the Rules
In 1988, the International Obfuscated C Code Contest (ioccc) decided a winner under the category of “Best abuse of the rules.” The c code that was submitted was a single line
#include "/dev/tty" .¹
The author, Diomidis Spinellis had this to say about his code:
This program can be configured to do almost everything.
The configuration is done during compile time by typing
in, C code, what one would like the program to perform.
A trivial example is given in the ‘how to compile’ section
but the possibilities are clearly limited only by your
imagination and programming skills.
To which the competition had this polite response:
We enjoyed this entry this year, however in the future programs
must be able to be compiled from within a makefile without the
need of human intervention.²
The compilation process is as follows
The user manually types in the c program to be compiled followed by an EOF character
When run, the program we configured to print “Hello, World!” does just that.
The C Pre-processor’s Role:
One of the functions of the pre-processor is to insert the contents of a file determined by
#include directive is almost always at the beginning of the file. The compiler requires header file contents when calling functions from the standard library during the linking phase of compilation. If prototypes (like
int putchar(char c);) or macro definitions like
#define NULL ((void *)0) are not defined before they are called, the program might not compile, or work as intended. However,
#include is not required to be at the beginning of the code, and can be placed anywhere; the content is inserted at the point in the file where the directive appears.
There are two ways to include a file. Directives like
#include <stdio.h> are used for system headers. The <> characters tell the pre-processor to search through a standard list of system directories, while directives like
#include “header.h" search for the files in the directory that contains the current file. These are stored as string literals, and any characters cannot be escaped, nor can they be expanded by macros. It is also possible to include a file with its absolute path, like
#include “absolute/filepat.h” In which case, the pre-processor inserts the contents of the file at the current position in the file.³
The /dev/tty “File”:
Spinellis won this category because the included file path was pointing to a special device file in the
/dev directory that is connected to physical hardware functionality through the kernel. On Linux, everything is considered to be a file. Even directories are a type of file that contains other files. Devices can be read from and written to, just like a file. The
/dev directory contains representations of hardware functionality in the form of files that data can be read from and/or written to. A tangible example is the representation of the physical speakers:
/dev/dsp. Any text sent to this file is output through the speakers.⁴
The device file
tty is a representation of the Teletype console, which can be either kernel-emulated or hardware implemented. Simply put, a terminal or console is an interface to issue commands to a computer. Teletype consoles were devices that resembled typewriters and could be used to issue commands, hence Tele as in telephone, and Type as in typewriter, or
tty for short. The modern linux file
tty represents the primary input and output of an application’s process.
When the command
gcc spinellis.c is executed, the pre-processor calls the file
/dev/tty , which opens up a new controlling terminal for the process and waits for the user to write something for it to compile. After the user enters an EOF (
CTL + d), the program complies as it normally would. This places the burden of programming functionality on the one compiling, how very tricky!
man 4 tty to bring up the manual page for
tty on a unix machine
dev is the location of special or device files. It is a very interesting directory that highlights one important aspect…www.tldp.org
To send text to a terminal you may redirect standard output of some command-line command to the appropriate special…tldp.org