我对 C 的了解非常有限。我正在尝试对从客户端传递给服务器的字符串进行标记化,因为我想使用传递给 execve
的参数。通过buffer
传递的参数需要复制到*argv
并进行标记化,以便buffer
的标记可以通过argv[ 0]
、argv[1]
等。显然我做错了什么。
n = read(sockfd, buffer, sizeof(buffer));
strcpy(*argv, buffer);
printf("buffer:%s\n", buffer);
printf("argv:%s\n", *argv);
printf("argv[0]:%s\n", argv[0]);
printf("argv[1]:%s\n", argv[1]);
*argv = strtok_r(*argv, " ", argv);
printf("argv:%s\n", *argv);
i = fork();
if (i < 0) {
//Close socket on fork error.
perror("fork");
exit(-1);
} else if (i == 0) {
//execve on input args
execve(argv[0], &argv[0], 0);
exit(0);
} else {
wait(&status);
//close(sockfd);
}
将参数“/bin/date -u”与上述代码一起传递会得到以下输出:
buffer:/bin/date -u
argv:/bin/date -u
argv[0]:/bin/date -u
argv[1]:(null)
我的输出是什么:
buffer:/bin/date -u
argv:/bin/date -u
argv[0]:/bin/date
argv[1]:-u
我尝试使用strtok_r()
,但它并没有像我预期的那样工作。我插入的片段是:
*argv = strtok_r(*argv, " ", argv);
printf("argv:%s\n", *argv);
输出 argv:/bin/date
。
提前致谢,SO。
编辑:我不必像上面那样显式标记buffer
。从客户端获取传递给服务器的参数的任何方式都可以正常工作。
最佳答案
好吧,您要处理几个问题。第一个是选择 argv
作为您要写入缓冲区的变量。虽然它只是一个指针数组,但您通常将 argv
视为包含传递给 即时过程的参数的数组,而不是要修改的变量。但是,这确实是语义,据我所知,没有禁止这样做的规定。但是,您不能在将标记分配给 *argv
的同时对 *argv
进行标记,因为 strtok_r
修改了 *argv
在此过程中。
除此之外,真正的问题似乎是 strtok_r
的使用。看看 man strtok_r
。为了标记字符串,您需要重复调用strtok_r
以提取所有标记。使用第一个参数 (*argv...) 对 strtok_r
的第一次调用仅提取 first 标记。为了完成提取,您必须传递 NULL
作为第一个参数,直到提取完所有标记。此外,您从中提取 token 的字符串已通过调用 strtok_r
进行修改,不应在提取后使用。如果以后需要,通常会制作字符串的副本以保留原始字符串。
在您的代码中,您只调用一次 strtok_r
例如:
*argv = strtok_r(*argv, " ", argv); // extracts the first token and modifies *argv
如果您的目的是提取所有字符串,那么您将需要重复调用 strtok_r
,例如:
char *token = malloc (sizeof (token) * 128); // or something large enough to hold the tokens
token = strtok_r(*argv, " ", argv);
if (token)
printf (" token: %s\n", token);
while ((token = strtok_r (NULL, " ", argv)) != NULL)
{
printf (" token: %s\n", token);
}
您可以根据需要捕获单个 token ,以便将它们传递给 execve
。但是,您将无法在写回 argv
的同时从 argv
中剥离 token 。如上所述,argv
在提取期间由 strtok_r
修改,因此您需要一个单独的数组来保存标记。希望这会有所帮助。
关于c - 标记一个字符串以作为 char * 传递给 execve(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24796266/