Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

executable postscript programs?

240 views
Skip to first unread message

luser- -droog

unread,
Dec 6, 2010, 10:47:06 PM12/6/10
to
Is there a way to trick bash into accepting % instead of #
on the bang line?
I'd like to put
%!/usr/bin/gs
at the front of my postscript program to run the script as a command.

If you could only put a full command there, I think
#!/bin/sed 1d|/usr/bin/gs
could work.

Do I have to make a helper script to prune the first line
and then pipe to gs?

Barry Margolin

unread,
Dec 7, 2010, 12:02:59 AM12/7/10
to
In article
<fd9a58c4-28ac-4c3f...@n30g2000vbb.googlegroups.com>,
luser- -droog <mij...@yahoo.com> wrote:

> Is there a way to trick bash into accepting % instead of #
> on the bang line?

It's not bash, it's the kernel that processes shebang lines. And AFAIK
there's no way to trick it into recognizing %! instead of #!.

> I'd like to put
> %!/usr/bin/gs
> at the front of my postscript program to run the script as a command.
>
> If you could only put a full command there, I think
> #!/bin/sed 1d|/usr/bin/gs
> could work.

Nope. It only allows a program name and one optional argument.

>
> Do I have to make a helper script to prune the first line
> and then pipe to gs?

Yes. I'm surprised there isn't one included with ghostscript.

Note that the program named on the shebang line has to be a binary, not
a script, so you'll need to do:

#!/bin/bash /path/to/script

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***

Lew Pitcher

unread,
Dec 7, 2010, 12:30:20 AM12/7/10
to
On December 6, 2010 22:47, in comp.unix.shell, mij...@yahoo.com wrote:

> Is there a way to trick bash into accepting % instead of #
> on the bang line?

Nope.

It's not a bash trick (although it started as one), but is a trick in the
kernel.

> I'd like to put
> %!/usr/bin/gs
> at the front of my postscript program to run the script as a command.

What you need is to use the kernel's binfmt_misc interface, and register an
execution interpreter for postscript files (see below). Once that's done,
you chmod a+x your postscript file, and execute it from the commandline as
you if you had managed to get your % shebang to work.

The /proc/sys/fs/binfmt_misc/ tree only exists when you enable the
binfmt_misc kernel module, and mount the binfmt_misc filesystem.

In this directory tree there will be a file called "register"
(/proc/sys/fs/binfmt_misc/register), which is a text file into which you
write details about each executable file format, and the kernel or user
binary that will load and execute it.

To quote the binfmt_misc readme:
To actually register a new binary type, you have to set up a string
looking like
:name:type:offset:magic:mask:interpreter:flags
(where you can choose the ':' upon your needs) and echo it to
/proc/sys/fs/binfmt_misc/register.

Here is what the fields mean:
- 'name' is an identifier string. A new /proc file will be created with
this name below /proc/sys/fs/binfmt_misc
- 'type' is the type of recognition. Give 'M' for magic and 'E' for
extension.
- 'offset' is the offset of the magic/mask in the file, counted in bytes.
This defaults to 0 if you omit it (i.e. you
write ':name:type::magic...')
- 'magic' is the byte sequence binfmt_misc is matching for. The magic
string may contain hex-encoded characters like \x0a or \xA4. In a shell
environment you will have to write \\x0a to prevent the shell from
eating your \.
If you chose filename extension matching, this is the extension to be
recognised (without the '.', the \x0a specials are not allowed).
Extension matching is case sensitive!
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out
some bits from matching by supplying a string like magic and as long as
magic. The mask is anded with the byte sequence of the file.
- 'interpreter' is the program that should be invoked with the binary as
first argument (specify the full path)
- 'flags' is an optional field that controls several aspects of the
invocation of the interpreter. It is a string of capital letters, each
controls a certain aspect. The following flags are supported -
'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to
overwrite the original argv[0] with the full path to the
binary. When this flag is included, binfmt_misc will add an
argument to the argument vector for this purpose, thus
preserving the original argv[0].
'O' - open-binary. Legacy behavior of binfmt_misc is to pass the
full path of the binary to the interpreter as an argument.
When this flag is included, binfmt_misc will open the file for
reading and pass its descriptor as an argument, instead of the
full path, thus allowing the interpreter to execute
non-readable binaries. This feature should be used with care -
the interpreter has to be trusted not to emit the contents of
the non-readable binary.
'C' - credentials. Currently, the behavior of binfmt_misc is to
calculate the credentials and security token of the new
process according to the interpreter. When this flag is
included, these attributes are calculated according to the
binary. It also implies the 'O' flag. This feature should be
used with care as the interpreter will run with root
permissions when a setuid binary owned by root is run with
binfmt_misc.


If you (as root) echo the proper line to /proc/sys/fs/binfmt_misc, you can
register the postscript interpreter as the "interpreter" for executable
files that contain postscript code. Thus, you can (as you wanted) "execute"
a postscript file and have it print.


