Implementations for some of the stubs
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35221 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
f22d860b26
commit
a3c0d7684a
@ -1,9 +1,10 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: utils.cpp
|
||||
// Purpose: DOS implementations of utility functions
|
||||
// Author: Vaclav Slavik
|
||||
// Author: Vaclav Slavik, M.J.Wetherell
|
||||
// Id: $Id$
|
||||
// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
|
||||
// (c) 2005 M.J.Wetherell
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -21,16 +22,24 @@
|
||||
#include "wx/apptrait.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/process.h"
|
||||
#include "wx/confbase.h" // for wxExpandEnvVars()
|
||||
#include "wx/app.h"
|
||||
#include "wx/cmdline.h"
|
||||
#include "wx/filename.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#include <process.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// misc.
|
||||
// Sleep
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void wxSleep(int nSecs)
|
||||
@ -47,7 +56,14 @@ void wxMilliSleep(unsigned long milliseconds)
|
||||
#else
|
||||
clock_t start = clock();
|
||||
while ((clock() - start) * 1000 / CLOCKS_PER_SEC < (clock_t)milliseconds)
|
||||
; // FIXME: need to yield here
|
||||
{
|
||||
// yield if in a multitasking environment
|
||||
// "Release Current Virtual Machine's Time Slice" in DPMI 1.0
|
||||
REGS r;
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x1680;
|
||||
int386(0x2f, &r, &r);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -60,11 +76,9 @@ void wxMicroSleep(unsigned long microseconds)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get Process ID
|
||||
unsigned long wxGetProcessId()
|
||||
{
|
||||
return (unsigned long)getpid();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
// Get/Set environment variables
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool wxGetEnv(const wxString& var, wxString *value)
|
||||
{
|
||||
@ -95,21 +109,102 @@ bool wxSetEnv(const wxString& variable, const wxChar *value)
|
||||
return putenv(buf) == 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Hostname, username, home directory
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Based on the MSW implementation
|
||||
//
|
||||
// Respects the following environment variables in this order: %HomeDrive% +
|
||||
// %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
|
||||
// wxApp has been initialised, otherwise returns ".".
|
||||
//
|
||||
const wxChar* wxGetHomeDir(wxString *home)
|
||||
{
|
||||
*home = wxT(".");
|
||||
return home->c_str();
|
||||
wxString& strDir = *home;
|
||||
|
||||
strDir.clear();
|
||||
|
||||
// try HOMEDRIVE/PATH
|
||||
const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
|
||||
if ( szHome != NULL )
|
||||
strDir << szHome;
|
||||
szHome = wxGetenv(wxT("HOMEPATH"));
|
||||
|
||||
if ( szHome != NULL )
|
||||
{
|
||||
strDir << szHome;
|
||||
|
||||
// the idea is that under NT these variables have default values of
|
||||
// "%systemdrive%:" and "\\". As we don't want to create our config
|
||||
// files in the root directory of the system drive, we will create it
|
||||
// in our program's dir. However, if the user took care to set
|
||||
// HOMEPATH to something other than "\\", we suppose that he knows
|
||||
// what he is doing and use the supplied value.
|
||||
if ( wxStrcmp(szHome, wxT("\\")) == 0 )
|
||||
strDir.clear();
|
||||
}
|
||||
|
||||
if ( strDir.empty() )
|
||||
{
|
||||
// If we have a valid USERPROFILE directory, as is the case in
|
||||
// Windows NT, 2000 and XP, we should use that as our home directory.
|
||||
szHome = wxGetenv(wxT("USERPROFILE"));
|
||||
|
||||
if ( szHome != NULL )
|
||||
strDir = szHome;
|
||||
}
|
||||
|
||||
if ( strDir.empty() )
|
||||
{
|
||||
// If we have a valid HOME directory, as is used on many machines
|
||||
// that have unix utilities on them, we should use that.
|
||||
szHome = wxGetenv(wxT("HOME"));
|
||||
|
||||
if ( szHome != NULL )
|
||||
{
|
||||
strDir = szHome;
|
||||
// when msys sets %HOME% it uses '/' (cygwin uses '\\')
|
||||
strDir.Replace(_T("/"), _T("\\"));
|
||||
}
|
||||
}
|
||||
|
||||
if ( !strDir.empty() )
|
||||
{
|
||||
// sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
|
||||
// value once again, it shouldn't hurt anyhow
|
||||
strDir = wxExpandEnvVars(strDir);
|
||||
}
|
||||
else // fall back to the program directory
|
||||
{
|
||||
if ( wxTheApp )
|
||||
{
|
||||
wxString prog(wxTheApp->argv[0]);
|
||||
#ifdef __DJGPP__
|
||||
// djgpp startup code switches the slashes around, so restore them
|
||||
prog.Replace(_T("/"), _T("\\"));
|
||||
#endif
|
||||
// it needs to be a full path to be usable
|
||||
if ( prog.compare(1, 2, _T(":\\")) == 0 )
|
||||
wxSplitPath(prog, &strDir, NULL, NULL);
|
||||
}
|
||||
if ( strDir.empty() )
|
||||
{
|
||||
strDir = _T(".");
|
||||
}
|
||||
}
|
||||
|
||||
return strDir.c_str();
|
||||
}
|
||||
|
||||
const wxChar* wxGetUserHomeDir(wxString *home)
|
||||
wxChar *wxGetUserHome(const wxString& user)
|
||||
{
|
||||
*home = wxT(".");
|
||||
return home->c_str();
|
||||
}
|
||||
static wxString home;
|
||||
|
||||
wxChar *wxGetUserHome(const wxString &user)
|
||||
{
|
||||
return wxT(".");
|
||||
if (user.empty() || user == wxGetUserId())
|
||||
return wx_const_cast(wxChar*, wxGetHomeDir(&home));
|
||||
else
|
||||
return _T("");
|
||||
}
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_2
|
||||
@ -123,53 +218,272 @@ void wxFatalError(const wxString &msg, const wxString &title)
|
||||
}
|
||||
#endif // WXWIN_COMPATIBILITY_2_2
|
||||
|
||||
bool wxGetUserId(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
|
||||
// returns %UserName%, $USER or just "user"
|
||||
//
|
||||
bool wxGetUserId(wxChar *buf, int n)
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxGetUserId not implemented under MS-DOS!") );
|
||||
return FALSE;
|
||||
const wxChar *user = wxGetenv(_T("UserName"));
|
||||
|
||||
if (!user)
|
||||
user = wxGetenv(_T("USER"));
|
||||
|
||||
if (!user)
|
||||
user = _T("user");
|
||||
|
||||
wxStrncpy(buf, user, n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxGetUserName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
|
||||
bool wxGetUserName(wxChar *buf, int n)
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxGetUserName not implemented under MS-DOS!") );
|
||||
return FALSE;
|
||||
return wxGetUserId(buf, n);
|
||||
}
|
||||
|
||||
bool wxGetHostName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
|
||||
// returns %ComputerName%, or $HOSTNAME, or "host"
|
||||
//
|
||||
bool wxGetHostName(wxChar *buf, int n)
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxGetHostName not implemented under MS-DOS!") );
|
||||
return FALSE;
|
||||
const wxChar *host = wxGetenv(_T("ComputerName"));
|
||||
|
||||
if (!host)
|
||||
host = wxGetenv(_T("HOSTNAME"));
|
||||
|
||||
if (!host)
|
||||
host = _T("host");
|
||||
|
||||
wxStrncpy(buf, host, n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxGetFullHostName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
|
||||
// adds %UserDnsDomain% to wxGetHostName()
|
||||
//
|
||||
bool wxGetFullHostName(wxChar *buf, int n)
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxGetFullHostName not implemented under MS-DOS!") );
|
||||
return FALSE;
|
||||
wxGetHostName(buf, n);
|
||||
|
||||
const wxChar *domain = wxGetenv(_T("UserDnsDomain"));
|
||||
|
||||
if (domain)
|
||||
wxStrncat(wxStrncat(buf, _T("."), n), domain, n);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxKill(long WXUNUSED(pid), wxSignal WXUNUSED(sig), wxKillError *WXUNUSED(rc), int WXUNUSED(flags))
|
||||
//----------------------------------------------------------------------------
|
||||
// Processes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
unsigned long wxGetProcessId()
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxKill not implemented under MS-DOS!") );
|
||||
return 0;
|
||||
return (unsigned long)getpid();
|
||||
}
|
||||
|
||||
long wxExecute(const wxString& WXUNUSED(command), int WXUNUSED(flags), wxProcess *WXUNUSED(process))
|
||||
int wxKill(long pid, wxSignal sig, wxKillError *rc, int WXUNUSED(flags))
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxExecute not implemented under MS-DOS!") );
|
||||
return 0;
|
||||
int result = -1;
|
||||
|
||||
if (pid != (long)wxGetProcessId())
|
||||
{
|
||||
result = raise(sig);
|
||||
if (rc)
|
||||
*rc = result == 0 ? wxKILL_OK : wxKILL_BAD_SIGNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
|
||||
if (rc)
|
||||
*rc = wxKILL_NO_PROCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
long wxExecute(char **WXUNUSED(argv), int WXUNUSED(flags), wxProcess *WXUNUSED(process))
|
||||
bool wxShell(const wxString& command /*=wxEmptyString*/)
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxExecute not implemented under MS-DOS!") );
|
||||
return 0;
|
||||
// FIXME: suspend/resume gui
|
||||
int result = system(command);
|
||||
|
||||
if (result == -1)
|
||||
wxLogSysError(_("can't execute '%s'"), command.c_str());
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
long wxExecute(const wxString& command, int flags, wxProcess *process)
|
||||
{
|
||||
// FIXME: shouldn't depend on wxCmdLineParser
|
||||
wxArrayString args(wxCmdLineParser::ConvertStringToArgs(command));
|
||||
size_t n = args.size();
|
||||
wxChar **argv = new wxChar*[n + 1];
|
||||
|
||||
argv[n] = NULL;
|
||||
while (n-- > 0)
|
||||
argv[n] = wx_const_cast(wxChar*, args[n].c_str());
|
||||
|
||||
long result = wxExecute(argv, flags, process);
|
||||
|
||||
delete [] argv;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if wxUSE_STREAMS
|
||||
|
||||
// A wxFFileInputStream that deletes the file in it's destructor
|
||||
//
|
||||
class wxTempFileInStream : public wxFFileInputStream
|
||||
{
|
||||
public:
|
||||
wxTempFileInStream(const wxString& name)
|
||||
: wxFFileInputStream(name, _T("rt"))
|
||||
{ }
|
||||
|
||||
~wxTempFileInStream()
|
||||
{
|
||||
m_file->Close();
|
||||
wxRemoveFile(m_file->GetName());
|
||||
}
|
||||
};
|
||||
|
||||
// A file descriptor that can be redirected to a file
|
||||
//
|
||||
class wxRedirectableFd
|
||||
{
|
||||
public:
|
||||
wxRedirectableFd(int fd) : m_fd(fd), m_dup(-1) { }
|
||||
~wxRedirectableFd();
|
||||
|
||||
// Redirect the descriptor to a file, similar to ANSI C's freopen, but
|
||||
// for low level descriptors. The desctructor un-redirects. If O_CREAT
|
||||
// is in the flags then the destructor will delete the file unless it is
|
||||
// given away with Release().
|
||||
bool Reopen(const wxString& name, int flags);
|
||||
|
||||
// un-redirect the redirected file descriptor, closing the file, and give
|
||||
// away the filename without deleting it
|
||||
wxString Release();
|
||||
|
||||
private:
|
||||
// un-redirect the descriptor, closing the file
|
||||
void Restore();
|
||||
|
||||
int m_fd;
|
||||
int m_dup;
|
||||
wxString m_name;
|
||||
};
|
||||
|
||||
wxRedirectableFd::~wxRedirectableFd()
|
||||
{
|
||||
Restore();
|
||||
if (!m_name.empty())
|
||||
wxRemoveFile(m_name);
|
||||
}
|
||||
|
||||
bool wxRedirectableFd::Reopen(const wxString& name, int flags)
|
||||
{
|
||||
wxASSERT(m_dup == -1);
|
||||
bool result = false;
|
||||
|
||||
// save a duplicate so that the descriptor can be closed now and
|
||||
// restored later
|
||||
m_dup = dup(m_fd);
|
||||
|
||||
if (m_dup != -1)
|
||||
{
|
||||
int tmp = open(name.mb_str(), flags);
|
||||
|
||||
if (tmp != -1)
|
||||
{
|
||||
close(m_fd);
|
||||
|
||||
if (flags & O_CREAT)
|
||||
m_name = name;
|
||||
|
||||
result = dup2(tmp, m_fd) == m_fd;
|
||||
close(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
wxLogSysError(_("error opening '%s'"), name.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void wxRedirectableFd::Restore()
|
||||
{
|
||||
if (m_dup != -1)
|
||||
{
|
||||
close(m_fd);
|
||||
dup2(m_dup, m_fd);
|
||||
close(m_dup);
|
||||
m_dup = -1;
|
||||
}
|
||||
}
|
||||
|
||||
wxString wxRedirectableFd::Release()
|
||||
{
|
||||
Restore();
|
||||
wxString name = m_name;
|
||||
m_name.clear();
|
||||
return name;
|
||||
}
|
||||
|
||||
#endif // wxUSE_STREAMS
|
||||
|
||||
// wxExecute implementation
|
||||
//
|
||||
long wxExecute(wxChar **argv, int flags, wxProcess *process)
|
||||
{
|
||||
#if wxUSE_STREAMS
|
||||
const int STDIN = 0;
|
||||
const int STDOUT = 1;
|
||||
const int STDERR = 2;
|
||||
|
||||
wxRedirectableFd in(STDIN), out(STDOUT), err(STDERR);
|
||||
bool redirect = process && process->IsRedirected() && (flags & wxEXEC_SYNC);
|
||||
|
||||
if (redirect)
|
||||
{
|
||||
// close stdin/out/err and reopen them as files
|
||||
if (!in.Reopen(_T("NUL"), O_RDONLY | O_TEXT))
|
||||
return -1;
|
||||
|
||||
if (!out.Reopen(wxFileName::CreateTempFileName(_T("out")),
|
||||
O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
|
||||
return -1;
|
||||
|
||||
if (!err.Reopen(wxFileName::CreateTempFileName(_T("err")),
|
||||
O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
|
||||
return -1;
|
||||
}
|
||||
#endif // wxUSE_STREAMS
|
||||
|
||||
// FIXME: suspend/resume gui
|
||||
int mode = flags & wxEXEC_SYNC ? P_WAIT : P_NOWAIT;
|
||||
int result = spawnvp(mode, argv[0], argv);
|
||||
|
||||
if (result == -1)
|
||||
wxLogSysError(_("can't execute '%s'"), argv[0]);
|
||||
|
||||
#if wxUSE_STREAMS
|
||||
if (redirect)
|
||||
process->SetPipeStreams(new wxTempFileInStream(out.Release()),
|
||||
new wxFFileOutputStream(_T("NUL"), _T("wt")),
|
||||
new wxTempFileInStream(err.Release()));
|
||||
#endif // wxUSE_STREAMS
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Traits for console apps
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
|
||||
{
|
||||
static wxToolkitInfo info;
|
||||
info.versionMajor = -1; // FIXME
|
||||
info.versionMinor = -1;
|
||||
info.versionMajor = _osmajor;
|
||||
info.versionMinor = _osminor;
|
||||
info.name = _T("wxBase");
|
||||
info.os = wxDOS;
|
||||
return info;
|
||||
|
Loading…
Reference in New Issue
Block a user