]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/utilsunx.cpp
   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" 
  25 #include "wx/process.h" 
  27 #include "wx/unix/execute.h" 
  33 #include <sys/types.h> 
  40 #include <fcntl.h>          // for O_WRONLY and friends 
  41 #include <time.h>           // nanosleep() and/or usleep() 
  42 #include <ctype.h>          // isspace() 
  44 // JACS: needed for FD_SETSIZE 
  48     #include <sys/utsname.h> // for uname() 
  51 // ---------------------------------------------------------------------------- 
  52 // conditional compilation 
  53 // ---------------------------------------------------------------------------- 
  55 // many versions of Unices have this function, but it is not defined in system 
  56 // headers - please add your system here if it is the case for your OS. 
  57 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. 
  58 #if !defined(HAVE_USLEEP) && \ 
  59     (defined(__SUN__) && !defined(__SunOs_5_6) && \ 
  60                          !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ 
  65             int usleep(unsigned int usec
); 
  67             void usleep(unsigned long usec
); 
  70 #endif // Unices without usleep() 
  72 // ============================================================================ 
  74 // ============================================================================ 
  76 // ---------------------------------------------------------------------------- 
  78 // ---------------------------------------------------------------------------- 
  80 void wxSleep(int nSecs
) 
  85 void wxUsleep(unsigned long milliseconds
) 
  89     tmReq
.tv_sec 
= milliseconds 
/ 1000; 
  90     tmReq
.tv_nsec 
= (milliseconds 
% 1000) * 1000 * 1000; 
  92     // we're not interested in remaining time nor in return value 
  93     (void)nanosleep(&tmReq
, (timespec 
*)NULL
); 
  95     // uncomment this if you feel brave or if you are sure that your version 
  96     // of Solaris has a safe usleep() function but please notice that usleep() 
  97     // is known to lead to crashes in MT programs in Solaris 2.[67] and is not 
  98     // documented as MT-Safe 
  99     #if defined(__SUN__) && wxUSE_THREADS 
 100         #error "usleep() cannot be used in MT programs under Solaris." 
 103     usleep(milliseconds 
* 1000); // usleep(3) wants microseconds 
 104 #else // !sleep function 
 105     #error "usleep() or nanosleep() function required for wxUsleep" 
 106 #endif // sleep function 
 109 // ---------------------------------------------------------------------------- 
 110 // process management 
 111 // ---------------------------------------------------------------------------- 
 113 int wxKill(long pid
, wxSignal sig
) 
 115     return kill(pid
, (int)sig
); 
 118 #define WXEXECUTE_NARGS   127 
 120 long wxExecute( const wxString
& command
, bool sync
, wxProcess 
*process 
) 
 122     wxCHECK_MSG( !command
.IsEmpty(), 0, _T("can't exec empty command") ); 
 125     wxChar 
*argv
[WXEXECUTE_NARGS
]; 
 127     const wxChar 
*cptr 
= command
.c_str(); 
 128     wxChar quotechar 
= _T('\0'); // is arg quoted? 
 129     bool escaped 
= FALSE
; 
 131     // split the command line in arguments 
 135         quotechar 
= _T('\0'); 
 137         // eat leading whitespace: 
 138         while ( wxIsspace(*cptr
) ) 
 141         if ( *cptr 
== _T('\'') || *cptr 
== _T('"') ) 
 146             if ( *cptr 
== _T('\\') && ! escaped 
) 
 153             // all other characters: 
 157             // have we reached the end of the argument? 
 158             if ( (*cptr 
== quotechar 
&& ! escaped
) 
 159                  || (quotechar 
== _T('\0') && wxIsspace(*cptr
)) 
 160                  || *cptr 
== _T('\0') ) 
 162                 wxASSERT_MSG( argc 
< WXEXECUTE_NARGS
, 
 163                               _T("too many arguments in wxExecute") ); 
 165                 argv
[argc
] = new wxChar
[argument
.length() + 1]; 
 166                 wxStrcpy(argv
[argc
], argument
.c_str()); 
 169                 // if not at end of buffer, swallow last character: 
 173                 break; // done with this one, start over 
 179     // do execute the command 
 180     long lRc 
= wxExecute(argv
, sync
, process
); 
 185         delete [] argv
[argc
++]; 
 190 bool wxShell(const wxString
& command
) 
 194         cmd
.Printf(_T("xterm -e %s"), command
.c_str()); 
 198     return wxExecute(cmd
) != 0; 
 201 void wxHandleProcessTermination(wxEndProcessData 
*proc_data
) 
 203     int pid 
= (proc_data
->pid 
> 0) ? proc_data
->pid 
: -(proc_data
->pid
); 
 205     // waitpid is POSIX so should be available everywhere, however on older 
 206     // systems wait() might be used instead in a loop (until the right pid 
 209     if ( waitpid(pid
, &status
, 0) == -1 || !WIFEXITED(status
) ) 
 211         wxLogSysError(_("Waiting for subprocess termination failed")); 
 215         // notify user about termination if required 
 216         if (proc_data
->process
) 
 218             proc_data
->process
->OnTerminate(proc_data
->pid
, 
 219                                             WEXITSTATUS(status
)); 
 224     if ( proc_data
->pid 
> 0 ) 
 230         // wxExecute() will know about it 
 231         proc_data
->exitcode 
= status
; 
 237 long wxExecute( wxChar 
**argv
, bool sync
, wxProcess 
*process 
) 
 239     wxCHECK_MSG( *argv
, 0, _T("can't exec empty command") ); 
 241     int end_proc_detect
[2]; 
 244     char *mb_argv
[WXEXECUTE_NARGS
]; 
 246     while (argv
[mb_argc
]) { 
 247       wxWX2MBbuf mb_arg 
= wxConv_libc
.cWX2MB(argv
[mb_argc
]); 
 248       mb_argv
[mb_argc
] = strdup(mb_arg
); 
 251     mb_argv
[mb_argc
] = (char *) NULL
; 
 253     wxChar 
**mb_argv 
= argv
; 
 257     if (pipe(end_proc_detect
) == -1) 
 259         wxLogSysError( _("Pipe creation failed") ); 
 262         while (mb_argv
[mb_argc
]) 
 263           free(mb_argv
[mb_argc
++]); 
 276         wxLogSysError( _("Fork failed") ); 
 279         while (mb_argv
[mb_argc
]) 
 280           free(mb_argv
[mb_argc
++]); 
 287         close(end_proc_detect
[0]); // close reading side 
 289         // These three lines close the open file descriptors to to avoid any 
 290         // input/output which might block the process or irritate the user. If 
 291         // one wants proper IO for the subprocess, the right thing to do is 
 292         // to start an xterm executing it. 
 295             // leave stderr opened, it won't do any hurm 
 296             for ( int fd 
= 0; fd 
< FD_SETSIZE
; fd
++ ) 
 298                 if ( fd 
!= end_proc_detect
[1] && fd 
!= STDERR_FILENO 
) 
 304         close(STDERR_FILENO
); 
 306         // some programs complain about stderr not being open, so redirect 
 308         open("/dev/null", O_RDONLY
);  // stdin 
 309         open("/dev/null", O_WRONLY
);  // stdout 
 310         open("/dev/null", O_WRONLY
);  // stderr 
 313         execvp (*mb_argv
, mb_argv
); 
 315         // there is no return after successful exec() 
 316         wxFprintf(stderr
, _("Can't execute '%s'\n"), *argv
); 
 323         close(end_proc_detect
[1]); // close writing side 
 325         wxEndProcessData 
*data 
= new wxEndProcessData
; 
 326         data
->tag 
= wxAddProcessCallback(data
, end_proc_detect
[0]); 
 330         while (mb_argv
[mb_argc
]) 
 331           free(mb_argv
[mb_argc
++]); 
 336             wxASSERT_MSG( !process
, _T("wxProcess param ignored for sync exec") ); 
 337             data
->process 
= NULL
; 
 339             // sync execution: indicate it by negating the pid 
 342             // it will be set to 0 from GTK_EndProcessDetector 
 343             while (data
->pid 
!= 0) 
 346             int exitcode 
= data
->exitcode
; 
 354             // async execution, nothing special to do - caller will be 
 355             // notified about the process terminationif process != NULL, data 
 356             // will be deleted in GTK_EndProcessDetector 
 357             data
->process 
= process
; 
 365 // ---------------------------------------------------------------------------- 
 366 // file and directory functions 
 367 // ---------------------------------------------------------------------------- 
 369 const wxChar
* wxGetHomeDir( wxString 
*home  
) 
 371     *home 
= wxGetUserHome( wxString() ); 
 372     if ( home
->IsEmpty() ) 
 375     return home
->c_str(); 
 379 const wxMB2WXbuf 
wxGetUserHome( const wxString 
&user 
) 
 380 #else // just for binary compatibility 
 381 char *wxGetUserHome( const wxString 
&user 
) 
 384     struct passwd 
*who 
= (struct passwd 
*) NULL
; 
 388         register wxChar 
*ptr
; 
 390         if ((ptr 
= wxGetenv(_T("HOME"))) != NULL
) 
 394         if ((ptr 
= wxGetenv(_T("USER"))) != NULL 
|| (ptr 
= wxGetenv(_T("LOGNAME"))) != NULL
) 
 396             who 
= getpwnam(wxConv_libc
.cWX2MB(ptr
)); 
 399         // We now make sure the the user exists! 
 402             who 
= getpwuid(getuid()); 
 407       who 
= getpwnam (user
.mb_str()); 
 411     return who 
? wxConv_libc
.cMB2WX(who
->pw_dir
) : (wxMB2WXbuf
)((wxChar
*)NULL
); 
 413     return who 
? who
->pw_dir 
: ((char*)NULL
); 
 417 // ---------------------------------------------------------------------------- 
 418 // network and user id routines 
 419 // ---------------------------------------------------------------------------- 
 421 // retrieve either the hostname or FQDN depending on platform (caller must 
 422 // check whether it's one or the other, this is why this function is for 
 424 static bool wxGetHostNameInternal(wxChar 
*buf
, int sz
) 
 426     wxCHECK_MSG( buf
, FALSE
, _T("NULL pointer in wxGetHostNameInternal") ); 
 430     // we're using uname() which is POSIX instead of less standard sysinfo() 
 431 #if defined(HAVE_UNAME) 
 433     bool ok 
= uname(&uts
) != -1; 
 436         wxStrncpy(buf
, wxConv_libc
.cMB2WX(uts
.nodename
), sz 
- 1); 
 439 #elif defined(HAVE_GETHOSTNAME) 
 440     bool ok 
= gethostname(buf
, sz
) != -1; 
 441 #else // no uname, no gethostname 
 442     wxFAIL_MSG(_T("don't know host name for this machine")); 
 445 #endif // uname/gethostname 
 449         wxLogSysError(_("Cannot get the hostname")); 
 455 bool wxGetHostName(wxChar 
*buf
, int sz
) 
 457     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 461         // BSD systems return the FQDN, we only want the hostname, so extract 
 462         // it (we consider that dots are domain separators) 
 463         wxChar 
*dot 
= wxStrchr(buf
, _T('.')); 
 474 bool wxGetFullHostName(wxChar 
*buf
, int sz
) 
 476     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 480         if ( !wxStrchr(buf
, _T('.')) ) 
 482             struct hostent 
*host 
= gethostbyname(wxConv_libc
.cWX2MB(buf
)); 
 485                 wxLogSysError(_("Cannot get the official hostname")); 
 491                 // the canonical name 
 492                 wxStrncpy(buf
, wxConv_libc
.cMB2WX(host
->h_name
), sz
); 
 495         //else: it's already a FQDN (BSD behaves this way) 
 501 bool wxGetUserId(wxChar 
*buf
, int sz
) 
 506     if ((who 
= getpwuid(getuid ())) != NULL
) 
 508         wxStrncpy (buf
, wxConv_libc
.cMB2WX(who
->pw_name
), sz 
- 1); 
 515 bool wxGetUserName(wxChar 
*buf
, int sz
) 
 521     if ((who 
= getpwuid (getuid ())) != NULL
) { 
 522        comma 
= strchr(who
->pw_gecos
, ','); 
 524            *comma 
= '\0'; // cut off non-name comment fields 
 525        wxStrncpy (buf
, wxConv_libc
.cMB2WX(who
->pw_gecos
), sz 
- 1); 
 532 // ---------------------------------------------------------------------------- 
 533 // error and debug output routines (deprecated, use wxLog) 
 534 // ---------------------------------------------------------------------------- 
 536 void wxDebugMsg( const char *format
, ... ) 
 539   va_start( ap
, format 
); 
 540   vfprintf( stderr
, format
, ap 
); 
 545 void wxError( const wxString 
&msg
, const wxString 
&title 
) 
 547   wxFprintf( stderr
, _("Error ") ); 
 548   if (!title
.IsNull()) wxFprintf( stderr
, _T("%s "), WXSTRINGCAST(title
) ); 
 549   if (!msg
.IsNull()) wxFprintf( stderr
, _T(": %s"), WXSTRINGCAST(msg
) ); 
 550   wxFprintf( stderr
, _T(".\n") ); 
 553 void wxFatalError( const wxString 
&msg
, const wxString 
&title 
) 
 555   wxFprintf( stderr
, _("Error ") ); 
 556   if (!title
.IsNull()) wxFprintf( stderr
, _T("%s "), WXSTRINGCAST(title
) ); 
 557   if (!msg
.IsNull()) wxFprintf( stderr
, _T(": %s"), WXSTRINGCAST(msg
) ); 
 558   wxFprintf( stderr
, _T(".\n") ); 
 559   exit(3); // the same exit code as for abort()