【问题标题】:How to portably use system or popen, but with array of arguments?如何可移植地使用 system 或 popen,但有一系列参数?
【发布时间】:2013-09-08 14:47:30
【问题描述】:

system/popen - 可移植,但使用 shell - 一个字符串参数

pipe+fork+dup2+exec - 更多代码,更少可移植性,但可以指定数组。

中间有什么简单的吗?期待类似的东西:

const char* args = {"/usr/bin/myprogram", "myprogram", "--option", NULL};
FILE* outfile = popen_read_end_args(args);
fscanf(outfile, "...");
fclose(outfile);

使用数组调用外部程序并在 C 中读取其输出的最佳方法是什么?是否有任何不臃肿的包装器?

【问题讨论】:

  • popenv()systemv(),类比execv()?有趣的想法。后备实现将简单地将参数转换为单个字符串并调用标准函数(尽管“简单”可能有点随意;您需要确保正确引用事物)。然后,您可以在时间允许的情况下实现自己的版本。

标签: c popen argv


【解决方案1】:

自己实现了这样的包装器:https://github.com/vi/udpserv/blob/master/popen_arr.c

这是头文件:

/**
* For and exec the program, enabling stdio access to stdin and stdout of the program
* You may close opened streams with fclose.
* Note: the procedure does no signal handling except of signal(SIGPIPE, SIG_IGN);
* You should waitpid for the returned PID to collect the zombie or use signal(SIGCHLD, SIG_IGN);
*
* @arg in stdin of the program, to be written to. If NULL then not redirected
* @arg out stdout of the program, to be read from. If NULL then not redirected
* @arg program full path of the program, without reference to $PATH
* @arg argv NULL terminated array of strings, program arguments (includiong program name)
* @arg envp NULL terminated array of environment variables, NULL => preserve environment
* @return PID of the program or -1 if failed
*/
int popen2_arr (FILE** in, FILE** out, const char* program, const char* argv[], const char* envp[]);

/** like popen2_arr, but uses execvp/execvpe instead of execve/execv, so looks up $PATH */
int popen2_arr_p(FILE** in, FILE** out, const char* program, const char* argv[], const char* envp[]);

/**
* Simplified interface to popen2_arr.
* You may close the returned stream with fclose.
* Note: the procedure does no signal handling except of signal(SIGPIPE, SIG_IGN);
* You should wait(2) after closing the descriptor to collect zombie process or use signal(SIGCHLD, SIG_IGN)
*
* @arg program program name, can rely on $PATH
* @arg argv program arguments, NULL-terminated const char* array
* @arg pipe_into_program 1 to be like popen(...,"w"), 0 to be like popen(...,"r")
* @return FILE* instance or NULL if error
*/
FILE* popen_arr(const char* program, const char* argv[], int pipe_into_program);

【讨论】:

  • 你能评论一下这段代码的平台可移植性吗(你在哪里运行它)?它看起来很不错,我正在寻找适应我的目的。我正在尝试使用popen 转换代码,因为它正在生成一个shell,这让我很恼火,但我不想用fork 变得太脏。
【解决方案2】:

不,没有。除了通过system,ISO C 没有其他方法可以启动新流程。除了systempopenfork(+vfork 在 POSIX.2008 之前)之外,POSIX 没有其他方法可以启动进程。

【讨论】:

  • 是否有一些简单的库可以做到这一点?
  • @Vi.:不是我所知道的“半标准”。您可以从 BSD 获取 popen 的源代码,然后破解它以获取您正在寻找的那种参数。例如。 OpenBSD 版本是here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 2016-03-09
  • 1970-01-01
  • 2023-03-24
  • 2017-03-11
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多