Find the answer to your Linux question:
Results 1 to 4 of 4
Hi! I am writing a server program (using C) that executes a script when the client asks for it, but I am not sure about how to see the output ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    May 2010
    Location
    Madrid
    Posts
    32

    Catch the output when a C program executes a script


    Hi! I am writing a server program (using C) that executes a script when the client asks for it, but I am not sure about how to see the output of that execution in the client side or, at least, to know if the execution was successful or not.

    can I redirect the script's output to a socket or something like that??

  2. #2
    Trusted Penguin
    Join Date
    May 2011
    Posts
    4,353
    I've done something like this in the past, to capture STDOUT of a system command:
    Code:
      FILE *cmd_out;        /* stream for storing system command's output */
      char *run_cmd;        /* variable for string containing GnuPG command */
    
      run_cmd = (char *) malloc (1000);
    
      /* format the system command to run into a string */
      sprintf(run_cmd, "somecommand");
    
      /* run command and pipe output to file */
      cmd_out = popen(run_cmd, "r");
    
      if (cmd_out != NULL) {
    
        /* do something with cmd_out */
    
        /* close pipe */
        pclose(cmd_out);
    
      }else{
        fprintf(stderr, "No pipes!\n");
        return 1;
      }

  3. #3
    Linux User
    Join Date
    Nov 2008
    Location
    Tokyo, Japan
    Posts
    260
    Well, calling "fork()" and then executing the script with the "exec()" command in the forked process will have your script inherit the STDIN, STDOUT, and STDERR from your C program. But if that is not what you want to do, Atreyu's suggestion to pipe the output is one method. "popen()" automatically forks and creates pipes for you.

    Another method is to create a fifo with "mkfifo()" or a UNIX socket, and once you have the file descriptor for the fifo or socket (lets call it "pipe_fd"), you can call "fork()". Then in the child process, close your STDOUT with "close(1)" and then use "fnctl(pipe_fd, F_DUPFD_CLOEXEC)".
    Code:
    sock_fd = socket(AF_UNIX, SOCK_STREAM, my_port_number);
    if(sock_fd < 0) { fprintf(stderr, "Socket FAIL: %s\n", strerror(errno)); }
    childpid = fork();
    if(childpid == 0) { /* I am the child process */
        close(1); /* close STDOUT */
        fnctl(sock_fd, F_DUPFD_CLOEXEC); /* re-connect socket to the place STDOUT used to be before it was closed */
        close(0); /* close STDIN */
        fnctl(sock_fd, F_DUPFD_CLOEXEC); /* re-connect socket to the place STDIN used to be before it was closed */
        execve(my_script, script_args, new_script_env);
    }
    else if(childpid > 0) {
        /* adults only (things the parent process will do) */
    }
    else { fprintf(stderr, "Fork FAIL: %s\n", strerror(errno)); }
    "fnctl()" will ask the operating system to assign a new integer value to the file descriptor, and it will use the lowest numbered unused file descriptor number, which should be 1 if you closed STDOUT. "F_DUPFD_CLOEXEC" will also flag the old file descriptor value to be released by the operating system when you call "exec()". What you have done is effectively "reconnected" the pipe from the socket/fifo to STDOUT. You can reconnect STDIN in the same way. Then execute the script with "exec()" or whatever, and it will use the socket/fifo as STDIN and STDOUT.

    WARNING: be sure not to use the same file descriptor for both input and output if you are using a fifo rather than a socket. In the code above, I use the same socket file descriptor as the parameter to "fnctl()" twice, once for STDOUT and once for STDIN. Sockets can do two-way communication, FIFO's generally cannot.

  4. #4
    Linux Guru Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,252
    I think that FIFOs may be a bit overkill here, though they certainly are an option. Also, ramin.honary: dup2 is generally a more appropriate function than fcntl for this.

    occam25: popen() is probably the most appropriate way to get the output of another program into your program. You should be aware that this is basically a shortcut for a pipe/fork/dup2/exec.

    As to your other question, you can use the waitpid() function to block until the child process exits. This function will tell you the return status of that program.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •