Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wasatch!cs.utexas.edu!usc!apple!sun-barr!decwrl!decvax!ima!minya!jc From: jc@minya.UUCP (John Chambers) Newsgroups: comp.unix.wizards Subject: How does Unix kernel find /bin/sh? Message-ID: <5@minya.UUCP> Date: 26 Aug 89 15:03:27 GMT Organization: home Lines: 66 Keywords: #!/bin/sh Well, here I am again, with yet another puzzle. It keeps coming to my attention that there are still Unices about that don't understand the "#!" notation. You'd think by now that everyone would realize what a Good Idea this is, and it'd have been installed everywhere. I realized how slow things can be when last week I tried some of my scripts for for first time on a brand-new, out-of-the-box Sys/V release 3.something, and to my surprise, the ones that started with lines like "#!/bin/awk" or "#!/bin/msh" (that's my menu shell) got some funny Bourne-shell diagnostics (rather than the awk or msh diagnostics that I expected ;-). Well, I decided to try to solve this problem once and for all, in the obvious way. I wrote myself a shell that I call ish (for Indirect SHell), and installed it in /bin, and also linked /bin/sh to /bin/bsh. After a bit of testing, I did rm /bin/sh ln /bin/ish /bin/sh and this should have solved the problem. What ish does, of course, is examines its command-line args, figures out what file the caller intended to exec, and opens it for reading. If it starts with "#!", ish does the obvious thing. It is, of course, quite paranoid about getting things wrong, so if it gets at all puzzled about what it should do, it just punts the job to /bin/bsh. For true binary files, of course, it never gets invoked, because the kernel knows how to handle that case. The problem is simple: when I exec a script directly, the kernel doesn't run /bin/sh, it runs /bin/bsh! I can prove this easily, since ish always writes a line to an audit trail showing when and how it was called. This code isn't conditional; there is no way that ish can work without writing to the audit trail. When I boot the machine, the audit trail shows a whole lot of entries from all the subprocesses started by /etc/*rc, and whenever anyone calls system(), the audit trail gets a new line. So basically the trick works. But there seems to be some sort of deal going between the Bourne shell and the kernel, so that when bsh starts up, it tells the kernel "Don't pay any attention to /bin/sh; I'm the real shell", and the kernel believes it. Does anyone know how this works? I'd like to see if my program can intercede and convince the kernel that it's the shell (after all, it *is* /bin/sh). I'd like an RTFM response or two. I've spent some time poring through some FMs, and so far I haven't even found any admission that the Unix kernel knows how to run scripts. The descriptions of the exec*() calls only talk about executable binary files, as does Bach's book. I've yet to see any mention of the "#!" notation in any document anywhere; I've picked it up by word-of-mouth (including a bunch of flames in several newsgroups about the idiots who don't use it correctly; such flames seems to be the best way to learn how it works. :-) Can someone explain what's going on, and why my imposter shell (hey, maybe that's what "ish" stands for |^) gets invoked correctly in every case except when a script is execed directly? I am truly bemused by this one. [A free copy of ish will be emailed (if possible;-) to the first five individuals who correctly answer the question...] -- #echo 'Opinions Copyright 1989 by John Chambers; for licensing information contact:' echo ' John Chambers <{adelie,ima,mit-eddie}!minya!{jc,root}> (617/484-6393)' echo '' saying