将命令行参数字符串解析为 posix_spawn/execve 的数组
Parse command line arguments string into array for posix_spawn/execve
给定表示程序命令行参数的单个字符串 cmd
,如何获取可以传递给 posix_spawn
或 execve
的字符串数组 argv
。
应适当处理各种形式的引用(和转义引号)(生成的调用应与 POSIX 兼容的 shell 相同)。支持其他转义字符将是可取的。示例:#1, #2, #3.
正如 Shawn 评论的那样,在 Linux 和其他 POSIXy 系统中,您可以使用 wordexp(),它作为此类系统上标准 C 库的一部分提供。例如,run.h:
#ifdef __cplusplus
extern "C" {
#endif
/* Execute binary 'bin' with arguments from string 'args';
'args' must not be NULL or empty.
Command substitution (`...` or $(...)$) is NOT performed.
If 'bin' is NULL or empty, the first token in 'args' is used.
Only returns if fails. Return value:
-1: error in execv()/execvp(); see errno.
-2: out of memory. errno==ENOMEM.
-3: NULL or empty args.
-4: args contains a command substitution. errno==EINVAL.
-5: args has an illegal newline or | & ; < > ( ) { }. errno==EINVAL.
-6: shell syntax error. errno==EINVAL.
In all cases, you can use strerror(errno) for a descriptive string.
*/
int run(const char *bin, const char *args);
#ifdef __cplusplus
}
#endif
并将以下 C 源代码编译为一个对象文件,您 link 将其放入您的 C 或 C++ 程序或库中:
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <wordexp.h>
#include <string.h>
#include <errno.h>
int run(const char *bin, const char *args)
{
/* Empty or NULL args is an invalid parameter. */
if (!args || !*args) {
errno = EINVAL;
return -3;
}
wordexp_t w;
switch (wordexp(args, &w, WRDE_NOCMD)) {
case 0: break; /* No error */
case WRDE_NOSPACE: errno = ENOMEM; return -2;
case WRDE_CMDSUB: errno = EINVAL; return -4;
case WRDE_BADCHAR: errno = EINVAL; return -5;
default: errno = EINVAL; return -6;
}
if (w.we_wordc < 1) {
errno = EINVAL;
return -3;
}
if (!bin || !*bin)
bin = w.we_wordv[0];
if (!bin || !*bin) {
errno = ENOENT;
return -1;
}
/* Note: w.ve_wordv[w.we_wordc] == NULL, per POSIX. */
if (strchr(bin, '/'))
execv(bin, w.we_wordv);
else
execvp(bin, w.we_wordv);
return -1;
}
例如,run(NULL, "ls -laF $HOME");
将列出当前用户主目录的内容。环境变量将被扩展。
run("bash", "sh -c 'date && echo'");
执行 bash
,argv[0]=="sh"
、argv[1]=="-c"
和 argv[2]=="date && echo"
。这使您可以控制要执行的二进制文件。
给定表示程序命令行参数的单个字符串 cmd
,如何获取可以传递给 posix_spawn
或 execve
的字符串数组 argv
。
应适当处理各种形式的引用(和转义引号)(生成的调用应与 POSIX 兼容的 shell 相同)。支持其他转义字符将是可取的。示例:#1, #2, #3.
正如 Shawn 评论的那样,在 Linux 和其他 POSIXy 系统中,您可以使用 wordexp(),它作为此类系统上标准 C 库的一部分提供。例如,run.h:
#ifdef __cplusplus
extern "C" {
#endif
/* Execute binary 'bin' with arguments from string 'args';
'args' must not be NULL or empty.
Command substitution (`...` or $(...)$) is NOT performed.
If 'bin' is NULL or empty, the first token in 'args' is used.
Only returns if fails. Return value:
-1: error in execv()/execvp(); see errno.
-2: out of memory. errno==ENOMEM.
-3: NULL or empty args.
-4: args contains a command substitution. errno==EINVAL.
-5: args has an illegal newline or | & ; < > ( ) { }. errno==EINVAL.
-6: shell syntax error. errno==EINVAL.
In all cases, you can use strerror(errno) for a descriptive string.
*/
int run(const char *bin, const char *args);
#ifdef __cplusplus
}
#endif
并将以下 C 源代码编译为一个对象文件,您 link 将其放入您的 C 或 C++ 程序或库中:
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <wordexp.h>
#include <string.h>
#include <errno.h>
int run(const char *bin, const char *args)
{
/* Empty or NULL args is an invalid parameter. */
if (!args || !*args) {
errno = EINVAL;
return -3;
}
wordexp_t w;
switch (wordexp(args, &w, WRDE_NOCMD)) {
case 0: break; /* No error */
case WRDE_NOSPACE: errno = ENOMEM; return -2;
case WRDE_CMDSUB: errno = EINVAL; return -4;
case WRDE_BADCHAR: errno = EINVAL; return -5;
default: errno = EINVAL; return -6;
}
if (w.we_wordc < 1) {
errno = EINVAL;
return -3;
}
if (!bin || !*bin)
bin = w.we_wordv[0];
if (!bin || !*bin) {
errno = ENOENT;
return -1;
}
/* Note: w.ve_wordv[w.we_wordc] == NULL, per POSIX. */
if (strchr(bin, '/'))
execv(bin, w.we_wordv);
else
execvp(bin, w.we_wordv);
return -1;
}
例如,run(NULL, "ls -laF $HOME");
将列出当前用户主目录的内容。环境变量将被扩展。
run("bash", "sh -c 'date && echo'");
执行 bash
,argv[0]=="sh"
、argv[1]=="-c"
和 argv[2]=="date && echo"
。这使您可以控制要执行的二进制文件。