spawn.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  1. /*++
  2. Copyright (c) 2016 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. spawn.c
  9. Abstract:
  10. This module implements support for the posix_spawn* family of functions.
  11. Author:
  12. Evan Green 20-Jul-2016
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <spawn.h>
  24. #include <stdlib.h>
  25. #include <sys/wait.h>
  26. #include <unistd.h>
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. typedef enum _POSIX_SPAWN_ACTION {
  34. SpawnActionInvalid,
  35. SpawnActionOpen,
  36. SpawnActionDup2,
  37. SpawnActionClose,
  38. } POSIX_SPAWN_ACTION, *PPOSIX_SPAWN_ACTION;
  39. /*++
  40. Structure Description:
  41. This structure stores an attribute related to spawn.
  42. Members:
  43. Flags - Stores the flags associated with the attribute. See
  44. POSIX_SPAWN_* definitions.
  45. ProcessGroup - Stores the process group to set the child process to.
  46. SchedulerParameter - Stores the scheduling parameter to set in the child
  47. process.
  48. SchedulerPolicy - Stores the scheduler policy to set in the process.
  49. DefaultMask - Stores the mask of signals to return back to the default.
  50. SignalMask - Stores the mask of signals to block.
  51. --*/
  52. typedef struct __posix_spawnattr_t {
  53. short Flags;
  54. pid_t ProcessGroup;
  55. struct sched_param SchedulerParameter;
  56. int SchedulerPolicy;
  57. sigset_t DefaultMask;
  58. sigset_t SignalMask;
  59. } POSIX_SPAWN_ATTRIBUTES, *PPOSIX_SPAWN_ATTRIBUTES;
  60. /*++
  61. Structure Description:
  62. This structure stores an open file spawn action.
  63. Members:
  64. Descriptor - Stores the descriptor to set the opened file to.
  65. Path - Stores a pointer to the path to open.
  66. OpenFlags - Stores the open flags to open the path with.
  67. CreateMode - Stores the creation mode to set if the file was newly created.
  68. --*/
  69. typedef struct _POSIX_SPAWN_OPEN {
  70. INT Descriptor;
  71. PSTR Path;
  72. INT OpenFlags;
  73. mode_t CreateMode;
  74. } POSIX_SPAWN_OPEN, *PPOSIX_SPAWN_OPEN;
  75. /*++
  76. Structure Description:
  77. This structure stores a dup2 file spawn action.
  78. Members:
  79. Descriptor - Stores the descriptor to duplicate.
  80. NewDescriptor - Stores the new file descriptor to duplicate the source to.
  81. --*/
  82. typedef struct _POSIX_SPAWN_DUP2 {
  83. INT Descriptor;
  84. INT NewDescriptor;
  85. } POSIX_SPAWN_DUP2, *PPOSIX_SPAWN_DUP2;
  86. /*++
  87. Structure Description:
  88. This structure stores a close file spawn action.
  89. Members:
  90. Descriptor - Stores the descriptor to close.
  91. --*/
  92. typedef struct _POSIX_SPAWN_CLOSE {
  93. INT Descriptor;
  94. } POSIX_SPAWN_CLOSE, *PPOSIX_SPAWN_CLOSE;
  95. /*++
  96. Structure Description:
  97. This structure stores a file attribute related to spawn.
  98. Members:
  99. EntryList - Stores the head of the list of POSIX_SPAWN_FILE_ENTRY actions.
  100. --*/
  101. typedef struct __posix_spawn_file_actions_t {
  102. LIST_ENTRY EntryList;
  103. } POSIX_SPAWN_FILE_ACTION, *PPOSIX_SPAWN_FILE_ACTION;
  104. /*++
  105. Structure Description:
  106. This structure stores a spawn file action entry.
  107. Members:
  108. ListEntry - Stores pointers to the next and previous file actions.
  109. Action - Stores the action type.
  110. U - Stores the union of action type parameters.
  111. Open - Stores the parameters for an open action.
  112. Dup2 - Stores the parameters for a dup2 action.
  113. Close - Stores the parameters for a close action.
  114. --*/
  115. typedef struct _POSIX_SPAWN_FILE_ENTRY {
  116. LIST_ENTRY ListEntry;
  117. POSIX_SPAWN_ACTION Action;
  118. union {
  119. POSIX_SPAWN_OPEN Open;
  120. POSIX_SPAWN_DUP2 Dup2;
  121. POSIX_SPAWN_CLOSE Close;
  122. } U;
  123. } POSIX_SPAWN_FILE_ENTRY, *PPOSIX_SPAWN_FILE_ENTRY;
  124. //
  125. // ----------------------------------------------- Internal Function Prototypes
  126. //
  127. INT
  128. ClpPosixSpawn (
  129. pid_t *ChildPid,
  130. const char *Path,
  131. PPOSIX_SPAWN_FILE_ACTION *FileActions,
  132. PPOSIX_SPAWN_ATTRIBUTES *Attributes,
  133. char *const Arguments[],
  134. char *const Environment[],
  135. BOOL UsePath
  136. );
  137. INT
  138. ClpProcessSpawnAttributes (
  139. PPOSIX_SPAWN_ATTRIBUTES Attributes
  140. );
  141. INT
  142. ClpProcessSpawnFileActions (
  143. PPOSIX_SPAWN_FILE_ACTION Actions
  144. );
  145. //
  146. // -------------------------------------------------------------------- Globals
  147. //
  148. //
  149. // ------------------------------------------------------------------ Functions
  150. //
  151. LIBC_API
  152. int
  153. posix_spawn (
  154. pid_t *ChildPid,
  155. const char *Path,
  156. const posix_spawn_file_actions_t *FileActions,
  157. const posix_spawnattr_t *Attributes,
  158. char *const Arguments[],
  159. char *const Environment[]
  160. )
  161. /*++
  162. Routine Description:
  163. This routine spawns a new child process.
  164. Arguments:
  165. ChildPid - Supplies an optional pointer where the child process ID will be
  166. returned on success.
  167. Path - Supplies a pointer to the file path to execute.
  168. FileActions - Supplies an optional pointer to the file actions to execute
  169. in the child.
  170. Attributes - Supplies an optional pointer to the spawn attributes that
  171. affect various properties of the child.
  172. Arguments - Supplies the arguments to pass to the new child.
  173. Environment - Supplies an optional pointer to the environment to pass
  174. to the new child.
  175. Return Value:
  176. 0 on success.
  177. Returns an error number on failure.
  178. --*/
  179. {
  180. INT Status;
  181. Status = ClpPosixSpawn(ChildPid,
  182. Path,
  183. (PPOSIX_SPAWN_FILE_ACTION *)FileActions,
  184. (PPOSIX_SPAWN_ATTRIBUTES *)Attributes,
  185. Arguments,
  186. Environment,
  187. FALSE);
  188. return Status;
  189. }
  190. LIBC_API
  191. int
  192. posix_spawnp (
  193. pid_t *ChildPid,
  194. const char *File,
  195. const posix_spawn_file_actions_t *FileActions,
  196. const posix_spawnattr_t *Attributes,
  197. char *const Arguments[],
  198. char *const Environment[]
  199. )
  200. /*++
  201. Routine Description:
  202. This routine spawns a new child process. It is identical to posix_spawn
  203. except the path is searched to find the file argument.
  204. Arguments:
  205. ChildPid - Supplies an optional pointer where the child process ID will be
  206. returned on success.
  207. File - Supplies a pointer to the file to execute. If this path contains a
  208. slash, it will be used as a relative path from the current directory
  209. or an absolute path. If this path does not contain a slash, it will
  210. use the PATH environment variable from the new child environment
  211. to attempt to find the path.
  212. FileActions - Supplies an optional pointer to the file actions to execute
  213. in the child.
  214. Attributes - Supplies an optional pointer to the spawn attributes that
  215. affect various properties of the child.
  216. Arguments - Supplies the arguments to pass to the new child.
  217. Environment - Supplies an optional pointer to the environment to pass
  218. to the new child.
  219. Return Value:
  220. 0 on success.
  221. Returns an error number on failure.
  222. --*/
  223. {
  224. INT Status;
  225. Status = ClpPosixSpawn(ChildPid,
  226. File,
  227. (PPOSIX_SPAWN_FILE_ACTION *)FileActions,
  228. (PPOSIX_SPAWN_ATTRIBUTES *)Attributes,
  229. Arguments,
  230. Environment,
  231. TRUE);
  232. return Status;
  233. }
  234. //
  235. // File action functions
  236. //
  237. LIBC_API
  238. int
  239. posix_spawn_file_actions_init (
  240. posix_spawn_file_actions_t *FileActions
  241. )
  242. /*++
  243. Routine Description:
  244. This routine initializes a set of posix spawn file action.
  245. Arguments:
  246. FileActions - Supplies a pointer to the file actions to initialize.
  247. Return Value:
  248. 0 on success. The caller must call the corresponding destroy routine to
  249. avoid leaking resources.
  250. Returns an error number on failure. The caller should not call destroy on
  251. this object.
  252. --*/
  253. {
  254. PPOSIX_SPAWN_FILE_ACTION Action;
  255. Action = malloc(sizeof(POSIX_SPAWN_FILE_ACTION));
  256. if (Action == NULL) {
  257. *FileActions = NULL;
  258. return errno;
  259. }
  260. INITIALIZE_LIST_HEAD(&(Action->EntryList));
  261. *FileActions = Action;
  262. return 0;
  263. }
  264. LIBC_API
  265. int
  266. posix_spawn_file_actions_destroy (
  267. posix_spawn_file_actions_t *FileActions
  268. )
  269. /*++
  270. Routine Description:
  271. This routine destroys a set of posix spawn file actions.
  272. Arguments:
  273. FileActions - Supplies a pointer to the file actions to destroy.
  274. Return Value:
  275. 0 always.
  276. --*/
  277. {
  278. PPOSIX_SPAWN_FILE_ACTION Action;
  279. PLIST_ENTRY CurrentEntry;
  280. PPOSIX_SPAWN_FILE_ENTRY Entry;
  281. Action = *FileActions;
  282. *FileActions = NULL;
  283. if (Action == NULL) {
  284. return 0;
  285. }
  286. CurrentEntry = Action->EntryList.Next;
  287. while (CurrentEntry != &(Action->EntryList)) {
  288. Entry = LIST_VALUE(CurrentEntry, POSIX_SPAWN_FILE_ENTRY, ListEntry);
  289. CurrentEntry = CurrentEntry->Next;
  290. free(Entry);
  291. }
  292. free(Action);
  293. return 0;
  294. }
  295. LIBC_API
  296. int
  297. posix_spawn_file_actions_addopen (
  298. posix_spawn_file_actions_t *FileActions,
  299. int FileDescriptor,
  300. const char *Path,
  301. int OpenFlags,
  302. mode_t CreatePermissions
  303. )
  304. /*++
  305. Routine Description:
  306. This routine adds an open call to the set of file attributes. The spawn
  307. function will attempt to open the given file in the child.
  308. Arguments:
  309. FileActions - Supplies a pointer to the initialized file actions.
  310. FileDescriptor - Supplies the descriptor number to set the open file to.
  311. Path - Supplies a pointer to the path to open.
  312. OpenFlags - Supplies the set of open flags to use when opening the file.
  313. See O_* flags or the definition of the open function for details.
  314. CreatePermissions - Supplies the permissions to set on the new file if it
  315. is creates. See S_I* definitions or the definition of the open function
  316. for details.
  317. Return Value:
  318. 0 on success.
  319. Returns an error number on failure.
  320. --*/
  321. {
  322. PPOSIX_SPAWN_FILE_ACTION Action;
  323. PPOSIX_SPAWN_FILE_ENTRY Entry;
  324. size_t PathLength;
  325. Action = *FileActions;
  326. if (FileDescriptor < 0) {
  327. return EBADF;
  328. }
  329. PathLength = strlen(Path);
  330. Entry = malloc(sizeof(POSIX_SPAWN_FILE_ENTRY) + PathLength + 1);
  331. if (Entry == NULL) {
  332. return ENOMEM;
  333. }
  334. Entry->Action = SpawnActionOpen;
  335. Entry->U.Open.Path = (PSTR)(Entry + 1);
  336. memcpy(Entry->U.Open.Path, Path, PathLength + 1);
  337. Entry->U.Open.Descriptor = FileDescriptor;
  338. Entry->U.Open.OpenFlags = OpenFlags;
  339. Entry->U.Open.CreateMode = CreatePermissions;
  340. INSERT_BEFORE(&(Entry->ListEntry), &(Action->EntryList));
  341. return 0;
  342. }
  343. LIBC_API
  344. int
  345. posix_spawn_file_actions_adddup2 (
  346. posix_spawn_file_actions_t *FileActions,
  347. int FileDescriptor,
  348. int DestinationDescriptor
  349. )
  350. /*++
  351. Routine Description:
  352. This routine adds a dup2 call to the set of file attributes. The spawn
  353. function will attempt to duplicate the given descriptor in the child.
  354. Arguments:
  355. FileActions - Supplies a pointer to the initialized file actions.
  356. FileDescriptor - Supplies the descriptor to copy.
  357. DestinationDescriptor - Supplies the descriptor number to copy the
  358. descriptor to.
  359. Return Value:
  360. 0 on success.
  361. Returns an error number on failure.
  362. --*/
  363. {
  364. PPOSIX_SPAWN_FILE_ACTION Action;
  365. PPOSIX_SPAWN_FILE_ENTRY Entry;
  366. Action = *FileActions;
  367. if ((FileDescriptor < 0) || (DestinationDescriptor < 0)) {
  368. return EBADF;
  369. }
  370. Entry = malloc(sizeof(POSIX_SPAWN_FILE_ENTRY));
  371. if (Entry == NULL) {
  372. return ENOMEM;
  373. }
  374. Entry->Action = SpawnActionDup2;
  375. Entry->U.Dup2.Descriptor = FileDescriptor;
  376. Entry->U.Dup2.NewDescriptor = DestinationDescriptor;
  377. INSERT_BEFORE(&(Entry->ListEntry), &(Action->EntryList));
  378. return 0;
  379. }
  380. LIBC_API
  381. int
  382. posix_spawn_file_actions_addclose (
  383. posix_spawn_file_actions_t *FileActions,
  384. int FileDescriptor
  385. )
  386. /*++
  387. Routine Description:
  388. This routine adds a close call to the set of file attributes. The spawn
  389. function will attempt to close the given descriptor in the child.
  390. Arguments:
  391. FileActions - Supplies a pointer to the initialized file actions.
  392. FileDescriptor - Supplies the descriptor to close.
  393. Return Value:
  394. 0 on success.
  395. Returns an error number on failure.
  396. --*/
  397. {
  398. PPOSIX_SPAWN_FILE_ACTION Action;
  399. PPOSIX_SPAWN_FILE_ENTRY Entry;
  400. Action = *FileActions;
  401. if (FileDescriptor < 0) {
  402. return EBADF;
  403. }
  404. Entry = malloc(sizeof(POSIX_SPAWN_FILE_ENTRY));
  405. if (Entry == NULL) {
  406. return ENOMEM;
  407. }
  408. Entry->Action = SpawnActionClose;
  409. Entry->U.Dup2.Descriptor = FileDescriptor;
  410. INSERT_BEFORE(&(Entry->ListEntry), &(Action->EntryList));
  411. return 0;
  412. }
  413. //
  414. // Spawn attribute functions
  415. //
  416. LIBC_API
  417. int
  418. posix_spawnattr_init (
  419. posix_spawnattr_t *Attributes
  420. )
  421. /*++
  422. Routine Description:
  423. This routine initializes a set of spawn attributes.
  424. Arguments:
  425. Attributes - Supplies a pointer to the attributes to initialize.
  426. Return Value:
  427. 0 on success. The caller must call the corresponding destroy routine to
  428. avoid leaking resources.
  429. Returns an error number on failure. The caller should not call destroy in
  430. this case.
  431. --*/
  432. {
  433. PPOSIX_SPAWN_ATTRIBUTES NewAttributes;
  434. NewAttributes = calloc(sizeof(POSIX_SPAWN_ATTRIBUTES), 1);
  435. if (NewAttributes == NULL) {
  436. *Attributes = NULL;
  437. return -1;
  438. }
  439. *Attributes = NewAttributes;
  440. return 0;
  441. }
  442. LIBC_API
  443. int
  444. posix_spawnattr_destroy (
  445. posix_spawnattr_t *Attributes
  446. )
  447. /*++
  448. Routine Description:
  449. This routine destroys a set of spawn attributes.
  450. Arguments:
  451. Attributes - Supplies a pointer to the attributes to destroy.
  452. Return Value:
  453. 0 always.
  454. --*/
  455. {
  456. free(*Attributes);
  457. return 0;
  458. }
  459. //
  460. // Spawn attribute get functions
  461. //
  462. LIBC_API
  463. int
  464. posix_spawnattr_getflags (
  465. const posix_spawnattr_t *Attributes,
  466. short *Flags
  467. )
  468. /*++
  469. Routine Description:
  470. This routine returns the current flags on a set of spawn attributes.
  471. Arguments:
  472. Attributes - Supplies a pointer to the initialized attributes.
  473. Flags - Supplies a pointer where the flags will be returned on success.
  474. Return Value:
  475. 0 on success (always).
  476. Returns an error number on failure.
  477. --*/
  478. {
  479. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  480. SpawnAttributes = *Attributes;
  481. *Flags = SpawnAttributes->Flags;
  482. return 0;
  483. }
  484. LIBC_API
  485. int
  486. posix_spawnattr_getpgroup (
  487. const posix_spawnattr_t *Attributes,
  488. pid_t *ProcessGroup
  489. )
  490. /*++
  491. Routine Description:
  492. This routine returns the current process group on a set of spawn attributes.
  493. Arguments:
  494. Attributes - Supplies a pointer to the initialized attributes.
  495. ProcessGroup - Supplies a pointer where the process group will be returned
  496. on success.
  497. Return Value:
  498. 0 on success (always).
  499. Returns an error number on failure.
  500. --*/
  501. {
  502. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  503. SpawnAttributes = *Attributes;
  504. *ProcessGroup = SpawnAttributes->ProcessGroup;
  505. return 0;
  506. }
  507. LIBC_API
  508. int
  509. posix_spawnattr_getschedparam (
  510. const posix_spawnattr_t *Attributes,
  511. struct sched_param *Parameters
  512. )
  513. /*++
  514. Routine Description:
  515. This routine returns the current scheduling parameters on a set of spawn
  516. attributes.
  517. Arguments:
  518. Attributes - Supplies a pointer to the initialized attributes.
  519. Parameters - Supplies a pointer where the scheduling parameters will be
  520. returned on success.
  521. Return Value:
  522. 0 on success (always).
  523. Returns an error number on failure.
  524. --*/
  525. {
  526. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  527. SpawnAttributes = *Attributes;
  528. *Parameters = SpawnAttributes->SchedulerParameter;
  529. return 0;
  530. }
  531. LIBC_API
  532. int
  533. posix_spawnattr_getschedpolicy (
  534. const posix_spawnattr_t *Attributes,
  535. int *Policy
  536. )
  537. /*++
  538. Routine Description:
  539. This routine returns the current scheduling policy on a set of spawn
  540. attributes.
  541. Arguments:
  542. Attributes - Supplies a pointer to the initialized attributes.
  543. Policy - Supplies a pointer where the scheduling policy will be returned on
  544. success.
  545. Return Value:
  546. 0 on success (always).
  547. Returns an error number on failure.
  548. --*/
  549. {
  550. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  551. SpawnAttributes = *Attributes;
  552. *Policy = SpawnAttributes->SchedulerPolicy;
  553. return 0;
  554. }
  555. LIBC_API
  556. int
  557. posix_spawnattr_getsigdefault (
  558. const posix_spawnattr_t *Attributes,
  559. sigset_t *DefaultSignals
  560. )
  561. /*++
  562. Routine Description:
  563. This routine returns the current default signal set on a set of spawn
  564. attributes.
  565. Arguments:
  566. Attributes - Supplies a pointer to the initialized attributes.
  567. DefaultSignals - Supplies a pointer where the set of signals to be returned
  568. to their default dispositions will be returned on success.
  569. Return Value:
  570. 0 on success (always).
  571. Returns an error number on failure.
  572. --*/
  573. {
  574. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  575. SpawnAttributes = *Attributes;
  576. *DefaultSignals = SpawnAttributes->DefaultMask;
  577. return 0;
  578. }
  579. LIBC_API
  580. int
  581. posix_spawnattr_getsigmask (
  582. const posix_spawnattr_t *Attributes,
  583. sigset_t *Mask
  584. )
  585. /*++
  586. Routine Description:
  587. This routine returns the current signal mask on a set of spawn attributes.
  588. Arguments:
  589. Attributes - Supplies a pointer to the initialized attributes.
  590. Mask - Supplies a pointer where the signal mask to be set on the child
  591. process will be returned on success.
  592. Return Value:
  593. 0 on success (always).
  594. Returns an error number on failure.
  595. --*/
  596. {
  597. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  598. SpawnAttributes = *Attributes;
  599. *Mask = SpawnAttributes->SignalMask;
  600. return 0;
  601. }
  602. //
  603. // Spawn attribute set functions
  604. //
  605. LIBC_API
  606. int
  607. posix_spawnattr_setflags (
  608. posix_spawnattr_t *Attributes,
  609. short Flags
  610. )
  611. /*++
  612. Routine Description:
  613. This routine sets the current flags on a set of spawn attributes.
  614. Arguments:
  615. Attributes - Supplies a pointer to the initialized attributes.
  616. Flags - Supplies the new flags to set.
  617. Return Value:
  618. 0 on success (always).
  619. Returns an error number on failure.
  620. --*/
  621. {
  622. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  623. SpawnAttributes = *Attributes;
  624. SpawnAttributes->Flags = Flags;
  625. return 0;
  626. }
  627. LIBC_API
  628. int
  629. posix_spawnattr_setpgroup (
  630. posix_spawnattr_t *Attributes,
  631. pid_t ProcessGroup
  632. )
  633. /*++
  634. Routine Description:
  635. This routine sets the current process group on a set of spawn attributes.
  636. Arguments:
  637. Attributes - Supplies a pointer to the initialized attributes.
  638. ProcessGroup - Supplies the process group to set the child to.
  639. Return Value:
  640. 0 on success (always).
  641. Returns an error number on failure.
  642. --*/
  643. {
  644. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  645. SpawnAttributes = *Attributes;
  646. SpawnAttributes->ProcessGroup = ProcessGroup;
  647. return 0;
  648. }
  649. LIBC_API
  650. int
  651. posix_spawnattr_setschedparam (
  652. posix_spawnattr_t *Attributes,
  653. const struct sched_param *Parameters
  654. )
  655. /*++
  656. Routine Description:
  657. This routine sets the current scheduling parameters on a set of spawn
  658. attributes.
  659. Arguments:
  660. Attributes - Supplies a pointer to the initialized attributes.
  661. Parameters - Supplies a pointer to the scheduling parameters to set in the
  662. child.
  663. Return Value:
  664. 0 on success (always).
  665. Returns an error number on failure.
  666. --*/
  667. {
  668. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  669. SpawnAttributes = *Attributes;
  670. SpawnAttributes->SchedulerParameter = *Parameters;
  671. return 0;
  672. }
  673. LIBC_API
  674. int
  675. posix_spawnattr_setschedpolicy (
  676. posix_spawnattr_t *Attributes,
  677. int Policy
  678. )
  679. /*++
  680. Routine Description:
  681. This routine sets the current scheduling policy on a set of spawn
  682. attributes.
  683. Arguments:
  684. Attributes - Supplies a pointer to the initialized attributes.
  685. Policy - Supplies the scheduling policy to set in the child.
  686. Return Value:
  687. 0 on success (always).
  688. Returns an error number on failure.
  689. --*/
  690. {
  691. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  692. SpawnAttributes = *Attributes;
  693. SpawnAttributes->SchedulerPolicy = Policy;
  694. return 0;
  695. }
  696. LIBC_API
  697. int
  698. posix_spawnattr_setsigdefault (
  699. posix_spawnattr_t *Attributes,
  700. const sigset_t *DefaultSignals
  701. )
  702. /*++
  703. Routine Description:
  704. This routine sets the current default signal set on a set of spawn
  705. attributes.
  706. Arguments:
  707. Attributes - Supplies a pointer to the initialized attributes.
  708. DefaultSignals - Supplies a pointer to the set of signals to return to
  709. their default dispositions in the child.
  710. Return Value:
  711. 0 on success (always).
  712. Returns an error number on failure.
  713. --*/
  714. {
  715. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  716. SpawnAttributes = *Attributes;
  717. SpawnAttributes->DefaultMask = *DefaultSignals;
  718. return 0;
  719. }
  720. LIBC_API
  721. int
  722. posix_spawnattr_setsigmask (
  723. posix_spawnattr_t *Attributes,
  724. const sigset_t *Mask
  725. )
  726. /*++
  727. Routine Description:
  728. This routine sets the current signal mask on a set of spawn attributes.
  729. Arguments:
  730. Attributes - Supplies a pointer to the initialized attributes.
  731. Mask - Supplies a pointer to the signal mask to set in the child.
  732. Return Value:
  733. 0 on success (always).
  734. Returns an error number on failure.
  735. --*/
  736. {
  737. PPOSIX_SPAWN_ATTRIBUTES SpawnAttributes;
  738. SpawnAttributes = *Attributes;
  739. SpawnAttributes->SignalMask = *Mask;
  740. return 0;
  741. }
  742. //
  743. // --------------------------------------------------------- Internal Functions
  744. //
  745. INT
  746. ClpPosixSpawn (
  747. pid_t *ChildPid,
  748. const char *Path,
  749. PPOSIX_SPAWN_FILE_ACTION *FileActions,
  750. PPOSIX_SPAWN_ATTRIBUTES *Attributes,
  751. char *const Arguments[],
  752. char *const Environment[],
  753. BOOL UsePath
  754. )
  755. /*++
  756. Routine Description:
  757. This routine executes the posix spawn function.
  758. Arguments:
  759. ChildPid - Supplies an optional pointer where the child process ID will be
  760. returned on success.
  761. Path - Supplies a pointer to the file path to execute.
  762. FileActions - Supplies an optional pointer to the file actions to execute
  763. in the child.
  764. Attributes - Supplies an optional pointer to the spawn attributes.
  765. Arguments - Supplies the arguments to pass to the new child.
  766. Environment - Supplies the environment to pass to the new child.
  767. UsePath - Supplies a boolean indicating whether to use the exec*p functions
  768. to find the path of the executable or just the regular exec function.
  769. Return Value:
  770. 0 on success.
  771. Returns an error number on failure.
  772. --*/
  773. {
  774. volatile int Error;
  775. pid_t Pid;
  776. //
  777. // TODO: Use vfork when it is implemented.
  778. //
  779. Error = 0;
  780. Pid = fork();
  781. if (Pid == -1) {
  782. return errno;
  783. //
  784. // In the child, process the attributes and execute the image. With vfork,
  785. // the values set in error here will be accessible by the parent, since
  786. // vfork temporarily shares the memory of the parent.
  787. //
  788. } else if (Pid == 0) {
  789. if (Attributes != NULL) {
  790. Error = ClpProcessSpawnAttributes(*Attributes);
  791. if (Error != 0) {
  792. _exit(127);
  793. }
  794. }
  795. if (FileActions != NULL) {
  796. Error = ClpProcessSpawnFileActions(*FileActions);
  797. if (Error != 0) {
  798. _exit(127);
  799. }
  800. }
  801. if (Environment == NULL) {
  802. Environment = environ;
  803. }
  804. if (UsePath != FALSE) {
  805. execvpe(Path, Arguments, Environment);
  806. } else {
  807. execve(Path, Arguments, Environment);
  808. }
  809. //
  810. // Oops, getting this far means exec didn't succeed. Fail.
  811. //
  812. Error = errno;
  813. _exit(127);
  814. //
  815. // In the parent, just return the child.
  816. //
  817. } else {
  818. //
  819. // If the child had a problem, then with vfork the error variable will
  820. // be set, and this routine can return a more detailed status. Reap the
  821. // child here.
  822. //
  823. if (Error != 0) {
  824. waitpid(Pid, NULL, 0);
  825. } else {
  826. if (ChildPid != NULL) {
  827. *ChildPid = Pid;
  828. }
  829. }
  830. }
  831. return Error;
  832. }
  833. INT
  834. ClpProcessSpawnAttributes (
  835. PPOSIX_SPAWN_ATTRIBUTES Attributes
  836. )
  837. /*++
  838. Routine Description:
  839. This routine performs the actions specified by the given posix spawn
  840. attributes.
  841. Arguments:
  842. Attributes - Supplies a pointer to the attributes to put into effect.
  843. Return Value:
  844. 0 on success.
  845. Returns an error number on failure.
  846. --*/
  847. {
  848. struct sigaction Action;
  849. int Signal;
  850. if ((Attributes->Flags & POSIX_SPAWN_SETPGROUP) != 0) {
  851. if (setpgid(0, Attributes->ProcessGroup) != 0) {
  852. return errno;
  853. }
  854. }
  855. //
  856. // TODO: Set the scheduler policy and scheduler parameter.
  857. //
  858. if ((Attributes->Flags & POSIX_SPAWN_RESETIDS) != 0) {
  859. if (setegid(getgid()) != 0) {
  860. return errno;
  861. }
  862. if (seteuid(getuid()) != 0) {
  863. return errno;
  864. }
  865. }
  866. if ((Attributes->Flags & POSIX_SPAWN_SETSIGMASK) != 0) {
  867. if (sigprocmask(SIG_SETMASK, &(Attributes->SignalMask), NULL) != 0) {
  868. return errno;
  869. }
  870. }
  871. //
  872. // If desired, reset any signals mentioned in the default mask back to
  873. // the default disposition.
  874. //
  875. if ((Attributes->Flags & POSIX_SPAWN_SETSIGDEF) != 0) {
  876. memset(&Action, 0, sizeof(Action));
  877. Action.sa_handler = SIG_DFL;
  878. for (Signal = 1; Signal < NSIG; Signal += 1) {
  879. if (sigismember(&(Attributes->DefaultMask), Signal) != 0) {
  880. if (sigaction(Signal, &Action, NULL) != 0) {
  881. return errno;
  882. }
  883. }
  884. }
  885. }
  886. return 0;
  887. }
  888. INT
  889. ClpProcessSpawnFileActions (
  890. PPOSIX_SPAWN_FILE_ACTION Actions
  891. )
  892. /*++
  893. Routine Description:
  894. This routine performs the actions specified by the given posix spawn
  895. file actions.
  896. Arguments:
  897. Actions - Supplies a pointer to the actions to perform.
  898. Return Value:
  899. 0 on success.
  900. Returns an error number on failure.
  901. --*/
  902. {
  903. PLIST_ENTRY CurrentEntry;
  904. INT Descriptor;
  905. PPOSIX_SPAWN_FILE_ENTRY Entry;
  906. CurrentEntry = Actions->EntryList.Next;
  907. while (CurrentEntry != &(Actions->EntryList)) {
  908. Entry = LIST_VALUE(CurrentEntry, POSIX_SPAWN_FILE_ENTRY, ListEntry);
  909. CurrentEntry = CurrentEntry->Next;
  910. switch (Entry->Action) {
  911. case SpawnActionOpen:
  912. Descriptor = open(Entry->U.Open.Path,
  913. Entry->U.Open.OpenFlags,
  914. Entry->U.Open.CreateMode);
  915. if (Descriptor < 0) {
  916. return errno;
  917. }
  918. if (Descriptor != Entry->U.Open.Descriptor) {
  919. if (dup2(Descriptor, Entry->U.Open.Descriptor) < 0) {
  920. close(Descriptor);
  921. return errno;
  922. }
  923. close(Descriptor);
  924. }
  925. break;
  926. case SpawnActionDup2:
  927. if (dup2(Entry->U.Dup2.Descriptor, Entry->U.Dup2.NewDescriptor) <
  928. 0) {
  929. return errno;
  930. }
  931. if (fcntl(Entry->U.Dup2.NewDescriptor, F_SETFD, 0) < 0) {
  932. return errno;
  933. }
  934. break;
  935. case SpawnActionClose:
  936. close(Entry->U.Close.Descriptor);
  937. break;
  938. default:
  939. assert(FALSE);
  940. return EINVAL;
  941. }
  942. }
  943. return 0;
  944. }