|
-
December 1st, 2008, 05:44 PM
#1
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.
-
December 1st, 2008, 06:00 PM
#2
Re: Call Secondary Executable
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.
-
December 1st, 2008, 06:20 PM
#3
Re: Call Secondary Executable
-
December 2nd, 2008, 04:32 PM
#4
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|