Last active
February 29, 2020 20:54
-
-
Save lelanthran/4763d288007b282998d46475feda46eb to your computer and use it in GitHub Desktop.
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
// gcc -o run_inferior run_inferior.c -W -Wall | |
/* A function to execute a child program and feed the input line-by-line back | |
* to the calling program. The function mst be called with a callback function | |
* that will receive each line as it is read in, a program to execute and the | |
* command line arguments for that program. | |
* | |
* There are two versions of this function: one that takes the command line | |
* arguments as variadic parameters delimited with a NULL pointer and one that | |
* takes an array of parameters with a length specified for the array. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdarg.h> | |
#define MAX_LINE_LEN ((1024 * 1024) * 10) // 10MB lines | |
typedef int (run_inferior_func_t) (const char *, void *); | |
int run_inferior (run_inferior_func_t *callback, | |
void *argp, | |
const char *program, | |
size_t nargs, | |
char **argv) | |
{ | |
int ret = EXIT_FAILURE; | |
char *cmd = NULL; | |
char *line = NULL; | |
FILE *inf = NULL; | |
size_t len = strlen (program); | |
if (!(cmd = malloc (len+1))) | |
goto errorexit; | |
strcpy (cmd, program); | |
for (size_t i=0; i<nargs; i++) { | |
size_t index = len; | |
len += strlen (argv[i]); | |
char *tmp = realloc (cmd, len + 2); | |
if (!tmp) | |
goto errorexit; | |
cmd = tmp; | |
cmd[index] = ' '; | |
len++; | |
strcpy (&cmd[index+1], argv[i]); | |
} | |
// printf ("Executing [%s]\n", cmd); | |
if (!(inf = popen (cmd, "r"))) | |
goto errorexit; | |
if (!(line = calloc (MAX_LINE_LEN, 1))) | |
goto errorexit; | |
size_t index = 0; | |
int c = 0; | |
while (!feof (inf) && !ferror (inf) && (c = fgetc (inf))!=EOF) { | |
if (c=='\n' || index>=MAX_LINE_LEN) { | |
line[index++] = c; | |
line[index] = 0; | |
if (callback (line, argp) < 0) | |
goto errorexit; | |
index = 0; | |
} else { | |
line[index++] = c; | |
} | |
} | |
errorexit: | |
if (inf) | |
pclose (inf); | |
free (cmd); | |
free (line); | |
return ret; | |
} | |
int run_inferior_v (run_inferior_func_t *callback, | |
void *argp, | |
const char *program, | |
...) | |
{ | |
int ret = EXIT_FAILURE; | |
char **argv = NULL; | |
size_t nargs = 0; | |
va_list ap, ap_count; | |
char *tmp = NULL; | |
size_t i = 0; | |
va_start (ap, program); | |
va_start (ap_count, program); | |
do { | |
if ((tmp = va_arg (ap_count, char *))) | |
nargs++; | |
} while (tmp); | |
if (!(argv = calloc (nargs + 1, sizeof *argv))) | |
goto errorexit; | |
do { | |
if ((tmp = va_arg (ap, char *))) | |
argv[i++] = tmp; | |
} while (tmp); | |
ret = run_inferior (callback, argp, program, nargs, argv); | |
free (argv); | |
va_end (ap); | |
va_end (ap_count); | |
errorexit: | |
return ret; | |
} | |
int main (void) | |
{ | |
int ret = EXIT_FAILURE; | |
int result = run_inferior_v ((run_inferior_func_t *)fputs, stdout, | |
"ls", "-l", "-a", "..", NULL); | |
printf ("%i\n", result); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment