X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cc743a6f79110647753c49f1dfe81f52605312cc..ea18eed94c637bee3343b929e09cae78a1b80928:/src/unix/utilsunx.cpp diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 2d3aa7ebcb..f7b9b01140 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -39,8 +39,12 @@ #include #include // for O_WRONLY and friends #include // nanosleep() and/or usleep() +#include // isspace() -#ifdef HAVE_UNAME +// JACS: needed for FD_SETSIZE +#include + +#if HAVE_UNAME #include // for uname() #endif // HAVE_UNAME @@ -51,36 +55,20 @@ // many versions of Unices have this function, but it is not defined in system // headers - please add your system here if it is the case for your OS. // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. -#if (defined(__SUN__) && !defined(__SunOs_5_6) && \ +#if !defined(HAVE_USLEEP) && \ + (defined(__SUN__) && !defined(__SunOs_5_6) && \ !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ defined(__osf__) extern "C" { - void usleep(unsigned long usec); + #ifdef __SUN__ + int usleep(unsigned int usec); + #else // !Sun + void usleep(unsigned long usec); + #endif // Sun/!Sun }; #endif // Unices without usleep() -// many versions of Unices have this function, but it is not defined in system -// headers - please add your system here if it is the case for your OS. -// SunOS (and Solaris) and DG-UX are like this. -#if defined(__SOLARIS__) || defined(__osf__) - extern "C" - { - pid_t wait4(pid_t pid, int *statusp, int options, - struct rusage *rusage); - } - - #define wxWait4(pid, stat, flags, rusage) wait4(pid, stat, flags, rusage) -#elif defined(__sgi) || defined(__HPUX__) - // no wait4() at all on these systems - // TODO verify whether wait3() really works in this situation - #define wxWait4(pid, stat, flags, rusage) wait3(stat, flags, rusage) -#else - // other Unices: assume have wait4(), although it's not standard (but - // Linux and FreeBSD do have it) - #define wxWait4(pid, stat, flags, rusage) wait4(pid, stat, flags, rusage) -#endif // wait4() - // ============================================================================ // implementation // ============================================================================ @@ -96,19 +84,19 @@ void wxSleep(int nSecs) void wxUsleep(unsigned long milliseconds) { -#if defined(HAVE_NANOSLEEP) +#if HAVE_NANOSLEEP timespec tmReq; tmReq.tv_sec = milliseconds / 1000; tmReq.tv_nsec = (milliseconds % 1000) * 1000 * 1000; // we're not interested in remaining time nor in return value (void)nanosleep(&tmReq, (timespec *)NULL); -#elif defined(HAVE_USLEEP) +#elif HAVE_USLEEP // uncomment this if you feel brave or if you are sure that your version // of Solaris has a safe usleep() function but please notice that usleep() // is known to lead to crashes in MT programs in Solaris 2.[67] and is not // documented as MT-Safe - #if defined(__SUN__) && defined(wxUSE_THREADS) + #if defined(__SUN__) && wxUSE_THREADS #error "usleep() cannot be used in MT programs under Solaris." #endif // Sun @@ -122,29 +110,79 @@ void wxUsleep(unsigned long milliseconds) // process management // ---------------------------------------------------------------------------- -int wxKill(long pid, int sig) +int wxKill(long pid, wxSignal sig) { - return kill(pid, sig); + return kill(pid, (int)sig); } +#define WXEXECUTE_NARGS 127 + long wxExecute( const wxString& command, bool sync, wxProcess *process ) { - static const char *IFS = " \t\n"; - wxCHECK_MSG( !command.IsEmpty(), 0, "can't exec empty command" ); int argc = 0; - char *argv[127]; - char *tmp = new char[command.Len() + 1]; - strcpy(tmp, command); + char *argv[WXEXECUTE_NARGS]; + wxString argument; + const char *cptr = command.c_str(); + char quotechar = '\0'; // is arg quoted? + bool escaped = FALSE; + + // split the command line in arguments + do + { + argument=""; + quotechar = '\0'; + + // eat leading whitespace: + while ( isspace(*cptr) ) + cptr++; + + if ( *cptr == '\'' || *cptr == '"' ) + quotechar = *cptr++; + + do + { + if ( *cptr == '\\' && ! escaped ) + { + escaped = TRUE; + cptr++; + continue; + } + + // all other characters: + argument += *cptr++; + escaped = FALSE; + + // have we reached the end of the argument? + if ( (*cptr == quotechar && ! escaped) + || (quotechar == '\0' && isspace(*cptr)) + || *cptr == '\0' ) + { + wxASSERT_MSG( argc < WXEXECUTE_NARGS, + "too many arguments in wxExecute" ); + + argv[argc] = new char[argument.length() + 1]; + strcpy(argv[argc], argument.c_str()); + argc++; - argv[argc++] = strtok(tmp, IFS); - while ((argv[argc++] = strtok((char *) NULL, IFS)) != NULL) - /* loop */ ; + // if not at end of buffer, swallow last character: + if(*cptr) + cptr++; + break; // done with this one, start over + } + } while(*cptr); + } while(*cptr); + argv[argc] = NULL; + + // do execute the command long lRc = wxExecute(argv, sync, process); - delete [] tmp; + // clean up + argc = 0; + while( argv[argc] ) + delete [] argv[argc++]; return lRc; } @@ -164,13 +202,26 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) { int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid); + // waitpid is POSIX so should be available everywhere, however on older + // systems wait() might be used instead in a loop (until the right pid + // terminates) int status = 0; - wxWait4(pid, &status, 0, (rusage *) NULL); - - if (proc_data->process) - proc_data->process->OnTerminate(proc_data->pid, status); + if ( waitpid(pid, &status, 0) == -1 || !WIFEXITED(status) ) + { + wxLogSysError(_("Waiting for subprocess termination failed")); + } + else + { + // notify user about termination if required + if (proc_data->process) + { + proc_data->process->OnTerminate(proc_data->pid, + WEXITSTATUS(status)); + } + } - if (proc_data->pid > 0) + // clean up + if ( proc_data->pid > 0 ) { delete proc_data; } @@ -214,7 +265,7 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) // These three lines close the open file descriptors to to avoid any // input/output which might block the process or irritate the user. If - // one wants proper IO for the subprocess, the "right thing to do is + // one wants proper IO for the subprocess, the right thing to do is // to start an xterm executing it. if (sync == 0) { @@ -236,11 +287,7 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) open("/dev/null", O_WRONLY); // stderr #endif -#ifdef _AIX - execvp ((const char *)*argv, (const char **)argv); -#else execvp (*argv, argv); -#endif // there is no return after successful exec() fprintf(stderr, _("Can't execute '%s'\n"), *argv); @@ -303,7 +350,7 @@ char *wxGetUserHome( const wxString &user ) { struct passwd *who = (struct passwd *) NULL; - if (user.IsNull() || (user== "")) + if ( !user ) { register char *ptr; @@ -331,12 +378,15 @@ char *wxGetUserHome( const wxString &user ) } // ---------------------------------------------------------------------------- -// id routines +// network and user id routines // ---------------------------------------------------------------------------- -bool wxGetHostName(char *buf, int sz) +// retrieve either the hostname or FQDN depending on platform (caller must +// check whether it's one or the other, this is why this function is for +// private use only) +static bool wxGetHostNameInternal(char *buf, int sz) { - wxCHECK_MSG( buf, FALSE, "NULL pointer in wxGetHostName" ); + wxCHECK_MSG( buf, FALSE, "NULL pointer in wxGetHostNameInternal" ); *buf = '\0'; @@ -351,11 +401,11 @@ bool wxGetHostName(char *buf, int sz) } #elif defined(HAVE_GETHOSTNAME) bool ok = gethostname(buf, sz) != -1; -#else +#else // no uname, no gethostname wxFAIL_MSG("don't know host name for this machibe"); bool ok = FALSE; -#endif +#endif // uname/gethostname if ( !ok ) { @@ -365,6 +415,52 @@ bool wxGetHostName(char *buf, int sz) return ok; } +bool wxGetHostName(char *buf, int sz) +{ + bool ok = wxGetHostNameInternal(buf, sz); + + if ( ok ) + { + // BSD systems return the FQDN, we only want the hostname, so extract + // it (we consider that dots are domain separators) + char *dot = strchr(buf, '.'); + if ( dot ) + { + // nuke it + *dot = '\0'; + } + } + + return ok; +} + +bool wxGetFullHostName(char *buf, int sz) +{ + bool ok = wxGetHostNameInternal(buf, sz); + + if ( ok ) + { + if ( !strchr(buf, '.') ) + { + struct hostent *host = gethostbyname(buf); + if ( !host ) + { + wxLogSysError(_("Cannot get the official hostname")); + + ok = FALSE; + } + else + { + // the canonical name + strncpy(buf, host->h_name, sz); + } + } + //else: it's already a FQDN (BSD behaves this way) + } + + return ok; +} + bool wxGetUserId(char *buf, int sz) { struct passwd *who; @@ -426,14 +522,3 @@ void wxFatalError( const wxString &msg, const wxString &title ) exit(3); // the same exit code as for abort() } -//------------------------------------------------------------------------ -// directory routines -//------------------------------------------------------------------------ - -bool wxDirExists( const wxString& dir ) -{ - char buf[500]; - strcpy( buf, WXSTRINGCAST(dir) ); - struct stat sbuf; - return ((stat(buf, &sbuf) != -1) && S_ISDIR(sbuf.st_mode) ? TRUE : FALSE); -}