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