程序变量获得system函数所执行语句的结果

上一篇 / 下一篇  2007-08-22 03:57:09

这个结果并不是system函数的返回值,而是调用外部程序的输出
一直以后我都是把结果重定向到一个文件,然后从文件中读取结果

不过后来我在chinaunix从看到了bleem1998写的一个函数,它解决了这个问题,函数原理很简单,只是为什么偶们没想到呢?

函数如下:

char *lazy(char *pCmd, char **env) {
        char *pResult, *p;
        int fd[2], fd_stdout;
        int count=0;
        int a1 = 0, a2 = 0;     //a1缓冲区总大小,a2缓冲区使用了多少
        int maxlen = 4096;      //为什么使用4096?因为这刚好是管道的大小,可以参考~/code/ipc/pipe/question.c里的Q4

        fd_stdout = dup(1);     //备份stdout,关闭之后想要再使用标准输出要靠这个备份的
        pipe(fd);
        close(1);
        dup2(fd[1],1);
        if (fork() == 0) {
                close(fd[1]);
                close(fd[0]);
                close(fd_stdout);
                if (env == NULL)        //exec和system都可以,不同的调用方法用不同的实现吧,呵呵
                        system(pCmd);   //调用方法:lazy("ls -al /root")
                else
                        execvp(pCmd, env);      //调用方法:lazy("ls",{"ls", "-al", "/root", (char *)0})

                exit(1);
        }
        close(fd[1]);
        close(1);
        fflush(stdout);
        dup2(fd_stdout, 1);     //打开stdout

        pResult = malloc(maxlen + 1);
        a1 += maxlen + 1;
        p = pResult;
        while ((count = read(fd[0], pResult, maxlen)) > 0) {    //如果在read过程中超过了缓冲区边缘会返回-1,调试了很久才发现这个问题
                a2 += count;
                if (a1 - a2 <= maxlen) {
                        p = realloc(p, a1 + maxlen);    //为什么要用个临时变量p来帮忙呢?:)这是一个小发现呵呵,看<Linux函数库参考手册>P33的笔记
                        pResult = p + a2;
                        a1 += maxlen;
                        continue;
                }
                pResult += count;
        }
        *pResult = 0;   //打上字符串结束符
        close(fd[0]);
        wait(&count);

        return p;
}

int main(void) {
        char *result;
        char *cmd = "ls";
        char *cmd2 = "ls /dev";
        char *env[] = {"ls", "-al", "/dev", (char *)0};

        //result = lazy(cmd, env);
        result = lazy(cmd2, NULL);

        printf("%s", result);
        free(result);
        return 0;
}

函数的原理也是比较简单的,bleem1998网友通过,子进程、管道、还是重定向的技术来完成的
函数用子进程来处理要执行的命令
在父进程时建立一个管道,把标准输出重定向到管理的写入口
在子进程执行的输入当然就写入管道了,而父进程只要从管道从读出结果就行了

如果有兴趣的朋友也可以修改一下这个函数,方便使用,因为:如果在子进程中重定向标准输出,那么根本不会影响父进程的标准输出,也不用进行备份了

如果执行的结果内容没有超过一次管道的长度,甚至于可以不用新建子进程,直接在一个程序中进行一个管道和读写,基本就是代替了那个零时文件的功能

TAG:

红尘弥漫 引用 删除 snail   /   2007-10-05 04:27:21
用glib的函数,可能会更简单一些
gboolean            g_spawn_command_line_sync           (const gchar *command_line,

                                                         gchar **standard_output,

                                                         gchar **standard_error,

                                                         gint *exit_status,

                                                         GError **error);
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

我的栏目

日历

« 2008-09-07  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 55702
  • 日志数: 170
  • 图片数: 12
  • 文件数: 6
  • 书签数: 10
  • 建立时间: 2007-02-10
  • 更新时间: 2008-01-14

RSS订阅

Open Toolbar