1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: generic Unix implementation of many wx functions
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
19 #include "wx/string.h"
26 #include "wx/process.h"
27 #include "wx/thread.h"
29 #include "wx/stream.h"
33 # include <sys/param.h>
34 # include <sys/mount.h>
41 #include <sys/statvfs.h>
43 #define statfs statvfs
44 #endif // HAVE_STATVFS
47 #include "wx/unix/execute.h"
50 // SGI signal.h defines signal handler arguments differently depending on
51 // whether _LANGUAGE_C_PLUS_PLUS is set or not - do set it
52 #if defined(__SGI__) && !defined(_LANGUAGE_C_PLUS_PLUS)
53 #define _LANGUAGE_C_PLUS_PLUS 1
60 #include <sys/types.h>
67 #include <fcntl.h> // for O_WRONLY and friends
68 #include <time.h> // nanosleep() and/or usleep()
69 #include <ctype.h> // isspace()
70 #include <sys/time.h> // needed for FD_SETSIZE
73 #include <sys/utsname.h> // for uname()
76 // ----------------------------------------------------------------------------
77 // conditional compilation
78 // ----------------------------------------------------------------------------
80 // many versions of Unices have this function, but it is not defined in system
81 // headers - please add your system here if it is the case for your OS.
82 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this.
83 #if !defined(HAVE_USLEEP) && \
84 (defined(__SUN__) && !defined(__SunOs_5_6) && \
85 !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \
86 defined(__osf__) || defined(__EMX__)
90 int usleep(unsigned int usec
);
93 /* I copied this from the XFree86 diffs. AV. */
94 #define INCL_DOSPROCESS
96 inline void usleep(unsigned long delay
)
98 DosSleep(delay
? (delay
/1000l) : 1l);
100 #else // !Sun && !EMX
101 void usleep(unsigned long usec
);
103 #endif // Sun/EMX/Something else
106 #define HAVE_USLEEP 1
107 #endif // Unices without usleep()
109 // ============================================================================
111 // ============================================================================
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
117 void wxSleep(int nSecs
)
122 void wxUsleep(unsigned long milliseconds
)
124 #if defined(HAVE_NANOSLEEP)
126 tmReq
.tv_sec
= (time_t)(milliseconds
/ 1000);
127 tmReq
.tv_nsec
= (milliseconds
% 1000) * 1000 * 1000;
129 // we're not interested in remaining time nor in return value
130 (void)nanosleep(&tmReq
, (timespec
*)NULL
);
131 #elif defined(HAVE_USLEEP)
132 // uncomment this if you feel brave or if you are sure that your version
133 // of Solaris has a safe usleep() function but please notice that usleep()
134 // is known to lead to crashes in MT programs in Solaris 2.[67] and is not
135 // documented as MT-Safe
136 #if defined(__SUN__) && wxUSE_THREADS
137 #error "usleep() cannot be used in MT programs under Solaris."
140 usleep(milliseconds
* 1000); // usleep(3) wants microseconds
141 #elif defined(HAVE_SLEEP)
142 // under BeOS sleep() takes seconds (what about other platforms, if any?)
143 sleep(milliseconds
* 1000);
144 #else // !sleep function
145 #error "usleep() or nanosleep() function required for wxUsleep"
146 #endif // sleep function
149 // ----------------------------------------------------------------------------
150 // process management
151 // ----------------------------------------------------------------------------
153 int wxKill(long pid
, wxSignal sig
, wxKillError
*rc
)
155 int err
= kill((pid_t
)pid
, (int)sig
);
165 *rc
= wxKILL_BAD_SIGNAL
;
169 *rc
= wxKILL_ACCESS_DENIED
;
173 *rc
= wxKILL_NO_PROCESS
;
177 // this goes against Unix98 docs so log it
178 wxLogDebug(_T("unexpected kill(2) return value %d"), err
);
188 #define WXEXECUTE_NARGS 127
190 long wxExecute( const wxString
& command
, int flags
, wxProcess
*process
)
192 wxCHECK_MSG( !command
.IsEmpty(), 0, wxT("can't exec empty command") );
195 wxChar
*argv
[WXEXECUTE_NARGS
];
197 const wxChar
*cptr
= command
.c_str();
198 wxChar quotechar
= wxT('\0'); // is arg quoted?
199 bool escaped
= FALSE
;
201 // split the command line in arguments
205 quotechar
= wxT('\0');
207 // eat leading whitespace:
208 while ( wxIsspace(*cptr
) )
211 if ( *cptr
== wxT('\'') || *cptr
== wxT('"') )
216 if ( *cptr
== wxT('\\') && ! escaped
)
223 // all other characters:
227 // have we reached the end of the argument?
228 if ( (*cptr
== quotechar
&& ! escaped
)
229 || (quotechar
== wxT('\0') && wxIsspace(*cptr
))
230 || *cptr
== wxT('\0') )
232 wxASSERT_MSG( argc
< WXEXECUTE_NARGS
,
233 wxT("too many arguments in wxExecute") );
235 argv
[argc
] = new wxChar
[argument
.length() + 1];
236 wxStrcpy(argv
[argc
], argument
.c_str());
239 // if not at end of buffer, swallow last character:
243 break; // done with this one, start over
249 // do execute the command
250 long lRc
= wxExecute(argv
, flags
, process
);
255 delete [] argv
[argc
++];
260 // ----------------------------------------------------------------------------
262 // ----------------------------------------------------------------------------
264 static wxString
wxMakeShellCommand(const wxString
& command
)
269 // just an interactive shell
274 // execute command in a shell
275 cmd
<< _T("/bin/sh -c '") << command
<< _T('\'');
281 bool wxShell(const wxString
& command
)
283 return wxExecute(wxMakeShellCommand(command
), wxEXEC_SYNC
) == 0;
286 bool wxShell(const wxString
& command
, wxArrayString
& output
)
288 wxCHECK_MSG( !!command
, FALSE
, _T("can't exec shell non interactively") );
290 return wxExecute(wxMakeShellCommand(command
), output
);
293 // Shutdown or reboot the PC
294 bool wxShutdown(wxShutdownFlags wFlags
)
299 case wxSHUTDOWN_POWEROFF
:
303 case wxSHUTDOWN_REBOOT
:
308 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
312 return system(wxString::Format(_T("init %c"), level
).mb_str()) == 0;
318 void wxHandleProcessTermination(wxEndProcessData
*proc_data
)
320 // notify user about termination if required
321 if ( proc_data
->process
)
323 proc_data
->process
->OnTerminate(proc_data
->pid
, proc_data
->exitcode
);
327 if ( proc_data
->pid
> 0 )
333 // let wxExecute() know that the process has terminated
340 // ----------------------------------------------------------------------------
341 // wxStream classes to support IO redirection in wxExecute
342 // ----------------------------------------------------------------------------
346 class wxProcessFileInputStream
: public wxInputStream
349 wxProcessFileInputStream(int fd
) { m_fd
= fd
; }
350 ~wxProcessFileInputStream() { close(m_fd
); }
352 virtual bool Eof() const;
355 size_t OnSysRead(void *buffer
, size_t bufsize
);
361 class wxProcessFileOutputStream
: public wxOutputStream
364 wxProcessFileOutputStream(int fd
) { m_fd
= fd
; }
365 ~wxProcessFileOutputStream() { close(m_fd
); }
368 size_t OnSysWrite(const void *buffer
, size_t bufsize
);
374 bool wxProcessFileInputStream::Eof() const
376 if ( m_lasterror
== wxSTREAM_EOF
)
379 // check if there is any input available
386 FD_SET(m_fd
, &readfds
);
387 switch ( select(m_fd
+ 1, &readfds
, NULL
, NULL
, &tv
) )
390 wxLogSysError(_("Impossible to get child process input"));
397 wxFAIL_MSG(_T("unexpected select() return value"));
398 // still fall through
401 // input available: check if there is any
402 return wxInputStream::Eof();
406 size_t wxProcessFileInputStream::OnSysRead(void *buffer
, size_t bufsize
)
408 int ret
= read(m_fd
, buffer
, bufsize
);
411 m_lasterror
= wxSTREAM_EOF
;
413 else if ( ret
== -1 )
415 m_lasterror
= wxSTREAM_READ_ERROR
;
420 m_lasterror
= wxSTREAM_NOERROR
;
426 size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer
, size_t bufsize
)
428 int ret
= write(m_fd
, buffer
, bufsize
);
431 m_lasterror
= wxSTREAM_WRITE_ERROR
;
436 m_lasterror
= wxSTREAM_NOERROR
;
442 // ----------------------------------------------------------------------------
443 // wxStreamTempBuffer
444 // ----------------------------------------------------------------------------
447 Extract of a mail to wx-users to give the context of the problem we are
448 trying to solve here:
450 MC> If I run the command:
451 MC> find . -name "*.h" -exec grep linux {} \;
452 MC> in the exec sample synchronously from the 'Capture command output'
453 MC> menu, wxExecute never returns. I have to xkill it. Has anyone
454 MC> else encountered this?
456 Yes, I can reproduce it too.
458 I even think I understand why it happens: before launching the external
459 command we set up a pipe with a valid file descriptor on the reading side
460 when the output is redirected. So the subprocess happily writes to it ...
461 until the pipe buffer (which is usually quite big on Unix, I think the
462 default is 4Mb) is full. Then the writing process stops and waits until we
463 read some data from the pipe to be able to continue writing to it but we
464 never do it because we wait until it terminates to start reading and so we
465 have a classical deadlock.
467 Here is the fix: we now read the output as soon as it appears into a temp
468 buffer (wxStreamTempBuffer object) and later just stuff it back into the
469 stream when the process terminates. See supporting code in wxExecute()
473 class wxStreamTempBuffer
476 wxStreamTempBuffer();
478 // call to associate a stream with this buffer, otherwise nothing happens
480 void Init(wxInputStream
*stream
);
482 // check for input on our stream and cache it in our buffer if any
485 ~wxStreamTempBuffer();
488 // the stream we're buffering, if NULL we don't do anything at all
489 wxInputStream
*m_stream
;
491 // the buffer of size m_size (NULL if m_size == 0)
494 // the size of the buffer
498 wxStreamTempBuffer::wxStreamTempBuffer()
505 void wxStreamTempBuffer::Init(wxInputStream
*stream
)
510 void wxStreamTempBuffer::Update()
512 if ( m_stream
&& !m_stream
->Eof() )
514 // realloc in blocks of 1Kb - surely not the best strategy but which
516 static const size_t incSize
= 1024;
518 void *buf
= realloc(m_buffer
, m_size
+ incSize
);
521 // don't read any more, we don't have enough memory to do it
524 else // got memory for the buffer
527 m_stream
->Read((char *)m_buffer
+ m_size
, incSize
);
533 wxStreamTempBuffer::~wxStreamTempBuffer()
537 m_stream
->Ungetch(m_buffer
, m_size
);
542 #endif // wxUSE_STREAMS
544 long wxExecute(wxChar
**argv
,
548 // for the sync execution, we return -1 to indicate failure, but for async
549 // case we return 0 which is never a valid PID
551 // we define this as a macro, not a variable, to avoid compiler warnings
552 // about "ERROR_RETURN_CODE value may be clobbered by fork()"
553 #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0)
555 wxCHECK_MSG( *argv
, ERROR_RETURN_CODE
, wxT("can't exec empty command") );
559 char *mb_argv
[WXEXECUTE_NARGS
];
561 while (argv
[mb_argc
])
563 wxWX2MBbuf mb_arg
= wxConvertWX2MB(argv
[mb_argc
]);
564 mb_argv
[mb_argc
] = strdup(mb_arg
);
567 mb_argv
[mb_argc
] = (char *) NULL
;
569 // this macro will free memory we used above
570 #define ARGS_CLEANUP \
571 for ( mb_argc = 0; mb_argv[mb_argc]; mb_argc++ ) \
572 free(mb_argv[mb_argc])
574 // no need for cleanup
577 wxChar
**mb_argv
= argv
;
578 #endif // Unicode/ANSI
582 int end_proc_detect
[2];
583 if ( pipe(end_proc_detect
) == -1 )
585 wxLogSysError( _("Pipe creation failed") );
586 wxLogError( _("Failed to execute '%s'\n"), *argv
);
590 return ERROR_RETURN_CODE
;
594 // pipes for inter process communication
595 int pipeIn
[2], // stdin
596 pipeOut
[2], // stdout
597 pipeErr
[2]; // stderr
599 pipeIn
[0] = pipeIn
[1] =
600 pipeOut
[0] = pipeOut
[1] =
601 pipeErr
[0] = pipeErr
[1] = -1;
603 if ( process
&& process
->IsRedirected() )
605 if ( pipe(pipeIn
) == -1 || pipe(pipeOut
) == -1 || pipe(pipeErr
) == -1 )
608 // free previously allocated resources
609 close(end_proc_detect
[0]);
610 close(end_proc_detect
[1]);
613 wxLogSysError( _("Pipe creation failed") );
614 wxLogError( _("Failed to execute '%s'\n"), *argv
);
618 return ERROR_RETURN_CODE
;
629 if ( pid
== -1 ) // error?
632 close(end_proc_detect
[0]);
633 close(end_proc_detect
[1]);
642 wxLogSysError( _("Fork failed") );
646 return ERROR_RETURN_CODE
;
648 else if ( pid
== 0 ) // we're in child
651 close(end_proc_detect
[0]); // close reading side
654 // These lines close the open file descriptors to to avoid any
655 // input/output which might block the process or irritate the user. If
656 // one wants proper IO for the subprocess, the right thing to do is to
657 // start an xterm executing it.
658 if ( !(flags
& wxEXEC_SYNC
) )
660 for ( int fd
= 0; fd
< FD_SETSIZE
; fd
++ )
662 if ( fd
== pipeIn
[0] || fd
== pipeOut
[1] || fd
== pipeErr
[1]
664 || fd
== end_proc_detect
[1]
668 // don't close this one, we still need it
672 // leave stderr opened too, it won't do any hurm
673 if ( fd
!= STDERR_FILENO
)
678 if ( flags
& wxEXEC_MAKE_GROUP_LEADER
)
680 // Set process group to child process' pid. Then killing -pid
681 // of the parent will kill the process and all of its children.
687 // redirect stdio, stdout and stderr
688 if ( pipeIn
[0] != -1 )
690 if ( dup2(pipeIn
[0], STDIN_FILENO
) == -1 ||
691 dup2(pipeOut
[1], STDOUT_FILENO
) == -1 ||
692 dup2(pipeErr
[1], STDERR_FILENO
) == -1 )
694 wxLogSysError(_("Failed to redirect child process input/output"));
702 execvp (*mb_argv
, mb_argv
);
704 // there is no return after successful exec()
707 // some compilers complain about missing return - of course, they
708 // should know that exit() doesn't return but what else can we do if
710 #if defined(__VMS) || defined(__INTEL_COMPILER)
714 else // we're in parent
718 // pipe initialization: construction of the wxStreams
720 wxStreamTempBuffer bufIn
, bufErr
;
721 #endif // wxUSE_STREAMS
723 if ( process
&& process
->IsRedirected() )
726 // in/out for subprocess correspond to our out/in
727 wxOutputStream
*outStream
= new wxProcessFileOutputStream(pipeIn
[1]);
728 wxInputStream
*inStream
= new wxProcessFileInputStream(pipeOut
[0]);
729 wxInputStream
*errStream
= new wxProcessFileInputStream(pipeErr
[0]);
731 process
->SetPipeStreams(inStream
, outStream
, errStream
);
733 bufIn
.Init(inStream
);
734 bufErr
.Init(inStream
);
735 #endif // wxUSE_STREAMS
737 close(pipeIn
[0]); // close reading side
738 close(pipeOut
[1]); // close writing side
739 close(pipeErr
[1]); // close writing side
742 #if wxUSE_GUI && !defined(__WXMICROWIN__)
743 wxEndProcessData
*data
= new wxEndProcessData
;
745 if ( flags
& wxEXEC_SYNC
)
747 // we may have process for capturing the program output, but it's
748 // not used in wxEndProcessData in the case of sync execution
749 data
->process
= NULL
;
751 // sync execution: indicate it by negating the pid
753 data
->tag
= wxAddProcessCallback(data
, end_proc_detect
[0]);
755 close(end_proc_detect
[1]); // close writing side
760 // data->pid will be set to 0 from GTK_EndProcessDetector when the
761 // process terminates
762 while ( data
->pid
!= 0 )
767 #endif // wxUSE_STREAMS
769 // give GTK+ a chance to call GTK_EndProcessDetector here and
770 // also repaint the GUI
774 int exitcode
= data
->exitcode
;
780 else // async execution
782 // async execution, nothing special to do - caller will be
783 // notified about the process termination if process != NULL, data
784 // will be deleted in GTK_EndProcessDetector
785 data
->process
= process
;
787 data
->tag
= wxAddProcessCallback(data
, end_proc_detect
[0]);
789 close(end_proc_detect
[1]); // close writing side
795 wxASSERT_MSG( flags
& wxEXEC_SYNC
,
796 wxT("async execution not supported yet") );
799 if ( waitpid(pid
, &exitcode
, 0) == -1 || !WIFEXITED(exitcode
) )
801 wxLogSysError(_("Waiting for subprocess termination failed"));
809 #undef ERROR_RETURN_CODE
812 // ----------------------------------------------------------------------------
813 // file and directory functions
814 // ----------------------------------------------------------------------------
816 const wxChar
* wxGetHomeDir( wxString
*home
)
818 *home
= wxGetUserHome( wxString() );
820 if ( home
->IsEmpty() )
824 if ( tmp
.Last() != wxT(']'))
825 if ( tmp
.Last() != wxT('/')) *home
<< wxT('/');
827 return home
->c_str();
831 const wxMB2WXbuf
wxGetUserHome( const wxString
&user
)
832 #else // just for binary compatibility -- there is no 'const' here
833 char *wxGetUserHome( const wxString
&user
)
836 struct passwd
*who
= (struct passwd
*) NULL
;
842 if ((ptr
= wxGetenv(wxT("HOME"))) != NULL
)
846 if ((ptr
= wxGetenv(wxT("USER"))) != NULL
|| (ptr
= wxGetenv(wxT("LOGNAME"))) != NULL
)
848 who
= getpwnam(wxConvertWX2MB(ptr
));
851 // We now make sure the the user exists!
854 who
= getpwuid(getuid());
859 who
= getpwnam (user
.mb_str());
862 return wxConvertMB2WX(who
? who
->pw_dir
: 0);
865 // ----------------------------------------------------------------------------
866 // network and user id routines
867 // ----------------------------------------------------------------------------
869 // retrieve either the hostname or FQDN depending on platform (caller must
870 // check whether it's one or the other, this is why this function is for
872 static bool wxGetHostNameInternal(wxChar
*buf
, int sz
)
874 wxCHECK_MSG( buf
, FALSE
, wxT("NULL pointer in wxGetHostNameInternal") );
878 // we're using uname() which is POSIX instead of less standard sysinfo()
879 #if defined(HAVE_UNAME)
881 bool ok
= uname(&uts
) != -1;
884 wxStrncpy(buf
, wxConvertMB2WX(uts
.nodename
), sz
- 1);
887 #elif defined(HAVE_GETHOSTNAME)
888 bool ok
= gethostname(buf
, sz
) != -1;
889 #else // no uname, no gethostname
890 wxFAIL_MSG(wxT("don't know host name for this machine"));
893 #endif // uname/gethostname
897 wxLogSysError(_("Cannot get the hostname"));
903 bool wxGetHostName(wxChar
*buf
, int sz
)
905 bool ok
= wxGetHostNameInternal(buf
, sz
);
909 // BSD systems return the FQDN, we only want the hostname, so extract
910 // it (we consider that dots are domain separators)
911 wxChar
*dot
= wxStrchr(buf
, wxT('.'));
922 bool wxGetFullHostName(wxChar
*buf
, int sz
)
924 bool ok
= wxGetHostNameInternal(buf
, sz
);
928 if ( !wxStrchr(buf
, wxT('.')) )
930 struct hostent
*host
= gethostbyname(wxConvertWX2MB(buf
));
933 wxLogSysError(_("Cannot get the official hostname"));
939 // the canonical name
940 wxStrncpy(buf
, wxConvertMB2WX(host
->h_name
), sz
);
943 //else: it's already a FQDN (BSD behaves this way)
949 bool wxGetUserId(wxChar
*buf
, int sz
)
954 if ((who
= getpwuid(getuid ())) != NULL
)
956 wxStrncpy (buf
, wxConvertMB2WX(who
->pw_name
), sz
- 1);
963 bool wxGetUserName(wxChar
*buf
, int sz
)
968 if ((who
= getpwuid (getuid ())) != NULL
)
970 // pw_gecos field in struct passwd is not standard
972 char *comma
= strchr(who
->pw_gecos
, ',');
974 *comma
= '\0'; // cut off non-name comment fields
975 wxStrncpy (buf
, wxConvertMB2WX(who
->pw_gecos
), sz
- 1);
976 #else // !HAVE_PW_GECOS
977 wxStrncpy (buf
, wxConvertMB2WX(who
->pw_name
), sz
- 1);
978 #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS
986 wxString
wxGetOsDescription()
988 #ifndef WXWIN_OS_DESCRIPTION
989 #error WXWIN_OS_DESCRIPTION should be defined in config.h by configure
991 return WXWIN_OS_DESCRIPTION
;
996 // this function returns the GUI toolkit version in GUI programs, but OS
997 // version in non-GUI ones
1000 int wxGetOsVersion(int *majorVsn
, int *minorVsn
)
1005 if ( sscanf(WXWIN_OS_DESCRIPTION
, "%s %d.%d", name
, &major
, &minor
) != 3 )
1007 // unreckognized uname string format
1019 #endif // !wxUSE_GUI
1021 unsigned long wxGetProcessId()
1023 return (unsigned long)getpid();
1026 long wxGetFreeMemory()
1028 #if defined(__LINUX__)
1029 // get it from /proc/meminfo
1030 FILE *fp
= fopen("/proc/meminfo", "r");
1036 if ( fgets(buf
, WXSIZEOF(buf
), fp
) && fgets(buf
, WXSIZEOF(buf
), fp
) )
1038 long memTotal
, memUsed
;
1039 sscanf(buf
, "Mem: %ld %ld %ld", &memTotal
, &memUsed
, &memFree
);
1046 #elif defined(__SUN__) && defined(_SC_AVPHYS_PAGES)
1047 return sysconf(_SC_AVPHYS_PAGES
)*sysconf(_SC_PAGESIZE
);
1048 //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably
1051 // can't find it out
1055 bool wxGetDiskSpace(const wxString
& path
, wxLongLong
*pTotal
, wxLongLong
*pFree
)
1057 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
1058 // the case to "char *" is needed for AIX 4.3
1060 if ( statfs((char *)path
.fn_str(), &fs
) != 0 )
1062 wxLogSysError("Failed to get file system statistics");
1067 // under Solaris we might have to use fs.f_frsize instead as I think it
1068 // may be a multiple of the block size in general (TODO)
1072 *pTotal
= wxLongLong(fs
.f_blocks
) * fs
.f_bsize
;
1077 *pFree
= wxLongLong(fs
.f_bavail
) * fs
.f_bsize
;
1081 #endif // HAVE_STATFS
1086 // ----------------------------------------------------------------------------
1088 // ----------------------------------------------------------------------------
1090 bool wxGetEnv(const wxString
& var
, wxString
*value
)
1092 // wxGetenv is defined as getenv()
1093 wxChar
*p
= wxGetenv(var
);
1105 bool wxSetEnv(const wxString
& variable
, const wxChar
*value
)
1107 #if defined(HAVE_SETENV)
1108 return setenv(variable
.mb_str(),
1109 value
? (const char *)wxString(value
).mb_str()
1111 1 /* overwrite */) == 0;
1112 #elif defined(HAVE_PUTENV)
1113 wxString s
= variable
;
1115 s
<< _T('=') << value
;
1117 // transform to ANSI
1118 const char *p
= s
.mb_str();
1120 // the string will be free()d by libc
1121 char *buf
= (char *)malloc(strlen(p
) + 1);
1124 return putenv(buf
) == 0;
1125 #else // no way to set an env var
1130 // ----------------------------------------------------------------------------
1132 // ----------------------------------------------------------------------------
1134 #if wxUSE_ON_FATAL_EXCEPTION
1138 extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER
)
1142 // give the user a chance to do something special about this
1143 wxTheApp
->OnFatalException();
1149 bool wxHandleFatalExceptions(bool doit
)
1152 static bool s_savedHandlers
= FALSE
;
1153 static struct sigaction s_handlerFPE
,
1159 if ( doit
&& !s_savedHandlers
)
1161 // install the signal handler
1162 struct sigaction act
;
1164 // some systems extend it with non std fields, so zero everything
1165 memset(&act
, 0, sizeof(act
));
1167 act
.sa_handler
= wxFatalSignalHandler
;
1168 sigemptyset(&act
.sa_mask
);
1171 ok
&= sigaction(SIGFPE
, &act
, &s_handlerFPE
) == 0;
1172 ok
&= sigaction(SIGILL
, &act
, &s_handlerILL
) == 0;
1173 ok
&= sigaction(SIGBUS
, &act
, &s_handlerBUS
) == 0;
1174 ok
&= sigaction(SIGSEGV
, &act
, &s_handlerSEGV
) == 0;
1177 wxLogDebug(_T("Failed to install our signal handler."));
1180 s_savedHandlers
= TRUE
;
1182 else if ( s_savedHandlers
)
1184 // uninstall the signal handler
1185 ok
&= sigaction(SIGFPE
, &s_handlerFPE
, NULL
) == 0;
1186 ok
&= sigaction(SIGILL
, &s_handlerILL
, NULL
) == 0;
1187 ok
&= sigaction(SIGBUS
, &s_handlerBUS
, NULL
) == 0;
1188 ok
&= sigaction(SIGSEGV
, &s_handlerSEGV
, NULL
) == 0;
1191 wxLogDebug(_T("Failed to uninstall our signal handler."));
1194 s_savedHandlers
= FALSE
;
1196 //else: nothing to do
1201 #endif // wxUSE_ON_FATAL_EXCEPTION
1203 // ----------------------------------------------------------------------------
1204 // error and debug output routines (deprecated, use wxLog)
1205 // ----------------------------------------------------------------------------
1207 #if WXWIN_COMPATIBILITY_2_2
1209 void wxDebugMsg( const char *format
, ... )
1212 va_start( ap
, format
);
1213 vfprintf( stderr
, format
, ap
);
1218 void wxError( const wxString
&msg
, const wxString
&title
)
1220 wxFprintf( stderr
, _("Error ") );
1221 if (!title
.IsNull()) wxFprintf( stderr
, wxT("%s "), WXSTRINGCAST(title
) );
1222 if (!msg
.IsNull()) wxFprintf( stderr
, wxT(": %s"), WXSTRINGCAST(msg
) );
1223 wxFprintf( stderr
, wxT(".\n") );
1226 void wxFatalError( const wxString
&msg
, const wxString
&title
)
1228 wxFprintf( stderr
, _("Error ") );
1229 if (!title
.IsNull()) wxFprintf( stderr
, wxT("%s "), WXSTRINGCAST(title
) );
1230 if (!msg
.IsNull()) wxFprintf( stderr
, wxT(": %s"), WXSTRINGCAST(msg
) );
1231 wxFprintf( stderr
, wxT(".\n") );
1232 exit(3); // the same exit code as for abort()
1235 #endif // WXWIN_COMPATIBILITY_2_2