Getting output from an executable application

Does anyone know how to catch the output (I think its stdout) from execvp instead of printing it (in c on linux) in the terminal?

+6
source share
5 answers

execvp replaces the current current process in memory. There is no "catch" way out.

I suspect that you are trying to start an external process from an existing process and analyze its output. To do this, you need to use popen() , which executes fork() , then exec() , returning FILE * for reading (which will be the stdout process you just executed).

+6
source

I do not trust popen/pclose , since I worked on too many systems where SIGCHLD handled slightly differently. And I don't trust the sh parsing used by popen , as I rarely use it.

A short 22-year-old book by O'Reilly Using C on UNIX , Dave Curry is still a very good reference for this kind of thing.

Anyway, here is some code. It is a bit long as it parses a sample string "/bin/ls /etc" in the array {"/bin/ls", "/etc", 0} . But I find that using the string format is simpler and shorter than 98% of the time, although this example contradicts this.

This code generates a list /etc. You will need to change some things, for example, for example. NUMBER() , which is the same as XtNumber() . And you need to decide if this matches your SIGCHLD processing.

 int main(void) { // list the files in /etc char buf[100]; FILE *fp; int pid = spawnfp("/bin/ls /etc", &fp); while (fgets(buf, sizeof buf, fp)) printf("%s", buf); fclose(fp); // pclose() replacement kill(pid, SIGKILL); // pclose() replacement return 0; } 

The following routines are listed below:

 static int spawnpipe(const char *argv[], int *fd) // popen() replacement { int pid; int pipe_fds[2]; if (pipe(pipe_fds) < 0) FatalError("pipe"); switch ((pid = fork())) { case -1: FatalError("fork"); case 0: // child close(1); close(2); dup(pipe_fds[0]); dup(pipe_fds[1]); close(pipe_fds[0]); close(pipe_fds[1]); execv(argv[0], (char * const *)argv); perror("execv"); _exit(EXIT_FAILURE); // sic, not exit() default: *fd = pipe_fds[0]; close(pipe_fds[1]); return pid; } } 

This converts the ascii string to an argv list, which is probably useless for you:

 Bool convertStringToArgvList(char *p, const char **argv, int maxNumArgs) { // Break up a string into tokens, on spaces, except that quoted bits, // with single-quotes, are kept together, without the quotes. Such // single-quotes cannot be escaped. A double-quote is just an ordinary char. // This is a *very* basic parsing, but ok for pre-programmed strings. int cnt = 0; while (*p) { while (*p && *p <= ' ') // skip spaces p++; if (*p == '\'') // single-quote block { if (cnt < maxNumArgs) argv[cnt++] = ++p; // drop quote while (*p && *p != '\'') p++; } else if (*p) // simple space-delineated token { if (cnt < maxNumArgs) argv[cnt++] = p; while (*p > ' ') p++; } if (*p) *p++ = 0; // nul-terminate } if (cnt < maxNumArgs) argv[cnt++] = 0; return cnt <= maxNumArgs; // check for too many tokens (unlikely) } 

This converts the argument string to tokens and, more importantly, fd to fp , as the OP requested stdout :

 int spawnfp(const char *command, FILE **fpp) { const char *argv[100]; int fd, pid; if (!convertStringToArgvList(strdupa(command), argv, NUMBER(argv))) FatalError("spawnfp"); pid = spawnpipe(argv, &fd); *fpp = fdopen(fd, "r"); return pid; } 
+4
source

See the popen documentation, I think this is exactly what you need.

+1
source

As others have said, popen is what you want to use. Something like that...

 #include <iomanip> #include <iostream> using namespace std; const int MAX_BUFFER = 255; int main() { string cmd; cout << "enter cmd: "; cin >> cmd; cout << endl << "running " << cmd << "…" << endl; string stdout; char buffer[MAX_BUFFER]; FILE *stream = popen(cmd.c_str(), "r"); while ( fgets(buffer, MAX_BUFFER, stream) != NULL ) stdout.append(buffer); pclose(stream); cout << endl << "output: " << endl << stdout << endl; } 
+1
source

I found this answer that gives the popen a execvp style interface.

https://codereview.stackexchange.com/questions/31063/popen-with-array-of-arguments

0
source

Source: https://habr.com/ru/post/903345/


All Articles