]> git.saurik.com Git - wxWidgets.git/blob - src/unix/dialup.cpp
fixed bug #129464 (hopefully)
[wxWidgets.git] / src / unix / dialup.cpp
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$
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 // ----------------------------------------------------------------------------
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 m_started = FALSE;
250 }
251
252 virtual bool Start( int millisecs = -1, bool WXUNUSED(one_shot) = FALSE )
253 { m_started = TRUE; return wxTimer::Start(millisecs, FALSE); }
254
255 virtual void Notify()
256 { wxLogTrace(wxT("Checking dial up network status.")); m_dupman->CheckStatus(); }
257
258 virtual void Stop()
259 { if ( m_started ) wxTimer::Stop(); }
260 public:
261 bool m_started;
262 wxDialUpManagerImpl *m_dupman;
263 };
264
265 class wxDialProcess : public wxProcess
266 {
267 public:
268 wxDialProcess(wxDialUpManagerImpl *dupman)
269 {
270 m_DupMan = dupman;
271 }
272 void Disconnect() { m_DupMan = NULL; }
273 virtual void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
274 {
275 if(m_DupMan)
276 {
277 m_DupMan->m_DialProcess = NULL;
278 m_DupMan->CheckStatus(TRUE);
279 }
280 }
281 private:
282 wxDialUpManagerImpl *m_DupMan;
283 };
284
285
286 wxDialUpManagerImpl::wxDialUpManagerImpl()
287 {
288 m_IsOnline =
289 m_connCard = Net_Unknown;
290 m_DialProcess = NULL;
291 m_timer = NULL;
292 m_CanUseIfconfig = -1; // unknown
293 m_CanUsePing = -1; // unknown
294 m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
295 m_BeaconPort = 80;
296
297 #ifdef __SGI__
298 m_ConnectCommand = _T("/usr/etc/ppp");
299 #elif defined(__LINUX__)
300 // default values for Debian/GNU linux
301 m_ConnectCommand = _T("pon");
302 m_HangUpCommand = _T("poff");
303 #endif
304
305 wxChar * dial = wxGetenv(_T("WXDIALUP_DIALCMD"));
306 wxChar * hup = wxGetenv(_T("WXDIALUP_HUPCMD"));
307 SetConnectCommand(dial ? wxString(dial) : m_ConnectCommand,
308 hup ? wxString(hup) : m_HangUpCommand);
309 }
310
311 wxDialUpManagerImpl::~wxDialUpManagerImpl()
312 {
313 if(m_timer) delete m_timer;
314 if(m_DialProcess)
315 {
316 m_DialProcess->Disconnect();
317 m_DialProcess->Detach();
318 }
319 }
320
321 bool
322 wxDialUpManagerImpl::Dial(const wxString &isp,
323 const wxString & WXUNUSED(username),
324 const wxString & WXUNUSED(password),
325 bool async)
326 {
327 if(m_IsOnline == Net_Connected)
328 return FALSE;
329 m_ISPname = isp;
330 wxString cmd;
331 if(m_ConnectCommand.Find(wxT("%s")))
332 cmd.Printf(m_ConnectCommand,m_ISPname.c_str());
333 else
334 cmd = m_ConnectCommand;
335
336 if ( async )
337 {
338 m_DialProcess = new wxDialProcess(this);
339 m_DialPId = (int)wxExecute(cmd, FALSE, m_DialProcess);
340 if(m_DialPId == 0)
341 {
342 delete m_DialProcess;
343 m_DialProcess = NULL;
344 return FALSE;
345 }
346 else
347 return TRUE;
348 }
349 else
350 return wxExecute(cmd, /* sync */ TRUE) == 0;
351 }
352
353 bool wxDialUpManagerImpl::HangUp()
354 {
355 if(m_IsOnline == Net_No)
356 return FALSE;
357 if(IsDialing())
358 {
359 wxLogError(_("Already dialling ISP."));
360 return FALSE;
361 }
362 wxString cmd;
363 if(m_HangUpCommand.Find(wxT("%s")))
364 cmd.Printf(m_HangUpCommand,m_ISPname.c_str(), m_DialProcess);
365 else
366 cmd = m_HangUpCommand;
367 return wxExecute(cmd, /* sync */ TRUE) == 0;
368 }
369
370
371 bool wxDialUpManagerImpl::CancelDialing()
372 {
373 if(! IsDialing())
374 return FALSE;
375 return kill(m_DialPId, SIGTERM) > 0;
376 }
377
378 bool wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds)
379 {
380 DisableAutoCheckOnlineStatus();
381 m_timer = new AutoCheckTimer(this);
382 bool rc = m_timer->Start(nSeconds*1000);
383 if(! rc)
384 {
385 delete m_timer;
386 m_timer = NULL;
387 }
388 return rc;
389 }
390
391 void wxDialUpManagerImpl::DisableAutoCheckOnlineStatus()
392 {
393 if(m_timer != NULL)
394 {
395 m_timer->Stop();
396 delete m_timer;
397 m_timer = NULL;
398 }
399 }
400
401
402 void wxDialUpManagerImpl::SetWellKnownHost(const wxString& hostname, int portno)
403 {
404 if(hostname.Length() == 0)
405 {
406 m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
407 m_BeaconPort = 80;
408 return;
409 }
410
411 // does hostname contain a port number?
412 wxString port = hostname.After(wxT(':'));
413 if(port.Length())
414 {
415 m_BeaconHost = hostname.Before(wxT(':'));
416 m_BeaconPort = wxAtoi(port);
417 }
418 else
419 {
420 m_BeaconHost = hostname;
421 m_BeaconPort = portno;
422 }
423 }
424
425
426 void wxDialUpManagerImpl::CheckStatus(bool fromAsync) const
427 {
428 // This function calls the CheckStatusInternal() helper function
429 // which is OS - specific and then sends the events.
430
431 NetConnection oldIsOnline = m_IsOnline;
432 ( /* non-const */ (wxDialUpManagerImpl *)this)->CheckStatusInternal();
433
434 // now send the events as appropriate: i.e. if the status changed and
435 // if we're in defined state
436 if(m_IsOnline != oldIsOnline
437 && m_IsOnline != Net_Unknown
438 && oldIsOnline != Net_Unknown )
439 {
440 wxDialUpEvent event(m_IsOnline == Net_Connected, ! fromAsync);
441 (void)wxTheApp->ProcessEvent(event);
442 }
443 }
444
445 /*
446 We first try to find out if ppp interface is active. If it is, we assume
447 that we're online but don't have a permanent connection (this is false if a
448 networked machine uses modem to connect to somewhere else, but we can't do
449 anything in this case anyhow).
450
451 If no ppp interface is detected, we check for eth interface. If it is
452 found, we check that we can, indeed, connect to an Internet host. The logic
453 here is that connection check should be fast enough in this case and we
454 don't want to give false positives in a (common) case of a machine on a LAN
455 which is not connected to the outside.
456
457 If we didn't find either ppp or eth interfaces, we stop here and decide
458 that we're connected. However, if couldn't check for this, we try to ping a
459 remote host just in case.
460
461 NB1: Checking for the interface presence can be done in 2 ways
462 a) reading /proc/net/dev under Linux
463 b) spawning ifconfig under any OS
464
465 The first method is faster but only works under Linux.
466
467 NB2: pinging, actually, means that we first try to connect "manually" to
468 a port on remove machine and if it fails, we run ping.
469 */
470
471 void wxDialUpManagerImpl::CheckStatusInternal()
472 {
473 m_IsOnline = Net_Unknown;
474
475 // first do quick checks to determine what kind of network devices do we
476 // have
477 int netDeviceType = CheckProcNet();
478 if ( netDeviceType == NetDevice_Unknown )
479 {
480 // nothing found, try ifconfig too
481 netDeviceType = CheckIfconfig();
482 }
483
484 switch ( netDeviceType )
485 {
486 case NetDevice_None:
487 // no network devices, no connection
488 m_IsOnline = Net_No;
489 break;
490
491 case NetDevice_LAN:
492 // we still do ping to confirm that we're connected but we only do
493 // it once and hope that the purpose of the network card (i.e.
494 // whether it used for connecting to the Internet or just to a
495 // LAN) won't change during the program lifetime
496 if ( m_connCard == Net_Unknown )
497 {
498 m_connCard = CheckConnectAndPing();
499 }
500 m_IsOnline = m_connCard;
501 break;
502
503 case NetDevice_Unknown:
504 // try to ping just in case
505 m_IsOnline = CheckConnectAndPing();
506 break;
507
508 case NetDevice_LAN + NetDevice_Modem:
509 case NetDevice_Modem:
510 // assume we're connected
511 m_IsOnline = Net_Connected;
512 break;
513
514 default:
515 wxFAIL_MSG(_T("Unexpected netDeviceType"));
516 }
517 }
518
519 bool wxDialUpManagerImpl::IsAlwaysOnline() const
520 {
521 wxDialUpManagerImpl *self = wxConstCast(this, wxDialUpManagerImpl);
522
523 int netDeviceType = self->CheckProcNet();
524 if ( netDeviceType == NetDevice_Unknown )
525 {
526 // nothing found, try ifconfig too
527 netDeviceType = self->CheckIfconfig();
528 }
529
530 if ( netDeviceType == NetDevice_Unknown )
531 {
532 // this is the only thing we can do unfortunately...
533 self->HangUp();
534 return IsOnline();
535 }
536 else
537 {
538 // we are only permanently online if we have a network card
539 return (netDeviceType & NetDevice_LAN) != 0;
540 }
541 }
542
543 wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnectAndPing()
544 {
545 NetConnection conn;
546
547 // first try connecting - faster
548 conn = CheckConnect();
549 if ( conn == Net_Unknown )
550 {
551 // try pinging too
552 conn = CheckPing();
553 }
554
555 return conn;
556 }
557
558 wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnect()
559 {
560 // second method: try to connect to a well known host:
561 // This can be used under Win 9x, too!
562 struct hostent *hp;
563 struct sockaddr_in serv_addr;
564
565 if((hp = gethostbyname(m_BeaconHost.mb_str())) == NULL)
566 return Net_No; // no DNS no net
567
568 serv_addr.sin_family = hp->h_addrtype;
569 memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length);
570 serv_addr.sin_port = htons(m_BeaconPort);
571
572 int sockfd;
573 if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
574 {
575 return Net_Unknown; // no info
576 }
577
578 if( connect(sockfd, (struct sockaddr *) &serv_addr,
579 sizeof(serv_addr)) >= 0)
580 {
581 close(sockfd);
582 return Net_Connected; // we can connect, so we have a network!
583 }
584 else // failed to connect
585 {
586 if(errno == ENETUNREACH)
587 return Net_No; // network is unreachable
588 else
589 return Net_Unknown; // connect failed, but don't know why
590 }
591 }
592
593
594 int
595 wxDialUpManagerImpl::CheckProcNet()
596 {
597 // assume that the test doesn't work
598 int netDevice = NetDevice_Unknown;
599
600 #ifdef __LINUX__
601 if (wxFileExists(_T("/proc/net/route")))
602 {
603 // cannot use wxFile::Length because file doesn't support seeking, so
604 // use stdio directly
605 FILE *f = fopen("/proc/net/route", "rt");
606 if (f != NULL)
607 {
608 // now we know that we will find all devices we may have
609 netDevice = NetDevice_None;
610
611 char output[256];
612
613 while (fgets(output, 256, f) != NULL)
614 {
615 if ( strstr(output, "eth") ) // network card
616 {
617 netDevice |= NetDevice_LAN;
618 }
619 else if (strstr(output,"ppp") // ppp
620 || strstr(output,"sl") // slip
621 || strstr(output,"pl")) // plip
622 {
623 netDevice |= NetDevice_Modem;
624 }
625 }
626
627 fclose(f);
628 }
629 }
630 #endif // __LINUX__
631
632 return netDevice;
633 }
634
635
636 int
637 wxDialUpManagerImpl::CheckIfconfig()
638 {
639 // assume that the test doesn't work
640 int netDevice = NetDevice_Unknown;
641
642 // first time check for ifconfig location
643 if ( m_CanUseIfconfig == -1 ) // unknown
644 {
645 static const wxChar *ifconfigLocations[] =
646 {
647 _T("/sbin"), // Linux, FreeBSD
648 _T("/usr/sbin"), // SunOS, Solaris, AIX, HP-UX
649 _T("/usr/etc"), // IRIX
650 };
651
652 for ( size_t n = 0; n < WXSIZEOF(ifconfigLocations); n++ )
653 {
654 wxString path(ifconfigLocations[n]);
655 path << _T("/ifconfig");
656
657 if ( wxFileExists(path) )
658 {
659 m_IfconfigPath = path;
660 break;
661 }
662 }
663 }
664
665 if ( m_CanUseIfconfig != 0 ) // unknown or yes
666 {
667 wxLogNull ln; // suppress all error messages
668
669 wxASSERT_MSG( m_IfconfigPath.length(),
670 _T("can't use ifconfig if it wasn't found") );
671
672 wxString tmpfile = wxGetTempFileName("_wxdialuptest");
673 wxString cmd = "/bin/sh -c \'";
674 cmd << m_IfconfigPath;
675 #if defined(__SOLARIS__) || defined (__SUNOS__)
676 // need to add -a flag
677 cmd << " -a";
678 #elif defined(__LINUX__) || defined(__SGI__)
679 // nothing to be added to ifconfig
680 #elif defined(__FREEBSD__)
681 // add -l flag
682 cmd << " -l";
683 #elif defined(__HPUX__)
684 // VZ: a wild guess (but without it, ifconfig fails completely)
685 cmd << _T(" ppp0");
686 #else
687 # pragma warning "No ifconfig information for this OS."
688 m_CanUseIfconfig = 0;
689 return -1;
690 #endif
691 cmd << " >" << tmpfile << '\'';
692 /* I tried to add an option to wxExecute() to not close stdout,
693 so we could let ifconfig write directly to the tmpfile, but
694 this does not work. That should be faster, as it doesn´t call
695 the shell first. I have no idea why. :-( (KB) */
696 if ( wxExecute(cmd,TRUE /* sync */) == 0 )
697 {
698 m_CanUseIfconfig = 1;
699 wxFFile file;
700 if( file.Open(tmpfile) )
701 {
702 wxString output;
703 if ( file.ReadAll(&output) )
704 {
705 // FIXME shouldn't we grep for "^ppp"? (VZ)
706
707 bool hasModem = FALSE,
708 hasLAN = FALSE;
709
710 #if defined(__SOLARIS__) || defined (__SUNOS__)
711 // dialup device under SunOS/Solaris
712 hasModem = strstr(output,"ipdptp") != (char *)NULL;
713 hasLAN = strstr(output, "hme") != (char *)NULL;
714 #elif defined(__LINUX__) || defined (__FREEBSD__)
715 hasModem = strstr(output,"ppp") // ppp
716 || strstr(output,"sl") // slip
717 || strstr(output,"pl"); // plip
718 hasLAN = strstr(output, "eth") != NULL;
719 #elif defined(__SGI__) // IRIX
720 hasModem = strstr(output, "ppp") != NULL; // PPP
721 #elif defined(__HPUX__)
722 // if could run ifconfig on interface, then it exists
723 hasModem = TRUE;
724 #endif
725
726 netDevice = NetDevice_None;
727 if ( hasModem )
728 netDevice |= NetDevice_Modem;
729 if ( hasLAN )
730 netDevice |= NetDevice_LAN;
731 }
732 //else: error reading the file
733 }
734 //else: error opening the file
735 }
736 else // could not run ifconfig correctly
737 {
738 m_CanUseIfconfig = 0; // don´t try again
739 }
740
741 (void) wxRemoveFile(tmpfile);
742 }
743
744 return netDevice;
745 }
746
747 wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckPing()
748 {
749 // First time check for ping location. We only use the variant
750 // which does not take arguments, a la GNU.
751 if(m_CanUsePing == -1) // unknown
752 {
753 if(wxFileExists("/bin/ping"))
754 m_PingPath = "/bin/ping";
755 else if(wxFileExists("/usr/sbin/ping"))
756 m_PingPath = "/usr/sbin/ping";
757 if(! m_PingPath)
758 {
759 m_CanUsePing = 0;
760 }
761 }
762
763 if(! m_CanUsePing)
764 {
765 // we didn't find ping
766 return Net_Unknown;
767 }
768
769 wxLogNull ln; // suppress all error messages
770 wxASSERT(m_PingPath.length());
771 wxString cmd;
772 cmd << m_PingPath << ' ';
773 #if defined(__SOLARIS__) || defined (__SUNOS__)
774 // nothing to add to ping command
775 #elif defined(__LINUX__) || defined ( __FREEBSD__)
776 cmd << "-c 1 "; // only ping once
777 #elif defined(__HPUX__)
778 cmd << "64 1 "; // only ping once (need also specify the packet size)
779 #else
780 # pragma warning "No Ping information for this OS."
781 m_CanUsePing = 0;
782 return Net_Unknown;
783 #endif
784 cmd << m_BeaconHost;
785 if(wxExecute(cmd, TRUE /* sync */) == 0)
786 return Net_Connected;
787 else
788 return Net_No;
789 }
790
791 /* static */
792 wxDialUpManager *wxDialUpManager::Create()
793 {
794 return new wxDialUpManagerImpl;
795 }
796
797 #endif // wxUSE_DIALUP_MANAGER