popen和系统命令的输出

时间:2018-05-23 16:00:18

标签: c arrays linux popen

我必须在我的应用程序中找出/ mnt /中的可用空间。我写了以下代码。但是,execute_cmd有时会从实际输出中返回垃圾。例如:4.5K(其次是垃圾)。我哪里错了?有人可以回顾一下,让我知道为什么execute_cmd会在结尾处返回一个垃圾字节?如何改进代码?

char *execute_cmd(char *cmd)
{
        FILE *fp;
        char path[100];
        int ii = 0;
        //char ii = 0;
        char *buffer = malloc(1024);
        char len = 0;

        /* Open the command for reading. */
        fp = popen(cmd, "r");
        if (fp == NULL) {
        printf("Failed to run command\n" );
        exit(1);
        }
        printf("Running command is: %s\n", cmd);

        memset(buffer, 0, sizeof(buffer));

        do {
        len = fread(path, 100, 1, fp); /* Is it okay to use fread? I do not know how many bytes to read as this function is a generic function which can be used for executing any command */
        strcat(buffer,path);
        printf("Number of bytes is: %d\n", len);
        } while (len != 0);

        len = strlen(buffer);
        printf("Buffer contents are: %s %d\n", buffer,len);

        /* close */
        pclose(fp);
}

void main()
{
        char *buffer = "df -h  | grep \"/mnt\" | awk '{ print $4}'"; /* FIXME */
        char len;
        char units;
        float number;
        char dummy = 0;
        char *avail_space;

        avail_space = execute_cmd(buffer);
        len = strlen(avail_space);
        units = avail_space[len - 1];

        printf("Available space is: %s %d %c end here\n", avail_space, len, units);
        number = strtof(avail_space, NULL);
        printf("Number is: %f\n", number);
}

1 个答案:

答案 0 :(得分:1)

sizeof(buffer)sizeof(char*),大概是8(或者4)。因此,memset只会清除一点buffer。但是使用fread时,不仅需要清除buffer;这是暂时的path

未初始化的局部变量(如path)不是零初始化的。您可以使用memset(path, 0, sizeof(path));清除它 - 这里sizeof有效,因为path确实是一个数组 - 但更简单的是在声明中初始化它:char path[100] = "";。< / p>

由于fread没有NUL终止它读取的内容,因此可能会有任意垃圾跟随它,从而产生strcat未定义的行为。实际上,strcat完全没必要,浪费了周期。你知道你读了多少数据(它在len中),所以你确切地知道在哪里读取下一个块,你可以直接这样做而没有临时缓冲区和没有副本。

为了将来参考,如果您打算调用malloc,然后使用memset清除已分配的区域,则应使用calloc。这就是它的用途。