c-将exec输出从函数发送到main方法



我有一个从调用的主方法调用的方法,该方法在某个目录上执行ls-l,我希望它执行它,并将结果作为字符串发送到主方法。

我当前有缺陷代码:

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在到达返回点之前被调用(。然而,我不知道我怎么可能做我想做的事,也不知道这是否真的可行。

我想使用管道和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] = '';
char buf[128];
size_t n;
while ((n = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
buf[n] = '';
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("%sn", 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;
}
  • 如果您将1024字节的缓冲区malloc(3)写入stringts指针,但随后您为指针分配了一个不同的值,使您的缓冲区在RAM的巨大空间中丢失
  • 当您调用execv(2)时,内核释放了进程的所有内存,并通过执行命令ls -l重新加载,您将在进程的标准输出中获得输出,然后您将获得shell的提示。这会使程序的其余部分变得毫无用处,因为一旦执行,就没有回头路了,程序就会被卸载并释放
  • 您可以将(+(添加到指针值中(您确实添加到了指向字符串"The result of the ls -l..."的地址中,并且--由于exec的结果为零,当加载新程序时--您一无所获(。如果execv失败,那么您将获得指向该字符串的前一个字符的指针,这在C中是一个有效的表达式,但会使您的程序以未定义的行为不稳定地运行。根据要在分配的缓冲区空间中复制的确切文本,使用strcpy(3)strcat(3)snprintf(3)
  • 因此,您的return地址无效。这里的问题是,如果execv(2)工作,它就不会返回。只有在失败的情况下,您才会得到一个无法使用的无效指针(由于上述原因(,当然ls -l还没有执行。好吧,你没有说你得到了什么,所以我很难猜测你是否真的exec()d了这个程序

另一方面,您有一个popen(3)库函数,它允许您执行子程序,并允许您从文件描述符中读取其输出(我建议您不要在程序中免费使用chdir,因为这是程序环境的全局变化,IMHO最好将要列为参数的目录传递给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");
}

然后你可以读取(因为它可能是很长的输出,如果你有一个巨大的目录,你可能没有足够的缓冲空间来处理内存中的所有内容(

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,因为放在这里(再次(要长得多,也要详细得多

最新更新