Shellskript aus einem C++ Programm starten



  • Bountblasher schrieb:

    Ich gebe in der Eingabeaufforderung folgendes ein:

    Telnet UNIX [Enter]

    dann kommt die Ausgabe:
    HP-UX UNIX B.11.11 U 9000/800 (tm)

    login: user [Enter]
    Password: pw [Enter]

    login und Password ist eine Ausgabe vom System, ich gebe nur den
    Benutzer "user" und das Passwort "pw" ein.

    Wenn du das gleich so gesagt hättest, dann hätte ich dir sofort diesen Code geben können:

    #include <windows.h>
    #include <winsock2.h>
    //---------------------------------------------------------------------------
    
    VOID ErrorMsg(HWND hwnd, LPCTSTR lpszErr)
    {
          MessageBox(hwnd, TEXT(lpszErr), TEXT("ERROR"), MB_OK | MB_ICONERROR);
    }
    //---------------------------------------------------------------------------
    
    VOID ShowLastSockError(HWND hwnd)
    {
        LPVOID lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                      FORMAT_MESSAGE_FROM_SYSTEM |
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL,
                      WSAGetLastError(),
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                      (LPTSTR)&lpMsgBuf,
                      0,
                      NULL);
    
           MessageBox(hwnd, (LPCTSTR)lpMsgBuf, TEXT("ERROR"), MB_OK | MB_ICONERROR);
    
        LocalFree(lpMsgBuf);
    }
    //---------------------------------------------------------------------------
    
    BOOL StartWinsock2()
    {
       WSADATA wsa;
       int retVal = WSAStartup(MAKEWORD(2,0), &wsa);
    
       if(retVal == 0)
          return TRUE;
       else
       {
          switch(retVal)
          {
             case WSASYSNOTREADY:
                ErrorMsg(NULL, "The underlying network subsystem is not ready for network communication");
    
             case WSAVERNOTSUPPORTED:
                ErrorMsg(NULL, "The version of Windows Sockets support requested (2.0) is not provided by this particular Windows Sockets implementation.");
    
             case WSAEINPROGRESS:
                ErrorMsg(NULL, "A blocking Windows Sockets 1.1 operation is in progress");
    
             case WSAEPROCLIM:
                ErrorMsg(NULL, "Limit on the number of tasks supported by the Windows Sockets implementation has been reached");
    
             case WSAEFAULT:
                ErrorMsg(NULL, "Implementation Error");
          }
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    BOOL EndWinsock2()
    {
       if( WSACleanup() == 0 )
          return TRUE;
       else
       {
          ShowLastSockError(NULL);
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    SOCKET SetupSocket()
    {
       SOCKET retVal = socket(AF_INET, SOCK_STREAM, 0);
       if(retVal != INVALID_SOCKET)
          return retVal;
       else
       {
          ShowLastSockError(NULL);
          return NULL;
       }
    }
    //---------------------------------------------------------------------------
    
    BOOL CloseSocket(SOCKET s)
    {
       if( closesocket(s) == 0 )
          return TRUE;
       else
       {
          ShowLastSockError(NULL);
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    ULONG GetIPFromString(LPTSTR hostnameOrIp)
    {
      ULONG retVal;
      HOSTENT* he;
    
      // Is there an IP in hostnameOrIp?
      retVal = inet_addr(hostnameOrIp);
    
      if(retVal == INADDR_NONE)       // NO
      {
        he = gethostbyname(hostnameOrIp);
        if(he == NULL)                // An error occured
        {
          ShowLastSockError(NULL);
          return 0;
        }
        else                          // everything's fine
          // Copy the first 4 bytes from he->h_addr_list to ip
          CopyMemory((PVOID)&retVal, he->h_addr_list[0], 4*sizeof(BYTE));
      }
    
      return retVal;
    }
    //---------------------------------------------------------------------------
    
    BOOL Connect(SOCKET s, USHORT port, LPCTSTR lpszCompName)
    {
       SOCKADDR_IN addr;
       int rc;
    
       ZeroMemory((PVOID)&addr, sizeof(SOCKADDR_IN));
       addr.sin_family = AF_INET;
       addr.sin_port = htons(port);
       addr.sin_addr.s_addr = GetIPFromString((LPTSTR)lpszCompName);
    
       rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
       if(rc == 0)
          return TRUE;
       else
       {
          ShowLastSockError(NULL);
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    BOOL Send(SOCKET s, char* buf, int len)
    {
       int bytes_sent;
    
       bytes_sent = send(s, buf, len, 0);
       if(bytes_sent != SOCKET_ERROR)
          return TRUE;
       else
       {
          ShowLastSockError(NULL);
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    BOOL Receive(SOCKET s, char* buf, int len)
    {
       int bytes_received;
    
       bytes_received = recv(s, buf, len, 0);
       if(bytes_received != SOCKET_ERROR)
          return TRUE;
       else
       {
          ShowLastSockError(NULL);
          return FALSE;
       }
    }
    //---------------------------------------------------------------------------
    
    #pragma argsused
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
       SOCKET s;
       char buf[4096];
    
       if( !StartWinsock2() )
          return 0;
    
       s = SetupSocket();
       if(s == NULL)
       {
          EndWinsock2();
          return 0;
       }
    
       if( !Connect(s, 23, "UNIX") )
       {
          CloseSocket(s);
          EndWinsock2();
          return 0;
       }
       Receive(s, buf, 4096);
    
       Send(s, "Username\r\n", 10);
       Receive(s, buf, 4096);
    
       Send(s, "Pass\r\n", 6);
       Receive(s, buf, 4096);
    
       Send(s, "cd Skripte\r\n", 12);
       Receive(s, buf, 4096);
    
       Send(s, "dvl_bk.sh\r\n", 11);
       Receive(s, buf, 4096);
    
       Send(s, "quit\r\n", 6);
       Receive(s, buf, 4096);
    
       if( !CloseSocket(s) )
       {
          EndWinsock2();
          return 0;
       }
    
       if( !EndWinsock2() )
          return 0;
    
       return 1;
    }
    //---------------------------------------------------------------------------
    

    Der Code ist nicht getestet, da ich keinen Server kenne, bei dem man Benutzername und Pass eingeben muss. Ich hoffe, du kannst auch damit ein wenig was anfangen.



  • äh ja, schön, Fritzi... nur sind wir hier im VCL Forum und haben glücklicherweise den TClientSocket, welcher uns n Haufen von dem WinAPI-Gewusel da abnimmt und die Verwendung von Sockets erheblich erleichtert (o;

    -junix



  • junix schrieb:

    äh ja, schön, Fritzi... nur sind wir hier im VCL Forum und haben glücklicherweise den TClientSocket, welcher uns n Haufen von dem WinAPI-Gewusel da abnimmt und die Verwendung von Sockets erheblich erleichtert (o;

    Ja schön, junix. Aber du hast wohl mitbekommen, dass Bountblasher mich darum gebeten hatte, ihm etwas Code zu geben. Wenn nicht, dann lies den Thread nochmal durch. Tut dir gut! Ich habe somit lediglich mein Versprechen eingelöst. Ganz davon abgesehen arbeitet deine tolle Klasse sicher auch mit genau den Funktionen, mit denen ich arbeite. Warum sollte Bountblasher nicht wissen, was wirklich dahinter steckt. Und nochmal außerdem: ich habe diese Klasse nicht, denn ich hab den BCB3.



  • WebFritzi schrieb:

    Aber du hast wohl mitbekommen, dass Bountblasher mich darum gebeten hatte, ihm etwas Code zu geben. Wenn nicht, dann lies den Thread nochmal durch. Tut dir gut!

    danke, brauche keine Leseübungen und ich wüsste nicht wieso sonst mir das gut tun sollte. (:

    WebFritzi schrieb:

    Ganz davon abgesehen arbeitet deine tolle Klasse sicher auch mit genau den Funktionen, mit denen ich arbeite.

    Ich glaube du solltest mein Posting nochmals lesen statt gleich rot zu sehen, nur weil man eine kritische Äusserung macht... täte dir wohl ganz gut.... Ich sagte ausdrücklich dass sie komfortabler im Handling sei. Zu deinem Funktionsset bräuchte man noch einen Thread der die IO-Aufgaben übernimmt um sie effizient einsetzen zu können.

    WebFritzi schrieb:

    Warum sollte Bountblasher nicht wissen, was wirklich dahinter steckt.

    Wer sagt denn sowas? Es geht nur darum, dass in der ersten Phase die Erfolgschancen höher und das Verständnis leichter ist als wenn man gleich aus dem Vollen schöpft... vor Allem dann, wenn man sich auf absolutem neuland bewegt...

    WebFritzi schrieb:

    Und nochmal außerdem: ich habe diese Klasse nicht, denn ich hab den BCB3.

    Tja... Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....

    Also spiel hier nicht gleich den beleidigten Webfritzen. War ja kein persönlicher Angriff sondern nur ein Hinweis am Rande...

    -junix



  • junix schrieb:

    Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....

    Ne, isse nich. Aber die ist nicht für den BCB3 gedacht, soweit ich mich erinnern kann.

    junix schrieb:

    Also spiel hier nicht gleich den beleidigten Webfritzen. War ja kein persönlicher Angriff sondern nur ein Hinweis am Rande...

    Auch wenn es nicht wie ein "Hinweis am Rande" daherkam... Ich bin nicht beleidigt. Ich habe lediglich meinen Post gerechtfertigt.

    Zum Thread: Wieso? Meinst du nicht, einer reicht? Ich hatte eben an ein Programm für ihn gedacht, dessen Symbol er nur anzuklicken braucht, und schon ist das Skript gestartet. Da braucht's kein Input.



  • WebFritzi schrieb:

    junix schrieb:

    Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....

    Ne, isse nich. Aber die ist nicht für den BCB3 gedacht, soweit ich mich erinnern kann.

    Äh die älteren Versionen... (damals hiess sie glaube ich WinShoes...) würden da helfen...

    WebFritzi schrieb:

    Zum Thread: Wieso? Meinst du nicht, einer reicht? Ich hatte eben an ein Programm für ihn gedacht, dessen Symbol er nur anzuklicken braucht, und schon ist das Skript gestartet. Da braucht's kein Input.

    Jo, dann gehts... trotzdem wäre ein Thread eleganter um das UI zu entkoppeln...

    -junix



  • Ich bedank mich für eure Hilfe.
    Es ist immer besser mehrere Möglichkeiten zu kennen...

    Danke!!!



  • Junix ich hab noch mal kurz eine Frage.

    Was bedeudet die Zahl, die man beim connect mit übergeben muss?

    TN1->Connect(1);



  • Falls du mich meinst: bei meiner Indy-Version (9.00.14) erwartet Connect keinen Parameter. Und auch bei der beim BCB6 mitgelieferten Version (ca. 8.0) wird kein Parameter benötigt, wenn ich die entsprechende Hilfedatei richtig lese.



  • Hallo Jansen,

    hab noch mal eine Frage.
    Wie muss ich das machen, das sich mein Programm mit der Unix Maschine verbindet und dann nur den Befehl () ausführt und danach die Verbindung gleich trennt?
    Weil so wie ich es gemacht hab (siehe unten) startet er mein Shellskript 2 mal.
    Kannst du mir bitte Helfen..

    void __fastcall TForm1::TN1DataAvailable(TIdTelnet *Sender,
          const AnsiString Buffer)
    {
    bool logged_in = false;
    bool bEnde     = false;
    String strLogin    = "user";
    String strPass     = "pw";
    String strCommand  = "nohup bin/dvl_bk.sh > log/dvl_bk.log &";
    String strResponse = "";
    String strText = "";
    
     if (Buffer != "")
      {
    
        if (!logged_in)
        {
        ShowMessage("Ja");
          // Loginprompt erreicht
          if (UpperCase(Buffer).Pos("LOGIN: ") == Buffer.Length() - 6)
            strText = strLogin;
          // Passwortprompt erreicht
          else if (UpperCase(Buffer).Pos("PASSWORD: ") == Buffer.Length() - 9)
            strText = strPass;
    
          // Eingabeprompt erreicht, Kommando abschicken
          else if (UpperCase(Buffer).Pos(UpperCase("$ ")) > 0)
          {
            logged_in = true;
            strText = strCommand;
          }
    
          if (UpperCase(Buffer).Pos(UpperCase("Controlling.sh")) > 0) {
             strText = "exit";
          }
        }
            ShowMessage("Befehl: " + strText);
    
        if (strText != "")
        { // das eigentliche Versenden
    
          for (int i = 1; i <= strText.Length(); i++)
    
              TN1->SendCh(strText[i]);
              TN1->SendCh(VK_RETURN);
    
          strText = "";
        }
    
        // Kontrollausgabe
        Memo1->Lines->Add(Buffer);
      }
    
    }
    

    Edit:
    Bitte die Code-Tags benutzen. Danke!



  • Ist die Kontrolle auf den String "Controlling.sh" die Prüfung auf den korrekten Start des Skripts?
    Wenn ja, dann darf die natürlich nicht innerhalb der if (!logged_in)-Klammern stehen, da sie ja nach erfolgreichem Login nie ausgeführt wird.



  • Mir ist aufgefallen, dass mein Programm die bool Variable nicht setzt.
    Hab sie jetzt mal global gemacht, jetzt funktioniert es.
    Mir ist aufgefallen, das nach jeder Eingabe über Telnet mein Programm wider zum Connect zurückspringt. An was kann das liegen?

    Ich hab die Inidi 9.. und Borland 5 und bei mir benötigt mein Connect eine const int.


Anmelden zum Antworten