Output redirection using fork() and execl()

I want to use fork() to spawn off a new process in my program. The new process will have only one task: To redirect the mouse input to a serial port. I have tested the following command with success in a terminal window: hexdump /dev/input/mice > /dev/ttyS0

So far I have managed to use fork to create a child process, but my problem is that I can't seem to get my execl() method to work properly:

execl("/usr/bin/hexdump", "hexdump", "/dev/input/mice > /dev/ttyS0", (char*) NULL);

I have tried other variants also, like this:

execl("/usr/bin/hexdump", "hexdump", "/dev/input/mice", ">", "/dev/ttyS0", (char*) NULL);

But always with the same result, an exit value of 1 (general error).

It's also worth mentioning that I have managed to make it work by using the popen() method, where you can type the command exactly like you would have done in a terminal. The problem with popen() is that I have not found a good way for terminating the process. With fork() I get the PID, and can terminate the process by using:

kill(pid, SIGKILL);

This is a requirement, as I have to be able to stop and restart the output redirection as desired while the program is running.


Solution 1:

You cannot perform redirection in this way.

If you want to redirect stdout for a process you're about to exec, you need to open the path and dup2 it onto the appropriate file descriptor.

Example:

 if (!(pid = fork()) 
 {
     int fd = open("/dev/ttyS0", O_WRONLY);
     dup2(fd, 1);  // redirect stdout
     execl("/usr/bin/hexdump", "hexdump", "/dev/input/mice", NULL);
 }

Solution 2:

The problem seems to be the ">" argument. This symbol is specific to the shell (bash or dash in your case). But execl() call does not invoke the shell and passes the arguments to the hexdump

As a possible solution I can propose using of system() call

Like system("hexdump /dev/input/mice > /dev/ttyS0")

This will simulate the behaviour of your command line experiment.

And to get the pid of your process you can continue doing fork(), just call the system() in place of execl()