From 6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 18:29:51 +0200 Subject: Adding upstream version 2.06. Signed-off-by: Daniel Baumann --- grub-core/osdep/unix/exec.c | 245 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 grub-core/osdep/unix/exec.c (limited to 'grub-core/osdep/unix/exec.c') diff --git a/grub-core/osdep/unix/exec.c b/grub-core/osdep/unix/exec.c new file mode 100644 index 0000000..e8db920 --- /dev/null +++ b/grub-core/osdep/unix/exec.c @@ -0,0 +1,245 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file, + const char *stdout_file, const char *stderr_file) +{ + pid_t pid; + int status = -1; + char *str, *pstr; + const char *const *ptr; + grub_size_t strl = 0; + for (ptr = argv; *ptr; ptr++) + strl += grub_strlen (*ptr) + 1; + if (stdin_file) + strl += grub_strlen (stdin_file) + 2; + if (stdout_file) + strl += grub_strlen (stdout_file) + 2; + if (stderr_file) + strl += grub_strlen (stderr_file) + 3; + + pstr = str = xmalloc (strl); + for (ptr = argv; *ptr; ptr++) + { + pstr = grub_stpcpy (pstr, *ptr); + *pstr++ = ' '; + } + if (stdin_file) + { + *pstr++ = '<'; + pstr = grub_stpcpy (pstr, stdin_file); + *pstr++ = ' '; + } + if (stdout_file) + { + *pstr++ = '>'; + pstr = grub_stpcpy (pstr, stdout_file); + *pstr++ = ' '; + } + if (stderr_file) + { + *pstr++ = '2'; + *pstr++ = '>'; + pstr = grub_stpcpy (pstr, stderr_file); + pstr++; + } + *--pstr = '\0'; + + grub_util_info ("executing %s", str); + grub_free (str); + + pid = fork (); + if (pid < 0) + grub_util_error (_("Unable to fork: %s"), strerror (errno)); + else if (pid == 0) + { + int fd; + /* Child. */ + + /* Close fd's. */ +#ifdef GRUB_UTIL + grub_util_devmapper_cleanup (); + grub_diskfilter_fini (); +#endif + + if (stdin_file) + { + fd = open (stdin_file, O_RDONLY); + if (fd < 0) + _exit (127); + dup2 (fd, STDIN_FILENO); + close (fd); + } + + if (stdout_file) + { + fd = open (stdout_file, O_WRONLY | O_CREAT, 0700); + if (fd < 0) + _exit (127); + dup2 (fd, STDOUT_FILENO); + close (fd); + } + + if (stderr_file) + { + fd = open (stderr_file, O_WRONLY | O_CREAT, 0700); + if (fd < 0) + _exit (127); + dup2 (fd, STDERR_FILENO); + close (fd); + } + + /* Ensure child is not localised. */ + setenv ("LC_ALL", "C", 1); + + execvp ((char *) argv[0], (char **) argv); + _exit (127); + } + waitpid (pid, &status, 0); + if (!WIFEXITED (status)) + return -1; + return WEXITSTATUS (status); +} + +int +grub_util_exec (const char *const *argv) +{ + return grub_util_exec_redirect_all (argv, NULL, NULL, NULL); +} + +int +grub_util_exec_redirect (const char *const *argv, const char *stdin_file, + const char *stdout_file) +{ + return grub_util_exec_redirect_all (argv, stdin_file, stdout_file, NULL); +} + +int +grub_util_exec_redirect_null (const char *const *argv) +{ + return grub_util_exec_redirect_all (argv, "/dev/null", "/dev/null", NULL); +} + +pid_t +grub_util_exec_pipe (const char *const *argv, int *fd) +{ + int pipe_fd[2]; + pid_t pid; + + *fd = 0; + + if (pipe (pipe_fd) < 0) + { + grub_util_warn (_("Unable to create pipe: %s"), + strerror (errno)); + return 0; + } + pid = fork (); + if (pid < 0) + grub_util_error (_("Unable to fork: %s"), strerror (errno)); + else if (pid == 0) + { + /* Child. */ + + /* Close fd's. */ +#ifdef GRUB_UTIL + grub_util_devmapper_cleanup (); + grub_diskfilter_fini (); +#endif + + /* Ensure child is not localised. */ + setenv ("LC_ALL", "C", 1); + + close (pipe_fd[0]); + dup2 (pipe_fd[1], STDOUT_FILENO); + close (pipe_fd[1]); + + execvp ((char *) argv[0], (char **) argv); + _exit (127); + } + else + { + close (pipe_fd[1]); + *fd = pipe_fd[0]; + return pid; + } +} + +pid_t +grub_util_exec_pipe_stderr (const char *const *argv, int *fd) +{ + int pipe_fd[2]; + pid_t pid; + + *fd = 0; + + if (pipe (pipe_fd) < 0) + { + grub_util_warn (_("Unable to create pipe: %s"), + strerror (errno)); + return 0; + } + pid = fork (); + if (pid < 0) + grub_util_error (_("Unable to fork: %s"), strerror (errno)); + else if (pid == 0) + { + /* Child. */ + + /* Close fd's. */ +#ifdef GRUB_UTIL + grub_util_devmapper_cleanup (); + grub_diskfilter_fini (); +#endif + + /* Ensure child is not localised. */ + setenv ("LC_ALL", "C", 1); + + close (pipe_fd[0]); + dup2 (pipe_fd[1], STDOUT_FILENO); + dup2 (pipe_fd[1], STDERR_FILENO); + close (pipe_fd[1]); + + execvp ((char *) argv[0], (char **) argv); + _exit (127); + } + else + { + close (pipe_fd[1]); + *fd = pipe_fd[0]; + return pid; + } +} -- cgit v1.2.3