我需要创建一个程序,它接受一些系统命令,如ls
,date
等,并检查是否有包含此命令(文件)的路径。我的变量commandandparameters
在上一个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");
}
答案 0 :(得分: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()
需要一组由空指针终止的参数,但是只有在知道有多少参数时才能写出。你可以写:
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个参数,这是不可接受的。 (例如,*
的shell扩展可以生成包含30个或更多参数的列表。
您的代码也没有将命令名称附加到路径组件; execl()
的第一个参数是程序可执行文件的路径。
因此,请使用execv()
(或execvp()
或execve()
,如果有的话,请使用execvpe()
)。这是对程序的或多或少的最小修改,如果找到你执行的命令,它可以正常工作;如果不是,那将是一场小小的灾难。这是一次性的外壳;它不像它应该fork()
和execv()
- 并且如果你在修改路径之前分叉,那么路径修改会更少,尽管进程运行会有一个最小到不存在的路径。 / p>
#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);
}
答案 1 :(得分:1)
您只存储strtok()
返回的指针,它们将指向command
。循环的每次迭代都将覆盖command
,从而导致“旧”指针指向的数据被更改。
您必须将command
之外的令牌复制到动态分配的内存中(查找malloc()
),或者例如一组staticallly大小的字符串。在这种情况下,请注意缓冲区溢出。