Shell scripts

1 view
Skip to first unread message

Will Ware

unread,
Oct 5, 1996, 3:00:00 AM10/5/96
to

I was thinking about how unfortunate it is that Scheme doesn't offer a
feature where the first line of a file can say something like

#!/usr/local/bin/scheme

so that the Scheme program can be a stand-alone executable, as is
available in Perl or Python. (At least none of the interpreters I'm
aware of offer this.)

Then it struck me that recognizing "#!" in the beginning of the first
line of a file is probably something done by the shell, not whatever
language's interpreter is involved. Then it struck me that it would
probably be possible to patch the source code for a shell to allow
";!" as an alternative to "#!". So then a stand-alone Scheme program
would begin

;!/usr/local/bin/scheme

or something like that. I believe that the shell would then pass the
entire file to the interpreter, so the first line must appear to be
a comment in Scheme, as it does here.

Has anybody ever seen such a patch, or have any thoughts on how hard
this would be? I'm thinking about trying to do this with Bash.
--
-------------------------------------------------------------
Will Ware <ww...@world.std.com> web <http://world.std.com/~wware/>
PGP fingerprint 45A8 722C D149 10CC F0CF 48FB 93BF 7289

Scott Schwartz

unread,
Oct 5, 1996, 3:00:00 AM10/5/96
to Will Ware

ww...@world.std.com (Will Ware) writes:
| (At least none of the interpreters I'm
| aware of offer this.)

Some do.

| Then it struck me that recognizing "#!" in the beginning of the first
| line of a file is probably something done by the shell,

No, it's done by the kernel, and necessarily so.

In any case, there isn't just one "the shell", so forget about trying
to hack ";!" in at that level.


Will Ware

unread,
Oct 5, 1996, 3:00:00 AM10/5/96
to

I (ww...@world.std.com) wrote:
: ... various stuff, leading up to ...
: ;!/usr/local/bin/scheme

I tried patching Bash to do this, and it worked fine. Here's the patch:


diff -r bash-tweaked/execute_cmd.c bash-1.14.5/execute_cmd.c
2445,2446c2445
< if (sample_len > 0 && (sample[0] == '#' || sample[0] == ';')
< && sample[1] == '!')
---
> if (sample_len > 0 && sample[0] == '#' && sample[1] == '!')


And here's an example of a Scheme file that works as a standalone script:


;!/usr/local/bin/mzscheme -i
(printf "This is working!~%")


Soon after my last post, I got two emails saying I needed to patch my OS,
but it seemed to work fine for me after only patching bash.

Once you do this diff, type "make" in your bash source directory, and
after much to-do it will create an executable called "bash". Use that
to replace your existing copy; on my Linux box it's at /bin/bash.

Christopher B. Browne

unread,
Oct 5, 1996, 3:00:00 AM10/5/96
to

In article <DytoD...@world.std.com>, Will Ware wrote:
>I was thinking about how unfortunate it is that Scheme doesn't offer a
>feature where the first line of a file can say something like
>
>#!/usr/local/bin/scheme
>so that the Scheme program can be a stand-alone executable, as is
>available in Perl or Python. (At least none of the interpreters I'm
>aware of offer this.)

As is available in most "shell-like" languages that accept "#" as the
beginning of a comment line.

>Then it struck me that recognizing "#!" in the beginning of the first

>line of a file is probably something done by the shell, not whatever
>language's interpreter is involved.

Either the shell or the UNIX kernel, depending on the situation. Commonly
the latter.

>Then it struck me that it would
>probably be possible to patch the source code for a shell to allow
>";!" as an alternative to "#!". So then a stand-alone Scheme program
>would begin

>;!/usr/local/bin/scheme

>Has anybody ever seen such a patch, or have any thoughts on how hard


>this would be? I'm thinking about trying to do this with Bash.

On many systems, this would require patching the kernel, because the
recognition of the "comment line" is commonly part of the system kernel.
This may be acceptable for an OS such as Linux, where sources are readily
available and patchable. Not so acceptable for Solaris/HPUX/AIX and other
commercial friends.

And your system administrator may not be too pleased with the idea either.
And this won't work on an unhacked kernel.

On the other hand, you could always have /usr/local/bin/scheme be a shell
utility that pipes the contents of the file, sans initial comment line, into
the *real* scheme interpreter.

The program:
#!/usr/local/bin/scheme
; Lots of scheme code...
(exit)


The wrapper: /usr/local/bin/scheme
#!/bin/ksh
size=`wc -l - < $0`
size=$(($size+1))
head -$size $0 | /usr/local/bin/real-scheme-interpreter

