0

我有一个算法,它查看一个包含多个路径的数组,并检查数组中列出的任何目录中是否存在命令(例如 ls、wc、cat ... 等)。如果在其中一个目录中找到该文件,则返回完整的目录路径。

char *LookupPath(char **argv, char **dir)
{
    /* String Name To Be Returned */
    char *result;
    char path_name[MAX_PATH_LEN] = {0};
    int i;

    /* Check To See If File Name Is Already An Absolute Path Name */
    if(*argv[0] == '/') {

    }

    /* Look In Path Directories */
    for(i = 0; dir[i] != NULL; i++) {
        strncat(path_name, dir[i], sizeof(path_name));
        strncat(path_name, "/", sizeof(path_name));
        strncat(path_name, argv[0], sizeof(path_name));
        printf("pathname: %s\n", path_name);
        result = path_name;
        if(access(result, F_OK) == 0) {
            printf("SUCCESS!\n");
            printf("result: %s\n", result);
            return result;
        }
        path_name[0] = '\0';
    }

    /* File Name Not Found In Any Path Variable */
    return NULL;
}

新问题:当使用诸如 ls -l 或其他任何命令时,结果效果很好,如下面的结果代码所示。

pathname: /usr/lib/lightdm/lightdm/ls
pathname: /usr/local/sbin/ls
pathname: /usr/local/bin/ls
pathname: /usr/sbin/ls
pathname: /usr/bin/ls
pathname: /sbin/ls
pathname: /bin/ls
SUCCESS!
result: /bin/ls

但是,现在当我只使用一个简单的命令(例如'ls')时...结果是错误的...因为某种原因,一个换行符被添加到ls...?它出现:

pathname: /usr/lib/lightdm/lightdm/ls

pathname: /usr/local/sbin/ls

pathname: /usr/local/bin/ls

pathname: /usr/sbin/ls

pathname: /usr/bin/ls

pathname: /sbin/ls

pathname: /bin/ls

pathname: /usr/games/ls

pathname: /usr/local/games/ls

ls
: Command Not Found!

我不知道为什么。有什么办法可以把它缩减为'ls'。当它只是一个简单的 ls 命令时,我不知道为什么要向 argv[0] 添加一个换行符。:S

4

3 回答 3

1

您不能在循环中调用它,因为您正在修改 dir 字符串: strcat() 通过修改将源字符串附加到目标(并且您使用 dir 字符串作为目标)。此外,由于您没有为扩展字符串长度做出任何规定,因此您正在写入字符串内存的末尾并破坏其他内存。

您需要创建一个足够长的 char 数组作为局部变量,并在其中构造要测试的路径名。最好使用 snprintf() 而不是 strcat() 并确保创建的路径适合您的字符串。此外,由于您无法返回本地字符串,因此在成功的情况下,您需要 malloc() 一个结果长度的新字符串并将结果复制到那里。

至于检查它不是绝对的,检查名称的第一个字母是否是'/'。看来你已经这样做了。

于 2013-10-21T22:50:41.107 回答
0

我很确定有一些库可以为你做这件事,但你真正的问题是你每次通过循环都附加到 dir 中的路径。

结果是ptr

每次进入循环时,这些行实际上都会将 /argv[0] 附加到路径中的每个元素

    result = dir[i];
    strcat(result, "/");
    strcat(result, argv[0]);

您需要创建一个临时字符缓冲区并使用多个 strcats 或 sprintf 来填充内容。FWIW,您应该真正养成使用 strncat 或类似的带有长度参数的字符串函数的习惯。像这样的代码是许多安全问题的开始。像这样的东西

     char result[PATH_MAX]; 
     strncpy(dir[i],result,length(dir[i))
于 2013-10-21T22:56:47.553 回答
0

是的,strcat看起来是这里的问题。假设这char **dir是一个标准的字符串数组,当你进入它时,你可能会跑到最后strcat,这很糟糕。正如我自己所说

不!不!不是strcatstrcat分配缓冲区溢出就像太阳分配阳光一样!...说真的,不要

您需要在循环中分配某种缓冲区;说,

char buf[BUFSIZE] = {0};
result = buf;

哪里d 足够大(我的疯狂估计:尝试 300)BUFSIZE#define

然后尝试以下操作:

strlcpy(buf, dir[i], BUFSIZE);
strlcat(buf, "/", BUFSIZE);
strlcat(buf, argv[0], BUFSIZE);

警告:我现在不能测试这个;我只认为它有效。不过应该没问题。

信息strlcpystrlcat

于 2013-10-21T22:58:03.090 回答