Created
June 7, 2023 01:22
-
-
Save opsJson/515644eff27b29ad91b79522ca3b2c40 to your computer and use it in GitHub Desktop.
Pipe output of any command line program to buffer in C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CMDL_H_ | |
#define CMDL_H_ | |
#ifdef _WIN32 | |
#include <windows.h> | |
static const char *cmdl_errlist[] = { | |
"No Error.", | |
"CreatePipe() failed: could not create a pipe.", | |
"CreateProcessA() failed: could not create child process.", | |
"CloseHandle() failed: could not close write end of pipe.", | |
"CloseHandle() failed: could not close read end of pipe.", | |
"CloseHandle() failed: could not close thread.", | |
"CloseHandle() failed: could not close process.", | |
}; | |
static const unsigned int cmdl_errlist_size = sizeof(cmdl_errlist)/sizeof(cmdl_errlist[0]); | |
static unsigned int cmdl_errno = 0; | |
const char *cmdl_strerror(void) { | |
if (cmdl_errno >= cmdl_errlist_size) return "Invalid Error."; | |
return cmdl_errlist[cmdl_errno]; | |
} | |
int cmdl_win32(char *command, char *buffer, int size) { | |
HANDLE pipefd[2]; | |
STARTUPINFOA si = {0}; | |
PROCESS_INFORMATION pi = {0}; | |
SECURITY_ATTRIBUTES sa = {0}; | |
DWORD bytes; | |
sa.nLength = sizeof(sa); | |
sa.lpSecurityDescriptor = 0; | |
sa.bInheritHandle = 1; | |
if (!CreatePipe(&pipefd[0], &pipefd[1], &sa, 0)) { | |
cmdl_errno = 1; | |
return 0; | |
} | |
si.cb = sizeof(si); | |
si.hStdOutput = pipefd[1]; | |
si.dwFlags = STARTF_USESTDHANDLES; | |
if (!CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { | |
cmdl_errno = 2; | |
return 0; | |
} | |
if (!CloseHandle(pipefd[1])) { | |
cmdl_errno = 3; | |
return 0; | |
} | |
while (size) { | |
if (!ReadFile(pipefd[0], buffer, size, &bytes, NULL)) break; | |
buffer += bytes; | |
size -= bytes; | |
} | |
if (!CloseHandle(pipefd[0])) { | |
cmdl_errno = 4; | |
return 0; | |
} | |
if (!CloseHandle(pi.hThread)) { | |
cmdl_errno = 5; | |
return 0; | |
} | |
if (!CloseHandle(pi.hProcess)) { | |
cmdl_errno = 6; | |
return 0; | |
} | |
return 1; | |
} | |
#define cmdl cmdl_win32 | |
#else | |
#include <unistd.h> | |
#include <sys/types.h> | |
static const char *cmdl_errlist[] = { | |
"No Error.", | |
"pipe() failed: could not create a pipe.", | |
"fork() failed: could fork the process.", | |
"close() failed: could close the read end of child process.", | |
"dup2() failed: could reopen the write end of child process as parent stdout.", | |
"close() failed: could close the old write end of child process.", | |
"execlp() failed: could not execute command.", | |
"close() failed: could close the write end of parent process.", | |
"read() failed: could read from child process.", | |
}; | |
static const unsigned int cmdl_errlist_size = sizeof(cmdl_errlist)/sizeof(cmdl_errlist[0]); | |
static unsigned int cmdl_errno = 0; | |
const char *cmdl_strerror(void) { | |
if (cmdl_errno >= cmdl_errlist_size) return "Invalid Error."; | |
return cmdl_errlist[cmdl_errno]; | |
} | |
int cmdl_posix(char *command, char *buffer, int size) { | |
pid_t pid; | |
int pipefd[2]; | |
if (pipe(pipefd) < 0) { | |
cmdl_errno = 1; | |
return 0; | |
} | |
pid = fork(); | |
if (pid < 0) { | |
cmdl_errno = 2; | |
return 0; | |
} | |
if (pid == 0) { | |
if (close(pipefd[0]) < 0) { | |
cmdl_errno = 3; | |
return 0; | |
} | |
if (dup2(pipefd[1], STDOUT_FILENO) < 0) { | |
cmdl_errno = 4; | |
return 0; | |
} | |
if (close(pipefd[1]) < 0) { | |
cmdl_errno = 5; | |
return 0; | |
} | |
if (execlp("sh", "sh", "-c", command, NULL) < 0) { | |
cmdl_errno = 6; | |
return 0; | |
} | |
} | |
else { | |
if (close(pipefd[1]) < 0) { | |
cmdl_errno = 7; | |
return 0; | |
} | |
if (read(pipefd[0], buffer, size) < 0) { | |
cmdl_errno = 8; | |
return 0; | |
} | |
} | |
return 1; | |
} | |
#define cmdl cmdl_posix | |
#endif /* _WIN32 */ | |
#endif /* CMDL_H_ */ | |
/*/////////////////////////////////// | |
Testing: | |
///////////////////////////////////*/ | |
#include <stdio.h> | |
int main() { | |
char buffer[2048] = {0}; | |
if (!cmdl("curl github.com -L", buffer, sizeof(buffer))) { | |
printf("ERROR: %s\n", cmdl_strerror()); | |
return 1; | |
} | |
printf("%s", buffer); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment