spawni.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. /* Guts of POSIX spawn interface. Generic POSIX.1 version.
  2. Copyright (C) 2000-2006, 2008-2022 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. This file is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. This file is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <spawn.h>
  17. #include "spawn_int.h"
  18. #include <alloca.h>
  19. #include <errno.h>
  20. #include <fcntl.h>
  21. #ifndef O_LARGEFILE
  22. # define O_LARGEFILE 0
  23. #endif
  24. #if _LIBC || HAVE_PATHS_H
  25. # include <paths.h>
  26. #else
  27. # define _PATH_BSHELL BOURNE_SHELL
  28. #endif
  29. #include <signal.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #if _LIBC
  34. # include <not-cancel.h>
  35. #else
  36. # define close_not_cancel close
  37. # define open_not_cancel open
  38. #endif
  39. #if _LIBC
  40. # include <local-setxid.h>
  41. #else
  42. # if !HAVE_SETEUID
  43. # define seteuid(id) setresuid (-1, id, -1)
  44. # endif
  45. # if !HAVE_SETEGID
  46. # define setegid(id) setresgid (-1, id, -1)
  47. # endif
  48. # define local_seteuid(id) seteuid (id)
  49. # define local_setegid(id) setegid (id)
  50. #endif
  51. #if _LIBC
  52. # define alloca __alloca
  53. # define execve __execve
  54. # define dup2 __dup2
  55. # define fork __fork
  56. # define getgid __getgid
  57. # define getuid __getuid
  58. # define sched_setparam __sched_setparam
  59. # define sched_setscheduler __sched_setscheduler
  60. # define setpgid __setpgid
  61. # define sigaction __sigaction
  62. # define sigismember __sigismember
  63. # define sigprocmask __sigprocmask
  64. # define strchrnul __strchrnul
  65. # define vfork __vfork
  66. #endif
  67. /* The Unix standard contains a long explanation of the way to signal
  68. an error after the fork() was successful. Since no new wait status
  69. was wanted there is no way to signal an error using one of the
  70. available methods. The committee chose to signal an error by a
  71. normal program exit with the exit code 127. */
  72. #define SPAWN_ERROR 127
  73. #if defined _WIN32 && ! defined __CYGWIN__
  74. /* Native Windows API. */
  75. /* Get declarations of the native Windows API functions. */
  76. # define WIN32_LEAN_AND_MEAN
  77. # include <windows.h>
  78. # include <stdbool.h>
  79. # include <stdio.h>
  80. # include "filename.h"
  81. # include "concat-filename.h"
  82. # include "findprog.h"
  83. # include "malloca.h"
  84. # include "windows-spawn.h"
  85. /* Don't assume that UNICODE is not defined. */
  86. # undef CreateFile
  87. # define CreateFile CreateFileA
  88. # undef STARTUPINFO
  89. # define STARTUPINFO STARTUPINFOA
  90. # undef CreateProcess
  91. # define CreateProcess CreateProcessA
  92. /* Grows inh_handles->count so that it becomes > newfd.
  93. Returns 0 upon success. In case of failure, -1 is returned, with errno set.
  94. */
  95. static int
  96. grow_inheritable_handles (struct inheritable_handles *inh_handles, int newfd)
  97. {
  98. if (inh_handles->allocated <= newfd)
  99. {
  100. size_t new_allocated = 2 * inh_handles->allocated + 1;
  101. if (new_allocated <= newfd)
  102. new_allocated = newfd + 1;
  103. HANDLE *new_handles_array =
  104. (HANDLE *)
  105. realloc (inh_handles->handles, new_allocated * sizeof (HANDLE));
  106. if (new_handles_array == NULL)
  107. {
  108. errno = ENOMEM;
  109. return -1;
  110. }
  111. unsigned char *new_flags_array =
  112. (unsigned char *)
  113. realloc (inh_handles->flags, new_allocated * sizeof (unsigned char));
  114. if (new_flags_array == NULL)
  115. {
  116. free (new_handles_array);
  117. errno = ENOMEM;
  118. return -1;
  119. }
  120. inh_handles->allocated = new_allocated;
  121. inh_handles->handles = new_handles_array;
  122. inh_handles->flags = new_flags_array;
  123. }
  124. HANDLE *handles = inh_handles->handles;
  125. for (; inh_handles->count <= newfd; inh_handles->count++)
  126. handles[inh_handles->count] = INVALID_HANDLE_VALUE;
  127. return 0;
  128. }
  129. /* Reduces inh_handles->count to the minimum needed. */
  130. static void
  131. shrink_inheritable_handles (struct inheritable_handles *inh_handles)
  132. {
  133. HANDLE *handles = inh_handles->handles;
  134. while (inh_handles->count > 3
  135. && handles[inh_handles->count - 1] == INVALID_HANDLE_VALUE)
  136. inh_handles->count--;
  137. }
  138. /* Closes all handles in inh_handles. */
  139. static void
  140. close_inheritable_handles (struct inheritable_handles *inh_handles)
  141. {
  142. HANDLE *handles = inh_handles->handles;
  143. size_t handles_count = inh_handles->count;
  144. unsigned int fd;
  145. for (fd = 0; fd < handles_count; fd++)
  146. {
  147. HANDLE handle = handles[fd];
  148. if (handle != INVALID_HANDLE_VALUE)
  149. CloseHandle (handle);
  150. }
  151. }
  152. /* Tests whether a memory region, starting at P and N bytes long, contains only
  153. zeroes. */
  154. static bool
  155. memiszero (const void *p, size_t n)
  156. {
  157. const char *cp = p;
  158. for (; n > 0; cp++, n--)
  159. if (*cp != 0)
  160. return 0;
  161. return 1;
  162. }
  163. /* Tests whether *S contains no signals. */
  164. static bool
  165. sigisempty (const sigset_t *s)
  166. {
  167. return memiszero (s, sizeof (sigset_t));
  168. }
  169. /* Opens a HANDLE to a file.
  170. Upon failure, returns INVALID_HANDLE_VALUE with errno set. */
  171. static HANDLE
  172. open_handle (const char *name, int flags, mode_t mode)
  173. {
  174. /* To ease portability. Like in open.c. */
  175. if (strcmp (name, "/dev/null") == 0)
  176. name = "NUL";
  177. /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>
  178. specifies: "More than two leading <slash> characters shall be treated as
  179. a single <slash> character." */
  180. if (ISSLASH (name[0]) && ISSLASH (name[1]) && ISSLASH (name[2]))
  181. {
  182. name += 2;
  183. while (ISSLASH (name[1]))
  184. name++;
  185. }
  186. size_t len = strlen (name);
  187. size_t drive_prefix_len = (HAS_DEVICE (name) ? 2 : 0);
  188. /* Remove trailing slashes (except the very first one, at position
  189. drive_prefix_len), but remember their presence. */
  190. size_t rlen;
  191. bool check_dir = false;
  192. rlen = len;
  193. while (rlen > drive_prefix_len && ISSLASH (name[rlen-1]))
  194. {
  195. check_dir = true;
  196. if (rlen == drive_prefix_len + 1)
  197. break;
  198. rlen--;
  199. }
  200. /* Handle '' and 'C:'. */
  201. if (!check_dir && rlen == drive_prefix_len)
  202. {
  203. errno = ENOENT;
  204. return INVALID_HANDLE_VALUE;
  205. }
  206. /* Handle '\\'. */
  207. if (rlen == 1 && ISSLASH (name[0]) && len >= 2)
  208. {
  209. errno = ENOENT;
  210. return INVALID_HANDLE_VALUE;
  211. }
  212. const char *rname;
  213. char *malloca_rname;
  214. if (rlen == len)
  215. {
  216. rname = name;
  217. malloca_rname = NULL;
  218. }
  219. else
  220. {
  221. malloca_rname = malloca (rlen + 1);
  222. if (malloca_rname == NULL)
  223. {
  224. errno = ENOMEM;
  225. return INVALID_HANDLE_VALUE;
  226. }
  227. memcpy (malloca_rname, name, rlen);
  228. malloca_rname[rlen] = '\0';
  229. rname = malloca_rname;
  230. }
  231. /* For the meaning of the flags, see
  232. <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open-wopen> */
  233. /* Open a handle to the file.
  234. CreateFile
  235. <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea>
  236. <https://docs.microsoft.com/en-us/windows/desktop/FileIO/creating-and-opening-files> */
  237. HANDLE handle =
  238. CreateFile (rname,
  239. ((flags & (O_WRONLY | O_RDWR)) != 0
  240. ? GENERIC_READ | GENERIC_WRITE
  241. : GENERIC_READ),
  242. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  243. NULL,
  244. ((flags & O_CREAT) != 0
  245. ? ((flags & O_EXCL) != 0
  246. ? CREATE_NEW
  247. : ((flags & O_TRUNC) != 0 ? CREATE_ALWAYS : OPEN_ALWAYS))
  248. : ((flags & O_TRUNC) != 0
  249. ? TRUNCATE_EXISTING
  250. : OPEN_EXISTING)),
  251. /* FILE_FLAG_BACKUP_SEMANTICS is useful for opening directories,
  252. which is out-of-scope here. */
  253. /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only
  254. in case as different) makes sense only when applied to *all*
  255. filesystem operations. */
  256. /* FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS */
  257. FILE_ATTRIBUTE_NORMAL
  258. | ((flags & O_TEMPORARY) != 0 ? FILE_FLAG_DELETE_ON_CLOSE : 0)
  259. | ((flags & O_SEQUENTIAL ) != 0 ? FILE_FLAG_SEQUENTIAL_SCAN : 0)
  260. | ((flags & O_RANDOM) != 0 ? FILE_FLAG_RANDOM_ACCESS : 0),
  261. NULL);
  262. if (handle == INVALID_HANDLE_VALUE)
  263. switch (GetLastError ())
  264. {
  265. /* Some of these errors probably cannot happen with the specific flags
  266. that we pass to CreateFile. But who knows... */
  267. case ERROR_FILE_NOT_FOUND: /* The last component of rname does not exist. */
  268. case ERROR_PATH_NOT_FOUND: /* Some directory component in rname does not exist. */
  269. case ERROR_BAD_PATHNAME: /* rname is such as '\\server'. */
  270. case ERROR_BAD_NETPATH: /* rname is such as '\\nonexistentserver\share'. */
  271. case ERROR_BAD_NET_NAME: /* rname is such as '\\server\nonexistentshare'. */
  272. case ERROR_INVALID_NAME: /* rname contains wildcards, misplaced colon, etc. */
  273. case ERROR_DIRECTORY:
  274. errno = ENOENT;
  275. break;
  276. case ERROR_ACCESS_DENIED: /* rname is such as 'C:\System Volume Information\foo'. */
  277. case ERROR_SHARING_VIOLATION: /* rname is such as 'C:\pagefile.sys'. */
  278. /* XXX map to EACCES or EPERM? */
  279. errno = EACCES;
  280. break;
  281. case ERROR_OUTOFMEMORY:
  282. errno = ENOMEM;
  283. break;
  284. case ERROR_WRITE_PROTECT:
  285. errno = EROFS;
  286. break;
  287. case ERROR_WRITE_FAULT:
  288. case ERROR_READ_FAULT:
  289. case ERROR_GEN_FAILURE:
  290. errno = EIO;
  291. break;
  292. case ERROR_BUFFER_OVERFLOW:
  293. case ERROR_FILENAME_EXCED_RANGE:
  294. errno = ENAMETOOLONG;
  295. break;
  296. case ERROR_DELETE_PENDING: /* XXX map to EACCES or EPERM? */
  297. errno = EPERM;
  298. break;
  299. default:
  300. errno = EINVAL;
  301. break;
  302. }
  303. if (malloca_rname != NULL)
  304. {
  305. int saved_errno = errno;
  306. freea (malloca_rname);
  307. errno = saved_errno;
  308. }
  309. return handle;
  310. }
  311. /* Executes an 'open' action.
  312. Returns 0 upon success. In case of failure, -1 is returned, with errno set.
  313. */
  314. static int
  315. do_open (struct inheritable_handles *inh_handles, int newfd,
  316. const char *filename, const char *directory,
  317. int flags, mode_t mode, HANDLE curr_process)
  318. {
  319. if (!(newfd >= 0 && newfd < _getmaxstdio ()))
  320. {
  321. errno = EBADF;
  322. return -1;
  323. }
  324. if (grow_inheritable_handles (inh_handles, newfd) < 0)
  325. return -1;
  326. if (inh_handles->handles[newfd] != INVALID_HANDLE_VALUE
  327. && !CloseHandle (inh_handles->handles[newfd]))
  328. {
  329. errno = EIO;
  330. return -1;
  331. }
  332. if (filename == NULL)
  333. {
  334. errno = EINVAL;
  335. return -1;
  336. }
  337. char *filename_to_free = NULL;
  338. if (directory != NULL && IS_RELATIVE_FILE_NAME (filename))
  339. {
  340. char *real_filename = concatenated_filename (directory, filename, NULL);
  341. if (real_filename == NULL)
  342. {
  343. errno = ENOMEM;
  344. return -1;
  345. }
  346. filename = real_filename;
  347. filename_to_free = real_filename;
  348. }
  349. HANDLE handle = open_handle (filename, flags, mode);
  350. if (handle == INVALID_HANDLE_VALUE)
  351. {
  352. free (filename_to_free);
  353. return -1;
  354. }
  355. free (filename_to_free);
  356. /* Duplicate the handle, so that it becomes inheritable. */
  357. if (!DuplicateHandle (curr_process, handle,
  358. curr_process, &inh_handles->handles[newfd],
  359. 0, TRUE,
  360. DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
  361. {
  362. errno = EBADF; /* arbitrary */
  363. return -1;
  364. }
  365. inh_handles->flags[newfd] = ((flags & O_APPEND) != 0 ? 32 : 0);
  366. return 0;
  367. }
  368. /* Executes a 'dup2' action.
  369. Returns 0 upon success. In case of failure, -1 is returned, with errno set.
  370. */
  371. static int
  372. do_dup2 (struct inheritable_handles *inh_handles, int oldfd, int newfd,
  373. HANDLE curr_process)
  374. {
  375. if (!(oldfd >= 0 && oldfd < inh_handles->count
  376. && inh_handles->handles[oldfd] != INVALID_HANDLE_VALUE))
  377. {
  378. errno = EBADF;
  379. return -1;
  380. }
  381. if (!(newfd >= 0 && newfd < _getmaxstdio ()))
  382. {
  383. errno = EBADF;
  384. return -1;
  385. }
  386. if (newfd != oldfd)
  387. {
  388. if (grow_inheritable_handles (inh_handles, newfd) < 0)
  389. return -1;
  390. if (inh_handles->handles[newfd] != INVALID_HANDLE_VALUE
  391. && !CloseHandle (inh_handles->handles[newfd]))
  392. {
  393. errno = EIO;
  394. return -1;
  395. }
  396. /* Duplicate the handle, so that it a forthcoming do_close action on oldfd
  397. has no effect on newfd. */
  398. if (!DuplicateHandle (curr_process, inh_handles->handles[oldfd],
  399. curr_process, &inh_handles->handles[newfd],
  400. 0, TRUE, DUPLICATE_SAME_ACCESS))
  401. {
  402. errno = EBADF; /* arbitrary */
  403. return -1;
  404. }
  405. inh_handles->flags[newfd] = 0;
  406. }
  407. return 0;
  408. }
  409. /* Executes a 'close' action.
  410. Returns 0 upon success. In case of failure, -1 is returned, with errno set.
  411. */
  412. static int
  413. do_close (struct inheritable_handles *inh_handles, int fd)
  414. {
  415. if (!(fd >= 0 && fd < inh_handles->count
  416. && inh_handles->handles[fd] != INVALID_HANDLE_VALUE))
  417. {
  418. errno = EBADF;
  419. return -1;
  420. }
  421. if (!CloseHandle (inh_handles->handles[fd]))
  422. {
  423. errno = EIO;
  424. return -1;
  425. }
  426. inh_handles->handles[fd] = INVALID_HANDLE_VALUE;
  427. return 0;
  428. }
  429. int
  430. __spawni (pid_t *pid, const char *prog_filename,
  431. const posix_spawn_file_actions_t *file_actions,
  432. const posix_spawnattr_t *attrp, const char *const prog_argv[],
  433. const char *const envp[], int use_path)
  434. {
  435. /* Validate the arguments. */
  436. if (prog_filename == NULL
  437. || (attrp != NULL
  438. && ((attrp->_flags & ~POSIX_SPAWN_SETPGROUP) != 0
  439. || attrp->_pgrp != 0
  440. || ! sigisempty (&attrp->_sd)
  441. || ! sigisempty (&attrp->_ss)
  442. || attrp->_sp.sched_priority != 0
  443. || attrp->_policy != 0)))
  444. return EINVAL;
  445. /* Process group handling:
  446. Native Windows does not have the concept of process group, but it has the
  447. concept of a console attached to a process.
  448. So, we interpret the three cases as follows:
  449. - Flag POSIX_SPAWN_SETPGROUP not set: Means, the child process is in the
  450. same process group as the parent process. We interpret this as a
  451. request to reuse the same console.
  452. - Flag POSIX_SPAWN_SETPGROUP set with attrp->_pgrp == 0: Means the child
  453. process starts a process group of its own. See
  454. <https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getpgroup.html>
  455. <https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgrp.html>
  456. We interpret this as a request to detach from the current console.
  457. - Flag POSIX_SPAWN_SETPGROUP set with attrp->_pgrp != 0: Means the child
  458. process joins another, existing process group. See
  459. <https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getpgroup.html>
  460. <https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html>
  461. We don't support this case; it produces error EINVAL above. */
  462. /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */
  463. DWORD process_creation_flags =
  464. (attrp != NULL && (attrp->_flags & POSIX_SPAWN_SETPGROUP) != 0 ? DETACHED_PROCESS : 0);
  465. char *argv_mem_to_free;
  466. const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
  467. if (argv == NULL)
  468. return errno; /* errno is set here */
  469. argv++;
  470. /* Compose the command. */
  471. char *command = compose_command (argv);
  472. if (command == NULL)
  473. {
  474. free (argv_mem_to_free);
  475. return ENOMEM;
  476. }
  477. /* Copy *ENVP into a contiguous block of memory. */
  478. char *envblock;
  479. if (envp == NULL)
  480. envblock = NULL;
  481. else
  482. {
  483. envblock = compose_envblock (envp);
  484. if (envblock == NULL)
  485. {
  486. free (command);
  487. free (argv_mem_to_free);
  488. return ENOMEM;
  489. }
  490. }
  491. /* Set up the array of handles to inherit.
  492. Duplicate each handle, so that a spawn_do_close action (below) has no
  493. effect on the file descriptors of the current process. Alternatively,
  494. we could store, for each handle, a bit that tells whether it is shared
  495. with the current process. But this is simpler. */
  496. struct inheritable_handles inh_handles;
  497. if (init_inheritable_handles (&inh_handles, true) < 0)
  498. goto failed_1;
  499. /* Directory in which to execute the new process. */
  500. const char *directory = NULL;
  501. /* Execute the file_actions, modifying the inh_handles instead of the
  502. file descriptors of the current process. */
  503. if (file_actions != NULL)
  504. {
  505. HANDLE curr_process = GetCurrentProcess ();
  506. int cnt;
  507. for (cnt = 0; cnt < file_actions->_used; ++cnt)
  508. {
  509. struct __spawn_action *action = &file_actions->_actions[cnt];
  510. switch (action->tag)
  511. {
  512. case spawn_do_close:
  513. {
  514. int fd = action->action.close_action.fd;
  515. if (do_close (&inh_handles, fd) < 0)
  516. goto failed_2;
  517. }
  518. break;
  519. case spawn_do_open:
  520. {
  521. int newfd = action->action.open_action.fd;
  522. const char *filename = action->action.open_action.path;
  523. int flags = action->action.open_action.oflag;
  524. mode_t mode = action->action.open_action.mode;
  525. if (do_open (&inh_handles, newfd, filename, directory,
  526. flags, mode, curr_process)
  527. < 0)
  528. goto failed_2;
  529. }
  530. break;
  531. case spawn_do_dup2:
  532. {
  533. int oldfd = action->action.dup2_action.fd;
  534. int newfd = action->action.dup2_action.newfd;
  535. if (do_dup2 (&inh_handles, oldfd, newfd, curr_process) < 0)
  536. goto failed_2;
  537. }
  538. break;
  539. case spawn_do_chdir:
  540. {
  541. char *newdir = action->action.chdir_action.path;
  542. if (directory != NULL && IS_RELATIVE_FILE_NAME (newdir))
  543. {
  544. newdir = concatenated_filename (directory, newdir, NULL);
  545. if (newdir == NULL)
  546. {
  547. errno = ENOMEM;
  548. goto failed_2;
  549. }
  550. }
  551. directory = newdir;
  552. }
  553. break;
  554. case spawn_do_fchdir:
  555. /* Not supported in this implementation. */
  556. errno = EINVAL;
  557. goto failed_2;
  558. }
  559. }
  560. }
  561. /* Reduce inh_handles.count to the minimum needed. */
  562. shrink_inheritable_handles (&inh_handles);
  563. /* CreateProcess
  564. <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
  565. /* STARTUPINFO
  566. <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
  567. STARTUPINFO sinfo;
  568. sinfo.cb = sizeof (STARTUPINFO);
  569. sinfo.lpReserved = NULL;
  570. sinfo.lpDesktop = NULL;
  571. sinfo.lpTitle = NULL;
  572. if (compose_handles_block (&inh_handles, &sinfo) < 0)
  573. goto failed_2;
  574. /* Perform the PATH search now, considering the final DIRECTORY. */
  575. char *resolved_prog_filename_to_free = NULL;
  576. {
  577. const char *resolved_prog_filename =
  578. find_in_given_path (prog_filename, use_path ? getenv ("PATH") : "",
  579. directory, false);
  580. if (resolved_prog_filename == NULL)
  581. goto failed_3;
  582. if (resolved_prog_filename != prog_filename)
  583. resolved_prog_filename_to_free = (char *) resolved_prog_filename;
  584. prog_filename = resolved_prog_filename;
  585. }
  586. PROCESS_INFORMATION pinfo;
  587. if (!CreateProcess (prog_filename, command, NULL, NULL, TRUE,
  588. process_creation_flags, envblock, directory, &sinfo,
  589. &pinfo))
  590. {
  591. DWORD error = GetLastError ();
  592. free (resolved_prog_filename_to_free);
  593. free (sinfo.lpReserved2);
  594. close_inheritable_handles (&inh_handles);
  595. free_inheritable_handles (&inh_handles);
  596. free (envblock);
  597. free (command);
  598. free (argv_mem_to_free);
  599. return convert_CreateProcess_error (error);
  600. }
  601. if (pinfo.hThread)
  602. CloseHandle (pinfo.hThread);
  603. free (resolved_prog_filename_to_free);
  604. free (sinfo.lpReserved2);
  605. close_inheritable_handles (&inh_handles);
  606. free_inheritable_handles (&inh_handles);
  607. free (envblock);
  608. free (command);
  609. free (argv_mem_to_free);
  610. if (pid != NULL)
  611. *pid = (intptr_t) pinfo.hProcess;
  612. return 0;
  613. failed_3:
  614. {
  615. int saved_errno = errno;
  616. free (sinfo.lpReserved2);
  617. close_inheritable_handles (&inh_handles);
  618. free_inheritable_handles (&inh_handles);
  619. free (envblock);
  620. free (command);
  621. free (argv_mem_to_free);
  622. return saved_errno;
  623. }
  624. failed_2:
  625. {
  626. int saved_errno = errno;
  627. close_inheritable_handles (&inh_handles);
  628. free_inheritable_handles (&inh_handles);
  629. free (envblock);
  630. free (command);
  631. free (argv_mem_to_free);
  632. return saved_errno;
  633. }
  634. failed_1:
  635. free (envblock);
  636. free (command);
  637. free (argv_mem_to_free);
  638. return errno;
  639. }
  640. #else
  641. /* Spawn a new process executing PATH with the attributes describes in *ATTRP.
  642. Before running the process perform the actions described in FILE-ACTIONS. */
  643. int
  644. __spawni (pid_t *pid, const char *file,
  645. const posix_spawn_file_actions_t *file_actions,
  646. const posix_spawnattr_t *attrp, const char *const argv[],
  647. const char *const envp[], int use_path)
  648. {
  649. pid_t new_pid;
  650. char *path, *p, *name;
  651. size_t len;
  652. size_t pathlen;
  653. /* Do this once. */
  654. short int flags = attrp == NULL ? 0 : attrp->_flags;
  655. /* Avoid gcc warning
  656. "variable 'flags' might be clobbered by 'longjmp' or 'vfork'" */
  657. (void) &flags;
  658. /* Generate the new process. */
  659. #if HAVE_VFORK
  660. if ((flags & POSIX_SPAWN_USEVFORK) != 0
  661. /* If no major work is done, allow using vfork. Note that we
  662. might perform the path searching. But this would be done by
  663. a call to execvp(), too, and such a call must be OK according
  664. to POSIX. */
  665. || ((flags & (POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF
  666. | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER
  667. | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0
  668. && file_actions == NULL))
  669. new_pid = vfork ();
  670. else
  671. #endif
  672. new_pid = fork ();
  673. if (new_pid != 0)
  674. {
  675. if (new_pid < 0)
  676. return errno;
  677. /* The call was successful. Store the PID if necessary. */
  678. if (pid != NULL)
  679. *pid = new_pid;
  680. return 0;
  681. }
  682. /* Set signal mask. */
  683. if ((flags & POSIX_SPAWN_SETSIGMASK) != 0
  684. && sigprocmask (SIG_SETMASK, &attrp->_ss, NULL) != 0)
  685. _exit (SPAWN_ERROR);
  686. /* Set signal default action. */
  687. if ((flags & POSIX_SPAWN_SETSIGDEF) != 0)
  688. {
  689. /* We have to iterate over all signals. This could possibly be
  690. done better but it requires system specific solutions since
  691. the sigset_t data type can be very different on different
  692. architectures. */
  693. int sig;
  694. struct sigaction sa;
  695. memset (&sa, '\0', sizeof (sa));
  696. sa.sa_handler = SIG_DFL;
  697. for (sig = 1; sig <= NSIG; ++sig)
  698. if (sigismember (&attrp->_sd, sig) != 0
  699. && sigaction (sig, &sa, NULL) != 0)
  700. _exit (SPAWN_ERROR);
  701. }
  702. #if (_LIBC ? defined _POSIX_PRIORITY_SCHEDULING : HAVE_SCHED_SETPARAM && HAVE_SCHED_SETSCHEDULER)
  703. /* Set the scheduling algorithm and parameters. */
  704. if ((flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER))
  705. == POSIX_SPAWN_SETSCHEDPARAM)
  706. {
  707. if (sched_setparam (0, &attrp->_sp) == -1)
  708. _exit (SPAWN_ERROR);
  709. }
  710. else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0)
  711. {
  712. if (sched_setscheduler (0, attrp->_policy,
  713. (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0
  714. ? &attrp->_sp : NULL) == -1)
  715. _exit (SPAWN_ERROR);
  716. }
  717. #endif
  718. /* Set the process group ID. */
  719. if ((flags & POSIX_SPAWN_SETPGROUP) != 0
  720. && setpgid (0, attrp->_pgrp) != 0)
  721. _exit (SPAWN_ERROR);
  722. /* Set the effective user and group IDs. */
  723. if ((flags & POSIX_SPAWN_RESETIDS) != 0
  724. && (local_seteuid (getuid ()) != 0
  725. || local_setegid (getgid ()) != 0))
  726. _exit (SPAWN_ERROR);
  727. /* Execute the file actions. */
  728. if (file_actions != NULL)
  729. {
  730. int cnt;
  731. for (cnt = 0; cnt < file_actions->_used; ++cnt)
  732. {
  733. struct __spawn_action *action = &file_actions->_actions[cnt];
  734. switch (action->tag)
  735. {
  736. case spawn_do_close:
  737. if (close_not_cancel (action->action.close_action.fd) != 0)
  738. /* Signal the error. */
  739. _exit (SPAWN_ERROR);
  740. break;
  741. case spawn_do_open:
  742. {
  743. int new_fd = open_not_cancel (action->action.open_action.path,
  744. action->action.open_action.oflag
  745. | O_LARGEFILE,
  746. action->action.open_action.mode);
  747. if (new_fd == -1)
  748. /* The 'open' call failed. */
  749. _exit (SPAWN_ERROR);
  750. /* Make sure the desired file descriptor is used. */
  751. if (new_fd != action->action.open_action.fd)
  752. {
  753. if (dup2 (new_fd, action->action.open_action.fd)
  754. != action->action.open_action.fd)
  755. /* The 'dup2' call failed. */
  756. _exit (SPAWN_ERROR);
  757. if (close_not_cancel (new_fd) != 0)
  758. /* The 'close' call failed. */
  759. _exit (SPAWN_ERROR);
  760. }
  761. }
  762. break;
  763. case spawn_do_dup2:
  764. if (dup2 (action->action.dup2_action.fd,
  765. action->action.dup2_action.newfd)
  766. != action->action.dup2_action.newfd)
  767. /* The 'dup2' call failed. */
  768. _exit (SPAWN_ERROR);
  769. break;
  770. case spawn_do_chdir:
  771. if (chdir (action->action.chdir_action.path) < 0)
  772. /* The 'chdir' call failed. */
  773. _exit (SPAWN_ERROR);
  774. break;
  775. case spawn_do_fchdir:
  776. if (fchdir (action->action.fchdir_action.fd) < 0)
  777. /* The 'fchdir' call failed. */
  778. _exit (SPAWN_ERROR);
  779. break;
  780. }
  781. }
  782. }
  783. if (! use_path || strchr (file, '/') != NULL)
  784. {
  785. /* The FILE parameter is actually a path. */
  786. execve (file, (char * const *) argv, (char * const *) envp);
  787. /* Oh, oh. 'execve' returns. This is bad. */
  788. _exit (SPAWN_ERROR);
  789. }
  790. /* We have to search for FILE on the path. */
  791. path = getenv ("PATH");
  792. if (path == NULL)
  793. {
  794. #if HAVE_CONFSTR
  795. /* There is no 'PATH' in the environment.
  796. The default search path is the current directory
  797. followed by the path 'confstr' returns for '_CS_PATH'. */
  798. len = confstr (_CS_PATH, (char *) NULL, 0);
  799. path = (char *) alloca (1 + len);
  800. path[0] = ':';
  801. (void) confstr (_CS_PATH, path + 1, len);
  802. #else
  803. /* Pretend that the PATH contains only the current directory. */
  804. path = "";
  805. #endif
  806. }
  807. len = strlen (file) + 1;
  808. pathlen = strlen (path);
  809. name = alloca (pathlen + len + 1);
  810. /* Copy the file name at the top. */
  811. name = (char *) memcpy (name + pathlen + 1, file, len);
  812. /* And add the slash. */
  813. *--name = '/';
  814. p = path;
  815. do
  816. {
  817. char *startp;
  818. path = p;
  819. p = strchrnul (path, ':');
  820. if (p == path)
  821. /* Two adjacent colons, or a colon at the beginning or the end
  822. of 'PATH' means to search the current directory. */
  823. startp = name + 1;
  824. else
  825. startp = (char *) memcpy (name - (p - path), path, p - path);
  826. /* Try to execute this name. If it works, execv will not return. */
  827. execve (startp, (char * const *) argv, (char * const *) envp);
  828. switch (errno)
  829. {
  830. case EACCES:
  831. case ENOENT:
  832. case ESTALE:
  833. case ENOTDIR:
  834. /* Those errors indicate the file is missing or not executable
  835. by us, in which case we want to just try the next path
  836. directory. */
  837. break;
  838. default:
  839. /* Some other error means we found an executable file, but
  840. something went wrong executing it; return the error to our
  841. caller. */
  842. _exit (SPAWN_ERROR);
  843. }
  844. }
  845. while (*p++ != '\0');
  846. /* Return with an error. */
  847. _exit (SPAWN_ERROR);
  848. }
  849. #endif