将exec输出从函数发送到主方法

将exec输出从函数发送到主方法,c,exec,C,Exec,我从主方法调用了一个方法,该方法在某个目录上执行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 directo

我从主方法调用了一个方法,该方法在某个目录上执行
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\u 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] = '\0';

    char buf[128];
    size_t n;
    while ((n = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
        buf[n] = '\0';
        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;
}
#包括
#包括
#包括
内部主(空){
文件*fp;
如果((fp=popen(“ls-l”,“r”))==NULL){
佩罗(“波本失败”);
返回退出失败;
}
大小=1024;
char*stringts=malloc(str_大小);
如果(!stringts){
perror(“stringts分配失败”);
返回退出失败;
}
stringts[0]='\0';
char-buf[128];
尺寸;
而((n=fread(buf,1,sizeof(buf)-1,fp))>0){
buf[n]='\0';
尺寸和容量=str尺寸-strlen(stringts)-1;
而(n>容量){
str_size*=2;
stringts=realloc(stringts,str_尺寸);
如果(!stringts){
perror(“stringts重组失败”);
返回退出失败;
}
容量=STRU尺寸-strlen(stringts)-1;
}
strcat(stringts,buf);
}
printf(“%s\n”,stringts);
自由(弦);
如果(pclose(fp)!=0){
perror(“pclose失败”);
返回退出失败;
}
返回退出成功;
}

正如乔纳森·莱夫勒(Jonathan Leffler)在评论中指出的那样,C语言中没有用于连接字符串的“+”运算符

动态扩展字符串的一种可能性是将realloc与strcat一起使用

对于从管道中读取的每个字节数,可以检查最初为字符串分配的内存的剩余容量,如果这还不够,可以重新分配两倍的大小

您必须自己跟踪当前字符串的大小。您可以使用类型为size\u 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] = '\0';

    char buf[128];
    size_t n;
    while ((n = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
        buf[n] = '\0';
        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;
}
#包括
#包括
#包括
内部主(空){
文件*fp;
如果((fp=popen(“ls-l”,“r”))==NULL){
佩罗(“波本失败”);
返回退出失败;
}
大小=1024;
char*stringts=malloc(str_大小);
如果(!stringts){
perror(“stringts分配失败”);
返回退出失败;
}
stringts[0]='\0';
char-buf[128];
尺寸;
而((n=fread(buf,1,sizeof(buf)-1,fp))>0){
buf[n]='\0';
尺寸和容量=str尺寸-strlen(stringts)-1;
而(n>容量){
str_size*=2;
stringts=realloc(stringts,str_尺寸);
如果(!stringts){
perror(“stringts重组失败”);
返回退出失败;
}
容量=STRU尺寸-strlen(stringts)-1;
}
strcat(stringts,buf);
}
printf(“%s\n”,stringts);
自由(弦);
如果(pclose(fp)!=0){
perror(“pclose失败”);
返回退出失败;
}
返回退出成功;
}

您的代码中有几个缺陷:

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的提示。这会使程序的其余部分不可用,因为一旦执行,就没有返回的方法,程序将被卸载和释放
  • 您可以将(
    ++
    )添加到指针值中(您确实将添加到指向字符串的地址
    “ls-l的结果…”“
    ”,并且---由于exec的结果为空,当加载新程序时---您将一无所获)如果
    execv
    失败,则您将获得指向该字符串上一个字符的指针,这在C中是一个有效的表达式,但会使程序在未定义的行为中表现不稳定。使用strcpy(3)、
    strcat(3)
    snprintf(3)
    ,具体取决于要在分配的缓冲区空间中复制的确切文本
  • 因此,您的
    返回的
    地址无效。这里的问题是,如果
    execv(2)
    起作用,它就不会返回。只有当它失败时,你才能得到一个无效的指针,你不能使用它(因为上面的原因),当然
    ls-l
    没有被执行。嗯,你没有说你得到了什么,所以我很难猜测你是否真的
    exec()
    d了程序
另一方面,您有一个
popen(3)
库函数,它允许您执行子程序,并允许您
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) */
}