2014-10-31 2 views
0

Надеюсь, я не пропустил аналогичный вопрос.Указатель, теряющий значение + предупреждение о компиляции execv

Я пытаюсь закодировать собственную мини-оболочку, используя примитивные функции С.

У меня есть что-то, что должно работать, но у меня есть указатель, который делает все ошибки.

У меня adrCmd указатель должен получить строку из командной строки из функции searchCmd() и сохранить то же значение в функции main.

Фактически: оно указывает на нужное значение на searchCmd(), но не в main().

Вот код:

int searchCmd(char* cmd, char* adrCmd){ 
    char* path = getenv("PATH"); 
    if(debug)printf("PATH : %s\n", 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 \n", 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 ! \n"); 
       printf("%s \n", adr); 
      } 
      adrCmd = adr; 
      printf("%s ?= %s \n",adrCmd, adr);// oui 
      return 1; 
     } 
    } 
    return 0; 
} 

/**********************\ 
     Main 
\**********************/ 

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

    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 \n", 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\n", splited[0]); 
     }else{ 
      if(debug)printf("Execution de la commande '%s' : \n", adrCmd); 
      params = splited[1]; // params = array(splited[1], splited[2], ......) 
      if(execv(adrCmd, params) == -1){ 
       printf("Erreur d'exection de la commande\n"); 
      } 
     } 

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

Вот то, что исполнение возвращается:

$ ./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 

И пока я здесь, когда я компилирую, execv возвращает предупреждение:

$ 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 *’ 

Что мне делать, чтобы этого избежать?

+1

Уверены ли вы в этом: 'char * adrCmd = malloc (sizeof (char *));'? – alk

+0

Возможный дубликат [вернуть более одного параметра из функции в C] (http://stackoverflow.com/questions/10264681/return-more-than-one-parameter-from-a-function-in-c) – ecatmur

+0

Ну нет ! Но когда я ставлю это так: char * adrCmd; Я получаю: Выполнение de la commande 'UWVS i' => В моей main(), adrCmd = "UWVS i" – Olbaid

ответ

1

C проходит по значению. Так что при выполнении этого

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

adrCmd является копией того, что было принято в. Перезаписи копии не изменит то, что он был скопирован из в вызывающем.

Чтобы исправить это передать вниз адрес adrCmd:

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

и использовать его как это:

*padrCmd = adr; 

Вызов searchCmd() так:

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

и определить и инициализирует adrCmd вот так;

char * adrCmd = NULL; 
+0

Спасибо большое! Он решил проблему, и я вижу, что я ошибся! :п – Olbaid