]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/utilsunx.cpp
c4a312efbd2e1fde56791f243e28055fcd75ab6a
   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)) || \ 
  61      defined(__osf__) || defined(__EMX__) 
  65             int usleep(unsigned int usec
); 
  68             /* I copied this from the XFree86 diffs. AV. */ 
  69             #define INCL_DOSPROCESS 
  71             void usleep(unsigned long delay
) 
  73                 DosSleep(delay 
? (delay
/1000l) : 1l); 
  76             void usleep(unsigned long usec
); 
  78         #endif // Sun/EMX/Something else 
  81 #endif // Unices without usleep() 
  83 // ============================================================================ 
  85 // ============================================================================ 
  87 // ---------------------------------------------------------------------------- 
  89 // ---------------------------------------------------------------------------- 
  91 void wxSleep(int nSecs
) 
  96 void wxUsleep(unsigned long milliseconds
) 
 100     tmReq
.tv_sec 
= milliseconds 
/ 1000; 
 101     tmReq
.tv_nsec 
= (milliseconds 
% 1000) * 1000 * 1000; 
 103     // we're not interested in remaining time nor in return value 
 104     (void)nanosleep(&tmReq
, (timespec 
*)NULL
); 
 106     // uncomment this if you feel brave or if you are sure that your version 
 107     // of Solaris has a safe usleep() function but please notice that usleep() 
 108     // is known to lead to crashes in MT programs in Solaris 2.[67] and is not 
 109     // documented as MT-Safe 
 110     #if defined(__SUN__) && wxUSE_THREADS 
 111         #error "usleep() cannot be used in MT programs under Solaris." 
 114     usleep(milliseconds 
* 1000); // usleep(3) wants microseconds 
 115 #else // !sleep function 
 116     #error "usleep() or nanosleep() function required for wxUsleep" 
 117 #endif // sleep function 
 120 // ---------------------------------------------------------------------------- 
 121 // process management 
 122 // ---------------------------------------------------------------------------- 
 124 int wxKill(long pid
, wxSignal sig
) 
 126     return kill(pid
, (int)sig
); 
 129 #define WXEXECUTE_NARGS   127 
 131 long wxExecute( const wxString
& command
, bool sync
, wxProcess 
*process 
) 
 133     wxCHECK_MSG( !command
.IsEmpty(), 0, wxT("can't exec empty command") ); 
 136     wxChar 
*argv
[WXEXECUTE_NARGS
]; 
 138     const wxChar 
*cptr 
= command
.c_str(); 
 139     wxChar quotechar 
= wxT('\0'); // is arg quoted? 
 140     bool escaped 
= FALSE
; 
 142     // split the command line in arguments 
 146         quotechar 
= wxT('\0'); 
 148         // eat leading whitespace: 
 149         while ( wxIsspace(*cptr
) ) 
 152         if ( *cptr 
== wxT('\'') || *cptr 
== wxT('"') ) 
 157             if ( *cptr 
== wxT('\\') && ! escaped 
) 
 164             // all other characters: 
 168             // have we reached the end of the argument? 
 169             if ( (*cptr 
== quotechar 
&& ! escaped
) 
 170                  || (quotechar 
== wxT('\0') && wxIsspace(*cptr
)) 
 171                  || *cptr 
== wxT('\0') ) 
 173                 wxASSERT_MSG( argc 
< WXEXECUTE_NARGS
, 
 174                               wxT("too many arguments in wxExecute") ); 
 176                 argv
[argc
] = new wxChar
[argument
.length() + 1]; 
 177                 wxStrcpy(argv
[argc
], argument
.c_str()); 
 180                 // if not at end of buffer, swallow last character: 
 184                 break; // done with this one, start over 
 190     // do execute the command 
 191     long lRc 
= wxExecute(argv
, sync
, process
); 
 196         delete [] argv
[argc
++]; 
 201 bool wxShell(const wxString
& command
) 
 205         cmd
.Printf(wxT("xterm -e %s"), command
.c_str()); 
 209     return wxExecute(cmd
) != 0; 
 212 void wxHandleProcessTermination(wxEndProcessData 
*proc_data
) 
 214     int pid 
= (proc_data
->pid 
> 0) ? proc_data
->pid 
: -(proc_data
->pid
); 
 216     // waitpid is POSIX so should be available everywhere, however on older 
 217     // systems wait() might be used instead in a loop (until the right pid 
 220     if ( waitpid(pid
, &status
, 0) == -1 || !WIFEXITED(status
) ) 
 222         wxLogSysError(_("Waiting for subprocess termination failed")); 
 226         // notify user about termination if required 
 227         if (proc_data
->process
) 
 229             proc_data
