9 static void whelk_close_pipe(HANDLE pipe[2])
15 /* Create a pipe with one end inheritable */
17 static BOOL whelk_child_pipe(HANDLE pipe[2],BOOL to_child)
19 SECURITY_ATTRIBUTES sa={0};
21 sa.nLength=sizeof(sa);
22 sa.bInheritHandle=TRUE;
23 if (!CreatePipe(pipe+0,pipe+1,&sa,0))
25 if (!DuplicateHandle(GetCurrentProcess(),pipe[to_child?0:1],
26 GetCurrentProcess(),&h,0,TRUE,DUPLICATE_SAME_ACCESS))
28 whelk_close_pipe(pipe);
31 CloseHandle(pipe[to_child?0:1]);
37 * spawn(application_name,command-line,working-directory,standard-input)
39 * Returns two strings (the data written to standard output and standard error
40 * respectively) and the exit code.
43 int whelk_spawn(lua_State *L)
46 PROCESS_INFORMATION pi={0};
47 WCHAR *application_name=whelk_utf8_to_utf16(luaL_checkstring(L,1),-1);
48 WCHAR *command_line=whelk_utf8_to_utf16(luaL_checkstring(L,2),-1);
49 WCHAR *working_directory=whelk_utf8_to_utf16(luaL_checkstring(L,3),-1);
51 const char *standard_input=luaL_checklstring(L,4,&stdin_len);
52 struct whelk_string standard_output={0};
53 struct whelk_string standard_error={0};
55 HANDLE stdin_pipe[2],stdout_pipe[2],stderr_pipe[2],h;
56 struct whelk_wait wait={0};
59 if (!whelk_child_pipe(stdin_pipe,TRUE))
61 free(application_name);
63 free(working_directory);
65 return whelk_perror(L,NULL);
67 if (!whelk_child_pipe(stdout_pipe,FALSE))
69 free(application_name);
71 free(working_directory);
72 whelk_close_pipe(stdin_pipe);
74 return whelk_perror(L,NULL);
76 if (!whelk_child_pipe(stderr_pipe,FALSE))
78 free(application_name);
80 free(working_directory);
81 whelk_close_pipe(stdin_pipe);
82 whelk_close_pipe(stdout_pipe);
84 return whelk_perror(L,NULL);
87 si.dwFlags=STARTF_USESTDHANDLES;
88 si.hStdInput=stdin_pipe[0];
89 si.hStdOutput=stdout_pipe[1];
90 si.hStdError=stderr_pipe[1];
91 if (!CreateProcessW(application_name,command_line,NULL,NULL,TRUE,
92 CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS,NULL,working_directory,
95 free(application_name);
97 free(working_directory);
98 whelk_close_pipe(stdin_pipe);
99 whelk_close_pipe(stdout_pipe);
100 whelk_close_pipe(stderr_pipe);
102 return whelk_perror(L,NULL);
104 free(application_name);
106 free(working_directory);
107 CloseHandle(stdout_pipe[1]);
108 CloseHandle(stderr_pipe[1]);
109 whelk_wait_add_object(&wait,stdout_pipe[0]);
110 whelk_wait_add_object(&wait,stderr_pipe[0]);
111 whelk_wait_add_object(&wait,pi.hProcess);
113 whelk_wait_add_object(&wait,stdin_pipe[1]);
116 whelk_close_pipe(stdin_pipe);
117 stdin_pipe[1]=INVALID_HANDLE_VALUE;
121 h=whelk_wait_poll(&wait);
122 if (h==INVALID_HANDLE_VALUE)
124 else if (h==stdout_pipe[0])
126 buffer=whelk_string_prealloc(&standard_output,1024);
127 if (ReadFile(stdout_pipe[0],buffer,1024,&nb,NULL))
128 whelk_string_seek(&standard_output,nb);
130 whelk_wait_remove_object(&wait,stdout_pipe[0]);
132 else if (h==stderr_pipe[0])
134 buffer=whelk_string_prealloc(&standard_error,1024);
135 if (ReadFile(stderr_pipe[0],buffer,1024,&nb,NULL))
136 whelk_string_seek(&standard_error,nb);
138 whelk_wait_remove_object(&wait,stderr_pipe[0]);
140 else if (h==pi.hProcess)
142 else if (h==stdin_pipe[1])
144 nb=max(stdin_len,512);
145 WriteFile(stdin_pipe[1],standard_input,nb,NULL,NULL);
150 whelk_wait_remove_object(&wait,stdin_pipe[1]);
151 whelk_close_pipe(stdin_pipe);
156 whelk_wait_free(&wait);
158 whelk_close_pipe(stdin_pipe);
159 if (GetExitCodeProcess(pi.hProcess,&nb))
163 CloseHandle(pi.hThread);
164 CloseHandle(pi.hProcess);
165 CloseHandle(stdout_pipe[0]);
166 CloseHandle(stderr_pipe[0]);
167 whelk_string_finalize(&standard_output);
168 whelk_string_finalize(&standard_error);
169 lua_pushlstring(L,standard_output.buffer,standard_output.len);
170 lua_pushlstring(L,standard_error.buffer,standard_error.len);
171 whelk_string_free(&standard_output);
172 whelk_string_free(&standard_error);
173 lua_pushnumber(L,exitcode);