Iniciar sesión

Ver la versión completa : Programacion en C++ y llamadas al sistema sobre linux



crossmax
15/07/2013, 13:10
Hola compañeros!

Estoy haciendo un programilla en C que corre sobre un linux y queria saber si se puede almacenar el valor devuelto por una llamada al sistema en una variable del programa.
Situacion:
Tengo un fichero de texto con parametros y antes de ponerme a ir linea por linea y espacio por espacio me gustaria hacer:
system("cat fichero.txt | awk '{ print $4 }' > variable);
Algo asi, donde "variable" es una variable del programa en C.

¿Se puede hacer algo como eso?

Como siempre, muchas gracias por vuestra ayuda

juanvvc
15/07/2013, 13:33
Eso no es una llamada al sistema, es una llamada a la shell :) Si quieres programar en Linux tienes que entender bien las diferencias entre llamadas al sistema (llamadas al kernel Linux) y ejecutar programas externos (como una shell) Para llamar a la shell uno de los pasos intermedios es llamar al sistema. ¡Pero eso solo es uno de los pasos intermedios!

Al lío. La forma tradicional es liarse con los fork() y los exec() y las mandangas. TIENES QUE HACERLO AL MENOS UNA VEZ EN LA VIDA para entender cómo funcionan los procesos en Linux. Ahora vamos a hacerlo a lo fácil, con popen. Vamos a crear una función tal que así:




void get_command_output(char* command, int max_output_size)
FILE *pf;
char *data;

data = (char *) malloc(sizeof(char) * max_output_size);
if(!data)
return NULL;

pf = popen(command,"r");
if(!pf)
return NULL;

fgets(data, max_output_size , pf);
if (pclose(pf) != 0)
fprintf(stderr," Error: Failed to close command stream \n");

return data;
}


Y la llamas tal que así:


char * variable = get_command_output("cat fichero.txt | awk '{ print $4 }'", 32);

El "32" final es el tamaño máximo esperado de la salida en bytes.

(No he probado este código, pero es más o menos así)

crossmax
15/07/2013, 17:19
Eres un maquina!! Funciona de lujo.
Ademas de que dicho así, me han entrado ganas de pelearme con el fork(). Estoy motivado ;)

Eso sí, te ha faltado cambiar el void por char *
La unica pena es que la variable pensaba concatenarla para dar nombre a unos ficheros que genera la aplicacion, pero entiendo que como la variable donde la almaceno es un puntero, debe de tener el delimitador 0x0A para saber donde acaba, y eso me genera el saldo de linea en el nombre.
¿La mejor forma es recorrerme el contenido del puntero hasta encontrar el 0x0A y hacer un substring? De esa forma conoceria el tamaño para crear un char array y copiar solo los caracteres. Asi no me salta de linea el nombre del fichero.

Vamos que te pregunto por curiosidad, que metodos para hacerlo hay miles pero lo mismo se te ocurre uno que es mas eficiente/sencillo y aprendo de ello.

Gracias

EDIT:

Ok, me he rallado con el tema de que debia tener un delimitador por ser un puntero y no saber cuanta memoria ocupa.
He probado con:
char * variable = get_command_output("cat fichero.txt | awk '{ print $5 }' | tr -d '\n'", 32);

Y funciona exactamenet como quiero :)

juanvvc
15/07/2013, 23:45
Aunque ya lo has solucionado con tr desde la shell, otros lenguajes tienen la función strip() precisamente para eso. No lo he mirado, pero es algo tan habitual que seguramente encontrarás una función strip() en strings.h