->process
->OnTerminate(proc_data
->pid
, 
 230                                             WEXITSTATUS(status
)); 
 235     if ( proc_data
->pid 
> 0 ) 
 241         // wxExecute() will know about it 
 242         proc_data
->exitcode 
= status
; 
 248 long wxExecute( wxChar 
**argv
, bool sync
, wxProcess 
*process 
) 
 250     wxCHECK_MSG( *argv
, 0, wxT("can't exec empty command") ); 
 254     char *mb_argv
[WXEXECUTE_NARGS
]; 
 256     while (argv
[mb_argc
]) 
 258       wxWX2MBbuf mb_arg 
= wxConvertWX2MB(argv
[mb_argc
]); 
 259       mb_argv
[mb_argc
] = strdup(mb_arg
); 
 262     mb_argv
[mb_argc
] = (char *) NULL
; 
 264     // this macro will free memory we used above 
 265     #define ARGS_CLEANUP                                 \ 
 266         for ( mb_argc = 0; mb_argv[mb_argc]; mb_argc++ ) \ 
 267             free(mb_argv[mb_argc]) 
 269     // no need for cleanup 
 272     wxChar 
**mb_argv 
= argv
; 
 273 #endif // Unicode/ANSI 
 277     int end_proc_detect
[2]; 
 278     if (pipe(end_proc_detect
) == -1) 
 280         wxLogSysError( _("Pipe creation failed") ); 
 296         wxLogSysError( _("Fork failed") ); 
 306         close(end_proc_detect
[0]); // close reading side 
 309         // These three lines close the open file descriptors to to avoid any 
 310         // input/output which might block the process or irritate the user. If 
 311         // one wants proper IO for the subprocess, the right thing to do is 
 312         // to start an xterm executing it. 
 315             // leave stderr opened, it won't do any hurm 
 316             for ( int fd 
= 0; fd 
< FD_SETSIZE
; fd
++ ) 
 319                 if ( fd 
== end_proc_detect
[1] ) 
 323                 if ( fd 
!= STDERR_FILENO 
) 
 329         close(STDERR_FILENO
); 
 331         // some programs complain about stderr not being open, so redirect 
 333         open("/dev/null", O_RDONLY
);  // stdin 
 334         open("/dev/null", O_WRONLY
);  // stdout 
 335         open("/dev/null", O_WRONLY
);  // stderr 
 338         execvp (*mb_argv
, mb_argv
); 
 340         // there is no return after successful exec() 
 341         wxFprintf(stderr
, _("Can't execute '%s'\n"), *argv
); 
 349         close(end_proc_detect
[1]); // close writing side 
 351         wxEndProcessData 
*data 
= new wxEndProcessData
; 
 352         data
->tag 
= wxAddProcessCallback(data
, end_proc_detect
[0]); 
 358             wxASSERT_MSG( !process
, wxT("wxProcess param ignored for sync exec") ); 
 359             data
->process 
= NULL
; 
 361             // sync execution: indicate it by negating the pid 
 364             // it will be set to 0 from GTK_EndProcessDetector 
 365             while (data
->pid 
!= 0) 
 368             int exitcode 
= data
->exitcode
; 
 376             // async execution, nothing special to do - caller will be 
 377             // notified about the process terminationif process != NULL, data 
 378             // will be deleted in GTK_EndProcessDetector 
 379             data
->process 
= process
; 
 385         wxASSERT_MSG( sync
, wxT("async execution not supported yet") ); 
 388         if ( waitpid(pid
, &exitcode
, 0) == -1 || !WIFEXITED(exitcode
) ) 
 390             wxLogSysError(_("Waiting for subprocess termination failed")); 
 400 // ---------------------------------------------------------------------------- 
 401 // file and directory functions 
 402 // ---------------------------------------------------------------------------- 
 404 const wxChar
* wxGetHomeDir( wxString 
*home  
) 
 406     *home 
= wxGetUserHome( wxString() ); 
 407     if ( home
->IsEmpty() ) 
 410     return home
->c_str(); 
 414 const wxMB2WXbuf 
wxGetUserHome( const wxString 
&user 
) 
 415 #else // just for binary compatibility -- there is no 'const' here 
 416 char *wxGetUserHome( const wxString 
&user 
) 
 419     struct passwd 
