Diferencias entre funcion execv() y system() en C

publicado por: Anonymous

Estoy haciendo un intérprete de comandos en C y tengo un problema con la función execv.

Utilizo un método llamado readCommand para leer una cadena de texto y dividirla en un array con el comando y los parámetros. Luego le paso a la función execv el array de la forma execv(params[0],params) pero me da error.

La cosa es que si en lugar de hacer execv hago system( )todo va correcto. ¿Alguna sugerencia?

Os dejo el código aquí:

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

#define MAX_LENGTH 256
#define DEFAULT_STRING_LENGTH  256
#define MAX_PARAMETERS  16


void  initParams(char  ***  params);
void  read_command(char  *** params);
void  freeParams(char  ***  params);
void type_prompt();
int comprobarSalir(char cadena[]);

int main(){

        int salir = 0;
        char ** params;
        int i;

        do{

                type_prompt();

                fflush(stdout);
                initParams (& params);
                read_command (& params);
                salir = comprobarSalir(params[0]);
                //execv(params [0],  params);
                if (execv(params [0],  params) ==  -1)
                       printf("Error  al  ejecutar  el  comando'%s':%sn",params [0],  strerror(errno));
                       freeParams (& params);

        }while(salir==0);

        return  0;

}


void  read_command(char  *** args) {
        char  input [256], *substr;
        int n = 0;
        fgets(input , sizeof(input), stdin);
        input[strlen(input) -1] = '';
        substr = strtok(input , " ");
        if (substr  != NULL)
                memcpy ((* args)[n], substr , strlen(substr));
        else
                (*args)[n] = NULL;
                n++;
        while ((* args)[n-1] != NULL) {
                substr = strtok(NULL , " ");
                if (substr  != NULL)
                        memcpy ((* args)[n], substr , strlen(substr));
                else
                        (*args)[n] = NULL;
                        n++;
        }
}

void  freeParams(char  *** params){
        int i;
        char ** parameter;
        for (i=0; i<MAX_PARAMETERS; i++) {
                parameter = ((* params) +i);
                if (* parameter  != NULL) free(* parameter);
        }
        free(* params);
        *params = NULL;
}


void  initParams(char  *** params) {
        int i, j;
        char ** parameter;
        *params = (char **) malloc(sizeof(parameter) * MAX_PARAMETERS);
        for (i = 0; i<MAX_PARAMETERS; i++) {
                parameter = (* params) + i;
                *parameter = (char*) malloc(DEFAULT_STRING_LENGTH);
                for (j = 0; j<DEFAULT_STRING_LENGTH; j++)  *((* parameter)+j) = '';
        }
}

void type_prompt(){
                char cwd[1024];
        getcwd(cwd, sizeof(cwd));
        printf("%s$ ",cwd);
}

int comprobarSalir(char cadena[]){

        int salir = 0;

        if((cadena[0]=='e')&&(cadena[1]=='x')&&(cadena[2]=='i')&&(cadena[3]=='t')){
                salir = 1;
        }

        return salir;
}

solución

Función system()

La función system() nos permite realiza la ejecución de un comando del sistema, de modo que la salida de este no podrá ser guardada en una variable, mas el retorno de esta función sera el valor retornado por el comando.

El prototipo de la función es:

int system(const char *command)

Donde el int que esta función nos retorna, puede ser un valor igual a cero (0) si el comando se ejecuto exitosamente, o distinto a cero !(0) si el comando NO se pudo ejecutar exitosamente.

Esta función se encuentra en el encabezado:

#include <stdlib.h> -> C

#include <cstdlib> -> C++

Ejemplo:

C

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

int main(void){
    
    int retorno = system("ls");
    
    printf("Resultado: %dn", retorno);

    return EXIT_SUCCESS;
}

C++

#include <iostream>
#include <cstdlib>

using namespace std;

int main(void){
    
    int retorno = system("ls");
    
    cout << "Resultado:" << retorno << endl;
    
    return EXIT_SUCCESS;
}

El resultado de la ejecucion (de ambos ejemplos) es:

main  main.cpp                                                                                                                                                                                                
Resultado:0 

Funcion execv()

Esta función nos permite realizar la ejecución de comandos, al igual que system() no nos permite guardar la salida del comando en una variable. Salvo que esta tiene una diferencia respecto a system(). Si execv() retorna algun valor, execv() tuvo un error.

El prototipo de la función es:

int execv(const char *path, char *const argv[]);

El int que esta función nos retorna (En caso que lo retorne) siempre es -1.

Es decir después de que un comando se ejecute con execv() tu programa principal finaliza después de la ejecución de este.

Esta función se encuentra en el encabezado:

#include <unistd.h> -> C / C++

Antes de mirar el ejemplo debes tener en cuenta que a la función execv() se le pasan los siguientes parametros:

  1. Ruta al ejecutable, Ej: "/bin/ls"
  2. Un arreglo que debe contener, como primer elemento, la ruta del ejecutable, y como ultimo NULL, quedando en el medio los parámetros que se pasaran a tu ejecutable, Ej: {"/bin/ls", "-l", NULL}

Ejemplo:

C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
    
int main(void){
    
    char *argumentos[] = {"/bin/ls", "-l", NULL}; 
    
    execv("/bin/ls", argumentos);
    
    printf("Termino!!!");
    
    return EXIT_SUCCESS;
}

C++

#include <iostream>
#include <cstdlib>
#include <unistd.h>

using namespace std;

int main(void){
    
    char *argumentos[] = {"/bin/ls", "-l", NULL}; 
    
    execv("/bin/ls", argumentos);
    
    cout << "Termino!!!" << endl;
    
    return EXIT_SUCCESS;
}

El resultado de la ejecución (de ambos ejemplos) es:

total 16                                                                                                                                                                                                      
-rwxr-xr-x 1 35878 35878 9221 Mar 14 00:23 main                                                                                                                                                               
-rw-r--r-- 1 35878 35878  329 Mar 14 00:23 main.cpp   

Has notado que el mensaje "Terminó!!!", no aparece en ninguna parte, es allí donde radica la diferencia entre estas funciones, mientras system() continua la ejecución de tu programa, execv() continua la ejecucion del programa que tu le indicas y no finaliza tu programa principal.

Espero te sirva de ayuda

Referencias:

system()

execv()

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *