Skip to content

Instantly share code, notes, and snippets.

@lelanthran
Last active February 29, 2020 20:54
Show Gist options
  • Save lelanthran/4763d288007b282998d46475feda46eb to your computer and use it in GitHub Desktop.
Save lelanthran/4763d288007b282998d46475feda46eb to your computer and use it in GitHub Desktop.
// 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