exec y sus derivadas

Iniciado por NewBe, 25 Octubre 2011, 19:34 PM

0 Miembros y 1 Visitante están viendo este tema.

NewBe

Hola,

S.O: linux
Ansi-C

Mi consulta es que he de ejecutar desde exec o una de sus derivadas (execlp, execle, ...) el comando cp para copiar un archivo a otro.
Lo he puesto de la siguiente manera:


int copy (char *src, char *dst)
{
ret = execlp("/bin/cp", "cp", "/home/linux/ejercicio1", (char*)src,(char*)dst)
return 0;
}


Desde la shell creo que seria cp origen.txt destino.txt  /home/linux/ejercicio1

Saludos

Foxy Rider

#1
Correcto, peeeero... el formato de cp es

Código (bash) [Seleccionar]
cp [origen] [destino]

así que el tercer argumento a  execlp está de más (no sé que habrás querido hacer), y el último argumento, sí o sí tiene que ser (char*) 0 (un puntero a char apuntando a 0, null )
lee esto (no tenés que leerlo completo, sólo lo que compete al ejercicio):

http://pubs.opengroup.org/onlinepubs/009695399/functions/execlp.html
http://pubs.opengroup.org/onlinepubs/009695399/utilities/cp.html

Saludos.

pucheto

Y recorda que exec pisa tu proceso con la imagen del proceso que estas llamando. ( osea que nunca llegas a hacer el return de copy. ).

Valkyr

Cita de: pucheto en 27 Octubre 2011, 13:24 PM
Y recorda que exec pisa tu proceso con la imagen del proceso que estas llamando. ( osea que nunca llegas a hacer el return de copy. ).
Es más, si es que se ejecutase cualquier cosa posterior al exec sería porque se ha producido algún error.

NewBe

Cita de: vertex@Symphony en 27 Octubre 2011, 06:56 AM
Correcto, peeeero... el formato de cp es

Código (bash) [Seleccionar]
cp [origen] [destino]

así que el tercer argumento a  execlp está de más (no sé que habrás querido hacer), y el último argumento, sí o sí tiene que ser (char*) 0 (un puntero a char apuntando a 0, null )
lee esto (no tenés que leerlo completo, sólo lo que compete al ejercicio):

http://pubs.opengroup.org/onlinepubs/009695399/functions/execlp.html
http://pubs.opengroup.org/onlinepubs/009695399/utilities/cp.html

Saludos.

He intentado hacer otra llamada exec fijandome en el ejemplo que me escribistes, pero me doy cuenta de que pueder ser que lo que yo prentendo hacer , como novato, no se puede. Es lo siguiente:

execlp("ls", "ls", filename, ">", otherfilename, NULL );

Saludos

Foxy Rider

Y no es más fácil usar popen() para eso?

Saludos.

P.S: Nunca traté de usar pipes en una llamada a exec, pero desde ya me parece que sería inválido ... por que es algo que se implementa en las shells, digo ...

Foxy Rider

#6

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
 FILE* pipeOutput = popen("ls /usr/home/vertex","r");
 FILE* fileOutput = fopen("/usr/home/vertex/Salida.txt","w");
 char fileBuffer[1024];
 
 if ( pipeOutput == 0 || fileOutput == 0)
 {
   printf("Failure opening input, output file or creating buffer\r\n");
   exit(EXIT_FAILURE);
 }
 
   
 while(!feof(pipeOutput))
 {
   fgets(fileBuffer, sizeof(fileBuffer), pipeOutput);
   fputs(fileBuffer, fileOutput);
 }
 
 fclose(fileOutput);
 pclose(pipeOutput);
 
 return EXIT_SUCCESS;
}



Desde ya eso es un boceto de lo que tenes que hacer ... yo que vos reviso open(), read() y write(), fork(), pipe() y demás (chequeando errores también, por que esas funciones PUEDEN FALLAR) si querés escribirlo en un POSIX LIMPIO

Saludos.

P.S → Pista : http://www.etsimo.uniovi.es/cscene/CS4/CS4-06.html

rir3760

Si bien es un boceto (aquí voy de metiche) hay tres detalles en ese programa.

Si la dirección en memoria del array "fileBuffer" es igual a NULL el programa ya esta mas allá de la salvación (supongo estabas pensando en reservar memoria via malloc o similar).

