将文件路径解析为C

时间:2015-09-16 02:33:04

标签: c shell path filepath

我目前的任务是在C中编写一个原始shell,并且很难实现shell功能,该功能构建了一个给定请求程序的路径。例如将用户输入wc转换为/usr/bin/wc

Getenv()正常工作以获得$ PATH的值。使用我的教师提供的代码,我还将此值解析为单个“令牌”,其中定义了令牌:typedef char *tok_t

我的问题是我如何修复以下函数的这个实现,该函数寻求返回给定文件名的绝对路径(如果找到),否则NULL

此处的主要问题是连接tok_tchar*以生成完整路径名。

char *resolve_path(char *filename) {
    printf("trying to resolve path...\n");
    char *path_var = getenv("PATH");
    tok_t *path_list = get_toks(path_var);
    //fprint_tok(stdout, path_list);
    char *path;
    for (int i = 0; path_list[i]; i++) {
       path = (char*) malloc(PATH_MAX);
       strcat(path, *path_list[i]);
       strcat(path, filename);
       printf("Trying... %s\n", path);
       if (file_exists(path)) {
           return path;
       }
       free(path);
    }
    return NULL;
}

我应该打扰malloc()和strcat(),还是有更好的方法来实现它?目前正在使用strcat()获取有关类型兼容性的段错误和警告。

2 个答案:

答案 0 :(得分:2)

您需要使用malloc(),因为您从函数返回结果路径(在函数返回后,指向此函数中创建的自动数组的指针无效)。您需要使用strcat()或类似内容才能生成一个连续的char *以传递给file_exists()

但是您的代码存在一些问题:

  • 不要将void *明确地投射到C中的其他类型 - 充其量,这是不必要的(I'm talking about casting the return value of your allocation, in this case)。
  • 检查malloc()是否失败。
  • 您不需要在循环中调用malloc()free() - 在循环外只需一次(每次)就足够了。
  • 如果tok_tchar *,则path_listchar **,因此当您将path_list[i]传递给strncpy()时,无需取消引用strncat() / char,因为当他们期望字符串时,它只是path。这可能是您的声明的原因"目前正在使用strcat()获取有关类型兼容性的段错误和警告。"
  • 您需要在第一次调用NULL之前将strcat()的第一个字符设置为strncpy(),或者更好地使用path,在这种情况下,您需要完成后,将strncat()的最后一个字符设置为NULL。
  • PATH_MAX - strlen(path)path一起使用,否则您可能会溢出char *resolve_path(const char *filename) { printf("trying to resolve path...\n"); char *path_var = getenv("PATH"); tok_t *path_list = get_toks(path_var); char *path = malloc(PATH_MAX+1); // See, no cast, and the +1 is for the NULL if (!path) { return NULL; // Check for failure } // strncpy/strncat won't null-terminate path if we run out of space path[PATH_MAX] = NULL; for (int i = 0; path_list[i]; i++) { // this could be done more efficiently with memcpy/hand-coding/etc strncpy(path, path_list[i], PATH_MAX); // don't dereference it strncat(path, filename, PATH_MAX - strlen(path)); printf("Trying... %s\n", path); if (file_exists(path)) { return path; } } free(path); return NULL; }

以下是一个例子:

{{1}}

答案 1 :(得分:0)

我在@Iskar_Jarak's answer上进行了阐述,因为使用该代码仍会导致分段错误。

因为tok_t只是char*的typedef,所以它会使代码混乱。 get_toks()是(没有typedef' s)技术上只返回{​​{1}}。

这意味着这一行:

char**

实际应该是

strncpy(path, *path_list[i], PATH_MAX);

因为你不应该取消引用strncpy(path, path_list[i], PATH_MAX); 。如果您这样做,则会在path_list[i]时将char传递给strncpy。这就是为什么你得到那个警告和一个段错误的原因。

所以,对于它的价值,这里是我对你的代码的更正:

char*