]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/dialup.cpp
added wxUSE_NOTEBOOK to include/wx/msw/setup0.h, removed wxUSE_RADIOBUTTON (we
[wxWidgets.git] / src / unix / dialup.cpp
index c649b265a7fef5556273cbe8537ab09f4051ace7..1e2154ce5eef5767ba8e2577b67cf0162adac5b7 100644 (file)
@@ -12,7 +12,7 @@
 #include "wx/setup.h"
 
 #ifdef __GNUG__
-    #pragma implementation "dialup.h"
+#   pragma implementation "dialup.h"
 #endif
 
 #if wxUSE_DIALUP_MANAGER
@@ -32,6 +32,7 @@
 #include "wx/process.h"
 #include "wx/intl.h"
 #include "wx/app.h"
+#include "wx/wxchar.h"
 
 #include <stdlib.h>
 
@@ -43,6 +44,7 @@
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <errno.h>
 
 // ----------------------------------------------------------------------------
 // A class which groups functions dealing with connecting to the network from a
@@ -103,12 +105,18 @@ public:
    virtual bool IsOnline() const
       {
          if( (! m_timer) // we are not polling, so test now:
-             || m_IsOnline == -1
+             || m_IsOnline < 0
             )
             CheckStatus();
          return m_IsOnline != 0;
       }
 
+   /// do we have a constant net connection? -- GUESS!
+   bool IsAlwaysOnline() const
+      {
+         ((wxDialUpManagerImpl *) this)->HangUp(); // brutal but necessary
+         return IsOnline();
+      }
    /// returns TRUE if (async) dialing is in progress
    inline virtual bool IsDialing() const
       { return m_DialProcess != NULL; }
@@ -117,6 +125,9 @@ public:
    // NB: this won't result in DISCONNECTED event being sent
    virtual bool CancelDialing();
 
+   size_t GetISPNames(class wxArrayString &) const
+      { return 0; }
+
    // sometimes the built-in logic for determining the online status may fail,
    // so, in general, the user should be allowed to override it. This function
    // allows to forcefully set the online status - whatever our internal
@@ -160,6 +171,11 @@ private:
    /// The path to ifconfig
    wxString m_IfconfigPath;
 
+   ///  Can we use ping to find hosts?
+   int m_CanUsePing;
+   /// The path to ping program
+   wxString m_PingPath;
+
    /// beacon host:
    wxString m_BeaconHost;
    /// beacon host portnumber for connect:
@@ -186,6 +202,14 @@ private:
 
    /// real status check
    void CheckStatusInternal(void);
+
+   /// Check output of ifconfig command for PPP/SLIP/PLIP devices
+   int CheckIfconfig(void);
+   /// Ping a host: 1 on success, -1 if it cannot be used, 0 if unreachable
+   int CheckPing(void);
+   /// Check by connecting to host on given port.
+   int CheckConnect(void);
+
 };
 
 
@@ -198,11 +222,11 @@ public:
          m_started = FALSE;
       }
 
-   virtual bool Start( int millisecs = -1 )
+   virtual bool Start( int millisecs = -1, bool WXUNUSED(one_shot) = FALSE )
       { m_started = TRUE; return wxTimer::Start(millisecs, FALSE); }
 
    virtual void Notify()
-      { wxLogTrace("Checking dial up network status."); m_dupman->CheckStatus(); }
+      { wxLogTrace(wxT("Checking dial up network status.")); m_dupman->CheckStatus(); }
 
    virtual void Stop()
       { if ( m_started ) wxTimer::Stop(); }
@@ -218,10 +242,14 @@ public:
       {
          m_DupMan = dupman;
       }
-   void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status)) const
+   void Disconnect(void) { m_DupMan = NULL; }
+   virtual void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
       {
-         m_DupMan->m_DialProcess = NULL;
-         m_DupMan->CheckStatus(TRUE);
+         if(m_DupMan)
+         {
+            m_DupMan->m_DialProcess = NULL;
+            m_DupMan->CheckStatus(TRUE);
+         }
       }
 private:
       wxDialUpManagerImpl *m_DupMan;
