C++ apt-get работи върху stdout на popen

Това може да звучи като глупав въпрос, нов съм в C++.

В debian се опитвам да извикам apt-get install с popen. Трябва да анализирам изхода на тази програма. За съжаление не мога да прочета пълния изход на apt-get.

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

Кой е последният ред (вижте примерите по-долу, редът, който липсва в моята програма е: "Искате ли да продължите [Y/n]?") не е изведен?

Когато стартирам ръчно командата 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 изглежда така в c++:

// $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
Zwick: Мога да изпратя Y или N обратно на apt-get. връщането работи, не е мой проблем. Но не мога да прочета последния ред, който изглежда е esnt от 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