c unix execl无法使用strcat构建的字符串

时间:2014-12-05 18:23:34

标签: c unix

我正在尝试使用使用命令行参数构建的路径名运行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”。

1 个答案:

答案 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; } ,可以直接使用asprintfsnprintf自行推送。如果您没有malloc获取真正的计算机。)