С++ apt-get работает над стандартным выводом popen

Это может показаться глупым вопросом, я новичок в C++.

В Debian я пытаюсь вызвать apt-get install с помощью popen. Мне нужно проанализировать вывод этой программы. К сожалению, я не могу прочитать полный вывод apt-get.

В какой-то момент apt-get может запросить пользовательский ввод (спрашивая, должны ли быть установлены зависимости). Моя программа не может вывести эту строку.

Почему последняя строка (см. примеры ниже, в моей программе отсутствует строка: «Вы хотите продолжить [Да/нет]?») не выводится?

Когда я запускаю команду apt-get вручную, вывод консоли выглядит так:

$ sudo apt-get install python-wxtools
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  python-wxgtk2.8 python-wxversion
Suggested packages:
  wx2.8-doc wx2.8-examples ruby wish tk8.5 tcsh csh octave3.0 mksh pdksh
  python-xml editra
The following NEW packages will be installed:
  python-wxgtk2.8 python-wxtools python-wxversion
0 upgraded, 3 newly installed, 0 to remove and 8 not upgraded.
Need to get 5,942kB of archives.
After this operation, 25.0MB of additional disk space will be used.
Do you want to continue [Y/n]? 

ПРИМЕЧАНИЕ: нет новой строки в конце последней строки.

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

$ sudo ./test/popen 
g++ -Wall -o test/popen test/popen.cpp
test/popen.cpp: In function ‘int main(int, char**, char**)’:
test/popen.cpp:22: warning: comparison between signed and unsigned integer expressions
apt-get install python-wxtools
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
  python-wxgtk2.8 python-wxversion
Suggested packages:
  wx2.8-doc wx2.8-examples ruby wish tk8.5 tcsh csh octave3.0 mksh pdksh
  python-xml editra
The following NEW packages will be installed:
  python-wxgtk2.8 python-wxtools python-wxversion
0 upgraded, 3 newly installed, 0 to remove and 8 not upgraded.
Need to get 5,942kB of archives.
After this operation, 25.0MB of additional disk space will be used.

ПРИМЕЧАНИЕ: новая строка в конце вывода

Моя эталонная реализация popen выглядит так на С++:

// $Id: popen.cpp 126 2011-04-25 18:48:02Z wus $

#include <iostream>
#include <stdio.h>

using namespace std;

/**
 * run debians apt-get and check output
 */
int main(int argc, char **argv, char **envp) { 

    FILE *fp;
    char buffer[9];
    // must use a package which asks for dependencies
    char command[255] = "apt-get install python-wxtools";
    cout << command << endl;

    // Execute command, open /dev/stdout for reading
    fp = popen(command, "r");

    // read output character by character
    while (fread(buffer, 1, 1, fp) != EOF) {
        cout << buffer;
    }

    // close
    pclose(fp);
}

Я пытаюсь это сделать в системе Linux

$ uname -a
Linux shell1 2.6.35-28-server #50-Ubuntu SMP Fri Mar 18 18:59:25 UTC 2011 x86_64 GNU/Linux

$ gcc --version
gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

person Spliffster    schedule 25.04.2011    source источник


Ответы (2)


Попробуйте добавить параметр -y к apt-get. Это заставит его предположить, что пользователь говорит «Да» всему, что должно заставить его «просто работать». Я думаю, что сейчас он терпит неудачу, потому что он хочет подсказать пользователю, но понимает, что ввод с клавиатуры недоступен (возможно, путем вызова isatty(3)), поэтому он сдается.

person John Zwinck    schedule 25.04.2011
comment
Я бы хотел, чтобы пользователь моей программы сам выбирал, хочет ли он получать дополнительные зависимости, поэтому apt-get install -y, к сожалению, для меня не вариант (-y автоматически ответит на все вопросы «Да»). Спасибо за Ваш ответ. - person Spliffster; 25.04.2011
comment
Итак, вы хотите зафиксировать вывод apt-get и ТАКЖЕ ввести его. Это не совсем возможно. См. здесь по некоторым причинам: lua-users.org/lists/ lua-l/2007-10/msg00189.html - person John Zwinck; 25.04.2011
comment
Вы можете рассмотреть возможность пробного прогона с -s, показывая пользователю вывод этого, подсказывая им, а затем снова запуская с -y, если они согласятся.... Вы также можете рассмотреть возможность использования для этого языка, отличного от C++. - person John Zwinck; 25.04.2011
comment
Цвик: Я могу отправить Y или N обратно в apt-get. вернуть работы, это не моя проблема. Но я не могу прочитать последнюю строку, которая кажется readline. Сухой прогон звучит как обходной путь, спасибо. Но я хотел бы также найти способ прочитать последнюю строку. - person Spliffster; 25.04.2011
comment
Меня беспокоит то, что последняя строка не выдается apt-get, потому что она распознает, что пользователя нет. Если вы запустите apt-get под strace, возможно, вы сможете увидеть, печатает ли он эту строку или нет, или вызывает ли он isatty (вероятно, с аргументом 0). Если он использует isatty, чтобы решить, следует ли печатать подсказку, один из способов заставить все это работать — запустить его внутри псевдотерминала, созданного в вашей программе. Однако это довольно темное искусство, и, вероятно, оно само по себе будет значительным проектом. - person John Zwinck; 26.04.2011

На самом деле проблема заключалась не в буферизации ввода, а в буферизации вывода cout. Ручная промывка решила проблему:

while (fread(buffer, 1, 1, fp) != EOF) {
    cout << buffer << flush;
}
person Spliffster    schedule 30.04.2011