您还没有定义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或其他程序。 –