Duda en un ejercicio de C

kritita

.

raulmevi2

#1 si he entendido bien lo que tienes que hacer, que no estoy seguro, podria ser usando la funcion system

un ejemplo para copiar carpetas:
system("cp c:\archivos c:\archivos2" );

entonces para ejecutar algo, creo que esto te funcionaria:
system("ruta completa del ejecutable del programa que le pasas como argumento" );

osea, por ejemplo
system("arg_p1" );

y arg_p1 tendria que ser algo asi como: C:\documents and settings\usuario\escritorio\programa1.exe

suponiendo que sea para windows, si es para linux me pillas, aunque tambien es con lo del system

LOc0

Linux y derivados:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	if(argc==5)
	{
		if(!fork())
			execlp(argv[1], argv[1], argv[3], NULL);
		else
		{
			wait(NULL);
			printf("\nEl programa <%s> ha terminado\n\n\n", argv[1]);
			
		if(!fork())
			execlp(argv[2], argv[2], argv[4], NULL);
		else
		{
			wait(NULL);
			printf("\nEl programa <%s> ha terminado\n", argv[2]);
			printf("\n\nLos dos programas han finalizado. Bye!\n");
		}
	}
}

return 0;
}

http://linux.die.net/man/3/exec

De nada.

Editado: los copy paste son peligrosos. Corregido un fallo en la llamada a execlp() (hay que repetir el primer argumento).

Salu2 ;)

1 1 respuesta
kritita

#3 Muchas gracias!
Si no es mucho preguntar... ¿por qué en la línea 5 argv es un puntero a un puntero? Siempre había visto eso escrito con *argv[]

1 respuesta
LOc0

#4 Resumidamente da lo mismo.

Salu2 ;)

2
dr_Rouman

Bonus, si quisieras recoger la salida de los programas, puedes hacerlo con popen()

1 1 respuesta
kritita

#6 gracias, por si me lo piden en algún momento.

mm... y qué significa

    if(!fork())

?

si no fork() ?

Yo lo que suelo poner es if (fork()==0) porque, además, ¿es necesario hacer dos fork()? ¿No te sirve con tener dos procesos (el padre y el hijo) y lanzar un programa desde cada uno? :S

1 respuesta
dr_Rouman

if a == 0 es lo mismo que if !a

if a es verdad cuando a es distinto de 0, así que !a es verdad sólo cuando no es distinto de cero.

B

#7 Cuando se hace un exec() se sustituye la imagen del programa que se está ejecutando, se guardan los descriptores de fichero y demás pero es una función que nunca hace return. Por eso si haces un exec() dentro de tu programa pasaría a ejecutar el llamado pero luego no podrías obtener el valor de terminación ni realizar una tarea, en este caso imprimir esos mensajes.

kritita

Ok, muchas gracias!

18 días después
kritita

Tengo una variante de este problema, esta vez tengo que ejecutar el programa que se pasa como primer parámetro con argumentos (no se sabe cuantos) que son el resto de parámetros. Lo que he hecho es

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main (int argc, char *argv[]) {
	pid_t childpid;
	char * programa;
	int i;
	
programa=argv[0];
for (i=1; i<=argc; i++) {
	argv[i]=argv[i-1];	
}

if ((childpid=fork())==-1) {
	printf("error");
}else {
	if (childpid==0) {
		execvp(programa, argv[]);
	}else {
		wait(NULL);
		printf("el programa ha finalizado \n");
	}
}
exit (0);
}

Pero me da un error en la línea 20: expected expression before ']' token.

Y no se por qué, la verdad que con los punteros me lio bastante pero según tengo en los apuntes argv[] es lo que debería ir ahí.

Tampoco sé si el programa en sí está bien, lo que he intentado hacer es quitar el primer parámetro para poder pasar el resto del array como argumentos, pero dados mis conocimientos de C lo mismo estoy haciendo una burrada.

1 respuesta
Markitos_182

#11 Te lo he fusilado "un poco". Aquí tienes el programa funcionando:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main (int argc, char* argv[]) {
        pid_t childpid;
        char * programa;	//aquí guardaremos el ejecutable
        int i;
        programa=argv[1];
	//Usaremos el array argv para pasar los argumentos a execvp
        for (i=1; i<argc; i++) {	//En este bucle cogemos los argumentos.
		argv[i-1]=argv[i];	// incluido el binario a ejecutar.
		argv[i]=NULL; //execvp nos exige que el último elemento sea del tipo NULL. Además así nos evitamos problemas puntuales con ejecuciones sin argumentos.
	}
	 
    if ((childpid=fork())==-1) {
            printf("error");
    }else {
            if (childpid==0) {
                    execvp(programa,argv);	//invocamos el programa 
            }else {
                    wait(NULL);
                    printf("\nEl programa ha finalizado.\n");
            }
    }
    exit (0);
}

El problema que tu exponías era que te daba error la línea 20 con argv[], simplemente para execvp tienes que poner el nombre de la variable, no el puntero al array.
Luego como eso no tiraba me he picado y al final he cambiado más cosas xD

Te he modificado en el bucle (además de la condición) cómo obtenías los argumentos, que estaba mal planteado, pero por ahí iban los tiros. Y lo último que he añadido ha sido el NULL que tiene que ir en el último elemento del array. Si tienes alguna duda mas pregunta :-)

Bueno, y lo he probado hasta con 4 argumentos y parece que tira, prueba por ejemplo con ls -l a distintos directorios.

$ ./a.out ls -l ~/ ~/Documentos
1 1 respuesta
dagavi

#12, si en vez de realizar una copia de argumentos pasas el puntero + algo?

        if ((childpid=fork())==-1) {
                printf("error");
        }else {
                if (childpid==0) {
                        execvp(argv[1], argv + 2);
                }else {
                        wait(NULL);
                        printf("\nEl programa ha finalizado.\n");
                }
        }
        exit (0);
1 respuesta
Markitos_182

#13 No estoy en linux ahora, ¿eso llega a compilar?
Aparte, supongo que como dices estás pasando el array entero de argv, por tanto también estás pasando en argv[0] el a.out, y el primero debería ser argv[1], por tanto se debería seguir modificando el array moviendo un elemento menos y poniendo el último como NULL.

1 respuesta
dagavi

#14 No lo he probado a compilar, pero piensa que no pasas un array, pasas un puntero.

El resultado es el mismo:
1) Mover todos los elementos 1 posición y pasarte la dirección &argv[0]
2) Dejar los elementos en su sitio y pasarte la dirección &argv[1] (aunk yo he puesto +2 ya que pensaba que no haría falta pasar el propio programa, pero si solo hay que movierlo 1 vez pos se puede poner +1 y listo)

Usuarios habituales