[snip]

HTH
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
---------- Slackware - Because I know what I'm doing. ------


John Reiser

unread,
Dec 7, 2010, 12:30:24 AM12/7/10
to

If all you have is a shell, then the file must conform
to the ordinary rules for an executable file, or you must
spoon-feed the file to the interpreter.

On Linux systems you can make any "file type" executable by
specifying the interpreter (such as gs) and the rules to
recognize the "file type." Begin at:
http://en.wikipedia.org/wiki/Binfmt_misc

--

Lew Pitcher

unread,
Dec 7, 2010, 12:31:13 AM12/7/10
to
On December 7, 2010 00:30, in comp.unix.shell, lpit...@teksavvy.com wrote:

> On December 6, 2010 22:47, in comp.unix.shell, mij...@yahoo.com wrote:
>
>> Is there a way to trick bash into accepting % instead of #
>> on the bang line?
>
> Nope.
>
> It's not a bash trick (although it started as one), but is a trick in the
> kernel.
>
>> I'd like to put
>> %!/usr/bin/gs
>> at the front of my postscript program to run the script as a command.
>
> What you need is to use the kernel's binfmt_misc interface, and register
> an execution interpreter for postscript files (see below).

I should note that this works (AFAIK) /only/ in Linux.

Helge Blischke

unread,
Dec 7, 2010, 9:30:19 AM12/7/10
to
luser- -droog wrote:

You need to force Ghostscript to skip the line starting with this magic
code.
If your Ghostscript has *not* be compiled with the init files compiled in,
you could simply edit gs_init.ps and insert the statement
(#!)cvn {currentfile =string readline pop pop}bind def
into an appropriate place, e.g. just following the line
<1a> cvn { } def
which turns the MS-DOS EOF marker into a noop.

But even then the problems with Ghostscript's command line options remains.
For example, Mac OS X 10.5 or higher correctly passes options to gs as in

#!/usr/bin/gs -dNODISPLAY

but Linux 2.6.27 (OpenSuSE 11.1) seems not to.

So it probably is better to hack a script, say /usr/bin/gscmd, which calls
Ghostscript with the needed command line options and the statement skipping
the shebang line.

Helge

Ilya Zakharevich

unread,
Dec 7, 2010, 1:23:33 PM12/7/10
to
On 2010-12-07, luser- -droog <mij...@yahoo.com> wrote:
> Is there a way to trick bash into accepting % instead of #
> on the bang line?
> I'd like to put
> %!/usr/bin/gs
> at the front of my postscript program to run the script as a command.

bash does not (AFAIK) read this line. You need to trick the kernel.
(Which may be not a big deal if you are on cygwin. ;-)

Hope this helps,
Ilya

Chris F.A. Johnson

unread,
Dec 7, 2010, 1:32:48 PM12/7/10
to

man bash:

If the program is a file beginning with #!, the remainder of
the first line specifies an interpreter for the program. The
shell executes the specified interpreter on operating systems
that do not handle this executable format themselves.

--
Chris F.A. Johnson, author <http://shell.cfajohnson.com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)

Sven Mascheck

unread,
Dec 7, 2010, 7:59:34 PM12/7/10
to
Helge Blischke wrote:

> But even then the problems with Ghostscript's command line options remains.
> For example, Mac OS X 10.5 or higher correctly passes options to gs as in
>
> #!/usr/bin/gs -dNODISPLAY
>
> but Linux 2.6.27 (OpenSuSE 11.1) seems not to.

MacOSX 10.4 ff. delivers the #! components separated, while Linux
delivers them as a single one. Are you speaking about passing several
"options" instead of only one like in the above?

Sven Mascheck

unread,
Dec 7, 2010, 8:07:27 PM12/7/10
to
Lew Pitcher wrote:
> mij...@yahoo.com wrote:
>
>> Is there a way to trick bash into accepting % instead of #
>> on the bang line?
>
> Nope.
>
> It's not a bash trick (although it started as one), but is a trick in the
> kernel.

to avoid ambiguity:
# was a hack on early BSDs to invoke csh (by both sh and csh)
#! was a Bell Labs hack to invoke arbitraty interpreters (by the kernel).

Sven Mascheck

unread,
Dec 7, 2010, 8:13:11 PM12/7/10
to
Barry Margolin wrote:

> Note that the program named on the shebang line has to be a binary, not
> a script, so you'll need to do:
>
> #!/bin/bash /path/to/script

alternatively /path/to/script starts with #!/bin/bash :)

Barry Margolin

unread,
Dec 7, 2010, 11:53:09 PM12/7/10
to
In article <idmm37...@news.in-ulm.de>,
Sven Mascheck <masc...@email.invalid> wrote:

No, that's the point I was making: the program named on the shebang line
can't be another script. The kernel only allows one level of
interpretation, it doesn't process #! recursively.

Sven Mascheck

unread,
Dec 8, 2010, 11:33:00 AM12/8/10
to
Barry Margolin wrote:

> No, that's the point I was making: [...]

Yes, I managed to miss it! :)
(although it's easy: it's two scripts, not one)

