int my_shell(char *cmd, char *result, int size) { HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStderrRd, hChildStderrWr, hSaveStdin, hSaveStdout, hSaveStderr; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; char buffer[10000]; DWORD dwRead, dwAvail, i; /* Set the bInheritHandle flag so pipe handles are inherited. */ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* Save the handle to the current STDOUT. */ hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); /* Create a pipe for the child's STDOUT. */ if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) return 0; /* Set a write handle to the pipe to be STDOUT. */ if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) return 0; /* Save the handle to the current STDERR. */ hSaveStderr = GetStdHandle(STD_ERROR_HANDLE); /* Create a pipe for the child's STDERR. */ if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0)) return 0; /* Set a read handle to the pipe to be STDERR. */ if (!SetStdHandle(STD_ERROR_HANDLE, hChildStderrWr)) return 0; /* Save the handle to the current STDIN. */ hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); /* Create a pipe for the child's STDIN. */ if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) return 0; /* Set a read handle to the pipe to be STDIN. */ if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) return 0; /* Duplicate the write handle to the pipe so it is not inherited. */ if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS)) return 0; CloseHandle(hChildStdinWr); /* Now create the child process. */ memset(&siStartInfo, 0, sizeof(siStartInfo)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.lpReserved = NULL; siStartInfo.lpReserved2 = NULL; siStartInfo.cbReserved2 = 0; siStartInfo.lpDesktop = NULL; siStartInfo.dwFlags = 0; /* command to execute */ sprintf(buffer, "cmd /q /c %s", cmd); if (!CreateProcess(NULL, buffer, /* command line */ NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ 0, /* creation flags */ NULL, /* use parent's environment */ NULL, /* use parent's current directory */ &siStartInfo, /* STARTUPINFO pointer */ &piProcInfo)) /* receives PROCESS_INFORMATION */ return 0; /* After process creation, restore the saved STDIN and STDOUT. */ SetStdHandle(STD_INPUT_HANDLE, hSaveStdin); SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout); SetStdHandle(STD_ERROR_HANDLE, hSaveStderr); memset(result, 0, size); do { /* query stdout */ do { if (!PeekNamedPipe(hChildStdoutRd, buffer, 256, &dwRead, &dwAvail, NULL)) break; if (dwRead > 0) { ReadFile(hChildStdoutRd, buffer, 256, &dwRead, NULL); buffer[dwRead] = 0; strlcat(result, buffer, size); } } while (dwAvail > 0); /* query stderr */ do { if (!PeekNamedPipe(hChildStderrRd, buffer, 256, &dwRead, &dwAvail, NULL)) break; if (dwRead > 0) { ReadFile(hChildStderrRd, buffer, 256, &dwRead, NULL); buffer[dwRead] = 0; strlcat(result, buffer, size); } } while (dwAvail > 0); /* check if subprocess still alive */ if (!GetExitCodeProcess(piProcInfo.hProcess, &i)) break; if (i != STILL_ACTIVE) break; /* give some CPU to subprocess */ Sleep(10); } while (TRUE); CloseHandle(hChildStdinWrDup); CloseHandle(hChildStdinRd); CloseHandle(hChildStderrRd); CloseHandle(hChildStdoutRd); /* strip trailing CR/LF */ while (strlen(result) > 0 && (result[strlen(result) - 1] == '\r' || result[strlen(result) - 1] == '\n')) result[strlen(result) - 1] = 0; return 1; }