2012-11-28 43 views
2

我需要一個程序,它像lsdate等,並檢查一些系統命令,如果有包括該指令(文件)的路徑。我有變量commandandparameters,開始在最後while循環中更改,我不知道爲什麼。爲什麼我的var在while循環中被更改?

我把puts(commandandparameters);表明,如果要運行它的輸出是不好的。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
void main() 
{ 
    char *arr[5];//for the command and his parameter 
    char command[10]; 
    int i,j; 
    char *path=NULL,*tempath,*finalpath,*commandandparameters; 
    do 
    { 
     i=0; 
     printf("enter new command:"); 
     gets(command); 
     arr[i]=strtok(command," "); 
     while(arr[i]!=NULL)//save the command and also the parametrs 
     { 
      i++; 
      arr[i]=strtok(NULL," "); 
     } 
     strcpy(commandandparameters,arr[0]);//add first command 
     for(j=1;j<i;j++)//add the parameters 
      { 
       strcat(commandandparameters," "); 
       strcat(commandandparameters,arr[j]); 
      } 
     //now we check if the command in every path 
     path = getenv("PATH"); 
     tempath = strtok(path,":"); 
     while (tempath != NULL) 
     { 
      strcpy(finalpath,tempath);//get the current path 
      puts(commandandparameters); 
      strcat(finalpath,"/");//we add '/' 
      execl(finalpath,commandandparameters,NULL); 
      tempath = strtok(NULL, ":");//get next path 
     } 
    }while(command!="leave"); 
} 
+2

不使用'得到()'這可能會導致溢出,喜歡'函數getline()'或'與fgets()' – Aif

+1

顯示1)方面,2)的努力,3)預期的行爲,4)結果(或錯誤消息),你會得到。然後它將有可能幫助... – ppeterka

+2

請注意,它應該是'int main(void)';在Unix系統上,根據C標準,'main()'返回一個'int'。返回的值是程序的退出狀態,報告給啓動該程序的shell或其他程序。 –

回答

1

你只存儲由strtok()返回指針,他們會點進去command。循環的每次迭代都會覆蓋command,從而導致「舊」指針指向的數據發生更改。

必須複製出令牌出command,無論是到動態分配的內存(查找malloc())或具有如一個靜態大小的字符串數組。在這種情況下,請注意緩衝區溢出。

4

您還沒有定義commandandparameters點的空間:

char *path=NULL,*tempath,*finalpath,*commandandparameters; 
... 
    strcpy(commandandparameters,arr[0]); 

你有一個指針指向隨機空間;你複製那個隨機空間。你會得到有趣的結果。如果你幸運的話,該程序將崩潰。如果你不走運,它會變得不合時宜。

您也有類似的問題,finalpath

