C 为什么我的var在while循环中被更改?

C 为什么我的var在while循环中被更改?,c,linux,C,Linux,我需要制作一个程序,接受一些系统命令,如ls,date等,并检查是否有包含此命令(文件)的路径。我有变量commandParameters,它在最后一次循环时开始改变,我不知道为什么 I putput(命令和参数)显示输出不好,如果要运行它 #include <stdio.h> #include <string.h> #include <stdlib.h> void main() { char *arr[5];//for the command and

我需要制作一个程序,接受一些系统命令,如
ls
date
等,并检查是否有包含此命令(文件)的路径。我有变量
commandParameters
,它在最后一次
循环时开始改变,我不知道为什么

I put
put(命令和参数)
显示输出不好,如果要运行它

#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");
}
#包括
#包括
#包括
void main()
{
char*arr[5];//用于命令及其参数
char命令[10];
int i,j;
char*path=NULL,*tempath,*finalpath,*commandParameters;
做
{
i=0;
printf(“输入新命令:”);
获取(命令);
arr[i]=strtok(命令“”);
while(arr[i]!=NULL)//保存命令和参数
{
i++;
arr[i]=strtok(空,“”);
}
strcpy(commandParameters,arr[0]);//添加第一个命令

对于(j=1;j您只存储由
strtok()
返回的指针,它们将指向
command
。循环的每次迭代都将覆盖
command
,从而导致“旧”指针指向的数据被更改


您必须将令牌从
命令
复制到动态分配的内存中(查找
malloc()
),或者具有一个静态大小的字符串数组。在这种情况下,请注意缓冲区溢出。

您尚未定义
命令和参数
指向以下位置的空间:

char *path=NULL,*tempath,*finalpath,*commandandparameters;
...
    strcpy(commandandparameters,arr[0]);
你有一个指向随机空间的指针;你在那个随机空间上复制。你会得到有趣的结果。如果你运气好,程序会崩溃。如果你运气不好,它会行为不端

finalpath
也有类似的问题:

    path = getenv("PATH");
    tempath = strtok(path,":");
    while (tempath != NULL)
    {
        strcpy(finalpath,tempath);
更糟糕的是,您也在破坏您的环境。
getenv()
返回的字符串应该被视为只读,除非您打算修改PATH的值。实际上,在循环之后,您将不会有太多的路径(如果第一个元素是
,则没有路径)

确保您知道每个指针指向的位置

你的代码有太多潜在的缓冲区溢出,令人毛骨悚然。永远不要使用
get()
;假设它会把你的计算机炸成碎片


如果您解决了这些问题,那么
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");
    }
}
但除非强制每个命令最多有4个参数(给定
char*arr[5];
),并使用以下模板:

execl(finalpath, arr[0], arr[1], arr[2], arr[3], arr[4]);
您不能使用
execl()
执行命令。但这将用户限制为最多N个参数,这是不可接受的。(例如,
*
的shell扩展可以生成包含30个或更多参数的列表。)

代码也没有将命令名附加到path组件中;
execl()
的第一个参数是程序可执行文件的路径

因此,使用
execv()
(或
execvp()
execve()
,甚至,如果你有它的话,
execvpe()
)。这里有一个对你的程序的或多或少的最小修改,如果你执行的命令被找到了,它可以正常工作;如果没有,那将是一个小灾难。它是一个一次性的shell;它不是
fork()
execv()
就像它应该的那样-如果您在咀嚼路径之前分叉,那么路径损坏的问题就不会那么严重,尽管进程运行的路径将是最小的,甚至是不存在的

#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);
}
#包括
#包括
#包括
#包括
内部主(空)
{
char*arr[5];//用于命令及其参数
char命令[100];//不是10
int i;
int j;
char*path=NULL;
恰尔坦帕斯;
char finalpath[200];
char命令和参数[200];
做
{
i=0;
printf(“输入新命令:”);
如果(fgets(命令,sizeof(命令),stdin)==0)
{
fprintf(标准“EOF或错误”);
打破
}
arr[i]=strtok(命令“”);
while(i<(5-1)&&arr[i]!=NULL)//保存命令和参数
{
printf(“arr[%d]=%s\n”,i,arr[i]);
i++;
arr[i]=strtok(空,“\n”);
}
arr[4]=0;
strcpy(commandParameters,arr[0]);//添加第一个命令

对于(j=1;jdon)不使用可能导致溢出的
gets()
,请选择
getline()
fgets()
显示1)尊重,2)努力,3)预期行为,4)得到的结果(或错误消息)。然后可能会有帮助…注意,它应该是
intmain(void)
;特别是在Unix系统上,根据C标准,
main()
返回一个
int
。返回的值是程序的退出状态,报告给shell或其他启动程序的程序。我修复了很多问题,但程序仍然没有完成任务,然后我尝试执行一个简单的程序,我发现execl不工作。有人能告诉我为什么“ls”命令不工作吗?include main(){int-pid,stat;if((pid=fork())==0){execl(“/bin/”,“ls”,NULL);printf(“1”);exit(1);}否则{wait(&stat);printf(“2”);}@AsafShay:请参阅我的修订(扩展)答案。
#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);
}