Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute program from within a C program

Tags:

c

linux

How should I run another program from within my C program? I need to be able to write data into STDIN of the launched program (and maybe read from it's STDOUT)

I am not sure if this is a standard C function. I need the solution that should work under Linux.

like image 991
Simon Avatar asked Sep 16 '08 09:09

Simon


People also ask

How does C program gets executed?

Loader loads the executable module to the main memory for execution. Linker takes the object code generated by an assembler, as input. Loader takes executable module generated by a linker as input. Linker combines all the object modules of a source code to generate an executable module.


3 Answers

You want to use popen. It gives you a unidirectional pipe with which you can access stdin and stdout of the program.

popen is standard on modern unix and unix-like OS, of which Linux is one :-)

Type

man popen

in a terminal to read more about it.

EDIT

Whether popen produces unidirectional or bidirectional pipes depends on the implementation. In Linux and OpenBSD, popen produces unidirectional pipes, which are read-only or write-only. On OS X, FreeBSD and NetBSD popen produces bidirectional pipes.

like image 162
freespace Avatar answered Oct 06 '22 01:10

freespace


I wrote some example C code for someone else a while back that shows how to do this. Here it is for you:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

void error(char *s);
char *data = "Some input data\n";

main()
{
  int in[2], out[2], n, pid;
  char buf[255];

  /* In a pipe, xx[0] is for reading, xx[1] is for writing */
  if (pipe(in) < 0) error("pipe in");
  if (pipe(out) < 0) error("pipe out");

  if ((pid=fork()) == 0) {
    /* This is the child process */

    /* Close stdin, stdout, stderr */
    close(0);
    close(1);
    close(2);
    /* make our pipes, our new stdin,stdout and stderr */
    dup2(in[0],0);
    dup2(out[1],1);
    dup2(out[1],2);

    /* Close the other ends of the pipes that the parent will use, because if
     * we leave these open in the child, the child/parent will not get an EOF
     * when the parent/child closes their end of the pipe.
     */
    close(in[1]);
    close(out[0]);

    /* Over-write the child process with the hexdump binary */
    execl("/usr/bin/hexdump", "hexdump", "-C", (char *)NULL);
    error("Could not exec hexdump");
  }

  printf("Spawned 'hexdump -C' as a child process at pid %d\n", pid);

  /* This is the parent process */
  /* Close the pipe ends that the child uses to read from / write to so
   * the when we close the others, an EOF will be transmitted properly.
   */
  close(in[0]);
  close(out[1]);

  printf("<- %s", data);
  /* Write some data to the childs input */
  write(in[1], data, strlen(data));

  /* Because of the small amount of data, the child may block unless we
   * close it's input stream. This sends an EOF to the child on it's
   * stdin.
   */
  close(in[1]);

  /* Read back any output */
  n = read(out[0], buf, 250);
  buf[n] = 0;
  printf("-> %s",buf);
  exit(0);
}

void error(char *s)
{
  perror(s);
  exit(1);
}
like image 35
Steve Baker Avatar answered Oct 05 '22 23:10

Steve Baker


  1. Create two pipes with pipe(...), one for stdin, one for stdout.
  2. fork(...) the process.
  3. In the child process (the one where fork(...) returns 0) dup (...) the pipes to stdin/stdout.
  4. exec[v][e] the to be started programm file in the child process.
  5. In the parent process (the one where fork) returns the PID of the child) do a loop that reads from the child's stdout (select(...) or poll(...), read(...) ) into a buffer, until the child terminates (waitpid(...)).
  6. Eventually supply the child with input on stdin if it expects some.
  7. When done close(...) the pipes.
like image 30
Jorge Ferreira Avatar answered Oct 05 '22 23:10

Jorge Ferreira