您還沒有定義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);
}
不使用'得到()'這可能會導致溢出,喜歡'函數getline()'或'與fgets()' – Aif
顯示1)方面,2)的努力,3)預期的行爲,4)結果(或錯誤消息),你會得到。然後它將有可能幫助... – ppeterka
請注意,它應該是'int main(void)';在Unix系統上,根據C標準,'main()'返回一個'int'。返回的值是程序的退出狀態,報告給啓動該程序的shell或其他程序。 –