home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / unix / dialup.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  25KB  |  811 lines

  1. // -*- c++ -*- ////////////////////////////////////////////////////////////////
  2. // Name:        unix/dialup.cpp
  3. // Purpose:     Network related wxWindows classes and functions
  4. // Author:      Karsten Ballⁿder
  5. // Modified by:
  6. // Created:     03.10.99
  7. // RCS-ID:      $Id: dialup.cpp,v 1.35.2.2 2002/11/03 16:19:31 RR Exp $
  8. // Copyright:   (c) Karsten Ballⁿder
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "wx/setup.h"
  13.  
  14. #ifdef __GNUG__
  15. #   pragma implementation "dialup.h"
  16. #endif
  17.  
  18. #if wxUSE_DIALUP_MANAGER
  19.  
  20. #ifndef  WX_PRECOMP
  21. #   include "wx/defs.h"
  22. #endif // !PCH
  23.  
  24. #include "wx/string.h"
  25. #include "wx/event.h"
  26. #include "wx/dialup.h"
  27. #include "wx/timer.h"
  28. #include "wx/filefn.h"
  29. #include "wx/utils.h"
  30. #include "wx/log.h"
  31. #include "wx/ffile.h"
  32. #include "wx/process.h"
  33. #include "wx/intl.h"
  34. #include "wx/app.h"
  35. #include "wx/wxchar.h"
  36.  
  37. #include <stdlib.h>
  38.  
  39. #include <signal.h>
  40. #include <fcntl.h>
  41. #include <unistd.h>
  42. #define __STRICT_ANSI__
  43. #include <sys/socket.h>
  44. #include <netdb.h>
  45. #include <netinet/in.h>
  46. #include <arpa/inet.h>
  47. #include <errno.h>
  48.  
  49. DEFINE_EVENT_TYPE(wxEVT_DIALUP_CONNECTED)
  50. DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED)
  51.  
  52. // ----------------------------------------------------------------------------
  53. // A class which groups functions dealing with connecting to the network from a
  54. // workstation using dial-up access to the net. There is at most one instance
  55. // of this class in the program accessed via GetDialUpManager().
  56. // ----------------------------------------------------------------------------
  57.  
  58. /* TODO
  59.  *
  60.  * 1. more configurability for Unix: i.e. how to initiate the connection, how
  61.  *    to check for online status, &c.
  62.  * 2. add a "long Dial(long connectionId = -1)" function which asks the user
  63.  *    about which connection to dial (this may be done using native dialogs
  64.  *    under NT, need generic dialogs for all others) and returns the identifier
  65.  *    of the selected connection (it's opaque to the application) - it may be
  66.  *    reused later to dial the same connection later (or use strings instead of
  67.  *    longs may be?)
  68.  * 3. add an async version of dialing functions which notify the caller about
  69.  *    the progress (or may be even start another thread to monitor it)
  70.  * 4. the static creation/accessor functions are not MT-safe - but is this
  71.  *    really crucial? I think we may suppose they're always called from the
  72.  *    main thread?
  73.  */
  74.  
  75. class WXDLLEXPORT wxDialUpManagerImpl : public wxDialUpManager
  76. {
  77. public:
  78.    wxDialUpManagerImpl();
  79.    ~wxDialUpManagerImpl();
  80.  
  81.    /** Could the dialup manager be initialized correctly? If this function
  82.        returns FALSE, no other functions will work neither, so it's a good idea
  83.        to call this function and check its result before calling any other
  84.        wxDialUpManager methods.
  85.    */
  86.    virtual bool IsOk() const
  87.       { return TRUE; }
  88.  
  89.    /** The simplest way to initiate a dial up: this function dials the given
  90.        ISP (exact meaning of the parameter depends on the platform), returns
  91.        TRUE on success or FALSE on failure and logs the appropriate error
  92.        message in the latter case.
  93.        @param nameOfISP optional paramater for dial program
  94.        @param username unused
  95.        @param password unused
  96.    */
  97.    virtual bool Dial(const wxString& nameOfISP,
  98.                      const wxString& WXUNUSED(username),
  99.                      const wxString& WXUNUSED(password),
  100.                      bool async);
  101.  
  102.    // Hang up the currently active dial up connection.
  103.    virtual bool HangUp();
  104.  
  105.    // returns TRUE if the computer is connected to the network: under Windows,
  106.    // this just means that a RAS connection exists, under Unix we check that
  107.    // the "well-known host" (as specified by SetWellKnownHost) is reachable
  108.    virtual bool IsOnline() const
  109.       {
  110.          CheckStatus();
  111.          return m_IsOnline == Net_Connected;
  112.       }
  113.  
  114.    // do we have a constant net connection?
  115.    virtual bool IsAlwaysOnline() const;
  116.  
  117.    // returns TRUE if (async) dialing is in progress
  118.    virtual bool IsDialing() const
  119.       { return m_DialProcess != NULL; }
  120.  
  121.    // cancel dialing the number initiated with Dial(async = TRUE)
  122.    // NB: this won't result in DISCONNECTED event being sent
  123.    virtual bool CancelDialing();
  124.  
  125.    size_t GetISPNames(class wxArrayString &) const
  126.       { return 0; }
  127.  
  128.    // sometimes the built-in logic for determining the online status may fail,
  129.    // so, in general, the user should be allowed to override it. This function
  130.    // allows to forcefully set the online status - whatever our internal
  131.    // algorithm may think about it.
  132.    virtual void SetOnlineStatus(bool isOnline = TRUE)
  133.       { m_IsOnline = isOnline ? Net_Connected : Net_No; }
  134.  
  135.    // set misc wxDialUpManager options
  136.    // --------------------------------
  137.  
  138.    // enable automatical checks for the connection status and sending of
  139.    // wxEVT_DIALUP_CONNECTED/wxEVT_DIALUP_DISCONNECTED events. The interval
  140.    // parameter is only for Unix where we do the check manually: under
  141.    // Windows, the notification about the change of connection status is
  142.    // instantenous.
  143.    //
  144.    // Returns FALSE if couldn't set up automatic check for online status.
  145.    virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds);
  146.  
  147.    // disable automatic check for connection status change - notice that the
  148.    // wxEVT_DIALUP_XXX events won't be sent any more neither.
  149.    virtual void DisableAutoCheckOnlineStatus();
  150.  
  151.    // under Unix, the value of well-known host is used to check whether we're
  152.    // connected to the internet. It's unused under Windows, but this function
  153.    // is always safe to call. The default value is www.yahoo.com.
  154.    virtual void SetWellKnownHost(const wxString& hostname,
  155.                                  int portno = 80);
  156.    /** Sets the commands to start up the network and to hang up
  157.        again. Used by the Unix implementations only.
  158.    */
  159.    virtual void SetConnectCommand(const wxString &command, const wxString &hupcmd)
  160.       { m_ConnectCommand = command; m_HangUpCommand = hupcmd; }
  161.  
  162. //private: -- Sun CC 4.2 objects to using NetConnection enum as the return
  163. //            type if it is declared private
  164.  
  165.    // the possible results of testing for Online() status
  166.    enum NetConnection
  167.    {
  168.        Net_Unknown = -1,    // we couldn't learn anything
  169.        Net_No,              // no network connection [currently]
  170.        Net_Connected        // currently connected
  171.    };
  172.  
  173.    // the possible net connection types
  174.    enum NetDeviceType
  175.    {
  176.        NetDevice_None    = 0x0000,  // no network devices (authoritative)
  177.        NetDevice_Unknown = 0x0001,  // test doesn't work on this OS
  178.        NetDevice_Modem   = 0x0002,  // we have a modem
  179.        NetDevice_LAN     = 0x0004   //         a network card
  180.    };
  181.  
  182. private:
  183.    // the current status
  184.    NetConnection m_IsOnline;
  185.  
  186.    // the connection we have with the network card
  187.    NetConnection m_connCard;
  188.  
  189.    // Can we use ifconfig to list active devices?
  190.    int m_CanUseIfconfig;
  191.  
  192.    // The path to ifconfig
  193.    wxString m_IfconfigPath;
  194.  
  195.    //  Can we use ping to find hosts?
  196.    int m_CanUsePing;
  197.    // The path to ping program
  198.    wxString m_PingPath;
  199.  
  200.    // beacon host:
  201.    wxString m_BeaconHost;
  202.    // beacon host portnumber for connect:
  203.    int m_BeaconPort;
  204.  
  205.    // command to connect to network
  206.    wxString m_ConnectCommand;
  207.    // command to hang up
  208.    wxString m_HangUpCommand;
  209.    // name of ISP
  210.    wxString m_ISPname;
  211.    // a timer for regular testing
  212.    class AutoCheckTimer *m_timer;
  213.    friend class AutoCheckTimer;
  214.  
  215.    // a wxProcess for dialling in background
  216.    class wxDialProcess *m_DialProcess;
  217.    // pid of dial process
  218.    int m_DialPId;
  219.    friend class wxDialProcess;
  220.  
  221.    // determine status
  222.    void CheckStatus(bool fromAsync = FALSE) const;
  223.  
  224.    // real status check
  225.    void CheckStatusInternal();
  226.  
  227.    // check /proc/net (Linux only) for ppp/eth interfaces, returns the bit
  228.    // mask of NetDeviceType constants
  229.    int CheckProcNet();
  230.  
  231.    // check output of ifconfig command for PPP/SLIP/PLIP devices, returns the
  232.    // bit mask of NetDeviceType constants
  233.    int CheckIfconfig();
  234.  
  235.    // combines the 2 possible checks for determining the connection status
  236.    NetConnection CheckConnectAndPing();
  237.  
  238.    // pings a host
  239.    NetConnection CheckPing();
  240.  
  241.    // check by connecting to host on given port.
  242.    NetConnection CheckConnect();
  243. };
  244.  
  245.  
  246. class AutoCheckTimer : public wxTimer
  247. {
  248. public:
  249.    AutoCheckTimer(wxDialUpManagerImpl *dupman)
  250.       {
  251.          m_dupman = dupman;
  252.          m_started = FALSE;
  253.       }
  254.  
  255.    virtual bool Start( int millisecs = -1, bool WXUNUSED(one_shot) = FALSE )
  256.       { m_started = TRUE; return wxTimer::Start(millisecs, FALSE); }
  257.  
  258.    virtual void Notify()
  259.       { wxLogTrace(wxT("Checking dial up network status.")); m_dupman->CheckStatus(); }
  260.  
  261.    virtual void Stop()
  262.       { if ( m_started ) wxTimer::Stop(); }
  263. public:
  264.    bool m_started;
  265.    wxDialUpManagerImpl *m_dupman;
  266. };
  267.  
  268. class wxDialProcess : public wxProcess
  269. {
  270. public:
  271.    wxDialProcess(wxDialUpManagerImpl *dupman)
  272.       {
  273.          m_DupMan = dupman;
  274.       }
  275.    void Disconnect() { m_DupMan = NULL; }
  276.    virtual void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
  277.       {
  278.          if(m_DupMan)
  279.          {
  280.             m_DupMan->m_DialProcess = NULL;
  281.             m_DupMan->CheckStatus(TRUE);
  282.          }
  283.       }
  284. private:
  285.       wxDialUpManagerImpl *m_DupMan;
  286. };
  287.  
  288.  
  289. wxDialUpManagerImpl::wxDialUpManagerImpl()
  290. {
  291.    m_IsOnline =
  292.    m_connCard = Net_Unknown;
  293.    m_DialProcess = NULL;
  294.    m_timer = NULL;
  295.    m_CanUseIfconfig = -1; // unknown
  296.    m_CanUsePing = -1; // unknown
  297.    m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
  298.    m_BeaconPort = 80;
  299.  
  300. #ifdef __SGI__
  301.    m_ConnectCommand = _T("/usr/etc/ppp");
  302. #elif defined(__LINUX__)
  303.    // default values for Debian/GNU linux
  304.    m_ConnectCommand = _T("pon");
  305.    m_HangUpCommand = _T("poff");
  306. #endif
  307.  
  308.    wxChar * dial = wxGetenv(_T("WXDIALUP_DIALCMD"));
  309.    wxChar * hup = wxGetenv(_T("WXDIALUP_HUPCMD"));
  310.    SetConnectCommand(dial ? wxString(dial) : m_ConnectCommand,
  311.                      hup ? wxString(hup) : m_HangUpCommand);
  312. }
  313.  
  314. wxDialUpManagerImpl::~wxDialUpManagerImpl()
  315. {
  316.    if(m_timer) delete m_timer;
  317.    if(m_DialProcess)
  318.    {
  319.       m_DialProcess->Disconnect();
  320.       m_DialProcess->Detach();
  321.    }
  322. }
  323.  
  324. bool
  325. wxDialUpManagerImpl::Dial(const wxString &isp,
  326.                           const wxString & WXUNUSED(username),
  327.                           const wxString & WXUNUSED(password),
  328.                           bool async)
  329. {
  330.    if(m_IsOnline == Net_Connected)
  331.       return FALSE;
  332.    m_ISPname = isp;
  333.    wxString cmd;
  334.    if(m_ConnectCommand.Find(wxT("%s")))
  335.       cmd.Printf(m_ConnectCommand,m_ISPname.c_str());
  336.    else
  337.       cmd = m_ConnectCommand;
  338.  
  339.    if ( async )
  340.    {
  341.       m_DialProcess = new wxDialProcess(this);
  342.       m_DialPId = (int)wxExecute(cmd, FALSE, m_DialProcess);
  343.       if(m_DialPId == 0)
  344.       {
  345.          delete m_DialProcess;
  346.          m_DialProcess = NULL;
  347.          return FALSE;
  348.       }
  349.       else
  350.          return TRUE;
  351.    }
  352.    else
  353.        return wxExecute(cmd, /* sync */ TRUE) == 0;
  354. }
  355.  
  356. bool wxDialUpManagerImpl::HangUp()
  357. {
  358.    if(m_IsOnline == Net_No)
  359.       return FALSE;
  360.    if(IsDialing())
  361.    {
  362.       wxLogError(_("Already dialling ISP."));
  363.       return FALSE;
  364.    }
  365.    wxString cmd;
  366.    if(m_HangUpCommand.Find(wxT("%s")))
  367.       cmd.Printf(m_HangUpCommand,m_ISPname.c_str(), m_DialProcess);
  368.    else
  369.       cmd = m_HangUpCommand;
  370.    return wxExecute(cmd, /* sync */ TRUE) == 0;
  371. }
  372.  
  373.  
  374. bool wxDialUpManagerImpl::CancelDialing()
  375. {
  376.    if(! IsDialing())
  377.       return FALSE;
  378.    return kill(m_DialPId, SIGTERM) > 0;
  379. }
  380.  
  381. bool wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds)
  382. {
  383.    DisableAutoCheckOnlineStatus();
  384.    m_timer = new AutoCheckTimer(this);
  385.    bool rc = m_timer->Start(nSeconds*1000);
  386.    if(! rc)
  387.    {
  388.       delete m_timer;
  389.       m_timer = NULL;
  390.    }
  391.    return rc;
  392. }
  393.  
  394. void wxDialUpManagerImpl::DisableAutoCheckOnlineStatus()
  395. {
  396.    if(m_timer != NULL)
  397.    {
  398.       m_timer->Stop();
  399.       delete m_timer;
  400.       m_timer = NULL;
  401.    }
  402. }
  403.  
  404.  
  405. void wxDialUpManagerImpl::SetWellKnownHost(const wxString& hostname, int portno)
  406. {
  407.    if(hostname.Length() == 0)
  408.    {
  409.       m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
  410.       m_BeaconPort = 80;
  411.       return;
  412.    }
  413.  
  414.    // does hostname contain a port number?
  415.    wxString port = hostname.After(wxT(':'));
  416.    if(port.Length())
  417.    {
  418.       m_BeaconHost = hostname.Before(wxT(':'));
  419.       m_BeaconPort = wxAtoi(port);
  420.    }
  421.    else
  422.    {
  423.       m_BeaconHost = hostname;
  424.       m_BeaconPort = portno;
  425.    }
  426. }
  427.  
  428.  
  429. void wxDialUpManagerImpl::CheckStatus(bool fromAsync) const
  430. {
  431.     // This function calls the CheckStatusInternal() helper function
  432.     // which is OS - specific and then sends the events.
  433.  
  434.     NetConnection oldIsOnline = m_IsOnline;
  435.     ( /* non-const */ (wxDialUpManagerImpl *)this)->CheckStatusInternal();
  436.  
  437.     // now send the events as appropriate: i.e. if the status changed and
  438.     // if we're in defined state
  439.     if(m_IsOnline != oldIsOnline
  440.             && m_IsOnline != Net_Unknown
  441.             && oldIsOnline != Net_Unknown )
  442.     {
  443.         wxDialUpEvent event(m_IsOnline == Net_Connected, ! fromAsync);
  444.         (void)wxTheApp->ProcessEvent(event);
  445.     }
  446. }
  447.  
  448. /*
  449.    We first try to find out if ppp interface is active. If it is, we assume
  450.    that we're online but don't have a permanent connection (this is false if a
  451.    networked machine uses modem to connect to somewhere else, but we can't do
  452.    anything in this case anyhow).
  453.  
  454.    If no ppp interface is detected, we check for eth interface. If it is
  455.    found, we check that we can, indeed, connect to an Internet host. The logic
  456.    here is that connection check should be fast enough in this case and we
  457.    don't want to give false positives in a (common) case of a machine on a LAN
  458.    which is not connected to the outside.
  459.  
  460.    If we didn't find either ppp or eth interfaces, we stop here and decide
  461.    that we're connected. However, if couldn't check for this, we try to ping a
  462.    remote host just in case.
  463.  
  464.    NB1: Checking for the interface presence can be done in 2 ways
  465.         a) reading /proc/net/dev under Linux
  466.         b) spawning ifconfig under any OS
  467.  
  468.         The first method is faster but only works under Linux.
  469.  
  470.    NB2: pinging, actually, means that we first try to connect "manually" to
  471.         a port on remove machine and if it fails, we run ping.
  472. */
  473.  
  474. void wxDialUpManagerImpl::CheckStatusInternal()
  475. {
  476.     m_IsOnline = Net_Unknown;
  477.  
  478.     // first do quick checks to determine what kind of network devices do we
  479.     // have
  480.     int netDeviceType = CheckProcNet();
  481.     if ( netDeviceType == NetDevice_Unknown )
  482.     {
  483.         // nothing found, try ifconfig too
  484.         netDeviceType = CheckIfconfig();
  485.     }
  486.  
  487.     switch ( netDeviceType )
  488.     {
  489.         case NetDevice_None:
  490.             // no network devices, no connection
  491.             m_IsOnline = Net_No;
  492.             break;
  493.  
  494.         case NetDevice_LAN:
  495.             // we still do ping to confirm that we're connected but we only do
  496.             // it once and hope that the purpose of the network card (i.e.
  497.             // whether it used for connecting to the Internet or just to a
  498.             // LAN) won't change during the program lifetime
  499.             if ( m_connCard == Net_Unknown )
  500.             {
  501.                 m_connCard = CheckConnectAndPing();
  502.             }
  503.             m_IsOnline = m_connCard;
  504.             break;
  505.  
  506.         case NetDevice_Unknown:
  507.             // try to ping just in case
  508.             m_IsOnline = CheckConnectAndPing();
  509.             break;
  510.  
  511.         case NetDevice_LAN + NetDevice_Modem:
  512.         case NetDevice_Modem:
  513.             // assume we're connected
  514.             m_IsOnline = Net_Connected;
  515.             break;
  516.  
  517.         default:
  518.             wxFAIL_MSG(_T("Unexpected netDeviceType"));
  519.     }
  520. }
  521.  
  522. bool wxDialUpManagerImpl::IsAlwaysOnline() const
  523. {
  524.     wxDialUpManagerImpl *self = wxConstCast(this, wxDialUpManagerImpl);
  525.  
  526.     int netDeviceType = self->CheckProcNet();
  527.     if ( netDeviceType == NetDevice_Unknown )
  528.     {
  529.         // nothing found, try ifconfig too
  530.         netDeviceType = self->CheckIfconfig();
  531.     }
  532.  
  533.     if ( netDeviceType == NetDevice_Unknown )
  534.     {
  535.         // this is the only thing we can do unfortunately...
  536.         self->HangUp();
  537.         return IsOnline();
  538.     }
  539.     else
  540.     {
  541.         // we are only permanently online if we have a network card
  542.         return (netDeviceType & NetDevice_LAN) != 0;
  543.     }
  544. }
  545.  
  546. wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnectAndPing()
  547. {
  548.     NetConnection conn;
  549.  
  550.     // first try connecting - faster
  551.     conn = CheckConnect();
  552.     if ( conn == Net_Unknown )
  553.     {
  554.         // try pinging too
  555.         conn = CheckPing();
  556.     }
  557.  
  558.     return conn;
  559. }
  560.  
  561. wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnect()
  562. {
  563.    // second method: try to connect to a well known host:
  564.    // This can be used under Win 9x, too!
  565.    struct hostent     *hp;
  566.    struct sockaddr_in  serv_addr;
  567.  
  568.    if((hp = gethostbyname(m_BeaconHost.mb_str())) == NULL)
  569.       return Net_No; // no DNS no net
  570.  
  571.    serv_addr.sin_family = hp->h_addrtype;
  572.    memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length);
  573.    serv_addr.sin_port = htons(m_BeaconPort);
  574.  
  575.    int sockfd;
  576.    if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
  577.    {
  578.       return Net_Unknown;  // no info
  579.    }
  580.  
  581.    if( connect(sockfd, (struct sockaddr *) &serv_addr,
  582.                sizeof(serv_addr)) >= 0)
  583.    {
  584.       close(sockfd);
  585.       return Net_Connected; // we can connect, so we have a network!
  586.    }
  587.    else // failed to connect
  588.    {
  589.        if(errno == ENETUNREACH)
  590.           return Net_No; // network is unreachable
  591.        else
  592.           return Net_Unknown; // connect failed, but don't know why
  593.    }
  594. }
  595.  
  596.  
  597. int
  598. wxDialUpManagerImpl::CheckProcNet()
  599. {
  600.     // assume that the test doesn't work
  601.     int netDevice = NetDevice_Unknown;
  602.  
  603. #ifdef __LINUX__
  604.     if (wxFileExists(_T("/proc/net/route")))
  605.     {
  606.         // cannot use wxFile::Length because file doesn't support seeking, so
  607.         // use stdio directly
  608.         FILE *f = fopen("/proc/net/route", "rt");
  609.         if (f != NULL)
  610.         {
  611.             // now we know that we will find all devices we may have
  612.             netDevice = NetDevice_None;
  613.  
  614.             char output[256];
  615.  
  616.             while (fgets(output, 256, f) != NULL)
  617.             {
  618.                 if ( strstr(output, "eth") ) // network card
  619.                 {
  620.                     netDevice |= NetDevice_LAN;
  621.                 }
  622.                 else if (strstr(output,"ppp")   // ppp
  623.                         || strstr(output,"sl")  // slip
  624.                         || strstr(output,"pl")) // plip
  625.                 {
  626.                     netDevice |= NetDevice_Modem;
  627.                 }
  628.             }
  629.  
  630.             fclose(f);
  631.         }
  632.     }
  633. #endif // __LINUX__
  634.  
  635.     return netDevice;
  636. }
  637.  
  638.  
  639. int
  640. wxDialUpManagerImpl::CheckIfconfig()
  641. {
  642. #ifdef __VMS
  643.        m_CanUseIfconfig = 0;
  644.         return -1;
  645. #else
  646.    // assume that the test doesn't work
  647.     int netDevice = NetDevice_Unknown;
  648.  
  649.     // first time check for ifconfig location
  650.     if ( m_CanUseIfconfig == -1 ) // unknown
  651.     {
  652.         static const wxChar *ifconfigLocations[] =
  653.         {
  654.             _T("/sbin"),         // Linux, FreeBSD, Darwin
  655.             _T("/usr/sbin"),     // SunOS, Solaris, AIX, HP-UX
  656.             _T("/usr/etc"),      // IRIX
  657.         };
  658.  
  659.         for ( size_t n = 0; n < WXSIZEOF(ifconfigLocations); n++ )
  660.         {
  661.             wxString path(ifconfigLocations[n]);
  662.             path << _T("/ifconfig");
  663.  
  664.             if ( wxFileExists(path) )
  665.             {
  666.                 m_IfconfigPath = path;
  667.                 break;
  668.             }
  669.         }
  670.     }
  671.  
  672.     if ( m_CanUseIfconfig != 0 ) // unknown or yes
  673.     {
  674.         wxLogNull ln; // suppress all error messages
  675.  
  676.         wxASSERT_MSG( m_IfconfigPath.length(),
  677.                       _T("can't use ifconfig if it wasn't found") );
  678.  
  679.         wxString tmpfile = wxGetTempFileName( wxT("_wxdialuptest") );
  680.         wxString cmd = wxT("/bin/sh -c \'");
  681.         cmd << m_IfconfigPath;
  682. #if defined(__SOLARIS__) || defined (__SUNOS__)
  683.         // need to add -a flag
  684.         cmd << wxT(" -a");
  685. #elif defined(__LINUX__) || defined(__SGI__)
  686.         // nothing to be added to ifconfig
  687. #elif defined(__FREEBSD__) || defined(__DARWIN__)
  688.         // add -l flag
  689.         cmd << wxT(" -l");
  690. #elif defined(__HPUX__)
  691.         // VZ: a wild guess (but without it, ifconfig fails completely)
  692.         cmd << wxT(" ppp0");
  693. #else
  694. # pragma warning "No ifconfig information for this OS."
  695.        m_CanUseIfconfig = 0;
  696.         return -1;
  697. #endif
  698.        cmd << wxT(" >") << tmpfile <<  wxT('\'');
  699.         /* I tried to add an option to wxExecute() to not close stdout,
  700.            so we could let ifconfig write directly to the tmpfile, but
  701.            this does not work. That should be faster, as it doesn┤t call
  702.            the shell first. I have no idea why. :-(  (KB) */
  703.         if ( wxExecute(cmd,TRUE /* sync */) == 0 )
  704.         {
  705.             m_CanUseIfconfig = 1;
  706.             wxFFile file;
  707.             if( file.Open(tmpfile) )
  708.             {
  709.                 wxString output;
  710.                 if ( file.ReadAll(&output) )
  711.                 {
  712.                     // FIXME shouldn't we grep for "^ppp"? (VZ)
  713.  
  714.                     bool hasModem = FALSE,
  715.                          hasLAN = FALSE;
  716.  
  717. #if defined(__SOLARIS__) || defined (__SUNOS__)
  718.                     // dialup device under SunOS/Solaris
  719.                     hasModem = strstr(output,"ipdptp") != (char *)NULL;
  720.                     hasLAN = strstr(output, "hme") != (char *)NULL;
  721. #elif defined(__LINUX__) || defined (__FREEBSD__)
  722.                     hasModem = strstr(output.fn_str(),"ppp")    // ppp
  723.                         || strstr(output.fn_str(),"sl")  // slip
  724.                         || strstr(output.fn_str(),"pl"); // plip
  725.                     hasLAN = strstr(output.fn_str(), "eth") != NULL;
  726. #elif defined(__SGI__)  // IRIX
  727.                     hasModem = strstr(output, "ppp") != NULL; // PPP
  728. #elif defined(__HPUX__)
  729.                     // if could run ifconfig on interface, then it exists
  730.                     hasModem = TRUE;
  731. #endif
  732.  
  733.                     netDevice = NetDevice_None;
  734.                     if ( hasModem )
  735.                         netDevice |= NetDevice_Modem;
  736.                     if ( hasLAN )
  737.                         netDevice |= NetDevice_LAN;
  738.                 }
  739.                 //else: error reading the file
  740.             }
  741.             //else: error opening the file
  742.         }
  743.         else // could not run ifconfig correctly
  744.         {
  745.             m_CanUseIfconfig = 0; // don┤t try again
  746.         }
  747.  
  748.         (void) wxRemoveFile(tmpfile);
  749.     }
  750.  
  751.     return netDevice;
  752. #endif
  753. }
  754.  
  755. wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckPing()
  756. {
  757.     // First time check for ping location. We only use the variant
  758.     // which does not take arguments, a la GNU.
  759.     if(m_CanUsePing == -1) // unknown
  760.     {
  761. #ifdef __VMS
  762.         if (wxFileExists( wxT("SYS$SYSTEM:TCPIP$PING.EXE") ))
  763.             m_PingPath = wxT("$SYS$SYSTEM:TCPIP$PING");
  764. #else
  765.         if (wxFileExists( wxT("/bin/ping") ))
  766.             m_PingPath = wxT("/bin/ping");
  767.         else if (wxFileExists( wxT("/usr/sbin/ping") ))
  768.             m_PingPath = wxT("/usr/sbin/ping");
  769. #endif
  770.         if (!m_PingPath)
  771.         {
  772.             m_CanUsePing = 0;
  773.         }
  774.     }
  775.  
  776.     if(! m_CanUsePing)
  777.     {
  778.        // we didn't find ping
  779.        return Net_Unknown;
  780.     }
  781.  
  782.    wxLogNull ln; // suppress all error messages
  783.    wxASSERT(m_PingPath.length());
  784.    wxString cmd;
  785.    cmd << m_PingPath << wxT(' ');
  786. #if defined(__SOLARIS__) || defined (__SUNOS__)
  787.    // nothing to add to ping command
  788. #elif defined(__LINUX__) || defined (__BSD__) || defined( __VMS )
  789.    cmd << wxT("-c 1 "); // only ping once
  790. #elif defined(__HPUX__)
  791.    cmd << wxT("64 1 "); // only ping once (need also specify the packet size)
  792. #else
  793. #   pragma warning "No Ping information for this OS."
  794.    m_CanUsePing = 0;
  795.    return Net_Unknown;
  796. #endif
  797.    cmd << m_BeaconHost;
  798.    if(wxExecute(cmd, TRUE /* sync */) == 0)
  799.       return Net_Connected;
  800.    else
  801.       return Net_No;
  802. }
  803.  
  804. /* static */
  805. wxDialUpManager *wxDialUpManager::Create()
  806. {
  807.    return new wxDialUpManagerImpl;
  808. }
  809.  
  810. #endif // wxUSE_DIALUP_MANAGER
  811.