diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index be3677c6..e558a61f 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -1120,7 +1120,7 @@ B sh_c2(B t, B w, B x) { bool any = false; if (ps[out_i].revents & POLLIN) while(true) { i64 len = read(p_out[0], &oBuf[0], bufsz); shDbg("read stdout "N64d"\n",len); if(len<=0) break; else any=true; *oBufIA = len; s_out = vec_join(s_out, incG(oBufObj)); } if (ps[err_i].revents & POLLIN) while(true) { i64 len = read(p_err[0], &oBuf[0], bufsz); shDbg("read stderr "N64d"\n",len); if(len<=0) break; else any=true; *oBufIA = len; s_err = vec_join(s_err, incG(oBufObj)); } - if (!iDone && ps[in_i].revents & POLLOUT) { + if (!iDone && ps[in_i].revents & POLLOUT) { shDbg("writing "N64u"\n", iLen-iOff); ssize_t ww = write(p_in[1], iBuf+iOff, iLen-iOff); shDbg("written %zd/"N64u"\n", ww, iLen-iOff); @@ -1228,16 +1228,18 @@ B sh_c2(B t, B w, B x) { } } else iBuf = ""; + // run command DWORD code = -1; u64 oLen = 0; char* oBuf; u64 eLen = 0; char* eBuf; DWORD dwResult = winCmd(arg, iLen, iBuf, &code, &oLen, &oBuf, &eLen, &eBuf); if (iLen>0) { if (raw) free_chars(iBufRaw); else TFREE(iBuf); } // FREE_INPUT TFREE(arg) - if (dwResult != ERROR_SUCCESS) { + if (dwResult != ERROR_SUCCESS) { thrF("•SH: Failed to run command: %S", winErrorEx(dwResult)); } + // prepare output u8* op; B s_out = m_c8arrv(&op, oLen); if (oLen > 0 && oBuf != NULL) { diff --git a/src/windows/sh.c b/src/windows/sh.c index 763f4ffe..56654a53 100644 --- a/src/windows/sh.c +++ b/src/windows/sh.c @@ -44,14 +44,18 @@ static char* winQuoteCmdArg(u64 len, char* source, char* target) { return target; } -char *dataInp, *dataOut, *dataErr; -u64 sizeInp, sizeOut, sizeErr; +typedef struct { + HANDLE hndl; + char* buf; + u64 len; +} ThreadIO; -static DWORD WINAPI winThreadWriteIn(LPVOID arg) { +static DWORD WINAPI winThreadWrite(LPVOID arg0) { DWORD dwResult = ERROR_SUCCESS; - HANDLE hndl = (HANDLE)arg; - char *wBuf = dataInp; - DWORD dwToWrite = sizeInp, dwWritten = 0, dwOff = 0; + ThreadIO* arg = arg0; + HANDLE hndl = arg->hndl; + char* wBuf = arg->buf; + DWORD dwToWrite = arg->len, dwWritten = 0, dwOff = 0; for (;;) { BOOL bOk = WriteFile(hndl, &wBuf[dwOff], dwToWrite-dwOff, &dwWritten, NULL); @@ -64,41 +68,42 @@ static DWORD WINAPI winThreadWriteIn(LPVOID arg) { return dwResult; } -#define winThreadRead(D) \ -static DWORD WINAPI winThreadRead##D(LPVOID arg) { \ - DWORD dwResult = ERROR_SUCCESS; \ - HANDLE hndl = (HANDLE)arg; \ - u8 buf[1024] = {0}; \ - const usz bufSize = sizeof(buf)/sizeof(u8); \ - DWORD dwRead = 0, dwHasRead = 0; \ - char *rBuf = NULL; \ - for (;;) { \ - ZeroMemory(buf, bufSize); \ - BOOL bOk = ReadFile(hndl, buf, bufSize, &dwRead, NULL); \ - if (!bOk) { \ - DWORD dwErr = GetLastError(); \ - if (dwErr == ERROR_BROKEN_PIPE) { break; } \ - else { dwResult = dwErr; break; } \ - } \ - char *newBuf = (rBuf==NULL)? \ - calloc(dwHasRead+dwRead, sizeof(char)) : \ - realloc(rBuf, (dwHasRead+dwRead)*sizeof(char)); \ - if (newBuf == NULL) { dwResult = GetLastError(); break; } \ - rBuf = newBuf; \ - memcpy(&rBuf[dwHasRead], buf, dwRead); \ - dwHasRead += dwRead; \ - } \ - data##D = rBuf; \ - size##D = dwHasRead; \ - CloseHandle(hndl); \ - return dwResult; \ +static DWORD WINAPI winThreadRead(LPVOID arg0) { + DWORD dwResult = ERROR_SUCCESS; + ThreadIO* arg = arg0; + HANDLE hndl = arg->hndl; + u8 buf[1024] = {0}; + const usz bufSize = sizeof(buf)/sizeof(u8); + DWORD dwRead = 0, dwHasRead = 0; + char* rBuf = NULL; + + for (;;) { + ZeroMemory(buf, bufSize); + BOOL bOk = ReadFile(hndl, buf, bufSize, &dwRead, NULL); + if (!bOk) { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_BROKEN_PIPE) { break; } + else { dwResult = dwErr; break; } + } + char* newBuf = (rBuf==NULL)? + calloc(dwHasRead+dwRead, sizeof(char)) : + realloc(rBuf, (dwHasRead+dwRead)*sizeof(char)); + if (newBuf == NULL) { dwResult = GetLastError(); break; } + rBuf = newBuf; + memcpy(&rBuf[dwHasRead], buf, dwRead); + dwHasRead += dwRead; + } + + if (dwResult != ERROR_SUCCESS) { + if (dwHasRead > 0 && rBuf != NULL) { free(rBuf); } + } else { + arg->buf = rBuf; + arg->len = dwHasRead; + } + CloseHandle(hndl); + return dwResult; } -winThreadRead(Out) -winThreadRead(Err) - -#undef winThreadRead - static DWORD winCmd(char* arg, u64 iLen, char* iBuf, DWORD* code, @@ -131,7 +136,7 @@ static DWORD winCmd(char* arg, si.hStdInput = hInpR; si.hStdOutput = hOutW; si.hStdError = hErrW; - si.dwFlags |= STARTF_USESTDHANDLES | STARTF_UNTRUSTEDSOURCE; + si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); @@ -145,18 +150,16 @@ static DWORD winCmd(char* arg, CloseHandle(hOutW); CloseHandle(hErrW); - // Now we are dealing with the globals and threads - - - - dataInp = iBuf; - sizeInp = iLen; + // Spawn the thread to deal with redirected io + ThreadIO data0 = {hInpW, iBuf, iLen}; + ThreadIO data1 = {hOutR, NULL, 0}; + ThreadIO data2 = {hErrR, NULL, 0}; DWORD exitCode = -1; HANDLE lpThreads[3]; - lpThreads[0] = CreateThread(NULL, 0, winThreadWriteIn, (LPVOID)hInpW, 0, NULL); - lpThreads[1] = CreateThread(NULL, 0, winThreadReadOut, (LPVOID)hOutR, 0, NULL); - lpThreads[2] = CreateThread(NULL, 0, winThreadReadErr, (LPVOID)hErrR, 0, NULL); + lpThreads[0] = CreateThread(NULL, 0, winThreadWrite, (LPVOID)&data0, 0, NULL); + lpThreads[1] = CreateThread(NULL, 0, winThreadRead, (LPVOID)&data1, 0, NULL); + lpThreads[2] = CreateThread(NULL, 0, winThreadRead, (LPVOID)&data2, 0, NULL); for (int i = 0; i < 3; ++i) { if (lpThreads[i] == NULL) { dwResult = GetLastError(); goto error; } @@ -180,8 +183,8 @@ static DWORD winCmd(char* arg, // Give outputs *code = exitCode; - *oLen = sizeOut; *oBuf = dataOut; - *eLen = sizeErr; *eBuf = dataErr; + *oLen = data1.len; *oBuf = data1.buf; + *eLen = data2.len; *eBuf = data2.buf; error: // Close handles @@ -189,7 +192,5 @@ error: CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - - return dwResult; }