Hacker News new | ask | show | jobs
by jsnell 3031 days ago
As a historical curiosity, in the very first versions of Unix chdir was a normal command rather than a shell builtin.

You see, at that point Unix had no fork system call. There were multiple processes, but they were created statically at startup rather than on-demand. Running a command in the shell would cause the command to replace the shell in the address space of the process, and the process quitting would put the shell back in there.

This worked perfectly with cd being a normal command. Then they implemented fork() and were for a while very confused trying to debug how in the world fork() could have broken the chdir() system call :)

2 comments

This is a really common way for software to become better.

The pattern of development:

  - Make A   
  - Make B better   
  - A now broken because it had dependencies on B   
  - (maybe) Realize a fundamental pattern that unifies A and B.
  - (maybe) Unify principles so that A and B become lemmas.
This is a very scientific way of working. The truth emerges as the byproduct of keeping all the plates spinning in your model. As long as you remain aware of all the plates, you'll eventually realize something deep. It's also the strongest argument I can think of in favour of rewriting a codebase plan-9 style. Once you have the truth in mind, bake your knowledge for big wins. Baked knowledge can form the foundation upon which you can climb higher.

But many developers don't keep all the plates spinning. If you don't have everything (or some subset) making sense in some unified theory, don't rewrite. Without a unified grand theory, then you can't make something better. This is why I write unit tests — doing so keeps your plates spinning. It's not about proving your language and libraries are doing what is expected (although that's valuable too in some languages without unified libraries) — it's about showing that everything is working together the way your grand theory intends. Unit tests should be written to reject some part of the null hypothesis.

This is such a cool way of presenting it, I'll reuse that. Thanks!
To elaborate, I really enjoyed reading Dennis Ritchie give some background on the evolution of Unix[1]:

> As a historical curiosity, in the very first versions of Unix chdir was a normal command rather than a shell builtin.

> You see, at that point Unix had no fork system call. There were multiple processes, but they were created statically at startup rather than on-demand. Running a command in the shell would cause the command to replace the shell in the address space of the process, and the process quitting would put the shell back in there.

> This worked perfectly with cd being a normal command. Then they implemented fork() and were for a while very confused trying to debug how in the world fork() could have broken the chdir() system call :)

[1] https://www.bell-labs.com/usr/dmr/www/hist.html

To clarify, these are very early revisions of Unix we're discussing, prior to Research Unix v1. By the time v1 happened, fork existed, and `chdir` was a shell builtin.