Para salir de la función "main" no es necesaria la llamada a "exit", basta con utilizar la sentencia "return N;".

Por ultimo es mejor (salvo excepciones) evitar la función "feof" ya que esta retorna verdadero solo después que una función de lectura falla. En su lugar es mejor (si aplica) utilizar el valor de retorno de la función, en este caso "fgets":
while (fgets(fileBuffer, sizeof(fileBuffer), pipeOutput))
   fputs(fileBuffer, fileOutput);


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Foxy Rider

#8
CitarSi la dirección en memoria del array "fileBuffer" es igual a NULL el programa ya esta mas allá de la salvación (supongo estabas pensando en reservar memoria via malloc o similar).

Si, puse con malloc y al toque borré y dije  "no, al stack! más sencillo"
olvidé modificar el if después de eso, claramente x'D

CitarPara salir de la función "main" no es necesaria la llamada a "exit", basta con utilizar la sentencia "return N;".

Gracias, ya sé que main es una función ... y sé sobre el tema "retornar códigoo de términación al sistema operativo" (sino no estarían los EXIT_* ... en vez de un return 0 por ejemplo)

CitarPor ultimo es mejor (salvo excepciones) evitar la función "feof" ya que esta retorna verdadero solo después que una función de lectura falla. En su lugar es mejor (si aplica) utilizar el valor de retorno de la función, en este caso "fgets":

Dije que era un boceto, no una solución, quería mantenerlo chiquitito y evitar muchas cosas como if's (y chequear el valor de retorno incluye un if) ... sino directamente iba con escribirlo en POSIX limpio, pero esa es la tarea del autor (en el mensaje que postee el código me avivé que es una tarea y que el autor seguramente está aprendiendo POSIX y que TIENE QUE reescribirlo a un POSIX limpio)
La idea de postear un código era "dibujar" qué es lo que tiene que hacer (usar un pipe para pasar la salida de un comando a un fichero en vez de usar ">" como parámetro) a exec*

Si te toca mucho los sentimientos te mando la solución correcta por PM

CitarEs más, si es que se ejecutase cualquier cosa posterior al exec sería porque se ha producido algún error.

Eso está en el link a la documentación del Open Group, si lo pongo (así como muchas veces en Unix y GNU/Linux me tomo el tiempo e insisto en enlazar manpages), *claramente* es para que lo lean, no voy a re-describir que hace exec acá.

Saludos.

P.S: no veo nada malo con feof, la idea era también quen si hay un error (cosa que un EOF también setea el bit), se interrumpa "el paso" de la salida al fichero ...

P.S 2 : Gracias por la observación, está bueno agregar un "por qué" a las cosas que uno hace (no iba a hacerlo a horas am)

P.S 3: Ahí cambié el if

rir3760

Cita de: [Alex] en  2 Noviembre 2011, 03:05 AMP.S: no veo nada malo con feof, la idea era también quen si hay un error (cosa que un EOF también setea el bit), se interrumpa "el paso" de la salida al fichero ...
El problema es, tal como se utiliza en el programa, el uso de "feof" es un error lógico. Eso porque usualmente se toma a esa función como ¿Hay mas caracteres que leer? cuando debería ser ¿Que paso con la ultima operación de lectura?

Dado el bucle:
while(!feof(pipeOutput))
{
   fgets(fileBuffer, sizeof(fileBuffer), pipeOutput);
   fputs(fileBuffer, fileOutput);
}

Supongamos que se leen todas las lineas menos la ultima, a partir de ese momento:

1) fgets lee la ultima linea, no hay problema.
2) fputs la imprime, ídem.
3) feof no retorna verdadero ya que la ultima operación de lectura fue exitosa.
4) lectura extra con fgets falla
5) escritura con fputs (no debería)
6) feof retorna verdadero y se termina el bucle.

Como puedes ver se realiza una iteracion de mas. Para evitarlo se tendría que modificar el bucle a:
fgets(fileBuffer, sizeof(fileBuffer), pipeOutput);
while(!feof(pipeOutput))
{
   fputs(fileBuffer, fileOutput);
   fgets(fileBuffer, sizeof(fileBuffer), pipeOutput);
}

Desde mi punto de vista es demasiado trabajo (ademas de reducir la claridad del código) cuando, para empezar, basta con simplemente verificar el valor de retorno de "fgets".

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language