1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msdos/utils.cpp
3 // Purpose: DOS implementations of utility functions
4 // Author: Vaclav Slavik, M.J.Wetherell
6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7 // (c) 2005 M.J.Wetherell
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
21 #include "wx/string.h"
27 #include "wx/apptrait.h"
28 #include "wx/process.h"
29 #include "wx/confbase.h" // for wxExpandEnvVars()
30 #include "wx/cmdline.h"
31 #include "wx/filename.h"
32 #include "wx/wfstream.h"
37 #include <sys/types.h>
44 //----------------------------------------------------------------------------
46 //----------------------------------------------------------------------------
48 void wxSleep(int nSecs)
50 wxMilliSleep(1000 * nSecs);
53 void wxMilliSleep(unsigned long milliseconds)
55 #if HAVE_USLEEP || defined __DJGPP__
56 usleep(milliseconds * 1000);
57 #elif defined __WATCOMC__
60 clock_t start = clock();
61 while ((clock() - start) * 1000 / CLOCKS_PER_SEC < (clock_t)milliseconds)
63 // yield if in a multitasking environment
64 // "Release Current Virtual Machine's Time Slice" in DPMI 1.0
66 memset(&r, 0, sizeof(r));
73 void wxMicroSleep(unsigned long microseconds)
75 #if HAVE_USLEEP || defined __DJGPP__
78 wxMilliSleep(microseconds/1000);
82 //----------------------------------------------------------------------------
83 // Get/Set environment variables
84 //----------------------------------------------------------------------------
86 bool wxGetEnv(const wxString& var, wxString *value)
88 // wxGetenv is defined as getenv()
89 wxChar *p = wxGetenv(var);
99 bool wxSetEnv(const wxString& variable, const wxChar *value)
101 wxString s = variable;
103 s << _T('=') << value;
106 const char *p = s.mb_str();
108 // the string will be free()d by libc
109 char *buf = (char *)malloc(strlen(p) + 1);
112 return putenv(buf) == 0;
115 //----------------------------------------------------------------------------
116 // Hostname, username, home directory
117 //----------------------------------------------------------------------------
119 // Based on the MSW implementation
121 // Respects the following environment variables in this order: %HomeDrive% +
122 // %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
123 // wxApp has been initialised, otherwise returns ".".
125 const wxChar* wxGetHomeDir(wxString *home)
127 wxString& strDir = *home;
131 // try HOMEDRIVE/PATH
132 const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
133 if ( szHome != NULL )
135 szHome = wxGetenv(wxT("HOMEPATH"));
137 if ( szHome != NULL )
141 // the idea is that under NT these variables have default values of
142 // "%systemdrive%:" and "\\". As we don't want to create our config
143 // files in the root directory of the system drive, we will create it
144 // in our program's dir. However, if the user took care to set
145 // HOMEPATH to something other than "\\", we suppose that he knows
146 // what he is doing and use the supplied value.
147 if ( wxStrcmp(szHome, wxT("\\")) == 0 )
151 if ( strDir.empty() )
153 // If we have a valid USERPROFILE directory, as is the case in
154 // Windows NT, 2000 and XP, we should use that as our home directory.
155 szHome = wxGetenv(wxT("USERPROFILE"));
157 if ( szHome != NULL )
161 if ( strDir.empty() )
163 // If we have a valid HOME directory, as is used on many machines
164 // that have unix utilities on them, we should use that.
165 szHome = wxGetenv(wxT("HOME"));
167 if ( szHome != NULL )
170 // when msys sets %HOME% it uses '/' (cygwin uses '\\')
171 strDir.Replace(_T("/"), _T("\\"));
175 if ( !strDir.empty() )
177 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
178 // value once again, it shouldn't hurt anyhow
179 strDir = wxExpandEnvVars(strDir);
181 else // fall back to the program directory
185 wxString prog(wxTheApp->argv[0]);
187 // djgpp startup code switches the slashes around, so restore them
188 prog.Replace(_T("/"), _T("\\"));
190 // it needs to be a full path to be usable
191 if ( prog.compare(1, 2, _T(":\\")) == 0 )
192 wxSplitPath(prog, &strDir, NULL, NULL);
194 if ( strDir.empty() )
200 return strDir.c_str();
203 wxChar *wxGetUserHome(const wxString& user)
205 static wxString home;
207 if (user.empty() || user == wxGetUserId())
208 return wx_const_cast(wxChar*, wxGetHomeDir(&home));
213 // returns %UserName%, $USER or just "user"
215 bool wxGetUserId(wxChar *buf, int n)
217 const wxChar *user = wxGetenv(_T("UserName"));
220 user = wxGetenv(_T("USER"));
225 wxStrncpy(buf, user, n);
229 bool wxGetUserName(wxChar *buf, int n)
231 return wxGetUserId(buf, n);
234 // returns %ComputerName%, or $HOSTNAME, or "host"
236 bool wxGetHostName(wxChar *buf, int n)
238 const wxChar *host = wxGetenv(_T("ComputerName"));
241 host = wxGetenv(_T("HOSTNAME"));
246 wxStrncpy(buf, host, n);
250 // adds %UserDnsDomain% to wxGetHostName()
252 bool wxGetFullHostName(wxChar *buf, int n)
254 wxGetHostName(buf, n);
256 const wxChar *domain = wxGetenv(_T("UserDnsDomain"));
259 wxStrncat(wxStrncat(buf, _T("."), n), domain, n);
264 //----------------------------------------------------------------------------
266 //----------------------------------------------------------------------------
268 unsigned long wxGetProcessId()
270 return (unsigned long)getpid();
273 int wxKill(long pid, wxSignal sig, wxKillError *rc, int WXUNUSED(flags))
277 if (pid != (long)wxGetProcessId())
281 *rc = result == 0 ? wxKILL_OK : wxKILL_BAD_SIGNAL;
285 wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
287 *rc = wxKILL_NO_PROCESS;
293 bool wxShell(const wxString& command /*=wxEmptyString*/)
295 // FIXME: suspend/resume gui
296 int result = system(command);
299 wxLogSysError(_("can't execute '%s'"), command.c_str());
304 long wxExecute(const wxString& command, int flags, wxProcess *process)
306 // FIXME: shouldn't depend on wxCmdLineParser
307 wxArrayString args(wxCmdLineParser::ConvertStringToArgs(command));
308 size_t n = args.size();
309 wxChar **argv = new wxChar*[n + 1];
313 argv[n] = wx_const_cast(wxChar*, args[n].c_str());
315 long result = wxExecute(argv, flags, process);
323 // A wxFFileInputStream that deletes the file in it's destructor
325 class wxTempFileInStream : public wxFFileInputStream
328 wxTempFileInStream(const wxString& name)
329 : wxFFileInputStream(name, _T("rt"))
332 ~wxTempFileInStream()
335 wxRemoveFile(m_file->GetName());
339 // A file descriptor that can be redirected to a file
341 class wxRedirectableFd
344 wxRedirectableFd(int fd) : m_fd(fd), m_dup(-1) { }
347 // Redirect the descriptor to a file, similar to ANSI C's freopen, but
348 // for low level descriptors. The desctructor un-redirects. If O_CREAT
349 // is in the flags then the destructor will delete the file unless it is
350 // given away with Release().
351 bool Reopen(const wxString& name, int flags);
353 // un-redirect the redirected file descriptor, closing the file, and give
354 // away the filename without deleting it
358 // un-redirect the descriptor, closing the file
366 wxRedirectableFd::~wxRedirectableFd()
370 wxRemoveFile(m_name);
373 bool wxRedirectableFd::Reopen(const wxString& name, int flags)
375 wxASSERT(m_dup == -1);
378 // save a duplicate so that the descriptor can be closed now and
384 int tmp = open(name.mb_str(), flags);
393 result = dup2(tmp, m_fd) == m_fd;
399 wxLogSysError(_("error opening '%s'"), name.c_str());
404 void wxRedirectableFd::Restore()
415 wxString wxRedirectableFd::Release()
418 wxString name = m_name;
423 #endif // wxUSE_STREAMS
425 // wxExecute implementation
427 long wxExecute(wxChar **argv, int flags, wxProcess *process)
431 const int STDOUT = 1;
432 const int STDERR = 2;
434 wxRedirectableFd in(STDIN), out(STDOUT), err(STDERR);
435 bool redirect = process && process->IsRedirected() && (flags & wxEXEC_SYNC);
439 // close stdin/out/err and reopen them as files
440 if (!in.Reopen(_T("NUL"), O_RDONLY | O_TEXT))
443 if (!out.Reopen(wxFileName::CreateTempFileName(_T("out")),
444 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
447 if (!err.Reopen(wxFileName::CreateTempFileName(_T("err")),
448 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
451 #endif // wxUSE_STREAMS
453 // FIXME: suspend/resume gui
454 int mode = flags & wxEXEC_SYNC ? P_WAIT : P_NOWAIT;
455 int result = spawnvp(mode, argv[0], argv);
458 wxLogSysError(_("can't execute '%s'"), argv[0]);
462 process->SetPipeStreams(new wxTempFileInStream(out.Release()),
463 new wxFFileOutputStream(_T("NUL"), _T("wt")),
464 new wxTempFileInStream(err.Release()));
465 #endif // wxUSE_STREAMS
470 //----------------------------------------------------------------------------
471 // Traits for console apps
472 //----------------------------------------------------------------------------
474 wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
476 static wxToolkitInfo info;
477 info.versionMajor = _osmajor;
478 info.versionMinor = _osminor;
479 info.name = _T("wxBase");
484 //----------------------------------------------------------------------------
486 //----------------------------------------------------------------------------
488 wxString wxGetOsDescription()
490 wxString osname(_T("DOS"));