]>
git.saurik.com Git - wxWidgets.git/blob - src/msdos/utilsdos.cpp
1 /////////////////////////////////////////////////////////////////////////////
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"
19 #include "wx/string.h"
22 #include "wx/apptrait.h"
24 #include "wx/process.h"
25 #include "wx/confbase.h" // for wxExpandEnvVars()
27 #include "wx/cmdline.h"
28 #include "wx/filename.h"
29 #include "wx/wfstream.h"
34 #include <sys/types.h>
41 //----------------------------------------------------------------------------
43 //----------------------------------------------------------------------------
45 void wxSleep(int nSecs
)
47 wxMilliSleep(1000 * nSecs
);
50 void wxMilliSleep(unsigned long milliseconds
)
52 #if HAVE_USLEEP || defined __DJGPP__
53 usleep(milliseconds
* 1000);
54 #elif defined __WATCOMC__
57 clock_t start
= clock();
58 while ((clock() - start
) * 1000 / CLOCKS_PER_SEC
< (clock_t)milliseconds
)
60 // yield if in a multitasking environment
61 // "Release Current Virtual Machine's Time Slice" in DPMI 1.0
63 memset(&r
, 0, sizeof(r
));
70 void wxMicroSleep(unsigned long microseconds
)
72 #if HAVE_USLEEP || defined __DJGPP__
75 wxMilliSleep(microseconds
/1000);
79 //----------------------------------------------------------------------------
80 // Get/Set environment variables
81 //----------------------------------------------------------------------------
83 bool wxGetEnv(const wxString
& var
, wxString
*value
)
85 // wxGetenv is defined as getenv()
86 wxChar
*p
= wxGetenv(var
);
96 bool wxSetEnv(const wxString
& variable
, const wxChar
*value
)
98 wxString s
= variable
;
100 s
<< _T('=') << value
;
103 const char *p
= s
.mb_str();
105 // the string will be free()d by libc
106 char *buf
= (char *)malloc(strlen(p
) + 1);
109 return putenv(buf
) == 0;
112 //----------------------------------------------------------------------------
113 // Hostname, username, home directory
114 //----------------------------------------------------------------------------
116 // Based on the MSW implementation
118 // Respects the following environment variables in this order: %HomeDrive% +
119 // %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
120 // wxApp has been initialised, otherwise returns ".".
122 const wxChar
* wxGetHomeDir(wxString
*home
)
124 wxString
& strDir
= *home
;
128 // try HOMEDRIVE/PATH
129 const wxChar
*szHome
= wxGetenv(wxT("HOMEDRIVE"));
130 if ( szHome
!= NULL
)
132 szHome
= wxGetenv(wxT("HOMEPATH"));
134 if ( szHome
!= NULL
)
138 // the idea is that under NT these variables have default values of
139 // "%systemdrive%:" and "\\". As we don't want to create our config
140 // files in the root directory of the system drive, we will create it
141 // in our program's dir. However, if the user took care to set
142 // HOMEPATH to something other than "\\", we suppose that he knows
143 // what he is doing and use the supplied value.
144 if ( wxStrcmp(szHome
, wxT("\\")) == 0 )
148 if ( strDir
.empty() )
150 // If we have a valid USERPROFILE directory, as is the case in
151 // Windows NT, 2000 and XP, we should use that as our home directory.
152 szHome
= wxGetenv(wxT("USERPROFILE"));
154 if ( szHome
!= NULL
)
158 if ( strDir
.empty() )
160 // If we have a valid HOME directory, as is used on many machines
161 // that have unix utilities on them, we should use that.
162 szHome
= wxGetenv(wxT("HOME"));
164 if ( szHome
!= NULL
)
167 // when msys sets %HOME% it uses '/' (cygwin uses '\\')
168 strDir
.Replace(_T("/"), _T("\\"));
172 if ( !strDir
.empty() )
174 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
175 // value once again, it shouldn't hurt anyhow
176 strDir
= wxExpandEnvVars(strDir
);
178 else // fall back to the program directory
182 wxString
prog(wxTheApp
->argv
[0]);
184 // djgpp startup code switches the slashes around, so restore them
185 prog
.Replace(_T("/"), _T("\\"));
187 // it needs to be a full path to be usable
188 if ( prog
.compare(1, 2, _T(":\\")) == 0 )
189 wxSplitPath(prog
, &strDir
, NULL
, NULL
);
191 if ( strDir
.empty() )
197 return strDir
.c_str();
200 wxChar
*wxGetUserHome(const wxString
& user
)
202 static wxString home
;
204 if (user
.empty() || user
== wxGetUserId())
205 return wx_const_cast(wxChar
*, wxGetHomeDir(&home
));
210 #if WXWIN_COMPATIBILITY_2_2
211 void wxFatalError(const wxString
&msg
, const wxString
&title
)
213 wxFprintf( stderr
, _("Error ") );
214 if (!title
.IsNull()) wxFprintf( stderr
, wxT("%s "), WXSTRINGCAST(title
) );
215 if (!msg
.IsNull()) wxFprintf( stderr
, wxT(": %s"), WXSTRINGCAST(msg
) );
216 wxFprintf( stderr
, wxT(".\n") );
217 exit(3); // the same exit code as for abort()
219 #endif // WXWIN_COMPATIBILITY_2_2
221 // returns %UserName%, $USER or just "user"
223 bool wxGetUserId(wxChar
*buf
, int n
)
225 const wxChar
*user
= wxGetenv(_T("UserName"));
228 user
= wxGetenv(_T("USER"));
233 wxStrncpy(buf
, user
, n
);
237 bool wxGetUserName(wxChar
*buf
, int n
)
239 return wxGetUserId(buf
, n
);
242 // returns %ComputerName%, or $HOSTNAME, or "host"
244 bool wxGetHostName(wxChar
*buf
, int n
)
246 const wxChar
*host
= wxGetenv(_T("ComputerName"));
249 host
= wxGetenv(_T("HOSTNAME"));
254 wxStrncpy(buf
, host
, n
);
258 // adds %UserDnsDomain% to wxGetHostName()
260 bool wxGetFullHostName(wxChar
*buf
, int n
)
262 wxGetHostName(buf
, n
);
264 const wxChar
*domain
= wxGetenv(_T("UserDnsDomain"));
267 wxStrncat(wxStrncat(buf
, _T("."), n
), domain
, n
);
272 //----------------------------------------------------------------------------
274 //----------------------------------------------------------------------------
276 unsigned long wxGetProcessId()
278 return (unsigned long)getpid();
281 int wxKill(long pid
, wxSignal sig
, wxKillError
*rc
, int WXUNUSED(flags
))
285 if (pid
!= (long)wxGetProcessId())
289 *rc
= result
== 0 ? wxKILL_OK
: wxKILL_BAD_SIGNAL
;
293 wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
295 *rc
= wxKILL_NO_PROCESS
;
301 bool wxShell(const wxString
& command
/*=wxEmptyString*/)
303 // FIXME: suspend/resume gui
304 int result
= system(command
);
307 wxLogSysError(_("can't execute '%s'"), command
.c_str());
312 long wxExecute(const wxString
& command
, int flags
, wxProcess
*process
)
314 // FIXME: shouldn't depend on wxCmdLineParser
315 wxArrayString
args(wxCmdLineParser::ConvertStringToArgs(command
));
316 size_t n
= args
.size();
317 wxChar
**argv
= new wxChar
*[n
+ 1];
321 argv
[n
] = wx_const_cast(wxChar
*, args
[n
].c_str());
323 long result
= wxExecute(argv
, flags
, process
);
331 // A wxFFileInputStream that deletes the file in it's destructor
333 class wxTempFileInStream
: public wxFFileInputStream
336 wxTempFileInStream(const wxString
& name
)
337 : wxFFileInputStream(name
, _T("rt"))
340 ~wxTempFileInStream()
343 wxRemoveFile(m_file
->GetName());
347 // A file descriptor that can be redirected to a file
349 class wxRedirectableFd
352 wxRedirectableFd(int fd
) : m_fd(fd
), m_dup(-1) { }
355 // Redirect the descriptor to a file, similar to ANSI C's freopen, but
356 // for low level descriptors. The desctructor un-redirects. If O_CREAT
357 // is in the flags then the destructor will delete the file unless it is
358 // given away with Release().
359 bool Reopen(const wxString
& name
, int flags
);
361 // un-redirect the redirected file descriptor, closing the file, and give
362 // away the filename without deleting it
366 // un-redirect the descriptor, closing the file
374 wxRedirectableFd::~wxRedirectableFd()
378 wxRemoveFile(m_name
);
381 bool wxRedirectableFd::Reopen(const wxString
& name
, int flags
)
383 wxASSERT(m_dup
== -1);
386 // save a duplicate so that the descriptor can be closed now and
392 int tmp
= open(name
.mb_str(), flags
);
401 result
= dup2(tmp
, m_fd
) == m_fd
;
407 wxLogSysError(_("error opening '%s'"), name
.c_str());
412 void wxRedirectableFd::Restore()
423 wxString
wxRedirectableFd::Release()
426 wxString name
= m_name
;
431 #endif // wxUSE_STREAMS
433 // wxExecute implementation
435 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*process
)
439 const int STDOUT
= 1;
440 const int STDERR
= 2;
442 wxRedirectableFd
in(STDIN
), out(STDOUT
), err(STDERR
);
443 bool redirect
= process
&& process
->IsRedirected() && (flags
& wxEXEC_SYNC
);
447 // close stdin/out/err and reopen them as files
448 if (!in
.Reopen(_T("NUL"), O_RDONLY
| O_TEXT
))
451 if (!out
.Reopen(wxFileName::CreateTempFileName(_T("out")),
452 O_CREAT
| O_WRONLY
| O_TRUNC
| O_TEXT
))
455 if (!err
.Reopen(wxFileName::CreateTempFileName(_T("err")),
456 O_CREAT
| O_WRONLY
| O_TRUNC
| O_TEXT
))
459 #endif // wxUSE_STREAMS
461 // FIXME: suspend/resume gui
462 int mode
= flags
& wxEXEC_SYNC
? P_WAIT
: P_NOWAIT
;
463 int result
= spawnvp(mode
, argv
[0], argv
);
466 wxLogSysError(_("can't execute '%s'"), argv
[0]);
470 process
->SetPipeStreams(new wxTempFileInStream(out
.Release()),
471 new wxFFileOutputStream(_T("NUL"), _T("wt")),
472 new wxTempFileInStream(err
.Release()));
473 #endif // wxUSE_STREAMS
478 //----------------------------------------------------------------------------
479 // Traits for console apps
480 //----------------------------------------------------------------------------
482 wxToolkitInfo
& wxConsoleAppTraits::GetToolkitInfo()
484 static wxToolkitInfo info
;
485 info
.versionMajor
= _osmajor
;
486 info
.versionMinor
= _osminor
;
487 info
.name
= _T("wxBase");