Migrate get_interpreter into postfork.cpp

It's only used after fork.
This commit is contained in:
ridiculousfish 2020-01-29 13:40:17 -08:00
parent 8e8a3846fb
commit 29af84d733
3 changed files with 31 additions and 32 deletions

View file

@ -66,33 +66,6 @@ void exec_close(int fd) {
}
}
/// Returns the interpreter for the specified script. Returns NULL if file is not a script with a
/// shebang.
char *get_interpreter(const char *command, char *interpreter, size_t buff_size) {
// OK to not use CLO_EXEC here because this is only called after fork.
int fd = open(command, O_RDONLY);
if (fd >= 0) {
size_t idx = 0;
while (idx + 1 < buff_size) {
char ch;
ssize_t amt = read(fd, &ch, sizeof ch);
if (amt <= 0) break;
if (ch == '\n') break;
interpreter[idx++] = ch;
}
interpreter[idx++] = '\0';
close(fd);
}
if (std::strncmp(interpreter, "#! /", 4) == 0) {
return interpreter + 3;
} else if (std::strncmp(interpreter, "#!/", 3) == 0) {
return interpreter + 2;
}
return nullptr;
}
/// This function is executed by the child process created by a call to fork(). It should be called
/// after \c child_setup_process. It calls execve to replace the fish process image with the command
/// specified in \c p. It never returns. Called in a forked child! Do not allocate memory, etc.

View file

@ -37,7 +37,4 @@ int exec_subshell_for_expand(const wcstring &cmd, parser_t &parser, wcstring_lis
/// Loops over close until the syscall was run without being interrupted.
void exec_close(int fd);
/// Gets the interpreter for a given command.
char *get_interpreter(const char *command, char *interpreter, size_t buff_size);
#endif

View file

@ -38,6 +38,8 @@
/// Fork error message.
#define FORK_ERROR "Could not create child process - exiting"
static char *get_interpreter(const char *command, char *buffer, size_t buff_size);
/// Called only by the child to set its own process group (possibly creating a new group in the
/// process if it is the first in a JOB_CONTROL job.
/// Returns true on success, false on failure.
@ -353,8 +355,9 @@ void safe_report_exec_error(int err, const char *actual_cmd, const char *const *
// an open file action fails. These cases appear to be impossible to distinguish. We
// address this by not using posix_spawn for file redirections, so all the ENOENTs we
// find must be errors from exec().
char interpreter_buff[128] = {}, *interpreter;
interpreter = get_interpreter(actual_cmd, interpreter_buff, sizeof interpreter_buff);
char interpreter_buff[128] = {};
const char *interpreter =
get_interpreter(actual_cmd, interpreter_buff, sizeof interpreter_buff);
if (interpreter && 0 != access(interpreter, X_OK)) {
debug_safe(0,
"The file '%s' specified the interpreter '%s', which is not an "
@ -378,3 +381,29 @@ void safe_report_exec_error(int err, const char *actual_cmd, const char *const *
}
}
}
/// Returns the interpreter for the specified script. Returns NULL if file is not a script with a
/// shebang.
static char *get_interpreter(const char *command, char *buffer, size_t buff_size) {
// OK to not use CLO_EXEC here because this is only called after fork.
int fd = open(command, O_RDONLY);
if (fd >= 0) {
size_t idx = 0;
while (idx + 1 < buff_size) {
char ch;
ssize_t amt = read(fd, &ch, sizeof ch);
if (amt <= 0) break;
if (ch == '\n') break;
buffer[idx++] = ch;
}
buffer[idx++] = '\0';
close(fd);
}
if (std::strncmp(buffer, "#! /", 4) == 0) {
return buffer + 3;
} else if (std::strncmp(buffer, "#!/", 3) == 0) {
return buffer + 2;
}
return nullptr;
}