¿Alguien sabe cómo capturar la salida (creo que es la salida estándar) de execvp
en lugar de que el sistema la imprima (en c en Linux) en el terminal?Obtención de la salida estándar desde una aplicación ejecutada
Respuesta
execvp
reemplaza el proceso de ejecución actual en memoria. No hay "captura" de la salida.
Sospecho que está intentando ejecutar un proceso externo desde un proceso existente y analizar su resultado. Para eso necesita usar popen()
que hace un fork()
luego un exec()
, devolviendo un FILE *
para leer (que será el stdout
del proceso que acaba de ejecutar).
Consulte la documentación de popen
, creo que es exactamente lo que necesita.
Como han dicho otros, popen
es lo que desea utilizar. Algo como esto ...
#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;
}
desconfío popen/pclose
, ya que he trabajado en muchos sistemas en los que se manejó SIGCHLD
ligeramente diferente. Y desconfío del sh
-shell parsing utilizado por popen
, ya que raramente lo uso.
El corto de 22 años de edad, libro de O'Reilly Using C on the UNIX System, by Dave Curry sigue siendo una muy buena referenciapara este tipo de cosas.
De todos modos, aquí hay algunos códigos. Es un poco largo, ya que analiza la cadena de muestra "/bin/ls /etc"
en la matriz {"/bin/ls", "/etc", 0}
. Pero me parece que el uso del formato de cadena más fácil y es más corto el 98% del tiempo, aunque este ejemplo desmiente eso.
Este código genera una lista de /etc.
. Deberá cambiar algunas cosas, como p. Ej. NUMBER()
que es lo mismo que XtNumber()
. Y deberá decidir si coincide con su manejo de SIGCHLD
.
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;
}
Las subrutinas aquí son:
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;
}
}
Esto convierte una cadena ASCII a una lista argv
, que es probablemente inútil para usted:
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)
}
Esto convierte la cadena de argumentos a los tokens y, más importante aún, el fd
a un fp
, ya que el OP solicitó 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;
}
Encontré esta respuesta, que da a popen
una interfaz de estilo execvp
.
https://codereview.stackexchange.com/questions/31063/popen-with-array-of-arguments
- 1. Obtención de un ARCHIVO * desde un archivo estándar
- 2. leer desde la entrada estándar de escritura a la salida estándar en C
- 3. ¿No hay salida a la consola desde una aplicación WPF?
- 4. Sincronización de la salida estándar en Clojure
- 5. observando la salida estándar de otro proceso
- 6. Obtención de la versión de la aplicación Grails desde la aplicación
- 7. Cómo utilizar la salida estándar en php
- 8. ¿Qué códigos de salida/retorno de aplicación "estándar" debe admitir una aplicación?
- 9. salida de entero a la salida estándar en Haskell
- 10. Salida de la salida estándar a un archivo y viceversa
- 11. Ejecutando código python desde la aplicación estándar Cocoa
- 12. Shell llamada script desde Android.mk, salida estándar y error
- 13. redireccionando la salida estándar en c y restableciendo la salida estándar
- 14. Obligar a la salida estándar de otro programa mediante Python
- 15. de impresión como la supresión de la salida estándar pitón
- 16. Obtención de la dirección IP del cliente desde una aplicación WSGI utilizando Eventlet
- 17. Obtención de una ruta virtual relativa desde la ruta física
- 18. redirigir la salida estándar a syslog
- 19. salida Minify HTML desde una aplicación ASP.Net MVC
- 20. Java: sincronización de salida estándar y error estándar
- 21. ¿La consulta SQL más ejecutada?
- 22. Cómo sobrescribir la salida estándar en C
- 23. Agregar espacios a la salida estándar
- 24. lectura() desde la entrada estándar
- 25. Capturar contenidos de salida estándar en C#
- 26. ¿Cómo borra una consulta MySQL no ejecutada desde la línea de comandos?
- 27. Redirigir la salida estándar de manera eficiente en .NET
- 28. Obtención de recursos de otra aplicación
- 29. Cómo restaurar la salida estándar después de usar freopen
- 30. Capturar estándares de una clase ejecutada por mvn exec: java
hará que el trabajo con argumentos así? – topherg
Bueno, el cin soltará los argumentos, pero si los relacionas correctamente con getline, popen puede manejar algo "ls -latr". – Ternary