spawn.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * spawnvp function
  3. *
  4. * Copyright 2003 Dimitrie O. Paun
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include "wine/port.h"
  22. #if !defined(HAVE__SPAWNVP) && (!defined(_WIN32) || defined(__CYGWIN__))
  23. #include <errno.h>
  24. #include <signal.h>
  25. #include <stdlib.h>
  26. #ifdef HAVE_SYS_WAIT_H
  27. #include <sys/wait.h>
  28. #endif
  29. #include <sys/stat.h>
  30. #ifdef HAVE_UNISTD_H
  31. # include <unistd.h>
  32. #endif
  33. int _spawnvp(int mode, const char *cmdname, const char *const argv[])
  34. {
  35. int pid, status, wret;
  36. if (mode == _P_OVERLAY)
  37. {
  38. execvp(cmdname, (char **)argv);
  39. /* if we get here it failed */
  40. #ifdef ENOTSUP
  41. if (errno != ENOTSUP) /* exec fails on MacOS if the process has multiple threads */
  42. #endif
  43. return -1;
  44. }
  45. pid = fork();
  46. if (pid == 0)
  47. {
  48. /* in child */
  49. if (mode == _P_DETACH)
  50. {
  51. pid = fork();
  52. if (pid == -1) _exit(1);
  53. else if (pid > 0) _exit(0);
  54. /* else in grandchild */
  55. }
  56. signal( SIGPIPE, SIG_DFL );
  57. execvp(cmdname, (char **)argv);
  58. _exit(1);
  59. }
  60. if (pid == -1)
  61. return -1;
  62. if (mode == _P_OVERLAY) exit(0);
  63. if (mode == _P_WAIT || mode == _P_DETACH)
  64. {
  65. while (pid != (wret = waitpid(pid, &status, 0)))
  66. if (wret == -1 && errno != EINTR) break;
  67. if (pid == wret && WIFEXITED(status))
  68. {
  69. if (mode == _P_WAIT)
  70. pid = WEXITSTATUS(status);
  71. else /* mode == _P_DETACH */
  72. if (WEXITSTATUS(status) != 0) /* child couldn't fork grandchild */
  73. pid = -1;
  74. }
  75. else
  76. {
  77. if (mode == _P_WAIT)
  78. pid = 255; /* abnormal exit with an abort or an interrupt */
  79. else /* mode == _P_DETACH */
  80. pid = -1;
  81. }
  82. }
  83. return pid;
  84. }
  85. #endif /* HAVE__SPAWNVP */