path = getenv("PATH"); 
    tempath = strtok(path,":"); 
    while (tempath != NULL) 
    { 
     strcpy(finalpath,tempath); 

更糟的是,你還屠宰環境。除非您打算修改PATH的值,否則getenv()返回的字符串應視爲只讀。實際上,在循環之後,您將不會留下太多PATH(如果第一個元素爲:),則不會執行PATH。

確保您知道每個指針指向的位置。

你的代碼有很多潛在的緩衝區溢出,它是令人毛骨悚然的。千萬不要使用gets();假設它會將你的電腦炸成碎片。


如果您解決了這些問題,則do { ... } while (command != "leave");循環等於無限循環。你不能像這樣有用地比較字符串;你需要使用strcmp()


我嘗試做一個簡單的程序,我看到execl()無法正常工作;有人能告訴我爲什麼「ls」命令不起作用嗎?

這裏是你的代碼註釋的稍作修改的版本。我添加了兩個標題和換行符,但關鍵的改變是在execl()行。你的原稿在評論中;工作版本不是評論。我無法決定這是您的主要問題還是評論中的拼寫錯誤。修改後的代碼編譯並運行。

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

int main(void) 
{ 
    int pid, stat; 

    if ((pid = fork()) == 0) 
    { 
     execl("/bin/ls", "ls", NULL); 
     //execl("/bin/", "ls", NULL); 
     printf("1\n"); 
     exit(1); 
    } 
    else 
    { 
     wait(&stat); 
     printf("2\n"); 
    } 
} 

在你的程序中的代碼拆除PATH;如果您未能執行第一個程序,此後它只會在原始PATH的第一個目錄中查找。您正嘗試使用execl()來處理可變數量的參數;這是工作的錯誤工具。例如,您必須使用execv()或其親屬之一(execvp()將執行PATH搜索,而不會搞亂PATH)。原因是execl()需要一組由null指針終止的參數,但只有當您知道有多少個參數時才能寫出該參數。你可以寫:

execl("/bin/ls", "ls", "-l", (char *)0); 

,但除非你強迫每個命令有最多4個參數(給出char *arr[5];),並使用一個模板,如:

execl(finalpath, arr[0], arr[1], arr[2], arr[3], arr[4]); 

不能使用execl()執行命令。但是這限制了用戶最多N個參數,這是不可接受的。 (例如,*殼膨脹,可產生的30個或更多參數的列表

您的代碼還沒有附加命令名添加到路徑分量;的第一個參數execl()是程序可執行文件的路徑

因此,使用execv()(或execvp()execve()甚至,如果你有的話,execvpe())這是你的程序的或多或少稍加修改,如果你執行命令,發現工程確定;它是一個小災難,如果它不是,它是一個一次性的外殼;它不像fork()execv(),它應該是這樣的 - 如果你在分割路徑之前分叉,路徑mangli ng會更少,儘管流程運行對於不存在的路徑是最小的。

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

int main(void) 
{ 
    char *arr[5];//for the command and his parameter 
    char command[100]; // Not 10 
    int i; 
    int j; 
    char *path=NULL; 
    char *tempath; 
    char finalpath[200]; 
    char commandandparameters[200]; 

    do 
    { 
     i = 0; 
     printf("enter new command: "); 
     if (fgets(command, sizeof(command), stdin) == 0) 
     { 
      fprintf(stderr, "EOF or error\n"); 
      break; 
     } 
     arr[i]=strtok(command, " "); 
     while (i < (5-1) && arr[i]!=NULL)//save the command and also the parameters 
     { 
      printf("arr[%d] = %s\n", i, arr[i]); 
      i++; 
      arr[i]=strtok(NULL, " \n"); 
     } 
     arr[4] = 0; 

     strcpy(commandandparameters, arr[0]);//add first command 
     for (j=1;j<i;j++)//add the parameters 
      { 
       strcat(commandandparameters, " "); 
       strcat(commandandparameters, arr[j]); 
      } 
     printf("Cmd&Params: %s\n", commandandparameters); 

     //now we check if the command in every path 
     path = getenv("PATH"); 
     tempath = strtok(path, ":"); 
     while (tempath != NULL) 
     { 
      puts(commandandparameters); 
      strcpy(finalpath, tempath);//get the current path 
      strcat(finalpath, "/");//we add '/' 
      strcat(finalpath, arr[0]); 
      puts(finalpath); 
      execv(finalpath, arr); 
      tempath = strtok(NULL, ":");//get next path 
     } 
    } while (strcmp(command, "leave") != 0); 
    return(0); 
} 
+0

我修復了很多事情,但stil程序沒有做這項工作,並且比我嘗試做簡單的程序,我發現execl不工作,有人可以告訴我爲什麼「ls」命令不工作 #inc main() int pid,stat; ((pid = fork())== 0) execl(「/ bin /」,「ls」,NULL); 012fprintf(「1」); \t exit(1); } 其他 { 等待(&stat); 的printf( 「2」);} } –

+0

@AsafShay:見我修改(擴展)的答案。 –

相關問題