popen и вывод системной команды - PullRequest
0 голосов
/ 23 мая 2018

Мне нужно выяснить доступное место в / mnt / в моем приложении.Я написал следующий код.Тем не менее, execute_cmd несколько раз возвращает мусор, кроме фактического вывода.Например: 4,5 тыс. (С последующим мусором).Куда я иду не так?Может ли какой-то один обзор и дать мне знать, почему 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 голосов
/ 23 мая 2018

sizeof(buffer) равно sizeof(char*), что, вероятно, равно 8 (или, возможно, 4).Таким образом, ваш memset очищает только немного buffer.Но с вашим использованием fread необходимо очищать не только buffer;это временные path.

Неинициализированные локальные переменные, такие как path, не инициализируются нулями.Вы можете использовать memset(path, 0, sizeof(path));, чтобы очистить его - здесь sizeof работает, потому что path действительно является массивом - но проще инициализировать его в объявлении: char path[100] = "";.

, так как fread не завершает NUL тем, что читает, может быть произвольный мусор, следующий за ним, что делает strcat неопределенным поведением.На самом деле, strcat совершенно ненужен и трата циклов.Вы знаете, сколько данных вы прочитали (это len), поэтому вы точно знаете, где читать следующий блок, и вы можете сделать это напрямую, без временного буфера и без копии.

Для дальнейшего использования, есливы планируете вызвать malloc, а затем использовать memset для очистки выделенного региона, вместо этого следует использовать calloc.Вот для чего это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...