1

I have a library - users are to create executable files, potentially with a hashbang to tell exec which executable to use. If they omit the hashbang, then I think most systems default to /bin/sh, I want to change that default.

So some files might start with:

#!/usr/bin/env foobar

other files might start with:

 #!/usr/bin/env perl

or

 #!/usr/bin/env ruby

And in some cases, the user will omit the hashbang altogether. In that case, I will still execute the file directly, and I want to default to using the foobar executable.

In other words, I don't know what the hashbang will be in advance, and I want the default to be foobar instead of the default being /bin/sh, if there is no hashbang present.

I think the way to do what I am doing is to create an executable that can run exec first, and if that fails with a particular error message, then run the script indirectly with the foobar executable?

Something like this:

function run {
  stdio=$("$1" 2>&1)
  if [[ stdout/stderr matches a certain error message ]]; then
    foobar $1
  fi
}

My question is - does anyone know what I am talking about - and does anyone know how I can default to a particular executable if no hashbang is present? Not that it's in theory less convenient to check if there is a hashbang, and more in theory more convenient just to run it?

  • Thanks, so it looks like the kernel will default to /bin/sh...I want to emulate that behavior, but instead of defaulting to /bin/sh I'd like to default to node. – Alexander Mills Nov 24 '17 at 21:08
  • 2
    @AlexP it’s not the kernel which uses /bin/sh, it’s the C library, and only for certain exec calls. – Stephen Kitt Nov 24 '17 at 21:53
  • I had to edit my comment because of typo, I meant "So what I was thinking, was using my own executable, manually checking for the hashbang, and if it's not there, run with foobar? does that make sense, or is there a better way?" – Alexander Mills Nov 24 '17 at 21:55
  • You're overthinking this massively, just always start it with foobar and you don't need to do any testing. – Lizardx Nov 24 '17 at 23:11
  • @Lizardx no, this is for a library...just like the Unix system itself, the sane default is /bin/sh, I simply want to create a different default, it's not as crazy as you think – Alexander Mills Nov 24 '17 at 23:12
  • always starting with foobar will ignore the hashbang, obviously – Alexander Mills Nov 24 '17 at 23:13
  • Correct, which is by what you said basically your goal, to handle either case, if all are being run by foobar, then foobar is always running it, so who cares if it has a hashbang or not, at least that's how I read your question. If you want to do something based on the fact it has none that would be a different scenario, but if that something is the same as starting it with foobar, it is hard to see the point, unless you're leaving something out. – Lizardx Nov 24 '17 at 23:19
  • the hashbang could be anything @Lizardx, I need to handle any hashbang, but instead of defaulting to /bin/sh, I want to default to /bin/foobar. Do you follow? – Alexander Mills Nov 24 '17 at 23:21
  • @Lizardx, I re-read the question, and I see why you said what you said, your observations were good, I updated the question to improve it so I won't confuse other people. – Alexander Mills Nov 24 '17 at 23:24
  • Oh, now it's clear. I frequently run into problems because I read the literal words, this happens to me often on websites where their instructions are actually ambiguous and if followed literally will lead to failure, heh. Your question is now totally clear, and much more interesting than what was originally posted. – Lizardx Nov 24 '17 at 23:31
  • Thanks, yeah you read the question correctly, it was poorly phrased, your suggestion was on point, I just needed to improve the question. – Alexander Mills Nov 24 '17 at 23:33

1 Answers1

3

You can implement this in two steps using execve: ask the C library to ask the kernel to execute the target, and if that fails, try again with foobar. This is actually how shells commonly implement execution.

There are other exec family functions which will run shebang-less scripts with /bin/sh, but execve won’t.

What exactly happens when I execute a file in my shell? has a lot more detail on this topic.

Stephen Kitt
  • 434,908
  • thanks Stephen, do you think I should write this in C or Bash? do you think you could provide a start? I think Bash would better since it's more cross-platform. – Alexander Mills Nov 24 '17 at 21:52
  • 1
    I would write it in C... See the linked answer, there’s an excerpt from the Zsh source code which shows how to go about it. In Bash, you won’t be able to circumvent the /bin/sh default. – Stephen Kitt Nov 24 '17 at 21:56
  • So you've answered the question nicely, to be very specific, what I want to do is default the executable to foobar IFF the hashbang is missing and the file ends with a certain extension, otherwise default to /bin/bash. – Alexander Mills Nov 24 '17 at 23:27