I remember reading about #! in the early 1980s, and
having mixed feelings about it, as I still do. The
basic idea is fine, if annoyingly limited; but that
the kernel has to decide, in effect, whether to treat
a header as binary or text bothers me. Were I designing
a new system from scratch today, I'd just make the
header all text; the small extra space and time for
the kernel to parse that for binaries doesn't matter
any more. It certainly did when #! was invented,
though.
I had the impression at the time that it came from
Berkeley, but I think I later heard from the horse's
mouth that it was originally Dennis's idea.
I don't think anyone has yet laid out the complete
story of what came before:
1. Originally, the shell would exec(file), and if
exec returned ENOEXEC, would open the file and treat
it as shell commands.
2. Then came the C shell, and a problem: did file
contain commands for csh or sh? A hack emerged:
if csh encountered a script file, it would read
the first character; if that was '#' it was a
csh script, otherwise it handed off to /bin/sh.
None of this helped when some program other than
the shell called exec on a shell script. That's one
reason execlp and execvp appeared. (The other is that
they observe $PATH if the command pathname has a
single element.)
I don't know offhand whether there was ever an execlp/vp
that implemented the #-means-csh convention. Anyone
else remember?
Norman Wilson
Toronto ON
> 8th edition was essentially a re-port of 4.1c BSD, correct?
"Re-port" may be a bit strong. Internet stuff from Berkeley
was folded into the research code (for a huge increase in
kernel size). But I think it was done by pasting Berkeley
code into local source, rather than the other way around.
But, since much of the rest of the BSD kernel was Bell
Labs code, it's probably right that the result of the
merge had more code in common with BSD than with Research.
If you ask, though, what fraction of Research code
survived the merge, it was probably larger than the
surviving fraction of the total BSD code.
Doug
> IIRC #! originated at Bell Labs but it got out to the world via BSD.
> Perhaps Dr. McIlroy could confirm / deny / expand upon the details (please?)
I recall Dennis discussing the feature at some length before installing it.
So the exact semantics, especially the injected argument, are almost]
certainly his. I don't know whether he built on a model from elsewhere.
#! appeared between v7 (1979) and v8 (1985). As v8 was never released,
it clearly made its way into the world via BSD and USG. BSD, being
more nimble, was likely first.
doug
On 9 September 2016 at 17:15, Mary Ann Horton <mah(a)mhorton.net> wrote (in part):
> When I was at Berkeley working on my dissertation, I wrote a tool that would
> let you edit a text file written in any language you could define with a
> grammar, with syntax and semantic error checking while you edited. I had
> grammars for several popular (in 1980) languages.
My curiosity is piqued. What were these languages?
N.
On 10 September 2016 at 05:41, Joerg Schilling <schily(a)schily.net> wrote:
> Michael Kjörling <michael(a)kjorling.se> wrote:
>
>> On 10 Sep 2016 09:45 +0200, from dnied(a)tiscali.it (Dario Niedermann):
>> > Il 15/07/2016 alle 14:27, Norman Wilson ha scritto:
>> >> lu$ cat /bin/cd
>> >> #!/bin/sh
>> >> builtin cd "$@"
>> >> lu$
>> >
>> > But doesn't this change the current dir only in the child shell?
>> > Which then exits right after the second line, parent shell's $PWD
>> > unaffected. I really don't see how this script is useful.
>>
>> It does appear rather useless. Curiously, Debian (checked on Wheezy =
>> bash 4.2+dfsg-0.1+deb7u3 and Jessie = bash 4.3-11+b1) seems to not
>> supply anything like that, so it would appear to be some kind of
>> Fedora-ism rather than a part of anything upstream; that, or the
>> Debian folks are actually paying attention to what they ship onto
>> users' systems.
>
> POSIX requires some commands to be callable via exec().
Solaris 10 has the following amusing implementation (/usr/bin/cd):
#!/bin/ksh -p
#
#ident "@(#)alias.sh 1.2 00/02/15 SMI"
#
# Copyright (c) 1995 by Sun Microsystems, Inc.
#
cmd=`basename $0`
$cmd "$@"
N.
> From: Blake McBride
> After about 30 years of C, there are only three things I would have
> liked to see:
> 1. Computed goto
Can't you make a switch statement do what you need there?
The two things I really missed were:
- BCPL's ValOf/ResultIs, for making more complex macros (although with the
latest modern compilers, which inline small functions, this is less
of an issue)
- The ability to 'break' out of more than one level of nesting; one either
has to stand on one's head (code-wise), or use a goto
Noel
> After about 30 years of C, there are only three things I would
have liked to see:
> 1. Computed goto
...
> Computed goto's are good for interpreters.
A computed goto, of course, is merely an optimized switch.
Dennis installed this optimization early in the evolution of C. The
main driving force was the performance and size of the PDP-11 Unix
kernel. As functionality grew, resource usage was repeatedly tamped
down by improving C's code generation.
The switch optimizer chose among three strategies: naive, binary
decision tree, and computed goto, depending on the number and density
of switch alternatives. Hybrid strategies may have been used, too,
but my memory is hazy on this point. In particular the optimization
improved system-call dispatch--thus achieving the objective,
"good for interpreters". I assume (I hope not unrealistically)
that this optimization has been in the repertoire of mainline C
compilers ever since.
> (Or perhaps require C to support tail recursion.)
I can imagine making a strong recommendation in the standard for
optimizing switches and (at least direct) tail recursion.
Doug
I sent a similar message some time ago, but I haven't
seen it appear in the mailing list, so here goes again.
Apologies if it ends up as a duplicate.
> After about 30 years of C, there are only three things I would have liked
> to see:
>
> 1. Computed goto
> ...
> Computed goto's are good for interpreters.
A computed goto is an optimized switch, and that optimization
goes back to the original C compiler. Mostly driven by
considerations of size and speed of the Unix kernel, Dennis
quite early on taught the compiler to choose among three
compilation strategies for a switch: a chain of comparisons,
a tree of comparisons, or a computed goto, depending on the
number and density of alternatives.
The compilation of the system-call dispatch table was
a perfect example of "good for interpreters."
I have always assumed that other mainline compilers behave
similarly, but I have no solid knowledge about that.
doug
Seen on another list... And I got quoted by Steve Bellovin :-)
--
Dave Horsfall DTM (VK2KFU) "Those who don't understand security will suffer."
---------- Forwarded message ----------
From: Kent Borg
To: cryptography(a)metzdowd.com
Subject: Re: [Cryptography]
"NSA-linked Cisco exploit poses bigger threat than previously thought"
On 08/25/2016 06:06 PM, Steven M. Bellovin wrote:
> I first heard more or less that line from Doug McIlroy himself; he
> called C the best assembler language he'd ever used.
Ancient fun-fact: Years ago there was an article in Byte magazine
describing how a useful subset of C could be directly assembled into 68000
code. Not compiled, assembled.
C is a stunning assembly language. When those wild-eyed nerds at AT&T
decided to write Unix not in assembly but in C (where was management!?),
it was radical. But C was up to (down to?) the task, it was pioneering
then and is still doing useful things decades later: From the fastest
supercomputers to some pretty slim microcontrollers (plus a hell of a lot
of Android devices) multitudes of computers run a Linux kernel compiled
from the *same* C source code, with almost no assembly. Big-endian,
little-endian: no matter. Different word lengths: no matter.
That is one impressive cross-platform assembly language!
Unfortunately, C is also a dangerous language that mortal programmers
cannot reliably wield.
-kb, the Kent who knows he is pressing his luck on a moderated
cryptography mailing list, but C deserves a lot of respect, as it also
deserves to be efficiently sent into a dignified retirement.
_______________________________________________
The cryptography mailing list
cryptography(a)metzdowd.com
http://www.metzdowd.com/mailman/listinfo/cryptography
Every time someone starts spouting about how unsafe
C is, and how all the world's problems would be solved
if only people would stop using it, I think of Flon's
Axiom, for 35 years my favourite one-liner about
programming and languages:
There does not now, nor will there ever, exist a
programming language in which it is the least bit
hard to write bad programs.
Flon's Axiom comes from a short note On Research
in Structured Programming, published in SIGPLAN
Notices in October 1975. It's just as true today.
Over the years I've seen people misinterpret the
Axiom as an argument against looking for better
programming languages at all, but that's not what
it means. (Read the original note--it's a page
and a half--for full context; it is, alas, behind
ACM's Digital Library paywall.) There are certainly
languages that make certain sorts of mistakes easier
or harder, or are easier or harder to read, but in
the end most of that really is up to the programmer.
Programming well requires a lot of thought and care
and careful rereading, and often throwing half the
code out and re-doing it better, and until we can
have a programming community the majority of whom
are up to those challenges, we will continue to have
crashes and security vulnerabilities and other
embarrassing bugs aplenty, no matter what language
is used.
Norman Wilson
Toronto ON