LINUX.ORG.RU

Как правильно закрывать popen?

 


0

1

Здравствуйте.

Помогите разобраться с закрытием потока, открытого popen: Язык СИ, линукс.

char curl_buff[64] = {0,};

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

if(curl_prog != NULL)
 {
   fgets(curl_buff, 63, curl_prog);
 }

if(pclose(curl_prog) == -1) error_log("close curl_prog.");

Закрытие должно быть после фигурных скобок или внутри...?

char curl_buff[64] = {0,};

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

if(curl_prog != NULL)
 {
   fgets(curl_buff, 63, curl_prog);
   if(pclose(curl_prog) == -1) error_log("close curl_prog.");
 }

То есть, мне не понятно, если curl_prog вернул NULL, то это значит что?

Поток открылся после этой строчки:

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

Или ещё не ясно, открылся он или нет и это проверяется здесь:

if(curl_prog != NULL)
 {
   ...

внутри. если вдруг ты попытаешься закрыть свой попен через указатель, принимающий значение NULL, то твоему попену может стать весьма неуютно.

anonymous
()
Ответ на: комментарий от anonymous

внутри. если вдруг ты попытаешься закрыть свой попен через указатель, принимающий значение NULL

Спасибо.

Я вот почему спрашиваю: если в строке - FILE *curl_prog = popen(«curl http://192.168.5.189 2> /dev/null», «r»);, указать неправильную команду, например так - FILE *curl_prog = popen(«murl http://192.168.5.189 2> /dev/null», «r»);, то всё равно возвращается != NULL, то есть получается, что открытие произошло?

stD
() автор топика
Ответ на: комментарий от anonymous

Может всё-таки использовать api curl, а не попе-н?

Допустим нужно запустить другую команду. Речь не про curl, а про popen.

stD
() автор топика
Ответ на: комментарий от anonymous

NULL вернется, если функция не может выделить память.

Я поторюсь.

Если в строке:

FILE *curl_prog = popen(«curl http://192.168.5.189 2> /dev/null», «r»);

Допустить ошибку:

FILE *curl_prog = popen(«Murl http://192.168.5.189 2> /dev/null», «r»);

То возвращается НЕ NULL - это что означает, поток открылся или не открылся?

stD
() автор топика
Ответ на: комментарий от stD

я повторюсь. это ничего не означает, кроме того, что память не выделилась, надо смотреть errno. (и читать мануалы)

anonymous
()
Ответ на: комментарий от stD

Оно у тебя в любом случае откроется, тк popen() вызывает (обычно) /bin/sh, а ему передаёт уже строку, которую ты написал. Если shell не сможет выполнить команду, это не значит, что popen() зафейлился.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

надо смотреть errno.

perror(«Error»); говорит - Error: Success

stD
() автор топика
Ответ на: комментарий от DELIRIUM

Если shell не сможет выполнить команду, это не значит, что popen() зафейлился.

Дык и я про то же, но как это обрабатывать?

Как правильно закрывать popen?

stD
() автор топика
Ответ на: комментарий от stD

Как pclose(). Обрабатывать самое простое - перенаправлять в самой команде stderr в stdout и вычитывать ошибку из канала. Ну и ЕМНИП pclose вернёт тебе код возврата последней команды, посмотри man для верности.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Как pclose().

Я имел в виду это:

char curl_buff[64] = {0,};

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

if(curl_prog != NULL)
 {
   fgets(curl_buff, 63, curl_prog);
 }

if(pclose(curl_prog) == -1) error_log("close curl_prog.");

pclose делать после фигурных скобок или внутри?

stD
() автор топика

1. Если у тебя ресурсов достаточно, и всё в порядке с шеллом пользователя popen всегда вернёт годный указатель.
2. После безошибочного pclose он вернёт статус завершения команды.

Если команда левая, можно после первого чтения из файла проверить что EOF, закрыть если да, и проверить возврат pclose.
Ещё раз, в нормальных условиях popen вернёт валидный указатель.

anonymous
()
Ответ на: комментарий от stD

Непроходимость и повторение вопроса когда на него уже два раза ответили оставим за скобками, но ты можешь хотя бы на базовом уровне включить голову и подумать - если тебе вернулся NULL, что ты вообще с ним можешь делать, когда он не содержит никакой информации которую можно было бы закрыть?

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Ну вот зачем ты спойлеришь? Так весело было читать..

deep-purple ★★★★★
()
Ответ на: комментарий от stD

Popen() возвращает NULL только одном случае, если не смог сделать fork(). А fork() на линуксе редко возвращает ошибку. Очень редко.

В строчке могут быть хоть стихи написаны, если fork() удался, popen() вернёт не NULL.

Чтобы получить реальную ошибку запуска, надо сначала прочитать весь поток до EOF-а, и только после этого pclose() вернет ошибку запуска.

iliyap ★★★★★
()
Последнее исправление: iliyap (всего исправлений: 1)
Ответ на: комментарий от iliyap

Popen() возвращает NULL только одном случае, если не смог сделать fork()

Спасибо.

stD
() автор топика

Закрытие должно быть после фигурных скобок или внутри...?

http://pubs.opengroup.org/onlinepubs/007904875/functions/pclose.html

If the argument stream to pclose() is not a pointer to a stream created by popen(), the result of pclose() is undefined.

Так что внутри. Ну или не внутри, главное — спроверкой на NULL.

sostupid
()
Ответ на: комментарий от iliyap

Popen() возвращает NULL только одном случае, если не смог сделать fork().

http://pubs.opengroup.org/onlinepubs/007904875/functions/popen.html

The popen() function may fail if:

[EMFILE]
{FOPEN_MAX} or {STREAM_MAX} streams are currently open in the calling process.
[EINVAL]
The mode argument is invalid.

sostupid
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.