exec.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <config-util.h>
  19. #include <config.h>
  20. #include <grub/misc.h>
  21. #include <unistd.h>
  22. #include <grub/emu/exec.h>
  23. #include <grub/emu/hostdisk.h>
  24. #include <grub/emu/getroot.h>
  25. #include <grub/util/misc.h>
  26. #include <grub/disk.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <fcntl.h>
  30. #include <errno.h>
  31. #include <string.h>
  32. #include <sys/wait.h>
  33. int
  34. grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
  35. const char *stdout_file, const char *stderr_file)
  36. {
  37. pid_t pid;
  38. int status = -1;
  39. char *str, *pstr;
  40. const char *const *ptr;
  41. grub_size_t strl = 0;
  42. for (ptr = argv; *ptr; ptr++)
  43. strl += grub_strlen (*ptr) + 1;
  44. if (stdin_file)
  45. strl += grub_strlen (stdin_file) + 2;
  46. if (stdout_file)
  47. strl += grub_strlen (stdout_file) + 2;
  48. if (stderr_file)
  49. strl += grub_strlen (stderr_file) + 3;
  50. pstr = str = xmalloc (strl);
  51. for (ptr = argv; *ptr; ptr++)
  52. {
  53. pstr = grub_stpcpy (pstr, *ptr);
  54. *pstr++ = ' ';
  55. }
  56. if (stdin_file)
  57. {
  58. *pstr++ = '<';
  59. pstr = grub_stpcpy (pstr, stdin_file);
  60. *pstr++ = ' ';
  61. }
  62. if (stdout_file)
  63. {
  64. *pstr++ = '>';
  65. pstr = grub_stpcpy (pstr, stdout_file);
  66. *pstr++ = ' ';
  67. }
  68. if (stderr_file)
  69. {
  70. *pstr++ = '2';
  71. *pstr++ = '>';
  72. pstr = grub_stpcpy (pstr, stderr_file);
  73. pstr++;
  74. }
  75. *--pstr = '\0';
  76. grub_util_info ("executing %s", str);
  77. grub_free (str);
  78. pid = fork ();
  79. if (pid < 0)
  80. grub_util_error (_("Unable to fork: %s"), strerror (errno));
  81. else if (pid == 0)
  82. {
  83. int fd;
  84. /* Child. */
  85. /* Close fd's. */
  86. #ifdef GRUB_UTIL
  87. grub_util_devmapper_cleanup ();
  88. grub_diskfilter_fini ();
  89. #endif
  90. if (stdin_file)
  91. {
  92. fd = open (stdin_file, O_RDONLY);
  93. if (fd < 0)
  94. exit (127);
  95. dup2 (fd, STDIN_FILENO);
  96. close (fd);
  97. }
  98. if (stdout_file)
  99. {
  100. fd = open (stdout_file, O_WRONLY | O_CREAT, 0700);
  101. if (fd < 0)
  102. exit (127);
  103. dup2 (fd, STDOUT_FILENO);
  104. close (fd);
  105. }
  106. if (stderr_file)
  107. {
  108. fd = open (stderr_file, O_WRONLY | O_CREAT, 0700);
  109. if (fd < 0)
  110. exit (127);
  111. dup2 (fd, STDERR_FILENO);
  112. close (fd);
  113. }
  114. /* Ensure child is not localised. */
  115. setenv ("LC_ALL", "C", 1);
  116. execvp ((char *) argv[0], (char **) argv);
  117. exit (127);
  118. }
  119. waitpid (pid, &status, 0);
  120. if (!WIFEXITED (status))
  121. return -1;
  122. return WEXITSTATUS (status);
  123. }
  124. int
  125. grub_util_exec (const char *const *argv)
  126. {
  127. return grub_util_exec_redirect_all (argv, NULL, NULL, NULL);
  128. }
  129. int
  130. grub_util_exec_redirect (const char *const *argv, const char *stdin_file,
  131. const char *stdout_file)
  132. {
  133. return grub_util_exec_redirect_all (argv, stdin_file, stdout_file, NULL);
  134. }
  135. int
  136. grub_util_exec_redirect_null (const char *const *argv)
  137. {
  138. return grub_util_exec_redirect_all (argv, "/dev/null", "/dev/null", NULL);
  139. }
  140. pid_t
  141. grub_util_exec_pipe (const char *const *argv, int *fd)
  142. {
  143. int pipe_fd[2];
  144. pid_t pid;
  145. *fd = 0;
  146. if (pipe (pipe_fd) < 0)
  147. {
  148. grub_util_warn (_("Unable to create pipe: %s"),
  149. strerror (errno));
  150. return 0;
  151. }
  152. pid = fork ();
  153. if (pid < 0)
  154. grub_util_error (_("Unable to fork: %s"), strerror (errno));
  155. else if (pid == 0)
  156. {
  157. /* Child. */
  158. /* Close fd's. */
  159. #ifdef GRUB_UTIL
  160. grub_util_devmapper_cleanup ();
  161. grub_diskfilter_fini ();
  162. #endif
  163. /* Ensure child is not localised. */
  164. setenv ("LC_ALL", "C", 1);
  165. close (pipe_fd[0]);
  166. dup2 (pipe_fd[1], STDOUT_FILENO);
  167. close (pipe_fd[1]);
  168. execvp ((char *) argv[0], (char **) argv);
  169. exit (127);
  170. }
  171. else
  172. {
  173. close (pipe_fd[1]);
  174. *fd = pipe_fd[0];
  175. return pid;
  176. }
  177. }
  178. pid_t
  179. grub_util_exec_pipe_stderr (const char *const *argv, int *fd)
  180. {
  181. int pipe_fd[2];
  182. pid_t pid;
  183. *fd = 0;
  184. if (pipe (pipe_fd) < 0)
  185. {
  186. grub_util_warn (_("Unable to create pipe: %s"),
  187. strerror (errno));
  188. return 0;
  189. }
  190. pid = fork ();
  191. if (pid < 0)
  192. grub_util_error (_("Unable to fork: %s"), strerror (errno));
  193. else if (pid == 0)
  194. {
  195. /* Child. */
  196. /* Close fd's. */
  197. #ifdef GRUB_UTIL
  198. grub_util_devmapper_cleanup ();
  199. grub_diskfilter_fini ();
  200. #endif
  201. /* Ensure child is not localised. */
  202. setenv ("LC_ALL", "C", 1);
  203. close (pipe_fd[0]);
  204. dup2 (pipe_fd[1], STDOUT_FILENO);
  205. dup2 (pipe_fd[1], STDERR_FILENO);
  206. close (pipe_fd[1]);
  207. execvp ((char *) argv[0], (char **) argv);
  208. exit (127);
  209. }
  210. else
  211. {
  212. close (pipe_fd[1]);
  213. *fd = pipe_fd[0];
  214. return pid;
  215. }
  216. }