]>
git.saurik.com Git - wxWidgets.git/blob - src/msdos/utilsdos.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msdos/utilsdos.cpp
3 // Purpose: DOS implementations of utility functions
4 // Author: Vaclav Slavik, M.J.Wetherell
5 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
6 // (c) 2005 M.J.Wetherell
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
20 #include "wx/string.h"
26 #include "wx/apptrait.h"
27 #include "wx/process.h"
28 #include "wx/confbase.h" // for wxExpandEnvVars()
29 #include "wx/cmdline.h"
30 #include "wx/filename.h"
31 #include "wx/wfstream.h"
36 #include <sys/types.h>
43 //----------------------------------------------------------------------------
45 //----------------------------------------------------------------------------
47 void wxSleep(int nSecs
)
49 wxMilliSleep(1000 * nSecs
);
52 void wxMilliSleep(unsigned long milliseconds
)
54 #if HAVE_USLEEP || defined __DJGPP__
55 usleep(milliseconds
* 1000);
56 #elif defined __WATCOMC__
59 clock_t start
= clock();
60 while ((clock() - start
) * 1000 / CLOCKS_PER_SEC
< (clock_t)milliseconds
)
62 // yield if in a multitasking environment
63 // "Release Current Virtual Machine's Time Slice" in DPMI 1.0
65 memset(&r
, 0, sizeof(r
));
72 void wxMicroSleep(unsigned long microseconds
)
74 #if HAVE_USLEEP || defined __DJGPP__
77 wxMilliSleep(microseconds
/1000);
81 //----------------------------------------------------------------------------
82 // Get/Set environment variables
83 //----------------------------------------------------------------------------
85 bool wxGetEnv(const wxString
& var
, wxString
*value
)
87 // wxGetenv is defined as getenv()
88 wxChar
*p
= wxGetenv(var
);
98 static bool wxDoSetEnv(const wxString
& variable
, const char *value
)
100 wxString s
= variable
;
102 s
<< wxT('=') << value
;
105 const char *p
= s
.mb_str();
107 // the string will be free()d by libc
108 char *buf
= (char *)malloc(strlen(p
) + 1);
111 return putenv(buf
) == 0;
114 bool wxSetEnv(const wxString
& variable
, const wxString
& value
)
116 return wxDoSetEnv(variable
, value
.mb_str());
119 bool wxUnsetEnv(const wxString
& variable
)
121 return wxDoSetEnv(variable
, NULL
);
125 //----------------------------------------------------------------------------
126 // Hostname, username, home directory
127 //----------------------------------------------------------------------------
129 // Based on the MSW implementation
131 // Respects the following environment variables in this order: %HomeDrive% +
132 // %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
133 // wxApp has been initialised, otherwise returns ".".
135 const wxChar
* wxGetHomeDir(wxString
*home
)
137 wxString
& strDir
= *home
;
141 // try HOMEDRIVE/PATH
142 const wxChar
*szHome
= wxGetenv(wxT("HOMEDRIVE"));
143 if ( szHome
!= NULL
)
145 szHome
= wxGetenv(wxT("HOMEPATH"));
147 if ( szHome
!= NULL
)
151 // the idea is that under NT these variables have default values of
152 // "%systemdrive%:" and "\\". As we don't want to create our config
153 // files in the root directory of the system drive, we will create it
154 // in our program's dir. However, if the user took care to set
155 // HOMEPATH to something other than "\\", we suppose that he knows
156 // what he is doing and use the supplied value.
157 if ( wxStrcmp(szHome
, wxT("\\")) == 0 )
161 if ( strDir
.empty() )
163 // If we have a valid USERPROFILE directory, as is the case in
164 // Windows NT, 2000 and XP, we should use that as our home directory.
165 szHome
= wxGetenv(wxT("USERPROFILE"));
167 if ( szHome
!= NULL
)
171 if ( strDir
.empty() )
173 // If we have a valid HOME directory, as is used on many machines
174 // that have unix utilities on them, we should use that.
175 szHome
= wxGetenv(wxT("HOME"));
177 if ( szHome
!= NULL
)
180 // when msys sets %HOME% it uses '/' (cygwin uses '\\')
181 strDir
.Replace(wxT("/"), wxT("\\"));
185 if ( !strDir
.empty() )
187 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
188 // value once again, it shouldn't hurt anyhow
189 strDir
= wxExpandEnvVars(strDir
);
191 else // fall back to the program directory
195 wxString
prog(wxTheApp
->argv
[0]);
197 // djgpp startup code switches the slashes around, so restore them
198 prog
.Replace(wxT("/"), wxT("\\"));
200 // it needs to be a full path to be usable
201 if ( prog
.compare(1, 2, wxT(":\\")) == 0 )
202 wxFileName::SplitPath(prog
, &strDir
, NULL
, NULL
);
204 if ( strDir
.empty() )
210 return strDir
.c_str();
213 wxString
wxGetUserHome(const wxString
& user
)
217 if (user
.empty() || user
== wxGetUserId())
223 // returns %UserName%, $USER or just "user"
225 bool wxGetUserId(wxChar
*buf
, int n
)
227 const wxChar
*user
= wxGetenv(wxT("UserName"));
230 user
= wxGetenv(wxT("USER"));
235 wxStrlcpy(buf
, user
, n
);
239 bool wxGetUserName(wxChar
*buf
, int n
)
241 return wxGetUserId(buf
, n
);
244 // returns %ComputerName%, or $HOSTNAME, or "host"
246 bool wxGetHostName(wxChar
*buf
, int n
)
248 const wxChar
*host
= wxGetenv(wxT("ComputerName"));
251 host
= wxGetenv(wxT("HOSTNAME"));
256 wxStrlcpy(buf
, host
, n
);
260 // adds %UserDnsDomain% to wxGetHostName()
262 bool wxGetFullHostName(wxChar
*buf
, int n
)
264 wxGetHostName(buf
, n
);
266 const wxChar
*domain
= wxGetenv(wxT("UserDnsDomain"));
269 wxStrncat(wxStrncat(buf
, wxT("."), n
), domain
, n
);
274 //----------------------------------------------------------------------------
276 //----------------------------------------------------------------------------
278 unsigned long wxGetProcessId()
280 return (unsigned long)getpid();
283 int wxKill(long pid
, wxSignal sig
, wxKillError
*rc
, int WXUNUSED(flags
))
287 if (pid
!= (long)wxGetProcessId())
291 *rc
= result
== 0 ? wxKILL_OK
: wxKILL_BAD_SIGNAL
;
295 wxLogDebug(wxT("wxKill can only send signals to the current process under MSDOS"));
297 *rc
= wxKILL_NO_PROCESS
;
303 bool wxShell(const wxString
& command
/*=wxEmptyString*/)
305 // FIXME: suspend/resume gui
306 int result
= system(command
);
310 wxLogSysError(_("can't execute '%s'"), command
.c_str());
316 long wxExecute(const wxString
& command
, int flags
, wxProcess
*process
,
317 const wxExecuteEnv
*env
)
319 // FIXME: shouldn't depend on wxCmdLineParser
320 wxArrayString
args(wxCmdLineParser::ConvertStringToArgs(command
));
321 size_t n
= args
.size();
322 wxChar
**argv
= new wxChar
*[n
+ 1];
326 argv
[n
] = const_cast<wxChar
*>((const char *)args
[n
].c_str());
328 long result
= wxExecute(argv
, flags
, process
);
336 // A wxFFileInputStream that deletes the file in it's destructor
338 class wxTempFileInStream
: public wxFFileInputStream
341 wxTempFileInStream(const wxString
& name
)
342 : wxFFileInputStream(name
, wxT("rt"))
345 virtual ~wxTempFileInStream()
348 wxRemoveFile(m_file
->GetName());
352 // A file descriptor that can be redirected to a file
354 class wxRedirectableFd
357 wxRedirectableFd(int fd
) : m_fd(fd
), m_dup(-1) { }
360 // Redirect the descriptor to a file, similar to ANSI C's freopen, but
361 // for low level descriptors. The desctructor un-redirects. If O_CREAT
362 // is in the flags then the destructor will delete the file unless it is
363 // given away with Release().
364 bool Reopen(const wxString
& name
, int flags
);
366 // un-redirect the redirected file descriptor, closing the file, and give
367 // away the filename without deleting it
371 // un-redirect the descriptor, closing the file
379 wxRedirectableFd::~wxRedirectableFd()
383 wxRemoveFile(m_name
);
386 bool wxRedirectableFd::Reopen(const wxString
& name
, int flags
)
388 wxASSERT(m_dup
== -1);
391 // save a duplicate so that the descriptor can be closed now and
397 int tmp
= open(name
.mb_str(), flags
);
406 result
= dup2(tmp
, m_fd
) == m_fd
;
413 wxLogSysError(_("error opening '%s'"), name
.c_str());
419 void wxRedirectableFd::Restore()
430 wxString
wxRedirectableFd::Release()
433 wxString name
= m_name
;
438 #endif // wxUSE_STREAMS
440 // wxExecute implementation
442 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*process
,
443 const wxString
* cwd
, const wxEnvVariableHashMap
* env
)
447 const int STDOUT
= 1;
448 const int STDERR
= 2;
450 wxRedirectableFd
in(STDIN
), out(STDOUT
), err(STDERR
);
451 bool redirect
= process
&& process
->IsRedirected() && (flags
& wxEXEC_SYNC
);
455 // close stdin/out/err and reopen them as files
456 if (!in
.Reopen(wxT("NUL"), O_RDONLY
| O_TEXT
))
459 if (!out
.Reopen(wxFileName::CreateTempFileName(wxT("out")),
460 O_CREAT
| O_WRONLY
| O_TRUNC
| O_TEXT
))
463 if (!err
.Reopen(wxFileName::CreateTempFileName(wxT("err")),
464 O_CREAT
| O_WRONLY
| O_TRUNC
| O_TEXT
))
467 #endif // wxUSE_STREAMS
469 // FIXME: suspend/resume gui
470 int mode
= flags
& wxEXEC_SYNC
? P_WAIT
: P_NOWAIT
;
471 int result
= spawnvp(mode
, argv
[0], argv
);
475 wxLogSysError(_("can't execute '%s'"), argv
[0]);
480 process
->SetPipeStreams(new wxTempFileInStream(out
.Release()),
481 new wxFFileOutputStream(wxT("NUL"), wxT("wt")),
482 new wxTempFileInStream(err
.Release()));
483 #endif // wxUSE_STREAMS
489 //----------------------------------------------------------------------------
491 //----------------------------------------------------------------------------
493 wxString
wxGetOsDescription()
495 wxString
osname(wxT("DOS"));
499 wxOperatingSystemId
wxGetOsVersion(int *verMaj
, int *verMin
)
509 bool wxIsPlatform64Bit()