C程序如何将空白参数传递给libc system(3)调用?

Wil*_*ard 1 c whitespace arguments

当C程序调用system()运行Unix命令时,我知道可以将参数传递给命令,并根据StackOverflow应答(来自非常高代表的用户),system()调用使用shell来执行命令.

让我感到惊讶的是,system("ls -lh >/dev/null 2>&1");作为system()一个C程序的示例调用,因为它看起来像使用相同的空格分隔的"单词",因为shell使用交互式.

从我作为系统管理员的角度来看,我想了解system()在C系统中对我的系统上的某些文件或命令执行调用时的附带条件和缺陷是什么.将包含空格的文件名传递到shell脚本非常容易出错 ; C程序调用命令时有类似的问题吗?

或者说点甚至更直观(虽然不太准确):新手编写的C程序是否有可能像包含空白的文件名那样打破shell脚本?

cuo*_*glm 6

这里的C源代码无关,传递给system()的字符串是在shell上下文中运行的.shell将解析该字符串,而您的C程序则不会.


如果你看一下system()函数原型:

#include <stdlib.h>

int system(const char *command);
Run Code Online (Sandbox Code Playgroud)

传递给的参数system()是一个字符串.它与字符串中的空格字符无关,它获取一个字符串并将该字符串传递给其他系统调用.和你一样:

sh -c 'ls -l'
Run Code Online (Sandbox Code Playgroud)

这里system()使用execve():

$ cat <<\CODE | gcc -xc -
#include <stdlib.h>
int main(void) {
  system("ls -l");
  return 0;
}
CODE

$ strace -fe execve ./a.out
execve("./a.out", ["./a.out"], [/* 64 vars */]) = 0
Process 16281 attached
[pid 16281] execve("/bin/sh", ["sh", "-c", "ls -l"], [/* 64 vars */]) = 0
Process 16282 attached
[pid 16282] execve("/bin/ls", ["ls", "-l"], [/* 64 vars */]) = 0
...
Run Code Online (Sandbox Code Playgroud)