ado@elsie.UUCP (Arthur David Olson) (10/03/84)
At the top of "sh" files in the "rn" distribution this line was included: export PATH || (echo "You didn't use sh, you clunch." ; kill \$\$) This was designed to ensure that if someone ran "csh" over the script things would come to a screeching halt. Seeing it set me to thinking...what if, instead of that line, this appeared: export PATH || exec sh $0 You'd get the protection without requiring the user to retype the command. You could even go so far as to: ( : oops >& /dev/null ) || exec sh $0 to avoid the both the generation of a diagnostic message and the possibility of mishap if someone had created an executable program named "export". Well friends, how about it? Such protection might make folks lives easier. Is it worthwhile? Is there a better way to do it? Mail me your responses; if there's sufficient volume, I'll summarize them in a followup article. -- ..decvax!seismo!elsie!ado (301) 496-5688 DEC, VAX and Elsie are Digital Equipment and Borden trademarks
danny@itm.UUCP (Danny) (10/08/84)
Well, even export PATH || echo "Don't use csh you clunch" doesn't work *every* time. Our csh gets the "||" and "&&" just backwards from sh. I remember that Guy Harris (rlgvax!guy) pointed this out once, too. So, when I tried it out (just testing, of course!) it failed miserably. Most of the time, if I point out a problem I like to include a solution, but for this --- any takers? Danny -- Daniel S. Cox ({gatech|akgua}!itm!danny)
guy@rlgvax.UUCP (Guy Harris) (10/13/84)
> Well, > > even > export PATH || echo "Don't use csh you clunch" > > doesn't work *every* time. Our csh gets the "||" and "&&" > just backwards from sh. I remember that Guy Harris (rlgvax!guy) > pointed this out once, too. So, when I tried it out (just testing, > of course!) it failed miserably. > > Most of the time, if I point out a problem I like to include a > solution, but for this --- any takers? If you've got the source to your C shell, change the line somewhere around line 286 in "sh.sem.c" from something like if ((getn(value("status")) != 0) != (t->t_dtyp == TAND)) or possibly if ((getn(value("status")) == 0) == (t->t_dtyp == TAND)) to if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) which will fix the problem quite nicely. If you don't have the source, find out who does and pester them to fix it. The C shell is supposed to handle "&&" and "||" the same as the Bourne shell, and the 4.2BSD (and, I think, 4.1BSD) versions do. It was a bug in earlier versions. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/16/84)
#!/bin/sh on line 1 will let the kernel exec the script using the correct shell no matter what shell the user is running at the time.
ado@elsie.UUCP (Arthur David Olson) (10/16/84)
brl-tgr!gwyn: > #!/bin/sh > on line 1 will let the kernel exec the script using the correct shell > no matter what shell the user is running at the time. 1. The "#!/bin/sh" line lacks a space or tab between the "#!" and the "/bin/sh". Quoting the second page of the exec(2) page in the UNIX Programmer's Manual for the Fourth Berkeley Software Distribution (dated 4/1/81--April Fools' Day), "The space (or tab) following the '#!' is mandatory." While some implementations may not require the space, it behooves those of us interested in portability to use the documentation when trying to create portable scripts, rather than finding out what we can "get away with" on a particular system. 2. The "#!" construct is not recognized on all UNIX systems. Some may respond that anyone who'd continue running a system that fails to recognize "#!" "ougtht to" upgrade. Alas, in the real world, there are legitimate economic, political, and legal reasons for staying with older versions of UNIX; those using older versions are ill-served by folks who would lecture them to upgrade rather than try to keep their needs in mind. 3. Even if the "#!/bin/sh" line is present at the start of a shell script, "/bin/sh" will NOT be used to interpret the script if the script is executed using the command csh script (This is, at any rate, true on 4.1bsd and 4.2bsd). "Clunch protection" lines are designed to guard against this possibility. Some may respond that anyone who'd use the above command is a clunch; a moment's reflection. . . -- UNIX is an AT&T Bell Laboratories trademark. "sh" may be a American Librarians' Association trademark. -- ..decvax!seismo!elsie!ado (301) 496-5688 DEC, VAX and Elsie are Digital Equipment and Borden trademarks
peter@rlgvax.UUCP (Peter Klosky) (10/16/84)
XXX
> ... will let the kernel exec the script using the correct shell
On our system, the kernel can't exec scripts: it only execs files
with magic numbers. I thought the choice of what command interpreter
to exec to read the script was made by the shell, not by the kernel.
guy@rlgvax.UUCP (Guy Harris) (10/17/84)
> XXX > > ... will let the kernel exec the script using the correct shell > > On our system, the kernel can't exec scripts: it only execs files > with magic numbers. I thought the choice of what command interpreter > to exec to read the script was made by the shell, not by the kernel. Well, that depends on which of "our" systems you're talking about. Our VAXes and Power 6es can exec scripts, because they're running 4.2BSD-based OSes; the Power 5s are running a V7/S3 based OS and can't. Dennis Ritchie came up with the notion of permitting executable files to be executable by an arbitrary interpreter other than the CPU hardware/ microcode; the way it's done is with a magic "number" of "#!". The characters following the "#!" are interpreted as the path of the program to be executed and optional arguments to that program; the path of the file to be "executed" is given as the last argument. This has only been implemented on Berkeley systems, to my knowledge. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
karsh@geowhiz.UUCP (Bruce Karsh) (10/17/84)
> Dennis Ritchie came up with the notion of permitting executable files to > be executable by an arbitrary interpreter other than the CPU hardware/ > microcode; the way it's done is with a magic "number" of "#!". The > characters following the "#!" are interpreted as the path of the program > to be executed and optional arguments to that program; the path of the > file to be "executed" is given as the last argument. > This has only been implemented on Berkeley systems, to my knowledge. This has also been implemented on Masscomp systems.
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/19/84)
> 1. The "#!/bin/sh" line lacks a space or tab between the "#!" and the > "/bin/sh". > > 2. The "#!" construct is not recognized on all UNIX systems. > > 3. Even if the "#!/bin/sh" line is present at the start of a shell script, > "/bin/sh" will NOT be used to interpret the script if the script is > executed using the command > csh script 1. The documentation was wrong; white space was optional all along. Later versions of the documentation have been corrected. Only LOCUS chose to force you to use white space, so far as I am aware. By all means stick in a space if it makes you happier. 2. On most systems where the kernel does not understand the #! magic number, the first line of the script will be taken as a comment and the Bourne shell /bin/sh will be used to interpret the script anyway. 7th Edition UNIXes that never upgraded their shells may break. Also, systems where the Cshell was imported with insufficient care may let the Cshell handle the script rather than either defaulting to the native shell or examining the #! line to see what to use. 3. Of course csh script will use the wrong shell! So will ed script or many other similar commands. 4. If one has to allow for || && vs && ||, lack of # comments, and zillions of other variations, then immense pains are required to produce anything close to a "portable" shell script that will either run correctly or detect that it has been misinvoked. The example that started this discussion took great pains but still had loopholes; the practicality of this approach is questionable. It is perhaps easier to give somebody a new shell than it is to accommodate WHATEVER he might already have.
crp@ccivax.UUCP (Chuck Privitera) (10/19/84)
> brl-tgr!gwyn: > > > #!/bin/sh > > on line 1 will let the kernel exec the script using the correct shell > > no matter what shell the user is running at the time. > > 2. The "#!" construct is not recognized on all UNIX systems. Some may respond > that anyone who'd continue running a system that fails to recognize "#!" > "ougtht to" upgrade. Alas, in the real world, there are legitimate > economic, political, and legal reasons for staying with older versions of > UNIX; those using older versions are ill-served by folks who would lecture > them to upgrade rather than try to keep their needs in mind. > We just ran into this on our Power5's. The kernel on the Power5 doesn't understand "#!your_favorite_interpreter", and we had some scripts that took advantage of this with #!/bin/sh. They no longer worked. Trivial changes to texec() in sh.exec.c of the csh solved the problem. Similar changes could be applied to function execs() in service.c for the Bourne shell (as is done on the VAX save that it should read a whole line and look for #!whatever instead of assuming '#' means use csh.) > 3. Even if the "#!/bin/sh" line is present at the start of a shell script, > "/bin/sh" will NOT be used to interpret the script if the script is > executed using the command > csh script > (This is, at any rate, true on 4.1bsd and 4.2bsd). "Clunch protection" > lines are designed to guard against this possibility. Some may respond > that anyone who'd use the above command is a clunch; a moment's > reflection. . . > -- The C-shell (and Bourne shell) on BSD systems have a primitive way of deciding which shell to execute if the kernel doesn't get it right. Both shells check the error returned from a failed exec and if it is ENOEXEC (exec format error) they check the first byte of the file. If it is a '#', BOTH shells assume that it must be a C-shell script. Not too cool since '#' is the Bourne shell's comment character too. Granted you could use ':' for comments, but then you are subject to some of the Bourne shell's features you may not intend to evoke. (e.g. Quoting across lines) This is one reason I personally prefer to use '#' for comments instead of ':'. Try putting this in a file and running it: : : This is Chuck's test sh script : echo test No output will result, because the shell is looking for a closing "'". Whereas the following will output "test" as was intended: : Start with one of these to force using the Bourne shell. # This is Chuck's second test sh script # echo test