我正在尝试使用使用命令行参数构建的路径名运行execl。它没有工作,所以我硬编码连接的字符串,所以它仍然无法正常工作。如果我提供char * path =“some path name”并将其传递给execl,它可以正常工作。
#include <stdio.h>
int main(int argc,char *argv[]){
//set char path name
char pathname[256];
strcat(pathname,"/bin/");
strcat(pathname,"ls"); //"ls" will be replaced with arg[1]
int pid=fork();
if (pid==0){
execl(pathname,"ls",(char *)0);
}
else{
wait((int*)0);
}
return 0;
}
我打印出路径名以确保它是“/ bin / ls”。
答案 0 :(得分:1)
问题在于:
char pathname[256];
strcat(pathname,"/bin/");
您没有初始化pathname
。因此,它的内容是“不确定的”,对strcat
的调用具有官方称为未定义的行为 - 它允许按字面意思任何。可能发生的具体事情是,分配给pathname
的内存空间中存在一些二进制垃圾,strcat
高兴地将其视为字符串,因此pathname
之后的内容{ {1}}调用类似于(十六进制)
strcat
打印出字符串时,那些前导控制字符不可见,但是当您调用01 02 03 2f 62 69 63 2f 6c 73 00
时,内核高兴地接受了执行名为execl
的文件的请求(相对于当前工作目录) ,当然),由于没有这样的文件,失败并将"\001\002\003/bin/ls"
设置为errno
。在ENOENT
之后立即使用perror(pathname)
,并使用execl
调用该程序,您会看到类似
./a.out 2>&1 | cat -v
将第一个^A^B^C/bin/ls: No such file or directory
更改为strcat
会更正此问题,因为strcpy
始终会复制到目标缓冲区的开头,而忽略之前的任何内容;一旦完成,strcpy
到第一个NUL并包括第一个NUL的字节是确定的,buf
具有明确定义的行为......
...但是,如果你将程序改回到strcat
之后从/bin/
读取要复制的东西,并且第一个命令行参数长度超过250个字节,那么,你再次有未定义的行为。 更好编写此程序的方法是使用asprintf
:
argv[1]
(如果您没有int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s program\n", argv[0]);
return 2;
}
char *pathname;
if (asprintf(&pathname, "/bin/%s", argv[1]) == -1) {
perror("asprintf");
return 1;
}
execl(pathname, argv[1], (char *)0);
perror(pathname);
return 127;
}
,可以直接使用asprintf
和snprintf
自行推送。如果您没有malloc
获取真正的计算机。)