Recent: Election Night RCS Photos Space Stamps Fireworks Long Black Curly Eyes Nixie Tubes Memory Scavengers Nightshade Cobras Magical Feedback of Oz Harp Case Reading List 2023 Moonrise Local Wildlife Centipede Recent Photos Mouse Teeth Reading List 2022 Connection Machine Photo |
The main philosophical difference between Unix and Multics
is that Multics provides facilities which are carefully engineered
to solve specific well-defined problems, while Unix is more like a
metal shop. You are given a bunch of very simple tools, and a first-aid
kit: do what you want, suffer the consequences if you do something stupid.
Unix is anarchy, Multics is newspeak.
A good example of how Unix copied a Multics feature, but
redesigned it with a "simple & sloppy" philosophy is
command output substitution. This did not show up in the earliest
versions of Unix (not until the Bourne Shell, 7th Edition Unix, 1979),
but it is still clearly a copy of a very key Multics feature.
In Multics, this is called an "active function", and it looks
something like:
"af-command arg arg" is executed and the results put back in the
command line string before it is further parsed & executed.
The Unix version looks almost exactly the same:
But the important thing is that the Unix developers managed to
duplicate this Multics feature using a completely different
internal mechanism.
In Multics, a program has to be specifically written to support
being invoked as an active function, and the code used to output
is completely different from a normal program. A Multics program
that is to be used as an active function calls the "cu_$af_return_arg"
subroutine which provides a "return string" pointer. The program writes
its output to that string, and then exits, instead of using the
normal output routines (PUT, WRITE, iox_, etc.).
For example, this is the PL/I code from the "calc" standard
utility that determines if it is currently being used as an
active function, gets the return string, and sets some
flags ("af_sw" (active function switch) is set to true (1) if
calc is being called as an active function, false (0) otherwise):
When calculations are complete, it checks if af_sw is true, and if so
"outputs" the results to return_string and exits:
Otherwise it formats the results differently, and outputs using
the iox_$put_chars call:
The Unix approach is to simply redirect a program's standard output to
a pipe before executing it, then read the data from that pipe. The
program doesn't even generally know that it's being called this way. (A
Unix program can go out of its way to detect whether standard output is
a pipe, but few programs do. A rare example is ls, which won't default
to multi-column if output is a pipe, since that would obviously screw
up pipeline filters.)
Aside from a different mechanism for output, any Multics program that
can be called as either a command or an active function must handle
formatting its output differently for either case. In Unix, the shell
simply strips all newlines from the output of the called program if it
is used for command output substitution. No other program needs to
worry about the difference.
The Unix approach is much simpler, and also much less safe.
The Multics approach ensures that the command makes sense, and the
program being called expects to be called in that way. It prevents you
from making insane calls. The Unix approach cuts out all the work
required to make special forms of commands, and lets you do anything
you want, even if it makes no sense and will likely screw up your
login session.
The Multics approach is safe, but extremely limited. Many commands
do not support active function use. For example, the Multics
equivalents of who and ls ("how_many_users" and "list") cannot
be used in this way. Given the ability to use anything for command
output substitution, Unix users have found ways to use it
that could never have been predicted by the original designers.
This is the point where the Multics approach fails - if they didn't
forsee it, you aren't allowed to do it.
Again: anarchy versus newspeak.
One obscure but amusing side effect of the Unix "simple & sloppy"
approach to this is that none of the mainstream Unix shells
correctly cancel a command when the process invoked for
command output substitution fails.
Bourne, Bash, Korn, Z-, all output something like this:
Note: I am describing one particular case where I think the "simple &
sloppy" approach turned out to work beautifully. This should not be
extrapolated to a complete dismissal of Multics. There are many
features of Multics that are impressive even by today's standards, and
we would probably be better off if Unix had copied them more closely.
(Sample PL/I code is copyright Honeywell Bull Inc.)
|