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