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