Linux C popen函数返回Shell命令执行结果

 

1、popen()

popen():进程I/O函数,与pclose函数一起使用。

1.1函数定义:

FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );

1.2包含头文件:

#include <stdio.h>

1.3函数说明:

popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数。pclose() 函数关闭标准 I/O 流,等待命令执行结束,然后返回 shell 的终止状态。如果 shell 不能被执行,则 pclose() 返回的终止状态与 shell 已执行 exit 一样。

type 参数只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 "r" 则文件指针连接到 command 的标准输出;如果 type 是 "w" 则文件指针连接到 command 的标准输入。

command 参数是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用-c 标志,shell 将执行这个命令。

popen 的返回值是个标准 I/O 流,必须由 pclose 来终止。前面提到这个流是单向的。所以向这个流写内容相当于写入该命令的标准输入;命令的标准输出和调用 popen 的进程相同。与之相反的,从流中读数据相当于读取命令的标准输出;命令的标准输入和调用 popen 的进程相同。

1.4函数返回值

如果调用 fork() 或 pipe() 失败,或者不能分配内存将返回NULL,否则返回标准 I/O 流。

1.5 函数错误状态

popen 没有为内存分配失败设置 errno 值。

如果调用 fork() 或 pipe() 时出现错误,errno 被设为相应的错误类型。

如果 type 参数不合法,errno将返回EINVAL。

1.6 实例1

C代码调用 Shell的 ls  命令 ,打印当前路径文件夹下的所有文件名:

#include<stdio.h>
#define _LINE_LENGTH 300
int main(void) 
{
    FILE *file;
    char line[_LINE_LENGTH];
    file = popen("ls", "r");
    if (NULL != file)
    {
        while (fgets(line, _LINE_LENGTH, file) != NULL)
        {
            printf("line=%s\n", line);
        }
    }
    else
    {
        return 1;
    }
    pclose(file);
    return 0;
}

输出结果:

line=ls_command.c

line=ls_command.o

line=popen.c

line=popen.o

 

2、从popen()返回的流中读取命令执行结果的字符串,字符串'\0'结尾符号前面还有一个'\n' 换行符号的问题

#include<stdio.h>
#include<string.h>
#define _LINE_LENGTH 256
#define COMMAND "sudo dmidecode -t2 | grep 'Product Name' | awk '{print $3}'"
int main(void) 
{
    FILE *file;
    char line[_LINE_LENGTH];
    file = popen(COMMAND, "r");
    int Length = -1;
    char *p = NULL;
    int count  = 0;
    if (NULL != file)
    {
        while (fgets(line, _LINE_LENGTH, file) != NULL)
        {
            // line is end with '\n''\0'
            printf("line=%s", line);

            Length = strlen(line);

            printf("Length = %d\n",Length);

            printf("line[Length - 1] = %d:%c",line[Length - 1],line[Length - 1]);

	    printf("line[Length] = %d:%c",line[Length],line[Length]);

            if(line[Length] == '\0')
            {
            	printf("line is end with \'\\0\'\n");
            }

            line[Length - 1] = '\0';\\ replace line[Length - 1] = '\n' with '\0'

	    if(strcmp(line,"LNVNB161216") == 0)
	    {
		printf("The Product Name is Matched!\n");
            }
        }
    }
    else
    {
        return 1;
    }
    pclose(file);
    return 0;
}

输出结果:

line=LNVNB161216
Length = 12
line[Length - 1] = 10:
line[Length] = 0:line is end with '\0'
The Product Name is Matched!

从上面的结果可以看出,从popen()返回的文件流指针file中读取的命令执行结果字符串,每一个行字符串是以ASCII的换行符'\n'结尾的,ASCII的换行符号(LF),ASCII值为10。

求执行结果一行字符串的长度strlen函数放回的长度值是包含换行符号的。

 

 

参考

[1]https://baike.baidu.com/item/popen/5301781?fr=aladdin

[2]https://baike.baidu.com/item/ASCII/309296?fromtitle=ascii%E7%A0%81&fromid=99077&fr=aladdin

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章