@@ -230,18 +258,41 @@ private:
 
 wxDialUpManagerImpl::wxDialUpManagerImpl()
 {
-   m_IsOnline = -1; // unknown
+   /* The isOnline flag can have the following values internally:
+      0  : not connected
+      1  : connected
+      -1 : unknown/undefined status
+   */
+   m_IsOnline = -1; 
    m_DialProcess = NULL;
    m_timer = NULL;
    m_CanUseIfconfig = -1; // unknown
+   m_CanUsePing = -1; // unknown
    m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
    m_BeaconPort = 80;
+
+#ifdef __SGI__
+   m_ConnectCommand = _T("/usr/etc/ppp");
+#elif defined(__LINUX__)
+   // default values for Debian/GNU linux
+   m_ConnectCommand = _T("pon");
+   m_HangUpCommand = _T("poff");
+#endif
+
+   wxChar * dial = wxGetenv(_T("WXDIALUP_DIALCMD"));
+   wxChar * hup = wxGetenv(_T("WXDIALUP_HUPCMD"));
+   SetConnectCommand(dial ? wxString(dial) : m_ConnectCommand,
+                     hup ? wxString(hup) : m_HangUpCommand);
 }
 
 wxDialUpManagerImpl::~wxDialUpManagerImpl()
 {
    if(m_timer) delete m_timer;
-   if(m_DialProcess) m_DialProcess->Detach();
+   if(m_DialProcess)
+   {
+      m_DialProcess->Disconnect();
+      m_DialProcess->Detach();
+   }
 }
 
 bool
