CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Dec 2008
    Posts
    3

    Question Call Secondary Executable

    I have a C++ program that I need to call a secondary program. I know I can make a system call to call the program, but this program I want to call normally takes input from the user in a prompt atmosphere. Unfortunately, the program is an old Fortran program with which I no longer have the code for, therefore I cannot just rewrite the code into C++ and add it to my program. How can I call this executable and then provide it automated answers, all of which I will be able to calculate? Thanks for your help and please let me know if you need any more information.

  2. #2
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    Re: Call Secondary Executable

    What platform ?
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

  3. #3
    Join Date
    Dec 2008
    Posts
    3

    Re: Call Secondary Executable

    Solaris 10.

  4. #4
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    Re: Call Secondary Executable

    The system calls you should be looking at, are fork, pipe, and execv (et al). I would recommend you to get a book about UNIX IPC as the topic is quite complex.

    Anyways, below is some test program I wrote many years ago (some of it might be taken from the net). It shows you the principles.
    Code:
    #include <iostream>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    
    pid_t exec_redirect(char * prog, char * args[], int* infd, int* outfd, int* errfd)
    {
            // Fork new process
            pid_t pchild = fork();
    
            if (pchild == 0) {
                    // Child process
    
                    // Redirect standard input
                    if (infd[0] >= 0) {
                            close(STDIN_FILENO);
                            dup2(infd[0], STDIN_FILENO);
                    }
    
                    // Redirect standard output
                    if (outfd[1] >= 0) {
                            close(STDOUT_FILENO);
                            dup2(outfd[1], STDOUT_FILENO);
                    }
    
                    // Redirect standard error
                    if (errfd[1] >= 0) {
                            close(STDERR_FILENO);
                            dup2(errfd[1], STDERR_FILENO);
                    }
    
                    // Close unneeded ends of pipes
                    if (infd[1] >= 0) close(infd[1]);
                    if (outfd[0] >= 0) close (outfd[0]);
                    if (errfd[0] >= 0) close (outfd[0]);
    
                    // Execute the command
                    execv(prog, args);
                    return 0;
    
            } else {
                    // Parent process
    
                    // Close unneeded ends of pipes
                    if (infd[0] >= 0) close(infd[0]);
                    if (outfd[1] >= 0) close (outfd[1]);
                    if (errfd[1] >= 0) close (errfd[1]);
    
                    return pchild;
            }
    
    }
    
    void readFromPipe(int pfd) {
            char buf;
            bool newline = true;
            while (read(pfd, &buf, 1) > 0) {
                    if (newline) {
                            std::cout << "[Child] ";
                            newline = false;
                    }
                    std::cout << buf;
                    if (buf == '\n') {
                            newline = true;
                    }
            }
    }
    
    int main(int argc, char* argv[]) {
            if (argc < 1) {
                    std::cerr << "Please supply an argument\n";
                    exit(1);
            }
            char * childproc = argv[1];
            char ** childprocargs = new char*[argc];
            std::cout << "Executing ";
            for (int i = 1; i < argc; ++i) {
                    std::cout << argv[i] << " ";
                    childprocargs[i-1] = strdup(argv[i]);
            }
            childprocargs[argc-1] = 0;
            std::cout << "\n";
    
            // Creating pipes for communication
            int pfddown[2]; // down: Parent writes, child reads
            int pfdup[2];   // up: Child writes, parent reads
            int pfderr[2];  // err: Child writes, parent reads
            if (pipe(pfdup) != 0 || pipe(pfddown) != 0 || pipe(pfderr) != 0) {
                    std::cerr << "Unable to create pipes. Aborting\n";
                    exit(1);
            }
    
            pid_t child = exec_redirect(childproc, childprocargs, pfddown, pfdup, pfderr);
    
            std::cout << "Forked child, pid is " << child << "\n";
    
            std::cout << "Sending Hello\\n\n";
            write(pfddown[1],"Hello\n",6);
            std::cout << "Sending World!\\n\n";
            write(pfddown[1],"World!\n",7);
            close(pfddown[1]);
            readFromPipe(pfdup[0]);
            close(pfdup[0]);
            wait(0);
    
            // cleaning the nasty arg array
            for (int i = 0; i < argc-1; ++i) {
                    free(childprocargs[i]);
            }
            delete [] childprocargs;
    }
    A quick try under Linux and it seems to do exactly as promised:
    Code:
    treuss@foo:~/src$ ./test /bin/cat
    Executing /bin/cat
    Forked child, pid is 9514
    Sending Hello\n
    Sending World!\n
    [Child] Hello
    [Child] World!
    treuss@foo:~/src$ ./test /usr/bin/tac
    Executing /usr/bin/tac
    Forked child, pid is 9526
    Sending Hello\n
    Sending World!\n
    [Child] World!
    [Child] Hello
    treuss@foo:~/src$ ./test /bin/sed -e's/o/x/g'
    Executing /bin/sed -es/o/x/g
    Forked child, pid is 9532
    Sending Hello\n
    Sending World!\n
    [Child] Hellx
    [Child] Wxrld!
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured