c - 为什么我的 var 在 while 循环中被改变?

标签 c linux

我需要制作一个程序,它接受一些系统命令,如lsdate等,并检查是否存在包含此命令(文件)的路径。我有变量 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");
}

最佳答案

您尚未定义 commandandparameters 指向的空间:

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 的值。事实上,循环之后不会留下太多 PATH(如果其第一个元素是 :,则没有 PATH)。

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

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


如果解决了这些问题,do { ... } while (command != "leave"); 循环就相当于无限循环。你不能像这样有效地比较字符串;您需要使用strcmp()


I try to do a simple program and I see that execl() not work; can someone tell me why "ls" command don't work?

这是评论中代码的稍微修改版本。我在打印中添加了两个标题和换行符,但关键的更改是在 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;如果您无法执行第一个程序,此后它只会在原始路径上的第一个目录中查找。您尝试使用 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 个参数,这是 Not Acceptable 。 (例如,* 的 shell 扩展可以生成包含 30 个或更多参数的列表。

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

因此,请使用 execv() (或 execvp()execve() ,甚至,如果有的话, execvpe())。这是对程序的或多或少的最小修改,如果找到您执行的命令,则可以正常工作;如果不是,那就是小灾难了。这是一枚一次性炮弹;它不像它应该的那样 fork()execv() - 如果你在修改路径之前进行 fork ,那么路径修改将不那么重要,尽管进程运行会有一条最小甚至不存在的路径。

#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);
}

关于c - 为什么我的 var 在 while 循环中被改变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13606255/

相关文章:

c++ - 为什么我的控制台不等待 VS2010 和 Windows7 中的输入?

linux - 我的 Centos 服务器上的日期和时间错误

.net - 如何从网络程序集调用shell脚本

linux - 我应该如何在 NASM Assembly 中使用动态大小的输入?

C 程序 Switch 和 If 语句

c - "variable"使用 C 预处理器进行长度初始化

c - 递归函数除以一个数

linux - 附加脚本是否试图破解密码?

linux - 直到 9999 年,Linux cal 命令是否正确?

c - 如何在c中读取内核日志消息?