mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:57:45 +00:00
Shell: Actually make shebangs work
Also check for executable permissions before actually trying to run, and print a helpful message if not executable. Fixes #4358
This commit is contained in:
parent
0141f7e7fd
commit
17e1e1f114
1 changed files with 16 additions and 5 deletions
|
@ -787,7 +787,17 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
|
|
||||||
int rc = execvp(argv[0], const_cast<char* const*>(argv.data()));
|
int rc = execvp(argv[0], const_cast<char* const*>(argv.data()));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if (errno == ENOENT) {
|
int saved_errno = errno;
|
||||||
|
struct stat st;
|
||||||
|
if (stat(argv[0], &st)) {
|
||||||
|
fprintf(stderr, "stat(%s): %s\n", argv[0], strerror(errno));
|
||||||
|
_exit(126);
|
||||||
|
}
|
||||||
|
if (!(st.st_mode & S_IXUSR)) {
|
||||||
|
fprintf(stderr, "%s: Not executable\n", argv[0]);
|
||||||
|
_exit(126);
|
||||||
|
}
|
||||||
|
if (saved_errno == ENOENT) {
|
||||||
int shebang_fd = open(argv[0], O_RDONLY);
|
int shebang_fd = open(argv[0], O_RDONLY);
|
||||||
auto close_argv = ScopeGuard([shebang_fd]() { if (shebang_fd >= 0) close(shebang_fd); });
|
auto close_argv = ScopeGuard([shebang_fd]() { if (shebang_fd >= 0) close(shebang_fd); });
|
||||||
char shebang[256] {};
|
char shebang[256] {};
|
||||||
|
@ -796,13 +806,14 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
StringView shebang_path_view(&shebang[2], num_read - 2);
|
StringView shebang_path_view(&shebang[2], num_read - 2);
|
||||||
Optional<size_t> newline_pos = shebang_path_view.find_first_of("\n\r");
|
Optional<size_t> newline_pos = shebang_path_view.find_first_of("\n\r");
|
||||||
shebang[newline_pos.has_value() ? (newline_pos.value() + 2) : num_read] = '\0';
|
shebang[newline_pos.has_value() ? (newline_pos.value() + 2) : num_read] = '\0';
|
||||||
fprintf(stderr, "%s: Invalid interpreter \"%s\": %s\n", argv[0], &shebang[2], strerror(ENOENT));
|
argv[0] = shebang;
|
||||||
|
int rc = execvp(argv[0], const_cast<char* const*>(argv.data()));
|
||||||
|
if (rc < 0)
|
||||||
|
fprintf(stderr, "%s: Invalid interpreter \"%s\": %s\n", argv[0], &shebang[2], strerror(errno));
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "%s: Command not found.\n", argv[0]);
|
fprintf(stderr, "%s: Command not found.\n", argv[0]);
|
||||||
} else {
|
} else {
|
||||||
int saved_errno = errno;
|
if (S_ISDIR(st.st_mode)) {
|
||||||
struct stat st;
|
|
||||||
if (stat(argv[0], &st) == 0 && S_ISDIR(st.st_mode)) {
|
|
||||||
fprintf(stderr, "Shell: %s: Is a directory\n", argv[0]);
|
fprintf(stderr, "Shell: %s: Is a directory\n", argv[0]);
|
||||||
_exit(126);
|
_exit(126);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue