8

I'm making a C program where it basically reads in a line from the user, interprets it and then tries to execute the command with execve. I'm also forking the execve to a child process if '&' is in the input.

Now I wish to hide any terminal output which comes from the execve command when it's running in the child process. Is there any relatively easy way to do this?

Burkhard
  • 14,596
  • 22
  • 87
  • 108
log234
  • 93
  • 1
  • 6

2 Answers2

6

You can hide the output by redirecting stdout and stderr to /dev/null after forking but before execve(). The idea is to open /dev/null, then make stdout and stderr duplicates of the obtained file descriptor with dup2() (which will also close the originals first). It's almost the same as redirecting to a pipe.

An example (incomplete program, and skipping most error checking):

  #include <unistd.h>
  #include <fcntl.h>
  ...

  int pid = fork();
  if (pid == -1) {
    /* fork error */
    exit(1);
  } else if (pid == 0) {
    /* child process */

    /* open /dev/null for writing */
    int fd = open("/dev/null", O_WRONLY);

    dup2(fd, 1);    /* make stdout a copy of fd (> /dev/null) */
    dup2(fd, 2);    /* ...and same with stderr */
    close(fd);      /* close fd */

    /* stdout and stderr now write to /dev/null */
    /* ready to call exec */

    execve(cmd, args, env);
    exit(1);
  } else {
    /* parent process */

  ...
Community
  • 1
  • 1
Dmitri
  • 9,175
  • 2
  • 27
  • 34
0

I've written simple example, maybe it will help you.

First, try to call it without | echo $1 > /dev/null - it should print files. When you add it, output is empty.

#include <stdio.h>
#include <unistd.h>

int main()
{
        int ret;
        char *cmd[] = { "ls", "-l", (char *)0 };
        char *env[] = {(char *)0 };
        ret = execve ("/bin/ls | echo $1 > /dev/null", cmd, env);
        return 0;
}
Sean Doe
  • 277
  • 2
  • 9
  • 1
    This shouldn't work (and doesn't for me). The IO redirection it attempts to use would be handled by the shell -- but `execve` doesn't use the shell to run the command. It only appears to work because when `execve` fails it isn't running `/bin/ls` at all. – Dmitri Oct 20 '14 at 00:31