Mit C++ Klasse Shell Befehle fernsteuern

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
alexander_ro
Beiträge: 298
Registriert: 16.01.2006 17:44:21
Lizenz eigener Beiträge: GNU General Public License

Mit C++ Klasse Shell Befehle fernsteuern

Beitrag von alexander_ro » 21.02.2015 12:47:55

Hi Mädels ... Jungs ... :-)

ich versuche gerade meiner KI das benutzen der Shell bei zu bringen. Dazu muss es aber erst mal eine möglichkeit geben das ein C++ Programm so tun kann als sei es ein normaler Benutzer. Daher die Idee Befehle über eine Umleitung von stdout, stderr und stdin zu steuern.

Leider war mein Versuch nur Teilweise erfolgreich. Solange die Befehle nur an stdout oder stderr ausgeben funktioniert das einwandfrei. Sobald ich aber Befehle wie fdisk benutze blockiert das ganze. Man sieht dann das der Prozess läuft aber die ausgaben lassen sich nicht mehr über die Umgeleitete Pipe lesen.

Hier mal der Konstruktor der die wichtigste arbeit macht. Der übersichtlichkeit halber habe ich die meisten Methoden weg gelassen weil die mit dem Problem nichts zu tun haben.

Code: Alles auswählen

  runCommand (std::string strCommand)
  {
    const int iRead  = 0;
    const int iWrite = 1;
    int pStdout[2];
    int pStderr[2];
    int pStdin[2];

    pid_t pid;

    if (pipe(pStdout) != 0 ||
        pipe(pStderr) != 0 ||
        pipe(pStdin)  != 0)
      std::cout << "Fehler beim anlegen der pipes" << std::endl;

    pid = fork();

    if (pid < 0)
      pid = pid;
    else
    if (pid == 0)
    {
      close (pStdout[iRead]);
      close (pStderr[iRead]);
      close (pStdin[iWrite]);

      dup2(pStdout[iWrite], STDOUT_FILENO);
      dup2(pStderr[iWrite], STDERR_FILENO);
      dup2(pStdin[iRead],   STDIN_FILENO);

      close(pStdout[iWrite]);
      close(pStderr[iWrite]);
      close(pStdin[iRead]);

      if (execl("/bin/bash", "bash", "-c", strCommand.c_str (), NULL) == 0)
      {
        std::cout << "Fehler beim starten des externen Prozesses: " << strerror (errno) << std::endl;
        exit (0);
      }

      std::cout << "In der C++-Klasse runCommand geschehen merkwürdige Dinge ..." << std::endl;
      exit(1);
    }

    close(pStdout[iWrite]);
    close(pStderr[iWrite]);
    close(pStdin[iRead]);

    pIntStreamOut = fdopen(pStdout[0], "r");
    if (pIntStreamOut == 0)
    {
      std::cout << "Fehler beim öffnen von stdout: " << strerror (errno) << std::endl;
      exit (0);
    }

    pIntStreamIn = fdopen(pStdin[1], "w");
    if (pIntStreamIn == 0)
    {
      std::cout << "Fehler beim öffnen von stdin: " << strerror (errno) << std::endl;
      exit (0);
    }

    readStdout ();
  }

  void sendBefehl (std::string strBefehl)
  {
    std::cout << "runCommand::sendBefehl: start" << std::endl;

    int iCount;

    int iRc = fwrite (strBefehl.c_str (), strBefehl.size (), iCount, pIntStreamIn);

    if (iRc == 0)
      std::cout << "Es wurden keine Daten geschrieben." << std::endl;
  }

  void readStdout (void)
  {
    std::cout << "runCommand::readStdout: start" << std::endl;

    char* pRc;
    for (;;)
    {
      std::unique_ptr<char> szZeile (new char[1000]);

      pRc = fgets (szZeile.get (), 1000, pIntStreamOut);

      if (pRc == nullptr)
        break;

      vecIntStdout.push_back (std::move (szZeile));
    }
  }

Code: Alles auswählen

// Beispiel wie ich getestet habe.
  //runCommand run ("find");

  //runCommand run ("fdisk /dev/sda");
  //run.sendBefehl ("q\n");

  for (auto&& out: *(run.getStdout ()))
  {
    std::cout << out.get ();
  }
Schon mal danke fürs angucken ...

Grüße
Alexander

Benutzeravatar
bmario
Beiträge: 1257
Registriert: 05.09.2007 12:15:47
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Dresden

Re: Mit C++ Klasse Shell Befehle fernsteuern

Beitrag von bmario » 22.02.2015 13:40:24

Was spricht dagegen bereits existierenden und getesteten Code zu benutzen, etwa http://qt-project.org/doc/qt-4.8/qprocess.html?
Nichts zu tun ist viel besser,
als mit viel Mühe nichts zu schaffen. - Laotse

alexander_ro
Beiträge: 298
Registriert: 16.01.2006 17:44:21
Lizenz eigener Beiträge: GNU General Public License

Re: Mit C++ Klasse Shell Befehle fernsteuern

Beitrag von alexander_ro » 22.02.2015 15:10:33

qt spricht dagegen. Ich will jetzt nicht die abhängigkeit zu einem Monster lib wie qt haben wenn ich nur eine funktion davon brauch. Sonst hat qt leider für KI Entwicklung nicht viel zu bieten.

[Edit]
Wissen wollen wie geht spricht auch noch dagegen.
[/Edit]

Antworten