hanss (10/29/82)
Thanks to all those that have told me about the 4.1 function. for those that like me, didn't know what I'm talking about, the csh accepts as a first line a command which will be taken as the 'real' command to run the shell with. 3.0 bourne does not support this, although 4.1 BSD bourne does. Does anyone know if 4.0 or 5.0 picked this up? Thus: #! /bin/csh -f will force whatever shell is running to pretend its command was really whatever was to the right of the first space, and actually run /bin/csh with a -f flag (even though it was started as /bin/sh...) Unfortunately this is documented only by a one line comment at the back of the csh manual but not documented for the 4.1 bourne shell at all. This comment does not mention that it will actually cause the shell to exec a new shell, nor does it accurately describe the syntax. Interestingly, it does describe the syntax I proposed last night. Obviously, since there was a precedent and the syntax is only a little stupid (what is the '!' for?) I now modify my proposal to follow that of BerkElEy. I also suggest that Berkeley had better get their documentation act cleaned up. The army is one of those organizations you don't want to have mad at you. They don't flame in the usenet. They flame with flamethrowers and tanks and such... In response to the lone remark that answered the point of my article, which was about csh -f, (fast...don't read .cshrc): Yes, combined with the above function, you can achieve the right thing, but you will only put the '#! /bin/csh -f' in after you get burned a few times. Since the reason people get burned by this sort of thing is because they don't know what they're doing, don't you think we would all be better off if the simple, consistent, efficient, safe version were the default, and allow you to override at your hearts content? Overriding the default is invariably easyer than putting it back (set nonoclobber? really, bill!). And most of the tools have facility for doing it already. Both major shells have a 'source' or '.' command, and most other tools, such as macroprocessors and editors have them too. Since you have the mechanism to do the thing efficiently and easily, why complicate matters by adding some new function, and then making people that want to do things right go out of their way to turn it off when it causes them grief? Elsewhere we call this hiding a bug by introducing another bug, or treating the symptom, not the disease. Not afraid to ignoreeof -Hans decvax!microsoft!hanss
mark (10/29/82)
For documentation of the #! feature in Berkeley UNIX, see exec(2). This is implemented in the kernel, NOT in csh or sh. This is probably why it's not documented in csh or sh other than in passing. This is not a Berkeley convention, by the way, it's a Bell Labs convention which Berkeley liked and adopted. (I'm not sure who at Bell Labs, I think it was the center 127 people who put out V6 and V7, e.g. Ritchie and Thompson.) As far as I know, system III and its descendents (done by different people) have not adopted this convention. If you think about how the kernel does execs (with two byte magic numbers) it should be obvious why #! was chosen.
thomas (10/29/82)
The #! mechanism is actually interpreted by the kernel, not by either shell. The syntax is somewhat restrictive, the #! must be followed by a single space, the (full path)name of the program to be executed, optionally a single space and one argument. All this may not be longer than 32 characters. But, it makes ANY script, etc. into something which may be executed via exec! Not only that, but an arbitrary interpreter can be supplied - if you put #! /bin/make -f at the beginning of your makefile and chmod +x it, it is now executable. A nice way to manage multiple makefiles. Similarly, saying #! /bin/awk -f as the first line of an awk program means you can just run it. No more awk -f foofile args just type foofile args and away you go! I think this was originally suggested by Dennis Ritchie, but I could be wrong. =Spencer