@@ -252,10 +303,9 @@ wxDialUpManagerImpl::Dial(const wxString &isp,
 {
    if(m_IsOnline == 1)
       return FALSE;
-   m_IsOnline = -1;
    m_ISPname = isp;
    wxString cmd;
-   if(m_ConnectCommand.Find("%s"))
+   if(m_ConnectCommand.Find(wxT("%s")))
       cmd.Printf(m_ConnectCommand,m_ISPname.c_str());
    else
       cmd = m_ConnectCommand;
@@ -263,7 +313,7 @@ wxDialUpManagerImpl::Dial(const wxString &isp,
    if ( async )
    {
       m_DialProcess = new wxDialProcess(this);
-      m_DialPId = wxExecute(cmd, FALSE, m_DialProcess);
+      m_DialPId = (int)wxExecute(cmd, FALSE, m_DialProcess);
       if(m_DialPId == 0)
       {
          delete m_DialProcess;
@@ -287,9 +337,8 @@ wxDialUpManagerImpl::HangUp(void)
       wxLogError(_("Already dialling ISP."));
       return FALSE;
    }
-   m_IsOnline = -1;
    wxString cmd;
-   if(m_HangUpCommand.Find("%s"))
+   if(m_HangUpCommand.Find(wxT("%s")))
       cmd.Printf(m_HangUpCommand,m_ISPname.c_str(), m_DialProcess);
    else
       cmd = m_HangUpCommand;
@@ -308,7 +357,7 @@ wxDialUpManagerImpl::CancelDialing()
 bool
 wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds)
 {
-   wxASSERT(m_timer == NULL);
+   DisableAutoCheckOnlineStatus();
    m_timer = new AutoCheckTimer(this);
    bool rc = m_timer->Start(nSeconds*1000);
    if(! rc)
@@ -322,22 +371,31 @@ wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds)
 void
 wxDialUpManagerImpl::DisableAutoCheckOnlineStatus()
 {
-   wxASSERT(m_timer != NULL);
-   m_timer->Stop();
-   delete m_timer;
-   m_timer = NULL;
+   if(m_timer != NULL)
+   {
+      m_timer->Stop();
+      delete m_timer;
+      m_timer = NULL;
+   }
 }
 
 
 void
 wxDialUpManagerImpl::SetWellKnownHost(const wxString& hostname, int portno)
 {
+   if(hostname.Length() == 0)
+   {
+      m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
+      m_BeaconPort = 80;
+      return;
+   }
+         
    /// does hostname contain a port number?
-   wxString port = hostname.After(':');
+   wxString port = hostname.After(wxT(':'));
    if(port.Length())
    {
-      m_BeaconHost = hostname.Before(':');
-      m_BeaconPort = atoi(port);
+      m_BeaconHost = hostname.Before(wxT(':'));
+      m_BeaconPort = wxAtoi(port);
    }
    else
    {
@@ -357,7 +415,12 @@ wxDialUpManagerImpl::CheckStatus(bool fromAsync) const
    ( /* non-const */ (wxDialUpManagerImpl *)this)->CheckStatusInternal();
 
    // now send the events as appropriate:
-   if(m_IsOnline != oldIsOnline && oldIsOnline != -1)
+   if(m_IsOnline != oldIsOnline // it changed
+      && ( m_IsOnline == 1      // and it is a defined status
+           || m_IsOnline == 0)
+      // only send events for well defined transitions
+      && ( oldIsOnline == 1 || oldIsOnline == 0) 
+      )
    {
       wxDialUpEvent event(m_IsOnline, ! fromAsync);
       (void)wxTheApp->ProcessEvent(event);
@@ -382,14 +445,78 @@ wxDialUpManagerImpl::CheckStatusInternal(void)
 {
    m_IsOnline = -1;
 
-   // First time check for ifconfig location. We only use the variant
-   // which does not take arguments, a la GNU.
-   if(m_CanUseIfconfig == -1) // unknown
+   int testResult;
+
+   testResult = CheckConnect();
+   if(testResult == -1)
+      testResult = CheckIfconfig();
+   if(testResult == -1)
+      testResult = CheckPing();
+      m_IsOnline = testResult;
+}
+
+int
+wxDialUpManagerImpl::CheckConnect(void)
+{
+   // second method: try to connect to a well known host:
+   // This can be used under Win 9x, too!
+   struct hostent     *hp;
+   struct sockaddr_in  serv_addr;
+
+   if((hp = gethostbyname(m_BeaconHost.mb_str())) == NULL)
+      return 0; // no DNS no net
+
+   serv_addr.sin_family = hp->h_addrtype;
+   memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length);
+   serv_addr.sin_port = htons(m_BeaconPort);
+
+   int sockfd;
+   if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
    {
-      if(wxFileExists("/sbin/ifconfig"))
-         m_IfconfigPath = "/sbin/ifconfig";
-      else if(wxFileExists("/usr/sbin/ifconfig"))
-         m_IfconfigPath = "/usr/sbin/ifconfig";
+      return -1;  // no info
+   }
+
+   if( connect(sockfd, (struct sockaddr *) &serv_addr,
+               sizeof(serv_addr)) >= 0)
+   {
+      close(sockfd);
+      return 1; // we cant connect, so we have a network!
+   }
+   //connected!
+   close(sockfd);
+   if(errno == ENETUNREACH)
+      return 0; // network is unreachable
+   // connect failed, but don't know why
+   return -1;
+}
+
+int
+wxDialUpManagerImpl::CheckIfconfig(void)
+{
+   int rc = -1;
+
+   // First time check for ifconfig location. We only use the variant which
+   // does not take arguments, a la GNU.
+   if ( m_CanUseIfconfig == -1 ) // unknown
+   {
+       static const wxChar *ifconfigLocations[] =
+       {
+           _T("/sbin"),         // Linux, FreeBSD
+           _T("/usr/sbin"),     // SunOS, Solaris, AIX, HP-UX
+           _T("/usr/etc"),      // IRIX
+       };
+
+       for ( size_t n = 0; n < WXSIZEOF(ifconfigLocations); n++ )
+       {
+           wxString path(ifconfigLocations[n]);
+           path << _T("/ifconfig");
+
+           if ( wxFileExists(path) )
+           {
+               m_IfconfigPath = path;
+               break;
+           }
+       }
    }
 
    wxLogNull ln; // suppress all error messages
@@ -400,35 +527,25 @@ wxDialUpManagerImpl::CheckStatusInternal(void)
 
       wxString tmpfile = wxGetTempFileName("_wxdialuptest");
       wxString cmd = "/bin/sh -c \'";
-      cmd << m_IfconfigPath << " >" << tmpfile <<  '\'';
+      cmd << m_IfconfigPath;
+#if defined(__SOLARIS__) || defined (__SUNOS__)
+      // need to add -a flag
+      cmd << " -a";
+#elif defined(__LINUX__) || defined (__FREEBSD__) || defined(__SGI__)
+      // nothing to be added to ifconfig
+#elif defined(__HPUX__)
+      // VZ: a wild guess (but without it, ifconfig fails completely)
+      cmd << _T(" ppp0");
+#else
+#     pragma warning "No ifconfig information for this OS."
+      m_CanUseIfconfig = 0;
+      return -1;
+#endif
+      cmd << " >" << tmpfile <<  '\'';
       /* I tried to add an option to wxExecute() to not close stdout,
          so we could let ifconfig write directly to the tmpfile, but
          this does not work. That should be faster, as it doesn´t call
          the shell first. I have no idea why. :-(  (KB) */
-#if 0
-      // temporarily redirect stdout/stderr:
-      int
-         new_stdout = dup(STDOUT_FILENO),
-         new_stderr = dup(STDERR_FILENO);
-      close(STDOUT_FILENO);
-      close(STDERR_FILENO);
-
-      int
-         // new stdout:
-         output_fd = open(tmpfile, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR),
-         // new stderr:
-         null_fd = open("/dev/null", O_CREAT, S_IRUSR|S_IWUSR);
-      // verify well behaved unix behaviour:
-      wxASSERT(output_fd == STDOUT_FILENO);
-      wxASSERT(null_fd == STDERR_FILENO);
-      int rc = wxExecute(m_IfconfigPath,TRUE /* sync */,NULL ,wxEXECUTE_DONT_CLOSE_FDS);
-      close(null_fd); close(output_fd);
-      // restore old stdout, stderr:
-      int test;
-      test = dup(new_stdout); close(new_stdout); wxASSERT(test == STDOUT_FILENO);
-      test = dup(new_stderr); close(new_stderr); wxASSERT(test == STDERR_FILENO);
-      if(rc == 0)
-#endif
       if(wxExecute(cmd,TRUE /* sync */) == 0)
       {
          m_CanUseIfconfig = 1;
@@ -439,63 +556,78 @@ wxDialUpManagerImpl::CheckStatusInternal(void)
             output[file.Length()] = '\0';
             if(file.Read(output,file.Length()) == file.Length())
             {
-               if(strstr(output,"ppp")   // ppp
-                  || strstr(output,"sl") // slip
-                  || strstr(output,"pl") // plip
-                  )
-                  m_IsOnline = 1;
-               else
-                  m_IsOnline = 0;
+               // FIXME shouldn't we grep for "^ppp"? (VZ)
+
+#if defined(__SOLARIS__) || defined (__SUNOS__)
+               // dialup device under SunOS/Solaris
+               rc = strstr(output,"ipdptp") != (char *)NULL;
+#elif defined(__LINUX__) || defined (__FREEBSD__)
+               rc = strstr(output,"ppp")    // ppp
+                    || strstr(output,"sl")  // slip
+                    || strstr(output,"pl"); // plip
+#elif defined(__SGI__)  // IRIX
+               rc = strstr(output, "ppp"); // PPP
+#elif defined(__HPUX__)
+               // if could run ifconfig on interface, then it exists
+               rc = TRUE;
+#endif
             }
             file.Close();
             delete [] output;
          }
-         // else m_IsOnline remains -1 as we don't know for sure
+         // else rc remains -1 as we don't know for sure
       }
       else // could not run ifconfig correctly
          m_CanUseIfconfig = 0; // don´t try again
       (void) wxRemoveFile(tmpfile);
-      if(m_IsOnline != -1) // we are done
-         return;
    }
 
-   // second method: try to connect to well known host:
-   // This can be used under Win 9x, too!
-   struct hostent     *hp;
-   struct sockaddr_in  serv_addr;
-   int sockfd;
+   return rc;
+}
 
-   m_IsOnline = 0; // assume false
-   if((hp = gethostbyname(m_BeaconHost)) == NULL)
-      return; // no DNS no net
+int
+wxDialUpManagerImpl::CheckPing(void)
+{
+   if(! m_CanUsePing)
+      return -1;
 
-   serv_addr.sin_family = hp->h_addrtype;
-   memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length);
-   serv_addr.sin_port = htons(m_BeaconPort);
-   if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
+   // First time check for ping location. We only use the variant
+   // which does not take arguments, a la GNU.
+   if(m_CanUsePing == -1) // unknown
    {
-      //  sys_error("cannot create socket for gw");
-      return;
+      if(wxFileExists("/bin/ping"))
+         m_PingPath = "/bin/ping";
+      else if(wxFileExists("/usr/sbin/ping"))
+         m_PingPath = "/usr/sbin/ping";
+      if(! m_PingPath)
+      {
+         m_CanUsePing = 0;
+         return -1;
+      }
    }
-#if 0
-   // PING method:
 
-   if(sendto(sockfd, "hello", strlen("hello"), /* flags */ 0, &serv_addr,
-             sizeof(serv_addr)) == -1)
-      return;
+   wxLogNull ln; // suppress all error messages
+   wxASSERT(m_PingPath.length());
+   wxString cmd;
+   cmd << m_PingPath << ' ';
+#if defined(__SOLARIS__) || defined (__SUNOS__)
+   // nothing to add to ping command
+#elif defined(__LINUX__)
+   cmd << "-c 1 "; // only ping once
+#elif defined(__HPUX__)
+   cmd << "64 1 "; // only ping once (need also specify the packet size)
+#else
+#   pragma warning "No Ping information for this OS."
+   m_CanUsePing = 0;
+   return -1;
 #endif
-
-   if( connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
-   {
-      //sys_error("cannot connect to server");
-      return;
-   }
-   //connected!
-   close(sockfd);
-   m_IsOnline = TRUE;
+   cmd << m_BeaconHost;
+   if(wxExecute(cmd, TRUE /* sync */) == 0)
+      return 1;
+   else
+      return 0;
 }
 
-
 /* static */
 wxDialUpManager *
 wxDialUpManager::Create(void)