*who 
= (struct passwd 
*) NULL
; 
 425         if ((ptr 
= wxGetenv(wxT("HOME"))) != NULL
) 
 429         if ((ptr 
= wxGetenv(wxT("USER"))) != NULL 
|| (ptr 
= wxGetenv(wxT("LOGNAME"))) != NULL
) 
 431             who 
= getpwnam(wxConvertWX2MB(ptr
)); 
 434         // We now make sure the the user exists! 
 437             who 
= getpwuid(getuid()); 
 442       who 
= getpwnam (user
.mb_str()); 
 445     return wxConvertMB2WX(who 
? who
->pw_dir 
: 0); 
 448 // ---------------------------------------------------------------------------- 
 449 // network and user id routines 
 450 // ---------------------------------------------------------------------------- 
 452 // retrieve either the hostname or FQDN depending on platform (caller must 
 453 // check whether it's one or the other, this is why this function is for 
 455 static bool wxGetHostNameInternal(wxChar 
*buf
, int sz
) 
 457     wxCHECK_MSG( buf
, FALSE
, wxT("NULL pointer in wxGetHostNameInternal") ); 
 461     // we're using uname() which is POSIX instead of less standard sysinfo() 
 462 #if defined(HAVE_UNAME) 
 464     bool ok 
= uname(&uts
) != -1; 
 467         wxStrncpy(buf
, wxConvertMB2WX(uts
.nodename
), sz 
- 1); 
 470 #elif defined(HAVE_GETHOSTNAME) 
 471     bool ok 
= gethostname(buf
, sz
) != -1; 
 472 #else // no uname, no gethostname 
 473     wxFAIL_MSG(wxT("don't know host name for this machine")); 
 476 #endif // uname/gethostname 
 480         wxLogSysError(_("Cannot get the hostname")); 
 486 bool wxGetHostName(wxChar 
*buf
, int sz
) 
 488     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 492         // BSD systems return the FQDN, we only want the hostname, so extract 
 493         // it (we consider that dots are domain separators) 
 494         wxChar 
*dot 
= wxStrchr(buf
, wxT('.')); 
 505 bool wxGetFullHostName(wxChar 
*buf
, int sz
) 
 507     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 511         if ( !wxStrchr(buf
, wxT('.')) ) 
 513             struct hostent 
*host 
= gethostbyname(wxConvertWX2MB(buf
)); 
 516                 wxLogSysError(_("Cannot get the official hostname")); 
 522                 // the canonical name 
 523                 wxStrncpy(buf
, wxConvertMB2WX(host
->h_name
), sz
); 
 526         //else: it's already a FQDN (BSD behaves this way) 
 532 bool wxGetUserId(wxChar 
*buf
, int sz
) 
 537     if ((who 
= getpwuid(getuid ())) != NULL
) 
 539         wxStrncpy (buf
, wxConvertMB2WX(who
->pw_name
), sz 
- 1); 
 546 bool wxGetUserName(wxChar 
*buf
, int sz
) 
 552     if ((who 
= getpwuid (getuid ())) != NULL
) { 
 553        comma 
= strchr(who
->pw_gecos
, ','); 
 555            *comma 
= '\0'; // cut off non-name comment fields 
 556        wxStrncpy (buf
, wxConvertMB2WX(who
->pw_gecos
), sz 
- 1); 
 563 // ---------------------------------------------------------------------------- 
 564 // error and debug output routines (deprecated, use wxLog) 
 565 // ---------------------------------------------------------------------------- 
 567 void wxDebugMsg( const char *format
, ... ) 
 570   va_start( ap
, format 
); 
 571   vfprintf( stderr
, format
, ap 
); 
 576 void wxError( const wxString 
&msg
, const wxString 
&title 
) 
 578   wxFprintf( stderr
, _("Error ") ); 
 579   if (!title
.IsNull()) wxFprintf( stderr
, wxT("%s "), WXSTRINGCAST(title
) ); 
 580   if (!msg
.IsNull()) wxFprintf( stderr
, wxT(": %s"), WXSTRINGCAST(msg
) ); 
 581   wxFprintf( stderr
, wxT(".\n") ); 
 584 void wxFatalError( const wxString 
&msg
, const wxString 
&title 
) 
 586   wxFprintf( stderr
, _("Error ") ); 
 587   if (!title
.IsNull()) wxFprintf( stderr
, wxT("%s "), WXSTRINGCAST(title
) ); 
 588   if (!msg
.IsNull()) wxFprintf( stderr
, wxT(": %s"), WXSTRINGCAST(msg
) ); 
 589   wxFprintf( stderr
, wxT(".\n") ); 
 590   exit(3); // the same exit code as for abort()