Ich würde popen() benutzen (++waqas).
Aber manchmal benötigen Sie Lese- und Schreibzugriff...
Es scheint, als würde niemand mehr die Dinge auf die harte Tour machen.
(Unter der Annahme einer Unix/Linux/Mac-Umgebung oder vielleicht Windows mit einer POSIX-Kompatibilitätsschicht...)
enum PIPE_FILE_DESCRIPTERS
{
READ_FD = 0,
WRITE_FD = 1
};
enum CONSTANTS
{
BUFFER_SIZE = 100
};
int
main()
{
int parentToChild[2];
int childToParent[2];
pid_t pid;
string dataReadFromChild;
char buffer[BUFFER_SIZE + 1];
ssize_t readResult;
int status;
ASSERT_IS(0, pipe(parentToChild));
ASSERT_IS(0, pipe(childToParent));
switch (pid = fork())
{
case -1:
FAIL("Fork failed");
exit(-1);
case 0: /* Kind */
ASSERT_NOT(-1, dup2(parentToChild[READ_FD], STDIN_FILENO));
ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDOUT_FILENO));
ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDERR_FILENO));
ASSERT_IS(0, close(parentToChild [WRITE_FD]));
ASSERT_IS(0, close(childToParent [READ_FD]));
/* file, arg0, arg1, arg2 */
execlp("ls", "ls", "-al", "--color");
FAIL("Diese Zeile sollte niemals erreicht werden!!!");
exit(-1);
default: /* Eltern */
cout << "Kind " << pid << " Prozess läuft..." << endl;
ASSERT_IS(0, close(parentToChild [READ_FD]));
ASSERT_IS(0, close(childToParent [WRITE_FD]));
while (true)
{
switch (readResult = read(childToParent[READ_FD],
buffer, BUFFER_SIZE))
{
case 0: /* Ende-der-Datei oder nicht-blockierendes Lesen. */
cout << "Ende der Datei erreicht..." << endl
<< "Empfangene Daten ("
<< dataReadFromChild.size() << "): " << endl
<< dataReadFromChild << endl;
ASSERT_IS(pid, waitpid(pid, & status, 0));
cout << endl
<< "Kind Exit-Status ist: " << WEXITSTATUS(status) << endl
<< endl;
exit(0);
case -1:
if ((errno == EINTR) || (errno == EAGAIN))
{
errno = 0;
break;
}
else
{
FAIL("read() fehlgeschlagen");
exit(-1);
}
default:
dataReadFromChild . append(buffer, readResult);
break;
}
} /* während (true) */
} /* switch (pid = fork())*/
}
Sie könnten auch mit select() und nicht-blockierenden Lesevorgänge herumspielen.
fd_set readfds;
struct timeval timeout;
timeout.tv_sec = 0; /* Sekunden */
timeout.tv_usec = 1000; /* Mikrosekunden */
FD_ZERO(&readfds);
FD_SET(childToParent[READ_FD], &readfds);
switch (select (1 + childToParent[READ_FD], &readfds, (fd_set*)NULL, (fd_set*)NULL, & timeout))
{
case 0: /* Zeitüberschreitung */
break;
case -1:
if ((errno == EINTR) || (errno == EAGAIN))
{
errno = 0;
break;
}
else
{
FAIL("Select() fehlgeschlagen");
exit(-1);
}
case 1: /* Wir haben Eingabe */
readResult = read(childToParent[READ_FD], buffer, BUFFER_SIZE);
// Wie auch immer Sie es bearbeiten möchten...
break;
default:
FAIL("Wie konnten wir Eingabe auf mehr als einem Dateideskriptor sehen?");
exit(-1);
}
3 Stimmen
Auch siehe Antworten in dieser Frage:
https://stackoverflow.com/questions/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
für eine Erweiterung der großartigen Antwort unten, die Methoden zum Abrufen desRückgabecodes
und vonstderr
sowiestdout
bereitstellt, die diese Antwort bereits erklärt.8 Stimmen
@code_fodder Sie können einen Link zu stackoverflow.com/questions/52164723/… erstellen.
1 Stimmen
Hier sind 5 Fragen und Antworten für C und/oder C++, die dieses Thema betreffen: 1) wie man aus stdout in C liest, 2) C: Führen Sie ein Systemkommando aus und erhalten Sie die Ausgabe?, 3) Wie kann ich ein externes Programm aus C heraus ausführen und seine Ausgabe analysieren?, 4) Optimales Erfassen von stdout aus einem system() Befehl, 5) (diese Frage).