irrelevant footnote: Linux since 2.6.27.9 (and Minix)
do accept Interpreters in the #!

luser- -droog

unread,
Dec 8, 2010, 8:56:30 PM12/8/10
to
On Dec 6, 9:47 pm, luser- -droog <mijo...@yahoo.com> wrote:
> Is there a way to trick bash into accepting % instead of #
> on the bang line?
[snip]

Thanks for all the responses.
I got it to work with the following C program.

#include <unistd.h>
int main(int i, char **v) {
execl("/usr/bin/gs", "gs",
"-dQUIET",
"-c", "(#!)cvn{currentfile =string readline pop pop}bind def",
"--", v[1], NULL);
}

--
luser

Robert Bonomi

unread,
Dec 12, 2010, 1:12:55 AM12/12/10
to
>Is there a way to trick bash into accepting % instead of #
>on the bang line?

*IF* you feel like doing kernel modifications, "yes". otherwise, "no".

>I'd like to put
>%!/usr/bin/gs
>at the front of my postscript program to run the script as a command.
>
>If you could only put a full command there, I think
>#!/bin/sed 1d|/usr/bin/gs
>could work.

pipes are not allowed.

>Do I have to make a helper script to prune the first line
>and then pipe to gs?

have you tried something like:
#!/bin/sh -c "sed -e 1d | /usr/bin/gs"

Some (many, most, all?) systems have a severe length limit on the
length of the bangpath.

If something like the above doesn't work for -that- reason, you _do_ have
to go the route of a helper script.

Barry Margolin

unread,
Dec 12, 2010, 9:49:39 PM12/12/10
to
In article
<mqqdnR9MLup6-pnQ...@posted.nuvoxcommunications>,
bon...@host122.r-bonomi.com (Robert Bonomi) wrote:

> In article
> <fd9a58c4-28ac-4c3f...@n30g2000vbb.googlegroups.com>,
> luser- -droog <mij...@yahoo.com> wrote:
> >Is there a way to trick bash into accepting % instead of #
> >on the bang line?
>
> *IF* you feel like doing kernel modifications, "yes". otherwise, "no".
>
> >I'd like to put
> >%!/usr/bin/gs
> >at the front of my postscript program to run the script as a command.
> >
> >If you could only put a full command there, I think
> >#!/bin/sed 1d|/usr/bin/gs
> >could work.
>
> pipes are not allowed.

That's why he said "if".

>
> >Do I have to make a helper script to prune the first line
> >and then pipe to gs?
>
> have you tried something like:
> #!/bin/sh -c "sed -e 1d | /usr/bin/gs"
>
> Some (many, most, all?) systems have a severe length limit on the
> length of the bangpath.

I don't know if there's a length limit, but most limit the number of
option arguments to 1. I assume SUS specifies this limit.

Geoff Clare

unread,
Dec 13, 2010, 8:30:14 AM12/13/10
to
Barry Margolin wrote:

>> have you tried something like:
>> #!/bin/sh -c "sed -e 1d | /usr/bin/gs"
>>
>> Some (many, most, all?) systems have a severe length limit on the
>> length of the bangpath.
>
> I don't know if there's a length limit, but most limit the number of
> option arguments to 1. I assume SUS specifies this limit.

SUS doesn't specify the #! mechanism at all.

--
Geoff Clare <net...@gclare.org.uk>

luser- -droog

unread,
Dec 15, 2010, 2:46:53 AM12/15/10
to
On Dec 6, 9:47 pm, luser- -droog <mijo...@yahoo.com> wrote:
> Is there a way to trick bash into accepting % instead of #
> on the bang line?
> I'd like to put
> %!/usr/bin/gs
> at the front of my postscript program to run the script as a command.


For anyone interested, I'm pursuing the more gs-specific aspects
of this issue back in comp.lang.postscript .

BTW, how's my netiquette with these crossposts?
Am I doing it right, with the followup back to one group?

--
lxt

Mirek

unread,
Dec 15, 2010, 3:21:33 PM12/15/10
to

%! /bin/bash
/usr/bin/gs -q - <<EOF
%!PS-Adobe-3.0
...

;)

luser- -droog

unread,
Dec 15, 2010, 4:38:57 PM12/15/10
to
On Dec 15, 2:21 pm, Mirek
<pisz_na.mi...@dionizos.zind.ikem.pwr.wroc.pl> wrote:

ITYM #! on the first line, but point taken.
That's much simpler than anything I've been trying.

0 new messages