将exec输出从函数发送到main方法
Sending exec output from function to main method
我有一个从 main 方法调用的方法,它在某个目录上执行 ls-l
,我希望它执行它并将结果作为字符串发送到 main 方法。
我当前的有缺陷代码:
char *lsl(){
char *stringts=malloc(1024);
chdir("/Users/file/path");
char * lsargs[] = { "/bin/ls" , "-l", NULL};
stringts="The result of ls-l in the created directory is:"+ execv(lsargs[0], lsargs);
return stringts;
}
目前我只在屏幕上得到 exec
输出,我理解 为什么会这样(exec
在到达 [=29 之前被调用=]点)。但是我不知道我怎么可能做我想做的事以及它是否真的可行。
我正在考虑使用管道和 dup2()
所以我不让 exec
函数使用 stdout
但我不知道是否可以将以字符串形式输出。
正如 Jonathan Leffler 已经在评论中指出的那样,C 中没有用于连接字符串的“+”运算符。
动态扩展字符串的一种可能性是将 realloc 与 strcat 一起使用。
对于从管道中读取的每个字节数,您可以检查最初为字符串分配的内存的剩余容量,如果这不够,则重新分配两倍大小。
您必须自己跟踪当前字符串的大小。您可以使用 size_t 类型的变量来执行此操作。
如果将它与 popen 处理结合起来,它可能看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
FILE *fp;
if ((fp = popen("ls -l", "r")) == NULL) {
perror("popen failed");
return EXIT_FAILURE;
}
size_t str_size = 1024;
char *stringts = malloc(str_size);
if (!stringts) {
perror("stringts allocation failed");
return EXIT_FAILURE;
}
stringts[0] = '[=10=]';
char buf[128];
size_t n;
while ((n = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
buf[n] = '[=10=]';
size_t capacity = str_size - strlen(stringts) - 1;
while (n > capacity) {
str_size *= 2;
stringts = realloc(stringts, str_size);
if (!stringts) {
perror("stringts realloation failed");
return EXIT_FAILURE;
}
capacity = str_size - strlen(stringts) - 1;
}
strcat(stringts, buf);
}
printf("%s\n", stringts);
free(stringts);
if (pclose(fp) != 0) {
perror("pclose failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
你的代码有几个缺陷:
char *lsl(){
char *stringts=malloc(1024);
chdir("/Users/file/path");
char * lsargs[] = { "/bin/ls" , "-l", NULL};
stringts="The result of ls-l in the created directory is:"+ execv(lsargs[0], lsargs);
return stringts;
}
- 如果您
malloc(3)
将一个 1024 字节的缓冲区放入 stringts
指针,但随后您为该指针分配了一个不同的值,从而使您的缓冲区在您的巨大 RAM 中丢失。
- 当您执行
execv(2)
调用时,您的进程的所有内存都被内核释放并通过执行命令 ls -l
重新加载,您将在标准输出中获得输出的过程,然后你会得到shell的提示。这会使您的程序的其余部分无用,因为一旦执行,就无法返回,您的程序将被卸载并释放。
- 您可以将 (
+
) 添加到一个指针值(您确实添加到指向字符串 "The result of the ls -l..."
的地址并且 --- 因为 exec 的结果是什么,作为一个新的程序已加载---你什么也得不到)如果 execv
失败,那么你会得到一个指向该字符串的前一个字符的指针,这是 C 中的有效表达式,但会使你的程序在 Undefined 中表现不稳定行为。使用 strcpy(3)
、strcat(3)
或 snprintf(3)
,具体取决于您要复制到您分配的缓冲区的 space 中的确切文本。
- 您的
return
结果是一个无效地址。这里的问题是,如果 execv(2)
有效,它不会 return。只有当它失败时,你才会得到一个你不能使用的无效指针(由于上述原因),当然 ls -l
还没有被执行。好吧,你没有说你得到了什么作为输出,所以我很难猜到你是否真的 exec()
d 程序。
另一方面,您有一个 popen(3)
库函数,它允许您执行子程序并允许您从文件描述符中读取其输出(我建议您不要无故地 chdir
您的程序,因为这是您程序环境中的全局更改,恕我直言,最好将 ls(1)
您要列出的目录作为参数传递)
#include <stdio.h>
FILE *lsl() {
/* the call creates a FILE * descriptor that you can use as input and
* read the output of the ls command. It's bad resources use to try to
* read all in a string and return the string instead. Better read as
* much as you can/need and then pclose() the descriptor. */
return popen("/bin/ls -l /Users/file/path|", "rt");
}
然后你可以阅读(因为它可能是很长的输出,如果你有一个巨大的目录,你可能没有足够的缓冲区 space 在内存中处理它)
FILE *dir = lsl();
if (dir) {
char buffer[1024];
while (fgets(buffer, sizeof buffer, dir)) {
process_line_of_lsl(buffer);
}
pclose(dir); /* you have to use pclose(3) with popen(3) */
}
如果你不想使用popen(3)
,那么你不能单独使用execv(2)
,你必须先fork(2)
,创建一个新进程,然后exec()
在子进程中(在你自己安装重定向之后)。阅读 fork()
/exec()
以及如何在 fork()
和 exec()
之间重定向 I/O 的很好的介绍,因为将它放在这里更长更详细(再次)
我有一个从 main 方法调用的方法,它在某个目录上执行 ls-l
,我希望它执行它并将结果作为字符串发送到 main 方法。
我当前的有缺陷代码:
char *lsl(){
char *stringts=malloc(1024);
chdir("/Users/file/path");
char * lsargs[] = { "/bin/ls" , "-l", NULL};
stringts="The result of ls-l in the created directory is:"+ execv(lsargs[0], lsargs);
return stringts;
}
目前我只在屏幕上得到 exec
输出,我理解 为什么会这样(exec
在到达 [=29 之前被调用=]点)。但是我不知道我怎么可能做我想做的事以及它是否真的可行。
我正在考虑使用管道和 dup2()
所以我不让 exec
函数使用 stdout
但我不知道是否可以将以字符串形式输出。
正如 Jonathan Leffler 已经在评论中指出的那样,C 中没有用于连接字符串的“+”运算符。
动态扩展字符串的一种可能性是将 realloc 与 strcat 一起使用。
对于从管道中读取的每个字节数,您可以检查最初为字符串分配的内存的剩余容量,如果这不够,则重新分配两倍大小。
您必须自己跟踪当前字符串的大小。您可以使用 size_t 类型的变量来执行此操作。
如果将它与 popen 处理结合起来,它可能看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
FILE *fp;
if ((fp = popen("ls -l", "r")) == NULL) {
perror("popen failed");
return EXIT_FAILURE;
}
size_t str_size = 1024;
char *stringts = malloc(str_size);
if (!stringts) {
perror("stringts allocation failed");
return EXIT_FAILURE;
}
stringts[0] = '[=10=]';
char buf[128];
size_t n;
while ((n = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
buf[n] = '[=10=]';
size_t capacity = str_size - strlen(stringts) - 1;
while (n > capacity) {
str_size *= 2;
stringts = realloc(stringts, str_size);
if (!stringts) {
perror("stringts realloation failed");
return EXIT_FAILURE;
}
capacity = str_size - strlen(stringts) - 1;
}
strcat(stringts, buf);
}
printf("%s\n", stringts);
free(stringts);
if (pclose(fp) != 0) {
perror("pclose failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
你的代码有几个缺陷:
char *lsl(){
char *stringts=malloc(1024);
chdir("/Users/file/path");
char * lsargs[] = { "/bin/ls" , "-l", NULL};
stringts="The result of ls-l in the created directory is:"+ execv(lsargs[0], lsargs);
return stringts;
}
- 如果您
malloc(3)
将一个 1024 字节的缓冲区放入stringts
指针,但随后您为该指针分配了一个不同的值,从而使您的缓冲区在您的巨大 RAM 中丢失。 - 当您执行
execv(2)
调用时,您的进程的所有内存都被内核释放并通过执行命令ls -l
重新加载,您将在标准输出中获得输出的过程,然后你会得到shell的提示。这会使您的程序的其余部分无用,因为一旦执行,就无法返回,您的程序将被卸载并释放。 - 您可以将 (
+
) 添加到一个指针值(您确实添加到指向字符串"The result of the ls -l..."
的地址并且 --- 因为 exec 的结果是什么,作为一个新的程序已加载---你什么也得不到)如果execv
失败,那么你会得到一个指向该字符串的前一个字符的指针,这是 C 中的有效表达式,但会使你的程序在 Undefined 中表现不稳定行为。使用strcpy(3)
、strcat(3)
或snprintf(3)
,具体取决于您要复制到您分配的缓冲区的 space 中的确切文本。 - 您的
return
结果是一个无效地址。这里的问题是,如果execv(2)
有效,它不会 return。只有当它失败时,你才会得到一个你不能使用的无效指针(由于上述原因),当然ls -l
还没有被执行。好吧,你没有说你得到了什么作为输出,所以我很难猜到你是否真的exec()
d 程序。
另一方面,您有一个 popen(3)
库函数,它允许您执行子程序并允许您从文件描述符中读取其输出(我建议您不要无故地 chdir
您的程序,因为这是您程序环境中的全局更改,恕我直言,最好将 ls(1)
您要列出的目录作为参数传递)
#include <stdio.h>
FILE *lsl() {
/* the call creates a FILE * descriptor that you can use as input and
* read the output of the ls command. It's bad resources use to try to
* read all in a string and return the string instead. Better read as
* much as you can/need and then pclose() the descriptor. */
return popen("/bin/ls -l /Users/file/path|", "rt");
}
然后你可以阅读(因为它可能是很长的输出,如果你有一个巨大的目录,你可能没有足够的缓冲区 space 在内存中处理它)
FILE *dir = lsl();
if (dir) {
char buffer[1024];
while (fgets(buffer, sizeof buffer, dir)) {
process_line_of_lsl(buffer);
}
pclose(dir); /* you have to use pclose(3) with popen(3) */
}
如果你不想使用popen(3)
,那么你不能单独使用execv(2)
,你必须先fork(2)
,创建一个新进程,然后exec()
在子进程中(在你自己安装重定向之后)。阅读 fork()
/exec()
以及如何在 fork()
和 exec()
之间重定向 I/O 的很好的介绍,因为将它放在这里更长更详细(再次)