我目前的任务是在C中编写一个原始shell,并且很难实现shell功能,该功能构建了一个给定请求程序的路径。例如将用户输入wc
转换为/usr/bin/wc
。
Getenv()正常工作以获得$ PATH的值。使用我的教师提供的代码,我还将此值解析为单个“令牌”,其中定义了令牌:typedef char *tok_t
我的问题是我如何修复以下函数的这个实现,该函数寻求返回给定文件名的绝对路径(如果找到),否则NULL
。
此处的主要问题是连接tok_t
和char*
以生成完整路径名。
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()获取有关类型兼容性的段错误和警告。
答案 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_t
是char *
,则path_list
是char **
,因此当您将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*