Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
266 views
in Technique[技术] by (71.8m points)

c - Pointer losing its value + execv compilation warning

I hope I haven't missed a similar question.

I'm trying to code a mini-shell of my own, using primitive C functions.

I got something that should work, but I have a pointer that makes everything bug.

My adrCmd pointer should get the command-path string from the searchCmd() function and keep the same value in the main function.

In fact: it points to the right value on searchCmd(), but not in the main().

Here's the code:

    int searchCmd(char* cmd, char* adrCmd){
    char* path = getenv("PATH");
    if(debug)printf("PATH : %s
", path);
    int nbPath = (compteLettre(path, ':')+1);
    char** pathTab = malloc(nbPath*sizeof(char*));
    decompose(path, pathTab, 2048, ':');

    int i;
    char* adr = malloc(sizeof(char*));
    for(i=0; i<nbPath; i++){
        sprintf(adr, "%s/%s", pathTab[i], cmd);
        if(debug)printf("   source : %s 
", adr);


        int fs = open(adr, O_RDONLY); // Si on peut ouvrir le fichier, c'est qu'il existe ! 
        if(fs != -1){ // si le fichier existe, on le renvoie;
            if(debug){
                printf("Commande trouvée dans path ! 
");
                printf("%s 
", adr);
            }
            adrCmd = adr;
            printf("%s ?= %s 
",adrCmd, adr );// oui
            return 1;
        }
    }
    return 0;
}

/**********************
        Main
**********************/

int main(int argc, char** argv){
    printf("Mini-shell : OK 
");

    char cmd[CMDSIZE];
    char** splited = malloc(CMDSIZE*sizeof(char*));
    char* adrCmd = malloc(sizeof(char*));
    char* params;
    while(printf("$ : ") && gets(cmd) && (strcmp(cmd, "exit")!=0 && strcmp(cmd, "quit")!=0)){ // On boucle tant que la commande != "exit" ou "quit"

        printf("Votre commande : %s 
", cmd);
        decompose(cmd, splited, CMDSIZE, ' ');
        if(debug)afficheCmd(splited, CMDSIZE);

        if(!searchCmd(splited[0], adrCmd)){
            printf("Commande n'existe pas, essayez apt-get install %s
", splited[0]);
        }else{
            if(debug)printf("Execution de la commande '%s' : 
", adrCmd);
            params = splited[1]; // params = array(splited[1], splited[2], ...... )
            if(execv(adrCmd, params) == -1){
                printf("Erreur d'exection de la commande
");
            }
        }

    }
    printf("Fin du programme %s 
", argv[0]);
    return 0;
}

Here's what the execution returns:

$ ./a.out 
Mini-shell : OK 
$ : ls /var
Votre commande : ls /var 
CMD[0] = ls 
CMD[1] = /var 
PATH : /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    source : /usr/lib/lightdm/lightdm/ls 
    source : /usr/local/sbin/ls 
    source : /usr/local/bin/ls 
    source : /usr/sbin/ls 
    source : /usr/bin/ls 
    source : /sbin/ls 
    source : /bin/ls 
Commande trouvée dans path ! 
/bin/ls 
/bin/ls ?= /bin/ls 
Execution de la commande '' : 
Erreur d'exection de la commande

And while I'm here, when I compile, execv returns a warning:

$ gcc shell.c 
shell.c: In function ‘main’:
shell.c:113:4: attention : passing argument 2 of ‘execv’ from incompatible pointer type [enabled by default]
/usr/include/unistd.h:564:12: note: expected ‘char * const*’ but argument is of type ‘char *’

What should I do to avoid this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

C is pass by value. So when doing this

 int searchCmd(char * cmd, char * adrCmd){

adrCmd is a copy of what had been passed in. Overwriting the copy won't change what it had been copied from in the caller.

To fix this pass down the address of adrCmd:

 int searchCmd(char * cmd, char ** padrCmd){

and use it like this:

    *padrCmd = adr;

Call searchCmd() like this:

  if(!searchCmd(splited[0], &adrCmd)){

and define and initialise adrCmd like this;

  char * adrCmd = NULL;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...