The low-level way to run a program with input taken from a file is to:
- open the file for reading using
open
- use the
dup2 system call to duplicate the open file handle over top of the handle for standard input (always handle 0)
close the old handle (the copy duplicated on top of handle 0 will stay open)
- use
execve or another function from the exec family to switch to the new program, which will now have its standard input opened to the file.
This is the same way the shell itself implements the < file input redirection.
Here's an example that runs /usr/bin/rev using input from a commands.txt file in the current directory:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern char **environ;
#define ERROR(msg) do { perror(msg); exit(1); } while(0)
int main()
{
// open the input file
int fd = open("commands.txt", O_RDONLY);
if (fd == -1)
ERROR("open");
// "dup" the handle to standard input (handle 0)
if (dup2(fd, 0) == -1)
ERROR("dup2");
// close the old handle
close(fd);
// exec the program
char *args[] = {"rev", NULL};
execve("/usr/bin/rev", args, environ);
// the program never gets here, unless the exec fails
ERROR("execve");
return -1;
}
You can also use the system command which executes a shell command including redirection, so the program:
#include <stdio.h>
#include <stdlib.h>
#define ERROR(msg) do { perror(msg); exit(1); } while(0)
int main()
{
if (system("/usr/bin/rev <commands.txt"))
ERROR("system");
// this *will* return after completion
return 0;
}
will work as well. Here, the system call is actually invoking a copy of a shell ("/bin/sh") to process the command line as if it was a shell command.
This is more convenient, but you have less control over the process of invoking the child program (e.g., setting up its environment, cleaning its argument list, etc.). There are also complex potential security issues with using system that can be a problem if your program will run as root, though that may not be an issue here.