execute_command_line.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Implementation of the EXECUTE_COMMAND_LINE intrinsic.
  2. Copyright (C) 2009-2015 Free Software Foundation, Inc.
  3. Contributed by François-Xavier Coudert.
  4. This file is part of the GNU Fortran runtime library (libgfortran).
  5. Libgfortran is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. Libgfortran is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. #include "libgfortran.h"
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #ifdef HAVE_SYS_WAIT_H
  27. #include <sys/wait.h>
  28. #endif
  29. enum { EXEC_SYNCHRONOUS = -2, EXEC_NOERROR = 0, EXEC_SYSTEMFAILED,
  30. EXEC_CHILDFAILED };
  31. static const char *cmdmsg_values[] =
  32. { "",
  33. "Termination status of the command-language interpreter cannot be obtained",
  34. "Execution of child process impossible" };
  35. static void
  36. set_cmdstat (int *cmdstat, int value)
  37. {
  38. if (cmdstat)
  39. *cmdstat = value;
  40. else if (value > EXEC_NOERROR)
  41. runtime_error ("Could not execute command line");
  42. }
  43. static void
  44. execute_command_line (const char *command, bool wait, int *exitstat,
  45. int *cmdstat, char *cmdmsg,
  46. gfc_charlen_type command_len,
  47. gfc_charlen_type cmdmsg_len)
  48. {
  49. /* Transform the Fortran string to a C string. */
  50. char *cmd = fc_strdup (command, command_len);
  51. /* Flush all I/O units before executing the command. */
  52. flush_all_units();
  53. #if defined(HAVE_FORK)
  54. if (!wait)
  55. {
  56. /* Asynchronous execution. */
  57. pid_t pid;
  58. set_cmdstat (cmdstat, EXEC_NOERROR);
  59. if ((pid = fork()) < 0)
  60. set_cmdstat (cmdstat, EXEC_CHILDFAILED);
  61. else if (pid == 0)
  62. {
  63. /* Child process. */
  64. int res = system (cmd);
  65. _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res);
  66. }
  67. }
  68. else
  69. #endif
  70. {
  71. /* Synchronous execution. */
  72. int res = system (cmd);
  73. if (res == -1)
  74. set_cmdstat (cmdstat, EXEC_SYSTEMFAILED);
  75. #ifndef HAVE_FORK
  76. else if (!wait)
  77. set_cmdstat (cmdstat, EXEC_SYNCHRONOUS);
  78. #endif
  79. else
  80. set_cmdstat (cmdstat, EXEC_NOERROR);
  81. if (res != -1)
  82. {
  83. #if defined(WEXITSTATUS) && defined(WIFEXITED)
  84. *exitstat = WIFEXITED(res) ? WEXITSTATUS(res) : res;
  85. #else
  86. *exitstat = res;
  87. #endif
  88. }
  89. }
  90. free (cmd);
  91. /* Now copy back to the Fortran string if needed. */
  92. if (cmdstat && *cmdstat > EXEC_NOERROR)
  93. {
  94. if (cmdmsg)
  95. fstrcpy (cmdmsg, cmdmsg_len, cmdmsg_values[*cmdstat],
  96. strlen (cmdmsg_values[*cmdstat]));
  97. else
  98. runtime_error ("Failure in EXECUTE_COMMAND_LINE: %s",
  99. cmdmsg_values[*cmdstat]);
  100. }
  101. }
  102. extern void
  103. execute_command_line_i4 (const char *command, GFC_LOGICAL_4 *wait,
  104. GFC_INTEGER_4 *exitstat, GFC_INTEGER_4 *cmdstat,
  105. char *cmdmsg, gfc_charlen_type command_len,
  106. gfc_charlen_type cmdmsg_len);
  107. export_proto(execute_command_line_i4);
  108. void
  109. execute_command_line_i4 (const char *command, GFC_LOGICAL_4 *wait,
  110. GFC_INTEGER_4 *exitstat, GFC_INTEGER_4 *cmdstat,
  111. char *cmdmsg, gfc_charlen_type command_len,
  112. gfc_charlen_type cmdmsg_len)
  113. {
  114. bool w = wait ? *wait : true;
  115. int estat, estat_initial, cstat;
  116. if (exitstat)
  117. estat_initial = estat = *exitstat;
  118. execute_command_line (command, w, &estat, cmdstat ? &cstat : NULL,
  119. cmdmsg, command_len, cmdmsg_len);
  120. if (exitstat && estat != estat_initial)
  121. *exitstat = estat;
  122. if (cmdstat)
  123. *cmdstat = cstat;
  124. }
  125. extern void
  126. execute_command_line_i8 (const char *command, GFC_LOGICAL_8 *wait,
  127. GFC_INTEGER_8 *exitstat, GFC_INTEGER_8 *cmdstat,
  128. char *cmdmsg, gfc_charlen_type command_len,
  129. gfc_charlen_type cmdmsg_len);
  130. export_proto(execute_command_line_i8);
  131. void
  132. execute_command_line_i8 (const char *command, GFC_LOGICAL_8 *wait,
  133. GFC_INTEGER_8 *exitstat, GFC_INTEGER_8 *cmdstat,
  134. char *cmdmsg, gfc_charlen_type command_len,
  135. gfc_charlen_type cmdmsg_len)
  136. {
  137. bool w = wait ? *wait : true;
  138. int estat, estat_initial, cstat;
  139. if (exitstat)
  140. estat_initial = estat = *exitstat;
  141. execute_command_line (command, w, &estat, cmdstat ? &cstat : NULL,
  142. cmdmsg, command_len, cmdmsg_len);
  143. if (exitstat && estat != estat_initial)
  144. *exitstat = estat;
  145. if (cmdstat)
  146. *cmdstat = cstat;
  147. }