bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH #3]: print missing interpreter name [Was: Re: binfmt_script and ^


From: Jan Nieuwenhuizen
Subject: [PATCH #3]: print missing interpreter name [Was: Re: binfmt_script and ^M]
Date: 05 Mar 2001 21:18:35 +0100
User-agent: Gnus/5.0807 (Gnus v5.8.7) Emacs/20.7

"Richard B. Johnson" <root@chaos.analogic.com> writes:

> No. I did not miss the point. The 'No such file or directory' error
> (when you can see the ^$^$)#@@*& filename with 'ls'), usually means
> that there is something wrong with the file.

Now, let's see.  When this error happens, it can be one of these:

    1a) the script itself is broken (eg, it has `#!/bin/bash\r')
    1b) the interpreter is missing, (eg, the script has
        `#!/usr/bin/perl', while perl got removed during the
        grand perl repackaging)
    2)  the interpreter is broken, (eg, missing shared library)
    3)  the script does not exist

In any case, the heart of the problems 1) and 2) is expressed by the
fact that there's something fishy with #!INTERPRETER.  In the case of
1a, the script should be fixed, in case 1b, the system should be
fixed, but this doesn't really matter.  Either way: INTERPRETER is the
file the kernel is talking about when it says ENOENT.  Only in case 3),
the ENOENT is about the script itself.

It seems reasonable, and helpful, for bash to print the name of the
INTERPRETER.

> Usually, I have found that it was an executable linked against some
> other runtime library than what I have. `strace` finds this quickly.

Well, this doesn't mean very much, other than you happen to experience
2) most (and you're fast at identifying the strange error).  But even
in this case, the name of the broken interpreter is what you should be
warned about.  Maybe others usually experience 1b), who cares?

In this third incarnation of my patch (today really isn't my day), you
see these messages for 1-3:

1)
    $ cat /bin/foo.sh 
    #!/foo/bar/baz
    echo bar

    $ /bin/bash -c /bin/foo.sh 
    /bin/bash: /bin/foo.sh: No such file or directory

    $ ./new/bash -c /bin/foo.sh 
    ./new/bash: /bin/foo.sh: /foo/bar/baz: No such file or directory

2)
    $ cat /bin/no-ld.sh 
    #!/usr/bin/urg
    $ ldd /bin/urg                
            libkpathsea.so.3 => not found
            [..]

    $ /bin/bash -c /bin/no-ld.sh 
    /bin/bash: /bin/no-ld.sh: No such file or directory

    $ ./new/bash -c /bin/no-ld.sh 
    ./new/bash: /bin/no-ld.sh: /usr/bin/urg: No such file or directory

3)
    $ /bin/bash -c /bin/no-such-foo.sh
    /bin/bash: /bin/no-such-foo.sh: No such file or directory

    $ ./new/bash -c /bin/no-such-foo.sh
    ./new/bash: /bin/no-such-foo.sh: No such file or directory


Ok, here goes try #3:

--- ../bash-2.04.orig/ChangeLog Mon Mar  5 21:06:11 2001
+++ ./ChangeLog Mon Mar  5 19:22:46 2001
@@ -0,0 +1,5 @@
+2001-03-05  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+       * execute_cmd.c (extract_hash_bang_interpreter): New function.
+       (shell_execve): More informative error message.
+
--- ../bash-2.04.orig/execute_cmd.c     Tue Jan 25 17:29:11 2000
+++ ./execute_cmd.c     Mon Mar  5 20:35:46 2001
@@ -3035,6 +3035,42 @@
     }
 }
 
+/* Look for #!INTERPRETER in file COMMAND, and return INTERPRETER . */
+static char *
+extract_hash_bang_interpreter (char *command, char buf[80])
+{
+  int fd;
+  char *interpreter;
+
+  interpreter = "";
+  fd = open (command, O_RDONLY);
+  if (fd >= 0)
+    {
+      int len;
+             
+      len = read (fd, (char *)buf, 80);
+      close (fd);
+             
+      if (len > 0
+         && buf[0] == '#' && buf[1] == '!')
+       {
+         int i;
+         int start;
+                 
+         for (i = 2; whitespace (buf[i]) && i < len; i++)
+           ;
+         
+         for (start = i;
+              !whitespace (buf[i]) && buf[i] != '\n' && i < len;
+              i++)
+           ;
+
+         interpreter = substring ((char *)buf, start, i);
+       }
+    }
+  return interpreter;
+}
+
 /* Execute a simple command that is hopefully defined in a disk file
    somewhere.
 
@@ -3326,7 +3362,17 @@
       else
        {
          errno = i;
-         file_error (command);
+         if (errno == ENOENT)
+           {
+             char buf[80];
+             char *interpreter = extract_hash_bang_interpreter (command, buf);
+             if (strlen (interpreter))
+               sys_error ("%s: %s", command, interpreter);
+             else
+               file_error (command);
+           }
+         else
+           file_error (command);
        }
       return ((i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);        /* XXX Posix.2 
says that exit status is 126 */
     }


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org




reply via email to

[Prev in Thread] Current Thread [Next in Thread]