My life as an hacker
I am not someone who breaks into computers and such.
I am someone that likes to play with computers and write programs.
It is sad that nowadays almost everybody gives the term hacker
a different meaning from its original
It is useless to ask me for help with breaking passwords and such.
I have no experience with such things, and even if I could, I will
not help you, for the simple reason that I am not for hire for this
kind of work.
As a young boy I already displayed a great interest in
electricity and electronics,
and did I dream about having my own computer center in
the future, as some drawings indicated.
My very first contact with real computers came through my cousin
Frans Faase, who gave me
a paper tape with one of his programs. At home I tried to decode this
tape by hand, and got some of the lines decoded.
I think it was part of an Algol 60 program.
And because we happen to have the same (calling) name, I also adopted
his account name at the university: FAAF, and used it whenever
I dreamed about doing something with computers.
My life as a hacker really started in high school,
when on December 9, 1977 (Dutch),
during an outing with our class, I met
through one of my teachers.
It was during a dinner in a Chinese restaurant that he concluded that
I must be good with computers, after he heard I was good in everything
in school except languages. Later that evening, at his home, he showed
me some books about Artificial Intelligence. In March 1978, I got a book
about Algol 60, and I started to write some programs.
On May 5 (Dutch),
I went to the Academic Computer Centre Utrecht (ACCU), where
I met with Henk. He shows me around and taught me how to use the
main frame (using NOS/BE). I had to use punch cards to
run programs. Henk was using a simulation program, where each line contains
a simulation rule. Henk told me that he sometimes shuffled the punch cards
just before putting them in the card reader, just to baffle the others,
because the order of the rules does not matter. I tried to run one of my
own Algol 60 programs, but not which much success.
In the months that follow, I receive several letters for Henk, and also
got some more books (including A Comparative
study of Programming Languages). He also told me about recursive
functions. On June 17 (Dutch),
I designed my first programming language, which was
a functional programming language with recursion. The next Monday, I also
got the idea of writing a program for a "artificial brain" (neural network)
with 84 nodes.
This congress was held at Amsterdam, August 22-25, 1978. When Henk Koppelaar
had to present a talk there, he invited me to join him on August 24 (Dutch). This became the
first computer science conference I attended.
At the end of the day, I also attended a chess match between Roland Lever and
the Russian chess program Kaissa.
When I was in England that summer,
on a language course, I bought the LISP 1.5 Programmer's Manual by
John McCarthy from
in London on July 21 (Dutch),
because Henk had told me that it was the language for Artificial
Intelligence. (Remember Eliza?) Of course, I read this book, and that is how I learned LISP.
(Read a discussion about the origin of
CAR and CDR, if you like.)
Summer of 78: Fortran on a Cyber main frame
On Tuesday, June 20, 1978, Henk phoned me up to tell me had a program,
called SOCPAC, in IBM Fortran that he wanted to be ported to the Cyber.
The next day (Dutch),
I went to his office to collect the box with approximately
1500 punch cards and found my way to the ACCU, and started working.
At first I would load the whole deck of cards repeatedly. Soon I
found I could store them, and edit them by giving commands that
would remove or add lines at a time. On the next Friday, I also used
a terminal to make some edits, and I showed my parents around the ACCU.
Every time when I ran a job, I would sit down in front of a monitor
showing the different queues of the main frame; the input, the running
and the printing queue. I used the FIBMCDC conversion program to
convert the program from IBM Fortran to CDC Fortran dialect, which
costed 900000 Kws (Kilo word seconds??).
That summer I learned Fortran, the batch language and the editing
language Update mostly by myself. After having gone to
England, I got the program running
Henk gave me the book `Finite Mathematics'
by Seymour Lipschutz as a reward for my work.
Because Henk had a budget on the computer
that he was afraid to lose, he let me use it freely. So in the years that
followed, I often went to Utrecht to either try out some kind of Fortran
program, or to work with LISP.
In Fortran I wrote my first program
that could be used to count Hamilton paths
in a square grid graph. (Of course, I did not know that they were called
Hamilton paths at that time.)
I wrote my own shortest path LISP function before I saw
Dijkstra's algorithm for this.
(On December 28, 1980
I also wrote a program to find all the shortest paths
in Fortran of order
n^2 log(n), which is also known
as Floyd's algorithm.)
I wrote some list matching functions
in LISP, as an extension to string matching ideas that I found in a language
called METEOR that Henk and a student of him worked on.
(For a description of METEOR see the chapter METEOR A List Interpreter for String Transformation in
The Programming Language LISP: Its Operation and Applications.)
Finally, I managed to write a recursive-decent LL(1)
compiler-compiler in LISP that generated LISP. This program consisted of
about one thousand lines of LISP. If you wanted to use it you had to make
a file that would contain:
The compiler-compiler would read the grammar rules, and based
on these define some LISP functions that would form the compiler.
These functions would then read the remaining of the input according
the grammar rules and execute the generated code, consisting
of some LISP functions.
I did this without any books about compilers or compiler-compilers.
Sadly enough, I lost the code.
I also wrote a set of functions for formatting text and (a primitive
form of) plotting to an ASCII file. (And of course, I tried to write
a LISP interpreter in Fortran.)
In my freshman year I learned Algol 68 (the most academical program
language, ever made) and Pascal (which was initially only intended
as a toy-language for a compiler construction course).
(Algol 68 compilers are still being developed, I found out recently.)
- The compiler-compiler.
- The grammar rules
(rather primitive, but it worked).
- The input to be compiled.
One of my room mates bought a Acorn Atom,
a home computer build around a 6502 processor.
It is a fairly unknown machine made by the British Acorn company, which
had a very nice dialect of Basic, that was designed rather
orthogonal. It also had a build in assembler, which I started to use
soon after I discovered it.
I came up with the idea for what is knows as Langton's Ant, and wrote a program for it.
Later, I also wrote a Hamilton path
counting program in machine language,
which took (at that time) almost a complete day to count the
number of Hamilton paths on a grid of 7 by 7 that started in
one of the corners. It found around 1.5 million paths.
The computer was also used for some serious work. I developed a
dorm administration program, which was
used for calculating how much we had to pay each other with respect
to the use of the telephone, coffee and joint meals.
Somewhere in my third year, I also wrote
a cross-assembler that generated code for a
The Atari 800 XL is another home computer build around the 6502.
On this we (a roommate and me) wrote our first complete compiler
for a small language to 6502 machine code.
It was written in Basic.
The first thing we did when it was ready, was writing the compiler
in the language and compile it with the compiler written in Basic.
At the end this took around 20 minutes, but we got our compiler
written in machine code. (A classical example of boots-trapping.)
This we got at our dorm, only at the end of my study.
As it had colour graphics I invested a lot of time in
writing a program in GfA-Basic that could generated Mandelbrot
fractals, in a way that you quickly get an impression of how
the picture was going to look, without having to calculate
all dots (line by line).
Another project I did was writing the software for an installation
of an artist, which consisted of three televisions. These three
televisions were put side-by-side, where the middle one could spin
around the centre of the screen. The sequence of events would start
with showing a Dutch soccer player (Koeman) kicking a ball in the
direction of the centre screen. Then the centre screen would start
spinning and display a bouncing ball. At some moment this ball would
fly out to one of the screens on the outside, where a reverse slide
show of the soccer player would catch the ball.
With all my previous experiences with compilers and compiler-compilers,
it was to be expected that I would do something like that for my
master thesis. My master thesis got the (horrible) title:
An attribute evaluator generator.
It was intended to become part of a compiler-compiler system,
and consisted of a Pascal program that would generate Pascal code for attribute evaluation in Abstract Program
In the three years after my graduation, I worked part-time at
the University of Twente on finishing the program and writing
the documentation for it.
Up to now, its my best documented program, which sadly enough, has
never been used, or read by someone, as far as I know.
It was the first big program that I wrote, which consisted of
about 500K of source code. The documentation consist of a
technical report describing the functional
specification of the program, and a technical report containing the source code and it documentation.
I also worked on a variant called Propertied Abstract Trees or PAT for short.
An Atari ST was used to read the position of the middle television
by means of the joystick interface, and control the speed and
direction of the motor attached to the middle television.
The video output of the Atari was switched between the three televisions.
Both the sensors and the accurators were rather primitive: only 16
different positions could be detected, and the motor control used
only 4 levels (including off), which were not linear. The motor would
not start running at the lower levels.
The most difficult part turned out to be the controlling of the turning
speed of the motor.
The installation was shown at several art-displays around the country.
Email and Relay
When I started to work at the University, it was also the first
time I came in contact, what is now known as the Internet. At that
time it consisted of a number of loosely connected networks, such
as ARPA and EARN. The oldest email I have kept was sent to me
on February 27, 1987 by Albert Nymeyer from Australia. My UUCP email
address from that time was mcvax!utrcu1!utrinu!fransjf.
My EARN email address was firstname.lastname@example.org.
Besides email, I also made use of Relay, an early predecessor of IIRC.
It was a simple command-line oriented interface. I did spend
some time writing a Turbo Pascal program implementing a little better interface.
This program would divide the screen into three parts. The top half
would contain the list of participants, the lower half the lines
that people wrote, and the bottom line was used as a command line.
In coming status change messages (people joining or leaving the channel)
were not displayed in the lower half but used to update the list
in the top half of the screen.
During this time, I also discovered that PostScript is a programming
language. Here are some of my PostScript programs based on the ones
that I wrote then:
(Please, modify these before printing, as they contain endless loops!)
- The Henon curve.
- A more interesting curve found by
a friend of me.
- An ever extending cloud of points.
View in Landscape mode, if using ghostview.
Only three years after I graduated, I started working in the real
world (with PC's), which was a refreshing experience, because I had to learn
many new things. So far, I had only used Pascal, now I learned C,
which since than became my prime programming language, and which I
still use for all my private hacking. In the four years that
I worked at the software company, I learned a lot about hacking.
Because I was working at many different projects, I often had to
change the config.sys and the autoexec.bat files.
Not soon, I wrote a the project.bat
batch file, which would do this for me. It makes us of the program
getjn, which asks a Yes/No question.
One time I had to write a program in AutoLISP (part of AutoCAD)
that had to read many small tables with information from external
files. I decided to only read this files on demand, and use
a LISP function that would redefine itself after having read
the table, in such a way that it would just return the contents
of the table as a single value. Such a function would look like:
(defun read_table_a ( / v)
(setq v (read_table 'format_fn "a.txt"))
(eval (list 'defun 'read_table_a '() (list 'quote v)))
And because I had many of these tables, I defined a LISP function
that could define them, based on a file name, and a format description
(in the form of a LISP function). To get the above definition
one would call:
(def_read_table 'read_table "a.txt" 'format_fm)
This function is a function that defined functions that can
redefine themselves. The function was loaded with quote, list and eval
functions, but it worked. It looks like:
(defun def_read_table (fn filename format)
(list 'defun fn '( / v)
(list 'setq 'v (list 'read_table (list 'quote format) filename))
(list 'eval (list 'list ''defun (list 'quote fn) ''() '(list 'quote v)))
The LISP function read_table was a function that read the
input file, line by line, ignoring commented lines starting with
percent-sign. Each line was converted to list of strings with
the `words' on the line. The format function would then be applied
to this list of strings to return a row in the table.
I leave it up to the reader to define this LISP function.
Export/import SQL script
One day a colleague of mine, needed to make some test input, based
on the contents of an SQL database. So, he wanted to have an
SQL select statement that would return insert statements with the
contents of a table. So, I wrote something like:
select 'insert into TAB1
||');' from TAB1;
This SQL script when executed will output for each row of the table
TAB1 an insert statement, assuming that the table has the
four columns: KEY, NAME1, NAME2 and
NUM1, where KEY and NUM1 are numeric and
the other fields strings.
And when I had written this, he wanted to have
a SQL statement that would return this SQL statement, given the
name of the table (TAB1 in this example),
using the contents of the data-dictionary tables.
So, I wrote:
1, 'select ''insert into TAB1 values(''||',
where table_name = TAB1
order by column_id;
select '||'');'' from TAB1;' from dual;
If this script is executed it will output the first select statement
I wrote, assuming the table user_tab_columns contains
the table definition of the above given definition of table TAB1.
And when we got this, he wanted to have a script that would
return the above two select statements for each table in the
database (again using the data dictionary tables).
Finally, we managed to do this using a single
SQL*Plus (of Oracle) script, using the ability of
redirect its output to a file, and to execute files.
The final script looked like this:
set heading off
set feedback off
set linesize 90
set pagesize 2000
select 'spool exps.sql ' from dual;
'select decode(column_id, 1,'||
'''select ''''insert into '||table_name||' values(''''||'',',
'from user_tab_columns '||
'where table_name = '''||table_name||'''',
' order by column_id; ',
'select ''||'''');'''' from '||table_name||';'' from dual;'
select 'spool off' from dual;
set linesize 120
If this script is executed the output of the select statements will
to spooled to the file e__.sql, which will contain two select
statements for each table name mentioned in the table user_tables.
Secondly, the script will execute the e__.sql script.
The e__.sql script will generate one select statement
for each table in the file exps.sql.
To generate a script import.sql containing an insert statement for
each single row in the database, we have to execute the following
Thus you only need SQL*Plus to make a dump of a database, and
import it in another instance of the database, with the added functionality
of being able to edit the dump.
of a fast variant of the bubble sort
Bubble sort, can be considered as the most simple sort algorithm,
but it is often characterised as not being very optimal. C-libraries
often contain the function qsort() which is (in most cases -- don't let
the name fool you) an implementation of the faster Quick-sort algorithm.
What many people don't know is that this is a recursive algorithm, which
can behave bad on an (almost) sorted array, and could lead to unwanted
stack-overflows. Of course, proper implementations should not cause
stack-overflows, and would not show bad behaviour on an (almost) sorted
array by selecting a good `pivot' element.
As this once happened to me (with the qsort() of an old version
of MSC), I wrote a faster bubble sort function, based on some ideas
that I read in some magazine somewhere. (Don't ask me which magazine.
I have a good memory for algorithms, but a bad memory for data.)
First of all bubble sort can be improved by using alternating
passes. Secondly, it can be improved by starting comparing pairs of
elements that are further away from each other.
The algorithm I implemented here, starts of with comparing pairs in
each half of the array, and reduces the distance after each pass.
The distance is reduced faster, depending how many elements were
exchanged. Although this algorithm is not
which is the optimal lower bound for sorting, it comes quite close
in practice, which makes it much better than traditional bubble
sort, which is
Gareth McCaughan compared
my program with some other sorting algorithms, wrote
a small test report about it.
I wrote a modified version of bsort.c,
bsort_s.c, which work for arrays
of simple types (like char, int and double)
with the default compare operator `<'.
When Lawrence Kirby made a
request on comp.lang.c
for (Quick) sort algorithm on list, I realized that my algorithm can
be adapted for lists: bsort_l.c
(Has not been tested yet). Later on, I wrote another version,
which sorts the list instead of swapping the contents:
My favourite editor on the DOS platform is q
from SemWare. The latest
version that I worked with was renamed into e.
(Nice names for editors, as hackers do not like to type much.)
For the last one, I wrote some extra
functions in its macro language.
During this time I also started decoding the DWG-format that is being used by AutoCAD (Release 12). My boss
had told me that some other company had taken a year to decode it.
Within a month I decode half of it, the remaining only being some
stupid work. A binary compare program that I had written
(bfc.c) turned out to be very
help full to find the main structure. So far, I have found nobody
that is interested, or that would like to finish the work.
When I wanted to convert some old MS Word 5.0
(on MSDOS) documents to the Word for Windows 97, I discovered that
these old file formats are no longer recognized. Of course, I searched
the web for this, but failed to find anything about this. Thus, I felt
there was no other option left but to reverse engineer the Word 5.0 file
format. (I vaguely remembered having seen a description of the format in
some book about five years ago. I blamed myself for not buying the book
then.) After some hours of puzzling, I discovered that the structure
is actually not so complicated. It is even rather redundant in many
ways, which made it easier to reverse engineer it for the matter.
I finally managed to write a program for
converting the documents into HTML. I have to admit that this program
is not one of my best designed one, but what do you expect for a
one time conversion program.
Because there are no free tools to export the contents
a Quark Xpress file,
I worked on reverse engineering the format by myself. The
story of this is found in my online
diary starting on Saturday, February 17,
2001. I worked on it till mid May 2002. On August 26, 2002,
I decided to make the results of this effort
public as free software.
This involved the conversion of a collection of Quark Xpress files
of a multi volume Dutch study bible into a logical structure output, which
has been used in the development of an online version of the study
Recovering data from tapes
Starting from September 16, 2002, I made many attempts to recover data
from tapes in the format used by the Acorn Atom.
I finally succeeded in on the weekend of January 18-19, 2003.
Starting the sample application that came with the Crystal Edit
I developed my own editor which I named
MySample. Most of my efforts went
into reimplementing the colour coding making use of the
Currently, I do not have time to embark on any large projects, although
I am often thinking about software engineering systems based on some
ideas I described on the page "The Art of Programming".
Some of the ideas presented there, I am trying to implement in a
project, that I named the "MetaMeta" project.
Other hacks and puzzles
- The 12 coin problem.
- A program for finding the word `KERST'
(Dutch for Christmas) in a diamond.
An diamond filled with as many
words `KERST' (?).
- Hacked together my own implementation of a Non-Networked File System.
- A small program to split up a string into
a given set of strings.
- A more forgiving uudecode program,
that can be used to process multi-part uuencode postings collected
in a single file, without having to edit the file.
- A small program that finds the
maximal lowest common multiplier of the numbers a_1, .., a_k
that sum up to n, for a given n. Or in other words:
the largest order of a permutation of length n
(already published in
`Bulletin de la Société Mathématique de France',
Vol. 97, page 187, 1969).
The results for n upto 100.
- The `King's beautiful fractal dream' hack.
- The You.cgi-script that fingers
the persons who want to know what I know about them (many want to
know this). It also keeps a log, so I can know who wants to know
what I know about them. The script uses
- Simple way of getting access log statistics.
- Something about sparse rulers.
- syncd.c, a program for
synchronizing the contents of a Unix directory and a DOS
directory on a floppy disk.
- Using Make for processing files with
LaTeX, makeindex, and tibb.
- Working out my own LaTeX style file
for my online diary.
- go2ps.c, a simple filter
for generating a PostScript file from a Go game record. Each page
of the generated file shows the board for the move with the same
- parse.c, a program to
parse expressions and evaluate expressions.
Someone needed it, and I wrote it in
about an hour. It is not complete, and also not correct.
- add_footer.c, a filter
which adds footers to PostScript files generated by Netscape
containing a (optional) URL, and a page number.
- Mixer: a program which slowly
changes the image on the root window of an X-terminal.
- BrainF*** interpreters and compilers
- Description of the I-LOVE-YOU computer virus
- Machine independent implementation of Cooperative
Multi-threading in C
- How to crack a Binary File Format
- Java/C# like class defintions in C++
- Implementing a C++ based Object-Oriented store with Memory Mapped Files
- Yokogawa NR800 Near Infrared Analyzer SP2 file format
I performed various hardware hacks on some
computers and even did some case moding.
Some hackerish links