The wrapper strips off line 1, and submits the remainder to the "real"
Scheme interpreter.

In practice, /usr/local/bin/scheme probably ought to be written in C. It'll
be half a page of code, and more robust than this.

Having a wrapper is going to be portable, not overly slow (it's just a
program loader, after all), and actually looks pretty flexible.
--
Christopher B. Browne, cbbr...@unicomp.net, chris_...@sdt.com
Web: http://www.conline.com/~cbbrowne SAP Basis Consultant, UNIX Guy
Windows NT - How to make a 100 MIPS Linux workstation perform like an 8 MHz 286


Bill Sommerfeld

unread,
Oct 6, 1996, 3:00:00 AM10/6/96
to

I was thinking about how unfortunate it is that Scheme doesn't offer a
feature where the first line of a file can say something like

#!/usr/local/bin/scheme

so that the Scheme program can be a stand-alone executable, as is
available in Perl or Python. (At least none of the interpreters I'm
aware of offer this.)

Scsh does this.

The way it does it is quite ingenious (and ties another thread to this
one):
It uses #! and !# as block comment delimiters.

#! /usr/local/bin/scsh \
-ds -e main -s
!#

(define (main . ignore-args)
(display "Hello, world")
(newline))

- Bill

Will Ware

unread,
Oct 6, 1996, 3:00:00 AM10/6/96
to

I (ww...@world.std.com) wrote:
: ...........
: #!/usr/local/bin/scheme

It turns out that MzScheme (my preferred Scheme interpreter) has a command
line flag for doing this. Yet another case where a few hours of my own
hacking and tinkering was able to save me the five grueling minutes it might
have taken to find and read the manual. So the MzScheme command line flag is
as follows:

#!/usr/local/bin/mzscheme -r
(...this space for rent...)

and don't forget to "chmod +x".

Marius Vollmer

unread,
Oct 8, 1996, 3:00:00 AM10/8/96
to

ww...@world.std.com (Will Ware) writes:
> Then it struck me that recognizing "#!" in the beginning of the first
> line of a file is probably something done by the shell, not whatever
> language's interpreter is involved.

It's actually the kernel who recognizes the #! magic `number' at the
start of an executable.

Now, the interpreter has to ignore the first line of the file (the one
containing the #! stuff). I think many, if not all Scheme
implementations do it.

With SCM you can write:

#! /somewhere/bin/scm -f
(display "Hi!")
(newline)
(quit)

You might even be able to write

#! /bin/sh
type;exec scm -f $0 $*
(display "Hi!")
(newline)
(quit)

if you don't know where "scm" is. You only have to make sure that
"type" is defined in the startup files of your Scheme.

Hope this helps,
Marius

Olin Shivers

unread,
Oct 10, 1996, 3:00:00 AM10/10/96
to

ww...@world.std.com (Will Ware) writes:
> Then it struck me that recognizing "#!" in the beginning of the first
> line of a file is probably something done by the shell, not whatever
> language's interpreter is involved.

It's actually the kernel who recognizes the #! magic `number' at the
start of an executable.

I beat on this issue pretty thoroughly in the design of scsh.

PLEASE NOTE:
If you are considering making your scheme interpreter a scripting vehicle,
go study the scsh manual and source code. It is available at
http://www-swiss.ai.mit.edu/scsh/

The Unix #! mechanism is quite problematic, in that its design is pretty
half-baked.

- You are allowed *exactly* one argument on the #! line, so you
can say
#!/usr/bin/scheme -f
but you can't say
#!/usr/bin/scheme -h 3000 -f

Scsh provides a nice fix for this, the meta arg, which I recommend to
other authors of interpreters designed for scripting. The scsh source
has two implementations of meta-arg processors, one in C and one in Scheme,
that can easily be ported to the interpreter of your choice.

- Many Unix implementations of exec(2) limit the #! line to 32 chars.
Break this limit, and your exec will silently fail, or the #! line
will be silently truncated, or some other less-than-useless failure
mode will occur.

This means that your interpreter's binary better have a short
filename. Scsh mandates a particular location for the scsh binary
which is under 32 chars.

One can also address this issue by using a /bin/sh trampoline, but
that is a pretty expensive solution, one I find distasteful, since
the point of scripting in Scheme is to avoid /bin/sh.

- The #! mechanism is not recursive. That is, if your script starts
#!/bin/foo
then /bin/foo better not be a #! script itself. If it is, your exec
will, again, silently lose.

The only way I was able to handle this one was to write an ARPA grant
and go to work building a non-Unix operating system for Scheme. The
operative image here is a horse with a broken leg.
-Olin

Reply all
Reply to author
Forward
0 new messages