Skip to content

Commit 9410f77

Browse files
authored
Merge pull request #208 from bgamari/wip/refactor
Refactoring of POSIX process logic
2 parents 7010ac3 + c7e5b06 commit 9410f77

15 files changed

+857
-414
lines changed

System/Process/Posix.hs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,20 @@ createProcess_Internal fun
139139
when mb_delegate_ctlc
140140
startDelegateControlC
141141

142+
let flags = (if mb_close_fds then RUN_PROCESS_IN_CLOSE_FDS else 0)
143+
.|.(if mb_create_group then RUN_PROCESS_IN_NEW_GROUP else 0)
144+
.|.(if mb_detach_console then RUN_PROCESS_DETACHED else 0)
145+
.|.(if mb_create_new_console then RUN_PROCESS_NEW_CONSOLE else 0)
146+
.|.(if mb_new_session then RUN_PROCESS_NEW_SESSION else 0)
147+
.|.(if mb_delegate_ctlc then RESET_INT_QUIT_HANDLERS else 0)
148+
142149
-- See the comment on runInteractiveProcess_lock
143150
proc_handle <- withMVar runInteractiveProcess_lock $ \_ ->
144151
c_runInteractiveProcess pargs pWorkDir pEnv
145152
fdin fdout fderr
146153
pfdStdInput pfdStdOutput pfdStdError
147154
pChildGroup pChildUser
148-
(if mb_delegate_ctlc then 1 else 0)
149-
((if mb_close_fds then RUN_PROCESS_IN_CLOSE_FDS else 0)
150-
.|.(if mb_create_group then RUN_PROCESS_IN_NEW_GROUP else 0)
151-
.|.(if mb_detach_console then RUN_PROCESS_DETACHED else 0)
152-
.|.(if mb_create_new_console then RUN_PROCESS_NEW_CONSOLE else 0)
153-
.|.(if mb_new_session then RUN_PROCESS_NEW_SESSION else 0))
155+
flags
154156
pFailedDoing
155157

156158
when (proc_handle == -1) $ do
@@ -273,7 +275,6 @@ foreign import ccall unsafe "runInteractiveProcess"
273275
-> Ptr FD
274276
-> Ptr CGid
275277
-> Ptr CUid
276-
-> CInt -- reset child's SIGINT & SIGQUIT handlers
277278
-> CInt -- flags
278279
-> Ptr CString
279280
-> IO PHANDLE

cbits/posix/common.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include "runProcess.h"
4+
5+
enum std_handle_behavior {
6+
// Close the handle
7+
STD_HANDLE_CLOSE,
8+
// dup2 the specified fd to standard handle
9+
STD_HANDLE_USE_FD,
10+
// dup2 the appropriate end of the given pipe to the standard handle and
11+
// close the other end.
12+
STD_HANDLE_USE_PIPE
13+
};
14+
15+
struct std_handle {
16+
enum std_handle_behavior behavior;
17+
union {
18+
int use_fd;
19+
struct {
20+
int parent_end, child_end;
21+
} use_pipe;
22+
};
23+
};
24+
25+
int get_max_fd(void);
26+
27+
// defined in find_executable.c
28+
#if !defined(HAVE_execvpe)
29+
char *find_executable(char *filename);
30+
#endif
31+
32+
// defined in fork_exec.c
33+
ProcHandle
34+
do_spawn_fork (char *const args[],
35+
char *workingDirectory, char **environment,
36+
struct std_handle *stdInHdl,
37+
struct std_handle *stdOutHdl,
38+
struct std_handle *stdErrHdl,
39+
gid_t *childGroup, uid_t *childUser,
40+
int flags,
41+
char **failed_doing);
42+
43+
// defined in posix_spawn.c
44+
ProcHandle
45+
do_spawn_posix (char *const args[],
46+
char *workingDirectory, char **environment,
47+
struct std_handle *stdInHdl,
48+
struct std_handle *stdOutHdl,
49+
struct std_handle *stdErrHdl,
50+
gid_t *childGroup, uid_t *childUser,
51+
int flags,
52+
char **failed_doing);

cbits/posix/find_executable.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* ----------------------------------------------------------------------------
2+
* search path search logic
3+
* (c) Ben Gamari 2021
4+
*/
5+
6+
#include <string.h>
7+
#include <unistd.h>
8+
#include <stdlib.h>
9+
#include <stdio.h>
10+
#include <stdbool.h>
11+
12+
#include "common.h"
13+
14+
// the below is only necessary when we don't have execvpe.
15+
#if !defined(HAVE_execvpe)
16+
17+
/* Return true if the given file exists and is an executable. */
18+
static bool is_executable(const char *path) {
19+
return access(path, X_OK) == 0;
20+
}
21+
22+
/* Find an executable with the given filename in the given search path. The
23+
* result must be freed by the caller. Returns NULL if a matching file is not
24+
* found.
25+
*/
26+
static char *find_in_search_path(char *search_path, const char *filename) {
27+
const int filename_len = strlen(filename);
28+
char *tokbuf;
29+
char *path = strtok_r(search_path, ":", &tokbuf);
30+
while (path != NULL) {
31+
const int tmp_len = filename_len + 1 + strlen(path) + 1;
32+
char *tmp = malloc(tmp_len);
33+
snprintf(tmp, tmp_len, "%s/%s", path, filename);
34+
if (is_executable(tmp)) {
35+
return tmp;
36+
} else {
37+
free(tmp);
38+
}
39+
40+
path = strtok_r(NULL, ":", &tokbuf);
41+
}
42+
return NULL;
43+
}
44+
45+
/* Identify the executable search path. The result must be freed by the caller. */
46+
static char *get_executable_search_path(void) {
47+
char *search_path;
48+
49+
search_path = getenv("PATH");
50+
if (search_path) {
51+
search_path = strdup(search_path);
52+
return search_path;
53+
}
54+
55+
#if defined(HAVE_CONFSTR)
56+
int len = confstr(_CS_PATH, NULL, 0);
57+
search_path = malloc(len + 1)
58+
if (search_path != NULL) {
59+
search_path[0] = ':';
60+
(void) confstr (_CS_PATH, search_path + 1, len);
61+
return search_path;
62+
}
63+
#endif
64+
65+
return strdup(":");
66+
}
67+
68+
/* Find the given executable in the executable search path. */
69+
char *find_executable(char *filename) {
70+
/* If it's an absolute or relative path name, it's easy. */
71+
if (strchr(filename, '/') && is_executable(filename)) {
72+
return filename;
73+
}
74+
75+
char *search_path = get_executable_search_path();
76+
return find_in_search_path(search_path, filename);
77+
}
78+
79+
#endif

0 commit comments

Comments
 (0)