1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/utilsunx.cpp
3 // Purpose: generic Unix implementation of many wx functions
4 // Author: Vadim Zeitlin
5 // Id: $Id: utilsunx.cpp 49239 2007-10-19 03:10:31Z DE $
6 // Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #include "wx/utils.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/string.h"
25 #include "wx/intl.h"
26 #include "wx/log.h"
27 #include "wx/app.h"
28 #endif
29
30 #include "wx/apptrait.h"
31
32 #include "wx/process.h"
33 #include "wx/thread.h"
34
35 #include "wx/wfstream.h"
36
37 #include "wx/unix/execute.h"
38 #include "wx/unix/private.h"
39
40 #include <pwd.h>
41
42 #ifdef HAVE_SYS_SELECT_H
43 # include <sys/select.h>
44 #endif
45
46 #define HAS_PIPE_INPUT_STREAM (wxUSE_STREAMS && wxUSE_FILE)
47
48 #if HAS_PIPE_INPUT_STREAM
49
50 // define this to let wxexec.cpp know that we know what we're doing
51 #define _WX_USED_BY_WXEXECUTE_
52 #include "../common/execcmn.cpp"
53
54 #endif // HAS_PIPE_INPUT_STREAM
55
56 #if wxUSE_BASE
57
58 #if defined(__MWERKS__) && defined(__MACH__)
59 #ifndef WXWIN_OS_DESCRIPTION
60 #define WXWIN_OS_DESCRIPTION "MacOS X"
61 #endif
62 #ifndef HAVE_NANOSLEEP
63 #define HAVE_NANOSLEEP
64 #endif
65 #ifndef HAVE_UNAME
66 #define HAVE_UNAME
67 #endif
68
69 // our configure test believes we can use sigaction() if the function is
70 // available but Metrowekrs with MSL run-time does have the function but
71 // doesn't have sigaction struct so finally we can't use it...
72 #ifdef __MSL__
73 #undef wxUSE_ON_FATAL_EXCEPTION
74 #define wxUSE_ON_FATAL_EXCEPTION 0
75 #endif
76 #endif
77
78 // not only the statfs syscall is called differently depending on platform, but
79 // one of its incarnations, statvfs(), takes different arguments under
80 // different platforms and even different versions of the same system (Solaris
81 // 7 and 8): if you want to test for this, don't forget that the problems only
82 // appear if the large files support is enabled
83 #ifdef HAVE_STATFS
84 #ifdef __BSD__
85 #include <sys/param.h>
86 #include <sys/mount.h>
87 #else // !__BSD__
88 #include <sys/vfs.h>
89 #endif // __BSD__/!__BSD__
90
91 #define wxStatfs statfs
92
93 #ifndef HAVE_STATFS_DECL
94 // some systems lack statfs() prototype in the system headers (AIX 4)
95 extern "C" int statfs(const char *path, struct statfs *buf);
96 #endif
97 #endif // HAVE_STATFS
98
99 #ifdef HAVE_STATVFS
100 #include <sys/statvfs.h>
101
102 #define wxStatfs statvfs
103 #endif // HAVE_STATVFS
104
105 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
106 // WX_STATFS_T is detected by configure
107 #define wxStatfs_t WX_STATFS_T
108 #endif
109
110 // SGI signal.h defines signal handler arguments differently depending on
111 // whether _LANGUAGE_C_PLUS_PLUS is set or not - do set it
112 #if defined(__SGI__) && !defined(_LANGUAGE_C_PLUS_PLUS)
113 #define _LANGUAGE_C_PLUS_PLUS 1
114 #endif // SGI hack
115
116 #include <stdarg.h>
117 #include <dirent.h>
118 #include <string.h>
119 #include <sys/stat.h>
120 #include <sys/types.h>
121 #include <sys/wait.h>
122 #include <unistd.h>
123 #include <errno.h>
124 #include <netdb.h>
125 #include <signal.h>
126 #include <fcntl.h> // for O_WRONLY and friends
127 #include <time.h> // nanosleep() and/or usleep()
128 #include <ctype.h> // isspace()
129 #include <sys/time.h> // needed for FD_SETSIZE
130
131 #ifdef HAVE_UNAME
132 #include <sys/utsname.h> // for uname()
133 #endif // HAVE_UNAME
134
135 // Used by wxGetFreeMemory().
136 #ifdef __SGI__
137 #include <sys/sysmp.h>
138 #include <sys/sysinfo.h> // for SAGET and MINFO structures
139 #endif
140
141 // ----------------------------------------------------------------------------
142 // conditional compilation
143 // ----------------------------------------------------------------------------
144
145 // many versions of Unices have this function, but it is not defined in system
146 // headers - please add your system here if it is the case for your OS.
147 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this.
148 #if !defined(HAVE_USLEEP) && \
149 ((defined(__SUN__) && !defined(__SunOs_5_6) && \
150 !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \
151 defined(__osf__) || defined(__EMX__))
152 extern "C"
153 {
154 #ifdef __EMX__
155 /* I copied this from the XFree86 diffs. AV. */
156 #define INCL_DOSPROCESS
157 #include <os2.h>
usleep(unsigned long delay)158 inline void usleep(unsigned long delay)
159 {
160 DosSleep(delay ? (delay/1000l) : 1l);
161 }
162 #else // Unix
163 int usleep(unsigned int usec);
164 #endif // __EMX__/Unix
165 };
166
167 #define HAVE_USLEEP 1
168 #endif // Unices without usleep()
169
170 // ============================================================================
171 // implementation
172 // ============================================================================
173
174 // ----------------------------------------------------------------------------
175 // sleeping
176 // ----------------------------------------------------------------------------
177
wxSleep(int nSecs)178 void wxSleep(int nSecs)
179 {
180 sleep(nSecs);
181 }
182
wxMicroSleep(unsigned long microseconds)183 void wxMicroSleep(unsigned long microseconds)
184 {
185 #if defined(HAVE_NANOSLEEP)
186 timespec tmReq;
187 tmReq.tv_sec = (time_t)(microseconds / 1000000);
188 tmReq.tv_nsec = (microseconds % 1000000) * 1000;
189
190 // we're not interested in remaining time nor in return value
191 (void)nanosleep(&tmReq, (timespec *)NULL);
192 #elif defined(HAVE_USLEEP)
193 // uncomment this if you feel brave or if you are sure that your version
194 // of Solaris has a safe usleep() function but please notice that usleep()
195 // is known to lead to crashes in MT programs in Solaris 2.[67] and is not
196 // documented as MT-Safe
197 #if defined(__SUN__) && wxUSE_THREADS
198 #error "usleep() cannot be used in MT programs under Solaris."
199 #endif // Sun
200
201 usleep(microseconds);
202 #elif defined(HAVE_SLEEP)
203 // under BeOS sleep() takes seconds (what about other platforms, if any?)
204 sleep(microseconds * 1000000);
205 #else // !sleep function
206 #error "usleep() or nanosleep() function required for wxMicroSleep"
207 #endif // sleep function
208 }
209
wxMilliSleep(unsigned long milliseconds)210 void wxMilliSleep(unsigned long milliseconds)
211 {
212 wxMicroSleep(milliseconds*1000);
213 }
214
215 // ----------------------------------------------------------------------------
216 // process management
217 // ----------------------------------------------------------------------------
218
wxKill(long pid,wxSignal sig,wxKillError * rc,int flags)219 int wxKill(long pid, wxSignal sig, wxKillError *rc, int flags)
220 {
221 int err = kill((pid_t) (flags & wxKILL_CHILDREN) ? -pid : pid, (int)sig);
222 if ( rc )
223 {
224 switch ( err ? errno : 0 )
225 {
226 case 0:
227 *rc = wxKILL_OK;
228 break;
229
230 case EINVAL:
231 *rc = wxKILL_BAD_SIGNAL;
232 break;
233
234 case EPERM:
235 *rc = wxKILL_ACCESS_DENIED;
236 break;
237
238 case ESRCH:
239 *rc = wxKILL_NO_PROCESS;
240 break;
241
242 default:
243 // this goes against Unix98 docs so log it
244 wxLogDebug(_T("unexpected kill(2) return value %d"), err);
245
246 // something else...
247 *rc = wxKILL_ERROR;
248 }
249 }
250
251 return err;
252 }
253
254 #define WXEXECUTE_NARGS 127
255
256 #if defined(__DARWIN__)
257 long wxMacExecute(wxChar **argv,
258 int flags,
259 wxProcess *process);
260 #endif
261
wxExecute(const wxString & command,int flags,wxProcess * process)262 long wxExecute( const wxString& command, int flags, wxProcess *process )
263 {
264 wxCHECK_MSG( !command.empty(), 0, wxT("can't exec empty command") );
265
266 wxLogTrace(wxT("exec"), wxT("Executing \"%s\""), command.c_str());
267
268 #if wxUSE_THREADS
269 // fork() doesn't mix well with POSIX threads: on many systems the program
270 // deadlocks or crashes for some reason. Probably our code is buggy and
271 // doesn't do something which must be done to allow this to work, but I
272 // don't know what yet, so for now just warn the user (this is the least we
273 // can do) about it
274 wxASSERT_MSG( wxThread::IsMain(),
275 _T("wxExecute() can be called only from the main thread") );
276 #endif // wxUSE_THREADS
277
278 int argc = 0;
279 wxChar *argv[WXEXECUTE_NARGS];
280 wxString argument;
281 const wxChar *cptr = command.c_str();
282 wxChar quotechar = wxT('\0'); // is arg quoted?
283 bool escaped = false;
284
285 // split the command line in arguments
286 do
287 {
288 argument = wxEmptyString;
289 quotechar = wxT('\0');
290
291 // eat leading whitespace:
292 while ( wxIsspace(*cptr) )
293 cptr++;
294
295 if ( *cptr == wxT('\'') || *cptr == wxT('"') )
296 quotechar = *cptr++;
297
298 do
299 {
300 if ( *cptr == wxT('\\') && ! escaped )
301 {
302 escaped = true;
303 cptr++;
304 continue;
305 }
306
307 // all other characters:
308 argument += *cptr++;
309 escaped = false;
310
311 // have we reached the end of the argument?
312 if ( (*cptr == quotechar && ! escaped)
313 || (quotechar == wxT('\0') && wxIsspace(*cptr))
314 || *cptr == wxT('\0') )
315 {
316 wxASSERT_MSG( argc < WXEXECUTE_NARGS,
317 wxT("too many arguments in wxExecute") );
318
319 argv[argc] = new wxChar[argument.length() + 1];
320 wxStrcpy(argv[argc], argument.c_str());
321 argc++;
322
323 // if not at end of buffer, swallow last character:
324 if(*cptr)
325 cptr++;
326
327 break; // done with this one, start over
328 }
329 } while(*cptr);
330 } while(*cptr);
331 argv[argc] = NULL;
332
333 long lRc;
334 #if defined(__DARWIN__)
335 // wxMacExecute only executes app bundles.
336 // It returns an error code if the target is not an app bundle, thus falling
337 // through to the regular wxExecute for non app bundles.
338 lRc = wxMacExecute(argv, flags, process);
339 if( lRc != ((flags & wxEXEC_SYNC) ? -1 : 0))
340 return lRc;
341 #endif
342
343 // do execute the command
344 lRc = wxExecute(argv, flags, process);
345
346 // clean up
347 argc = 0;
348 while( argv[argc] )
349 delete [] argv[argc++];
350
351 return lRc;
352 }
353
354 // ----------------------------------------------------------------------------
355 // wxShell
356 // ----------------------------------------------------------------------------
357
wxMakeShellCommand(const wxString & command)358 static wxString wxMakeShellCommand(const wxString& command)
359 {
360 wxString cmd;
361 if ( !command )
362 {
363 // just an interactive shell
364 cmd = _T("xterm");
365 }
366 else
367 {
368 // execute command in a shell
369 cmd << _T("/bin/sh -c '") << command << _T('\'');
370 }
371
372 return cmd;
373 }
374
wxShell(const wxString & command)375 bool wxShell(const wxString& command)
376 {
377 return wxExecute(wxMakeShellCommand(command), wxEXEC_SYNC) == 0;
378 }
379
wxShell(const wxString & command,wxArrayString & output)380 bool wxShell(const wxString& command, wxArrayString& output)
381 {
382 wxCHECK_MSG( !command.empty(), false, _T("can't exec shell non interactively") );
383
384 return wxExecute(wxMakeShellCommand(command), output);
385 }
386
387 // Shutdown or reboot the PC
wxShutdown(wxShutdownFlags wFlags)388 bool wxShutdown(wxShutdownFlags wFlags)
389 {
390 wxChar level;
391 switch ( wFlags )
392 {
393 case wxSHUTDOWN_POWEROFF:
394 level = _T('0');
395 break;
396
397 case wxSHUTDOWN_REBOOT:
398 level = _T('6');
399 break;
400
401 default:
402 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
403 return false;
404 }
405
406 return system(wxString::Format(_T("init %c"), level).mb_str()) == 0;
407 }
408
409 // ----------------------------------------------------------------------------
410 // wxStream classes to support IO redirection in wxExecute
411 // ----------------------------------------------------------------------------
412
413 #if HAS_PIPE_INPUT_STREAM
414
CanRead() const415 bool wxPipeInputStream::CanRead() const
416 {
417 if ( m_lasterror == wxSTREAM_EOF )
418 return false;
419
420 // check if there is any input available
421 struct timeval tv;
422 tv.tv_sec = 0;
423 tv.tv_usec = 0;
424
425 const int fd = m_file->fd();
426
427 fd_set readfds;
428
429 wxFD_ZERO(&readfds);
430 wxFD_SET(fd, &readfds);
431
432 switch ( select(fd + 1, &readfds, NULL, NULL, &tv) )
433 {
434 case -1:
435 wxLogSysError(_("Impossible to get child process input"));
436 // fall through
437
438 case 0:
439 return false;
440
441 default:
442 wxFAIL_MSG(_T("unexpected select() return value"));
443 // still fall through
444
445 case 1:
446 // input available -- or maybe not, as select() returns 1 when a
447 // read() will complete without delay, but it could still not read
448 // anything
449 return !Eof();
450 }
451 }
452
453 #endif // HAS_PIPE_INPUT_STREAM
454
455 // ----------------------------------------------------------------------------
456 // wxExecute: the real worker function
457 // ----------------------------------------------------------------------------
458
wxExecute(wxChar ** argv,int flags,wxProcess * process)459 long wxExecute(wxChar **argv, int flags, wxProcess *process)
460 {
461 // for the sync execution, we return -1 to indicate failure, but for async
462 // case we return 0 which is never a valid PID
463 //
464 // we define this as a macro, not a variable, to avoid compiler warnings
465 // about "ERROR_RETURN_CODE value may be clobbered by fork()"
466 #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0)
467
468 wxCHECK_MSG( *argv, ERROR_RETURN_CODE, wxT("can't exec empty command") );
469
470 #if wxUSE_UNICODE
471 int mb_argc = 0;
472 char *mb_argv[WXEXECUTE_NARGS];
473
474 while (argv[mb_argc])
475 {
476 wxWX2MBbuf mb_arg = wxSafeConvertWX2MB(argv[mb_argc]);
477 mb_argv[mb_argc] = strdup(mb_arg);
478 mb_argc++;
479 }
480 mb_argv[mb_argc] = (char *) NULL;
481
482 // this macro will free memory we used above
483 #define ARGS_CLEANUP \
484 for ( mb_argc = 0; mb_argv[mb_argc]; mb_argc++ ) \
485 free(mb_argv[mb_argc])
486 #else // ANSI
487 // no need for cleanup
488 #define ARGS_CLEANUP
489
490 wxChar **mb_argv = argv;
491 #endif // Unicode/ANSI
492
493 // we want this function to work even if there is no wxApp so ensure that
494 // we have a valid traits pointer
495 wxConsoleAppTraits traitsConsole;
496 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
497 if ( !traits )
498 traits = &traitsConsole;
499
500 // this struct contains all information which we pass to and from
501 // wxAppTraits methods
502 wxExecuteData execData;
503 execData.flags = flags;
504 execData.process = process;
505
506 // create pipes
507 if ( !traits->CreateEndProcessPipe(execData) )
508 {
509 wxLogError( _("Failed to execute '%s'\n"), *argv );
510
511 ARGS_CLEANUP;
512
513 return ERROR_RETURN_CODE;
514 }
515
516 // pipes for inter process communication
517 wxPipe pipeIn, // stdin
518 pipeOut, // stdout
519 pipeErr; // stderr
520
521 if ( process && process->IsRedirected() )
522 {
523 if ( !pipeIn.Create() || !pipeOut.Create() || !pipeErr.Create() )
524 {
525 wxLogError( _("Failed to execute '%s'\n"), *argv );
526
527 ARGS_CLEANUP;
528
529 return ERROR_RETURN_CODE;
530 }
531 }
532
533 // fork the process
534 //
535 // NB: do *not* use vfork() here, it completely breaks this code for some
536 // reason under Solaris (and maybe others, although not under Linux)
537 // But on OpenVMS we do not have fork so we have to use vfork and
538 // cross our fingers that it works.
539 #ifdef __VMS
540 pid_t pid = vfork();
541 #else
542 pid_t pid = fork();
543 #endif
544 if ( pid == -1 ) // error?
545 {
546 wxLogSysError( _("Fork failed") );
547
548 ARGS_CLEANUP;
549
550 return ERROR_RETURN_CODE;
551 }
552 else if ( pid == 0 ) // we're in child
553 {
554 // These lines close the open file descriptors to to avoid any
555 // input/output which might block the process or irritate the user. If
556 // one wants proper IO for the subprocess, the right thing to do is to
557 // start an xterm executing it.
558 if ( !(flags & wxEXEC_SYNC) )
559 {
560 // FD_SETSIZE is unsigned under BSD, signed under other platforms
561 // so we need a cast to avoid warnings on all platforms
562 for ( int fd = 0; fd < (int)FD_SETSIZE; fd++ )
563 {
564 if ( fd == pipeIn[wxPipe::Read]
565 || fd == pipeOut[wxPipe::Write]
566 || fd == pipeErr[wxPipe::Write]
567 || traits->IsWriteFDOfEndProcessPipe(execData, fd) )
568 {
569 // don't close this one, we still need it
570 continue;
571 }
572
573 // leave stderr opened too, it won't do any harm
574 if ( fd != STDERR_FILENO )
575 close(fd);
576 }
577 }
578
579 #if !defined(__VMS) && !defined(__EMX__)
580 if ( flags & wxEXEC_MAKE_GROUP_LEADER )
581 {
582 // Set process group to child process' pid. Then killing -pid
583 // of the parent will kill the process and all of its children.
584 setsid();
585 }
586 #endif // !__VMS
587
588 // reading side can be safely closed but we should keep the write one
589 // opened
590 traits->DetachWriteFDOfEndProcessPipe(execData);
591
592 // redirect stdin, stdout and stderr
593 if ( pipeIn.IsOk() )
594 {
595 if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 ||
596 dup2(pipeOut[wxPipe::Write], STDOUT_FILENO) == -1 ||
597 dup2(pipeErr[wxPipe::Write], STDERR_FILENO) == -1 )
598 {
599 wxLogSysError(_("Failed to redirect child process input/output"));
600 }
601
602 pipeIn.Close();
603 pipeOut.Close();
604 pipeErr.Close();
605 }
606
607 execvp (*mb_argv, mb_argv);
608
609 fprintf(stderr, "execvp(");
610 // CS changed ppc to ppc_ as ppc is not available under mac os CW Mach-O
611 for ( char **ppc_ = mb_argv; *ppc_; ppc_++ )
612 fprintf(stderr, "%s%s", ppc_ == mb_argv ? "" : ", ", *ppc_);
613 fprintf(stderr, ") failed with error %d!\n", errno);
614
615 // there is no return after successful exec()
616 _exit(-1);
617
618 // some compilers complain about missing return - of course, they
619 // should know that exit() doesn't return but what else can we do if
620 // they don't?
621 //
622 // and, sure enough, other compilers complain about unreachable code
623 // after exit() call, so we can just always have return here...
624 #if defined(__VMS) || defined(__INTEL_COMPILER)
625 return 0;
626 #endif
627 }
628 else // we're in parent
629 {
630 ARGS_CLEANUP;
631
632 // save it for WaitForChild() use
633 execData.pid = pid;
634
635 // prepare for IO redirection
636
637 #if HAS_PIPE_INPUT_STREAM
638 // the input buffer bufOut is connected to stdout, this is why it is
639 // called bufOut and not bufIn
640 wxStreamTempInputBuffer bufOut,
641 bufErr;
642 #endif // HAS_PIPE_INPUT_STREAM
643
644 if ( process && process->IsRedirected() )
645 {
646 #if HAS_PIPE_INPUT_STREAM
647 wxOutputStream *inStream =
648 new wxFileOutputStream(pipeIn.Detach(wxPipe::Write));
649
650 wxPipeInputStream *outStream =
651 new wxPipeInputStream(pipeOut.Detach(wxPipe::Read));
652
653 wxPipeInputStream *errStream =
654 new wxPipeInputStream(pipeErr.Detach(wxPipe::Read));
655
656 process->SetPipeStreams(outStream, inStream, errStream);
657
658 bufOut.Init(outStream);
659 bufErr.Init(errStream);
660
661 execData.bufOut = &bufOut;
662 execData.bufErr = &bufErr;
663 #endif // HAS_PIPE_INPUT_STREAM
664 }
665
666 if ( pipeIn.IsOk() )
667 {
668 pipeIn.Close();
669 pipeOut.Close();
670 pipeErr.Close();
671 }
672
673 return traits->WaitForChild(execData);
674 }
675
676 #if !defined(__VMS) && !defined(__INTEL_COMPILER)
677 return ERROR_RETURN_CODE;
678 #endif
679 }
680
681 #undef ERROR_RETURN_CODE
682 #undef ARGS_CLEANUP
683
684 // ----------------------------------------------------------------------------
685 // file and directory functions
686 // ----------------------------------------------------------------------------
687
wxGetHomeDir(wxString * home)688 const wxChar* wxGetHomeDir( wxString *home )
689 {
690 *home = wxGetUserHome( wxEmptyString );
691 wxString tmp;
692 if ( home->empty() )
693 *home = wxT("/");
694 #ifdef __VMS
695 tmp = *home;
696 if ( tmp.Last() != wxT(']'))
697 if ( tmp.Last() != wxT('/')) *home << wxT('/');
698 #endif
699 return home->c_str();
700 }
701
702 #if wxUSE_UNICODE
wxGetUserHome(const wxString & user)703 const wxMB2WXbuf wxGetUserHome( const wxString &user )
704 #else // just for binary compatibility -- there is no 'const' here
705 char *wxGetUserHome( const wxString &user )
706 #endif
707 {
708 struct passwd *who = (struct passwd *) NULL;
709
710 if ( !user )
711 {
712 wxChar *ptr;
713
714 if ((ptr = wxGetenv(wxT("HOME"))) != NULL)
715 {
716 #if wxUSE_UNICODE
717 wxWCharBuffer buffer( ptr );
718 return buffer;
719 #else
720 return ptr;
721 #endif
722 }
723 if ((ptr = wxGetenv(wxT("USER"))) != NULL || (ptr = wxGetenv(wxT("LOGNAME"))) != NULL)
724 {
725 who = getpwnam(wxSafeConvertWX2MB(ptr));
726 }
727
728 // We now make sure the the user exists!
729 if (who == NULL)
730 {
731 who = getpwuid(getuid());
732 }
733 }
734 else
735 {
736 who = getpwnam (user.mb_str());
737 }
738
739 return wxSafeConvertMB2WX(who ? who->pw_dir : 0);
740 }
741
742 // ----------------------------------------------------------------------------
743 // network and user id routines
744 // ----------------------------------------------------------------------------
745
746 // private utility function which returns output of the given command, removing
747 // the trailing newline
wxGetCommandOutput(const wxString & cmd)748 static wxString wxGetCommandOutput(const wxString &cmd)
749 {
750 FILE *f = popen(cmd.ToAscii(), "r");
751 if ( !f )
752 {
753 wxLogSysError(_T("Executing \"%s\" failed"), cmd.c_str());
754 return wxEmptyString;
755 }
756
757 wxString s;
758 char buf[256];
759 while ( !feof(f) )
760 {
761 if ( !fgets(buf, sizeof(buf), f) )
762 break;
763
764 s += wxString::FromAscii(buf);
765 }
766
767 pclose(f);
768
769 if ( !s.empty() && s.Last() == _T('\n') )
770 s.RemoveLast();
771
772 return s;
773 }
774
775 // retrieve either the hostname or FQDN depending on platform (caller must
776 // check whether it's one or the other, this is why this function is for
777 // private use only)
wxGetHostNameInternal(wxChar * buf,int sz)778 static bool wxGetHostNameInternal(wxChar *buf, int sz)
779 {
780 wxCHECK_MSG( buf, false, wxT("NULL pointer in wxGetHostNameInternal") );
781
782 *buf = wxT('\0');
783
784 // we're using uname() which is POSIX instead of less standard sysinfo()
785 #if defined(HAVE_UNAME)
786 struct utsname uts;
787 bool ok = uname(&uts) != -1;
788 if ( ok )
789 {
790 wxStrncpy(buf, wxSafeConvertMB2WX(uts.nodename), sz - 1);
791 buf[sz] = wxT('\0');
792 }
793 #elif defined(HAVE_GETHOSTNAME)
794 char cbuf[sz];
795 bool ok = gethostname(cbuf, sz) != -1;
796 if ( ok )
797 {
798 wxStrncpy(buf, wxSafeConvertMB2WX(cbuf), sz - 1);
799 buf[sz] = wxT('\0');
800 }
801 #else // no uname, no gethostname
802 wxFAIL_MSG(wxT("don't know host name for this machine"));
803
804 bool ok = false;
805 #endif // uname/gethostname
806
807 if ( !ok )
808 {
809 wxLogSysError(_("Cannot get the hostname"));
810 }
811
812 return ok;
813 }
814
wxGetHostName(wxChar * buf,int sz)815 bool wxGetHostName(wxChar *buf, int sz)
816 {
817 bool ok = wxGetHostNameInternal(buf, sz);
818
819 if ( ok )
820 {
821 // BSD systems return the FQDN, we only want the hostname, so extract
822 // it (we consider that dots are domain separators)
823 wxChar *dot = wxStrchr(buf, wxT('.'));
824 if ( dot )
825 {
826 // nuke it
827 *dot = wxT('\0');
828 }
829 }
830
831 return ok;
832 }
833
wxGetFullHostName(wxChar * buf,int sz)834 bool wxGetFullHostName(wxChar *buf, int sz)
835 {
836 bool ok = wxGetHostNameInternal(buf, sz);
837
838 if ( ok )
839 {
840 if ( !wxStrchr(buf, wxT('.')) )
841 {
842 struct hostent *host = gethostbyname(wxSafeConvertWX2MB(buf));
843 if ( !host )
844 {
845 wxLogSysError(_("Cannot get the official hostname"));
846
847 ok = false;
848 }
849 else
850 {
851 // the canonical name
852 wxStrncpy(buf, wxSafeConvertMB2WX(host->h_name), sz);
853 }
854 }
855 //else: it's already a FQDN (BSD behaves this way)
856 }
857
858 return ok;
859 }
860
wxGetUserId(wxChar * buf,int sz)861 bool wxGetUserId(wxChar *buf, int sz)
862 {
863 struct passwd *who;
864
865 *buf = wxT('\0');
866 if ((who = getpwuid(getuid ())) != NULL)
867 {
868 wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_name), sz - 1);
869 return true;
870 }
871
872 return false;
873 }
874
wxGetUserName(wxChar * buf,int sz)875 bool wxGetUserName(wxChar *buf, int sz)
876 {
877 #ifdef HAVE_PW_GECOS
878 struct passwd *who;
879
880 *buf = wxT('\0');
881 if ((who = getpwuid (getuid ())) != NULL)
882 {
883 char *comma = strchr(who->pw_gecos, ',');
884 if (comma)
885 *comma = '\0'; // cut off non-name comment fields
886 wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_gecos), sz - 1);
887 return true;
888 }
889
890 return false;
891 #else // !HAVE_PW_GECOS
892 return wxGetUserId(buf, sz);
893 #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS
894 }
895
wxIsPlatform64Bit()896 bool wxIsPlatform64Bit()
897 {
898 const wxString machine = wxGetCommandOutput(wxT("uname -m"));
899
900 // the test for "64" is obviously not 100% reliable but seems to work fine
901 // in practice
902 return machine.Contains(wxT("64")) ||
903 machine.Contains(wxT("alpha"));
904 }
905
906 // these functions are in mac/utils.cpp for wxMac
907 #ifndef __WXMAC__
908
wxGetOsVersion(int * verMaj,int * verMin)909 wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
910 {
911 // get OS version
912 int major, minor;
913 wxString release = wxGetCommandOutput(wxT("uname -r"));
914 if ( !release.empty() && wxSscanf(release, wxT("%d.%d"), &major, &minor) != 2 )
915 {
916 // unrecognized uname string format
917 major =
918 minor = -1;
919 }
920
921 if ( verMaj )
922 *verMaj = major;
923 if ( verMin )
924 *verMin = minor;
925
926 // try to understand which OS are we running
927 wxString kernel = wxGetCommandOutput(wxT("uname -s"));
928 if ( kernel.empty() )
929 kernel = wxGetCommandOutput(wxT("uname -o"));
930
931 if ( kernel.empty() )
932 return wxOS_UNKNOWN;
933
934 return wxPlatformInfo::GetOperatingSystemId(kernel);
935 }
936
wxGetOsDescription()937 wxString wxGetOsDescription()
938 {
939 return wxGetCommandOutput(wxT("uname -s -r -m"));
940 }
941
942 #endif // !__WXMAC__
943
wxGetProcessId()944 unsigned long wxGetProcessId()
945 {
946 return (unsigned long)getpid();
947 }
948
wxGetFreeMemory()949 wxMemorySize wxGetFreeMemory()
950 {
951 #if defined(__LINUX__)
952 // get it from /proc/meminfo
953 FILE *fp = fopen("/proc/meminfo", "r");
954 if ( fp )
955 {
956 long memFree = -1;
957
958 char buf[1024];
959 if ( fgets(buf, WXSIZEOF(buf), fp) && fgets(buf, WXSIZEOF(buf), fp) )
960 {
961 // /proc/meminfo changed its format in kernel 2.6
962 if ( wxPlatformInfo().CheckOSVersion(2, 6) )
963 {
964 unsigned long cached, buffers;
965 sscanf(buf, "MemFree: %ld", &memFree);
966
967 fgets(buf, WXSIZEOF(buf), fp);
968 sscanf(buf, "Buffers: %lu", &buffers);
969
970 fgets(buf, WXSIZEOF(buf), fp);
971 sscanf(buf, "Cached: %lu", &cached);
972
973 // add to "MemFree" also the "Buffers" and "Cached" values as
974 // free(1) does as otherwise the value never makes sense: for
975 // kernel 2.6 it's always almost 0
976 memFree += buffers + cached;
977
978 // values here are always expressed in kB and we want bytes
979 memFree *= 1024;
980 }
981 else // Linux 2.4 (or < 2.6, anyhow)
982 {
983 long memTotal, memUsed;
984 sscanf(buf, "Mem: %ld %ld %ld", &memTotal, &memUsed, &memFree);
985 }
986 }
987
988 fclose(fp);
989
990 return (wxMemorySize)memFree;
991 }
992 #elif defined(__SUN__) && defined(_SC_AVPHYS_PAGES)
993 return (wxMemorySize)(sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE));
994 #elif defined(__SGI__)
995 struct rminfo realmem;
996 if ( sysmp(MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0 )
997 return ((wxMemorySize)realmem.physmem * sysconf(_SC_PAGESIZE));
998 //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably
999 #endif
1000
1001 // can't find it out
1002 return -1;
1003 }
1004
wxGetDiskSpace(const wxString & path,wxDiskspaceSize_t * pTotal,wxDiskspaceSize_t * pFree)1005 bool wxGetDiskSpace(const wxString& path, wxDiskspaceSize_t *pTotal, wxDiskspaceSize_t *pFree)
1006 {
1007 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
1008 // the case to "char *" is needed for AIX 4.3
1009 wxStatfs_t fs;
1010 if ( wxStatfs((char *)(const char*)path.fn_str(), &fs) != 0 )
1011 {
1012 wxLogSysError( wxT("Failed to get file system statistics") );
1013
1014 return false;
1015 }
1016
1017 // under Solaris we also have to use f_frsize field instead of f_bsize
1018 // which is in general a multiple of f_frsize
1019 #ifdef HAVE_STATVFS
1020 wxDiskspaceSize_t blockSize = fs.f_frsize;
1021 #else // HAVE_STATFS
1022 wxDiskspaceSize_t blockSize = fs.f_bsize;
1023 #endif // HAVE_STATVFS/HAVE_STATFS
1024
1025 if ( pTotal )
1026 {
1027 *pTotal = wxDiskspaceSize_t(fs.f_blocks) * blockSize;
1028 }
1029
1030 if ( pFree )
1031 {
1032 *pFree = wxDiskspaceSize_t(fs.f_bavail) * blockSize;
1033 }
1034
1035 return true;
1036 #else // !HAVE_STATFS && !HAVE_STATVFS
1037 return false;
1038 #endif // HAVE_STATFS
1039 }
1040
1041 // ----------------------------------------------------------------------------
1042 // env vars
1043 // ----------------------------------------------------------------------------
1044
wxGetEnv(const wxString & var,wxString * value)1045 bool wxGetEnv(const wxString& var, wxString *value)
1046 {
1047 // wxGetenv is defined as getenv()
1048 wxChar *p = wxGetenv(var);
1049 if ( !p )
1050 return false;
1051
1052 if ( value )
1053 {
1054 *value = p;
1055 }
1056
1057 return true;
1058 }
1059
wxSetEnv(const wxString & variable,const wxChar * value)1060 bool wxSetEnv(const wxString& variable, const wxChar *value)
1061 {
1062 #if defined(HAVE_SETENV)
1063 if ( !value )
1064 {
1065 #ifdef HAVE_UNSETENV
1066 // don't test unsetenv() return value: it's void on some systems (at
1067 // least Darwin)
1068 unsetenv(variable.mb_str());
1069 return true;
1070 #else
1071 value = _T(""); // we can't pass NULL to setenv()
1072 #endif
1073 }
1074
1075 return setenv(variable.mb_str(),
1076 wxString(value).mb_str(),
1077 1 /* overwrite */) == 0;
1078 #elif defined(HAVE_PUTENV)
1079 wxString s = variable;
1080 if ( value )
1081 s << _T('=') << value;
1082
1083 // transform to ANSI
1084 const wxWX2MBbuf p = s.mb_str();
1085
1086 // the string will be free()d by libc
1087 char *buf = (char *)malloc(strlen(p) + 1);
1088 strcpy(buf, p);
1089
1090 return putenv(buf) == 0;
1091 #else // no way to set an env var
1092 return false;
1093 #endif
1094 }
1095
1096 // ----------------------------------------------------------------------------
1097 // signal handling
1098 // ----------------------------------------------------------------------------
1099
1100 #if wxUSE_ON_FATAL_EXCEPTION
1101
1102 #include <signal.h>
1103
wxFatalSignalHandler(wxTYPE_SA_HANDLER)1104 extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
1105 {
1106 if ( wxTheApp )
1107 {
1108 // give the user a chance to do something special about this
1109 wxTheApp->OnFatalException();
1110 }
1111
1112 abort();
1113 }
1114
wxHandleFatalExceptions(bool doit)1115 bool wxHandleFatalExceptions(bool doit)
1116 {
1117 // old sig handlers
1118 static bool s_savedHandlers = false;
1119 static struct sigaction s_handlerFPE,
1120 s_handlerILL,
1121 s_handlerBUS,
1122 s_handlerSEGV;
1123
1124 bool ok = true;
1125 if ( doit && !s_savedHandlers )
1126 {
1127 // install the signal handler
1128 struct sigaction act;
1129
1130 // some systems extend it with non std fields, so zero everything
1131 memset(&act, 0, sizeof(act));
1132
1133 act.sa_handler = wxFatalSignalHandler;
1134 sigemptyset(&act.sa_mask);
1135 act.sa_flags = 0;
1136
1137 ok &= sigaction(SIGFPE, &act, &s_handlerFPE) == 0;
1138 ok &= sigaction(SIGILL, &act, &s_handlerILL) == 0;
1139 ok &= sigaction(SIGBUS, &act, &s_handlerBUS) == 0;
1140 ok &= sigaction(SIGSEGV, &act, &s_handlerSEGV) == 0;
1141 if ( !ok )
1142 {
1143 wxLogDebug(_T("Failed to install our signal handler."));
1144 }
1145
1146 s_savedHandlers = true;
1147 }
1148 else if ( s_savedHandlers )
1149 {
1150 // uninstall the signal handler
1151 ok &= sigaction(SIGFPE, &s_handlerFPE, NULL) == 0;
1152 ok &= sigaction(SIGILL, &s_handlerILL, NULL) == 0;
1153 ok &= sigaction(SIGBUS, &s_handlerBUS, NULL) == 0;
1154 ok &= sigaction(SIGSEGV, &s_handlerSEGV, NULL) == 0;
1155 if ( !ok )
1156 {
1157 wxLogDebug(_T("Failed to uninstall our signal handler."));
1158 }
1159
1160 s_savedHandlers = false;
1161 }
1162 //else: nothing to do
1163
1164 return ok;
1165 }
1166
1167 #endif // wxUSE_ON_FATAL_EXCEPTION
1168
1169 #endif // wxUSE_BASE
1170
1171 #if wxUSE_GUI
1172
1173 #ifdef __DARWIN__
1174 #include <sys/errno.h>
1175 #endif
1176 // ----------------------------------------------------------------------------
1177 // wxExecute support
1178 // ----------------------------------------------------------------------------
1179
1180 /*
1181 NOTE: The original code shipped in 2.8 used __DARWIN__ && __WXMAC__ to wrap
1182 the wxGUIAppTraits differences but __DARWIN__ && (__WXMAC__ || __WXCOCOA__)
1183 to decide whether to call wxAddProcessCallbackForPid instead of
1184 wxAddProcessCallback. This define normalizes things so the two match.
1185
1186 Since wxCocoa was already creating the pipes in its wxGUIAppTraits I
1187 decided to leave that as is and implement wxAddProcessCallback in the
1188 utilsexec_cf.cpp file. I didn't see a reason to wrap that in a __WXCOCOA__
1189 check since it's valid for both wxMac and wxCocoa.
1190
1191 Since the existing code is working for wxMac I've left it as is although
1192 do note that the old task_for_pid method still used on PPC machines is
1193 expected to fail in Leopard PPC and theoretically already fails if you run
1194 your PPC app under Rosetta.
1195
1196 You thus have two choices if you find end process detect broken:
1197 1) Change the define below such that the new code is used for wxMac.
1198 This is theoretically ABI compatible since the old code still remains
1199 in utilsexec_cf.cpp it's just no longer used by this code.
1200 2) Change the USE_POLLING define in utilsexc_cf.cpp to 1 unconditionally
1201 This is theoretically not compatible since it removes the
1202 wxMAC_MachPortEndProcessDetect helper function. Though in practice
1203 this shouldn't be a problem since it wasn't prototyped anywhere.
1204 */
1205 #define USE_OLD_DARWIN_END_PROCESS_DETECT (defined(__DARWIN__) && defined(__WXMAC__))
1206 // #define USE_OLD_DARWIN_END_PROCESS_DETECT 0
1207
1208 // wxMac doesn't use the same process end detection mechanisms so we don't
1209 // need wxExecute-related helpers for it.
1210 #if !USE_OLD_DARWIN_END_PROCESS_DETECT
1211
CreateEndProcessPipe(wxExecuteData & execData)1212 bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& execData)
1213 {
1214 return execData.pipeEndProcDetect.Create();
1215 }
1216
IsWriteFDOfEndProcessPipe(wxExecuteData & execData,int fd)1217 bool wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& execData, int fd)
1218 {
1219 return fd == (execData.pipeEndProcDetect)[wxPipe::Write];
1220 }
1221
DetachWriteFDOfEndProcessPipe(wxExecuteData & execData)1222 void wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& execData)
1223 {
1224 execData.pipeEndProcDetect.Detach(wxPipe::Write);
1225 execData.pipeEndProcDetect.Close();
1226 }
1227
1228 #else // !Darwin
1229
CreateEndProcessPipe(wxExecuteData & WXUNUSED (execData))1230 bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& WXUNUSED(execData))
1231 {
1232 return true;
1233 }
1234
1235 bool
IsWriteFDOfEndProcessPipe(wxExecuteData & WXUNUSED (execData),int WXUNUSED (fd))1236 wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData),
1237 int WXUNUSED(fd))
1238 {
1239 return false;
1240 }
1241
1242 void
DetachWriteFDOfEndProcessPipe(wxExecuteData & WXUNUSED (execData))1243 wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData))
1244 {
1245 // nothing to do here, we don't use the pipe
1246 }
1247
1248 #endif // !Darwin/Darwin
1249
WaitForChild(wxExecuteData & execData)1250 int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
1251 {
1252 wxEndProcessData *endProcData = new wxEndProcessData;
1253
1254 const int flags = execData.flags;
1255
1256 // wxAddProcessCallback is now (with DARWIN) allowed to call the
1257 // callback function directly if the process terminates before
1258 // the callback can be added to the run loop. Set up the endProcData.
1259 if ( flags & wxEXEC_SYNC )
1260 {
1261 // we may have process for capturing the program output, but it's
1262 // not used in wxEndProcessData in the case of sync execution
1263 endProcData->process = NULL;
1264
1265 // sync execution: indicate it by negating the pid
1266 endProcData->pid = -execData.pid;
1267 }
1268 else
1269 {
1270 // async execution, nothing special to do -- caller will be
1271 // notified about the process termination if process != NULL, endProcData
1272 // will be deleted in GTK_EndProcessDetector
1273 endProcData->process = execData.process;
1274 endProcData->pid = execData.pid;
1275 }
1276
1277
1278 #if USE_OLD_DARWIN_END_PROCESS_DETECT
1279 endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
1280 #else
1281 endProcData->tag = wxAddProcessCallback
1282 (
1283 endProcData,
1284 execData.pipeEndProcDetect.Detach(wxPipe::Read)
1285 );
1286
1287 execData.pipeEndProcDetect.Close();
1288 #endif // USE_OLD_DARWIN_END_PROCESS_DETECT
1289
1290 if ( flags & wxEXEC_SYNC )
1291 {
1292 wxBusyCursor bc;
1293 wxWindowDisabler *wd = flags & wxEXEC_NODISABLE ? NULL
1294 : new wxWindowDisabler;
1295
1296 // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
1297 // process terminates
1298 while ( endProcData->pid != 0 )
1299 {
1300 bool idle = true;
1301
1302 #if HAS_PIPE_INPUT_STREAM
1303 if ( execData.bufOut )
1304 {
1305 execData.bufOut->Update();
1306 idle = false;
1307 }
1308
1309 if ( execData.bufErr )
1310 {
1311 execData.bufErr->Update();
1312 idle = false;
1313 }
1314 #endif // HAS_PIPE_INPUT_STREAM
1315
1316 // don't consume 100% of the CPU while we're sitting in this
1317 // loop
1318 if ( idle )
1319 wxMilliSleep(1);
1320
1321 // give GTK+ a chance to call GTK_EndProcessDetector here and
1322 // also repaint the GUI
1323 wxYield();
1324 }
1325
1326 int exitcode = endProcData->exitcode;
1327
1328 delete wd;
1329 delete endProcData;
1330
1331 return exitcode;
1332 }
1333 else // async execution
1334 {
1335 return execData.pid;
1336 }
1337 }
1338
1339 #endif // wxUSE_GUI
1340 #if wxUSE_BASE
1341
wxHandleProcessTermination(wxEndProcessData * proc_data)1342 void wxHandleProcessTermination(wxEndProcessData *proc_data)
1343 {
1344 // notify user about termination if required
1345 if ( proc_data->process )
1346 {
1347 proc_data->process->OnTerminate(proc_data->pid, proc_data->exitcode);
1348 }
1349
1350 // clean up
1351 if ( proc_data->pid > 0 )
1352 {
1353 delete proc_data;
1354 }
1355 else
1356 {
1357 // let wxExecute() know that the process has terminated
1358 proc_data->pid = 0;
1359 }
1360 }
1361
1362 #endif // wxUSE_BASE
1363