@@ -56,8 +56,25 @@ public func posix_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool
5656 dup2 (stderr_pipe[1 ], 2 )
5757 close (stderr_pipe[1 ])
5858 } else {}
59+ // stdin_data: create a temporary pipe in the child, write data, then dup2 to fd 0.
60+ // This is done in the child so the parent doesn't need a separate pipe.
61+ if (cfg.stdin_data.size () > 0 ) {
62+ unsafe var stdin_pipe_tmp : [2 ]int
63+ pipe (&raw mut stdin_pipe_tmp[0 ])
64+ // Write data to the pipe write end in the child, then close it.
65+ var written = write (stdin_pipe_tmp[1 ], cfg.stdin_data.data () as *void, cfg.stdin_data.size ())
66+ close (stdin_pipe_tmp[1 ])
67+ dup2 (stdin_pipe_tmp[0 ], 0 )
68+ close (stdin_pipe_tmp[0 ])
69+ } else {}
5970 var argv = build_argv (&raw mut cfg.args);
60- execvp (argv.ptrs[0 ], &raw argv.ptrs[0 ]);
71+ // If env vars are provided, use execve() with custom environment.
72+ if (cfg.env.size () > 0 ) {
73+ var envp = build_envp (&raw mut cfg.env);
74+ execve (argv.ptrs[0 ], &raw argv.ptrs[0 ], &raw envp.ptrs[0 ]);
75+ } else {
76+ execvp (argv.ptrs[0 ], &raw argv.ptrs[0 ]);
77+ }
6178 _exit (1 );
6279 } else {}
6380
@@ -94,7 +111,28 @@ public func posix_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool
94111 } else {}
95112
96113 var status : int = 0 ;
97- waitpid (pid, &raw mut status, 0 );
114+ var timed_out = false
115+ if (cfg.timeout_ms > 0 ) {
116+ // Poll with timeout: sleep in 10ms increments
117+ var elapsed : int = 0
118+ while (elapsed < cfg.timeout_ms) {
119+ var ret = waitpid (pid, &raw mut status, 1 ) // WNOHANG
120+ if (ret != 0 ) { break }
121+ usleep (10000 ) // 10ms
122+ elapsed += 10
123+ }
124+ if (elapsed >= cfg.timeout_ms) {
125+ // Check one more time
126+ var ret = waitpid (pid, &raw mut status, 1 )
127+ if (ret == 0 ) {
128+ timed_out = true
129+ kill (pid, 9 ) // SIGKILL
130+ waitpid (pid, &raw mut status, 0 )
131+ }
132+ }
133+ } else {
134+ waitpid (pid, &raw mut status, 0 )
135+ }
98136
99137 var exit_code : int = 0 ;
100138 var signaled : bool = false;
@@ -108,7 +146,7 @@ public func posix_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool
108146 out.status.code = exit_code;
109147 out.status.signaled = signaled;
110148 out.status.signal = signal_no;
111- out.success = (exit_code == 0 && ! signaled);
149+ out.success = (exit_code == 0 && ! signaled && ! timed_out );
112150 return true
113151}
114152
@@ -151,7 +189,12 @@ public func posix_spawn(cfg : *ProcessConfig, child : *mut ChildProcess) : bool
151189 // Child reads from stdin_pipe[0]; parent writes to stdin_pipe[1].
152190 close (stdin_pipe[1 ]); dup2 (stdin_pipe[0 ], 0 ); close (stdin_pipe[0 ]);
153191 var argv = build_argv (&raw mut cfg.args);
154- execvp (argv.ptrs[0 ], &raw argv.ptrs[0 ]);
192+ if (cfg.env.size () > 0 ) {
193+ var envp = build_envp (&raw mut cfg.env);
194+ execve (argv.ptrs[0 ], &raw argv.ptrs[0 ], &raw envp.ptrs[0 ]);
195+ } else {
196+ execvp (argv.ptrs[0 ], &raw argv.ptrs[0 ]);
197+ }
155198 _exit (1 );
156199 } else {}
157200
@@ -230,6 +273,18 @@ func build_argv(args : *vector<string>) : ArgvBuffer {
230273 return buf;
231274}
232275
276+ func build_envp (env : *vector<string>) : ArgvBuffer {
277+ unsafe var buf : ArgvBuffer;
278+ buf.count = env.size ();
279+ var i : size_t = 0 ;
280+ while (i < env.size ()) {
281+ buf.ptrs[i] = env.get_ptr (i).data ()
282+ i += 1 ;
283+ }
284+ buf.ptrs[i] = null;
285+ return buf;
286+ }
287+
233288func read_all_fd (fd : int, data : *mut vector<u8>) : bool {
234289 unsafe var buf : [4096 ]u8;
235290 while (true) {
@@ -252,6 +307,7 @@ func read_all_fd(fd : int, data : *mut vector<u8>) : bool {
252307@ extern public func fork () : int
253308@ extern public func dup2 (oldfd : int, newfd : int) : int
254309@ extern public func execvp (file : *char, argv : **char) : int
310+ @ extern public func execve (file : *char, argv : **char, envp : **char) : int
255311@ extern public func waitpid (pid : int, status : *mut int, options : int) : int
256312@ extern public func _exit (status : int)
257313@ extern public func close (fd : int) : int
@@ -260,6 +316,7 @@ func read_all_fd(fd : int, data : *mut vector<u8>) : bool {
260316@ extern public func getpid () : int
261317@ extern public func usleep (usec : int) : int
262318@ extern public func chdir (path : *char) : int
319+ @ extern public func kill (pid : int, sig : int) : int
263320
264321const _WIFEXITED_MASK = 0x7f ;
265322func WIFEXITED (status : int) : bool { return (status & _WIFEXITED_MASK) == 0 ; }
0 commit comments