]> git.saurik.com Git - wxWidgets.git/blame - src/msdos/utilsdos.cpp
Script updates
[wxWidgets.git] / src / msdos / utilsdos.cpp
CommitLineData
81d9e625 1/////////////////////////////////////////////////////////////////////////////
df91131c 2// Name: src/msdos/utils.cpp
81d9e625 3// Purpose: DOS implementations of utility functions
a3c0d768 4// Author: Vaclav Slavik, M.J.Wetherell
81d9e625
MW
5// Id: $Id$
6// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
a3c0d768 7// (c) 2005 M.J.Wetherell
81d9e625
MW
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#include "wx/utils.h"
df91131c
WS
19
20#ifndef WX_PRECOMP
21 #include "wx/string.h"
88a7a4e1 22 #include "wx/intl.h"
e4db172a 23 #include "wx/log.h"
670f9935 24 #include "wx/app.h"
df91131c 25#endif
81d9e625 26
81d9e625 27#include "wx/apptrait.h"
81d9e625 28#include "wx/process.h"
a3c0d768 29#include "wx/confbase.h" // for wxExpandEnvVars()
a3c0d768
MW
30#include "wx/cmdline.h"
31#include "wx/filename.h"
32#include "wx/wfstream.h"
81d9e625
MW
33
34#include <stdarg.h>
35#include <string.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <unistd.h>
a3c0d768 39#include <signal.h>
81d9e625 40#include <time.h>
a3c0d768
MW
41#include <dos.h>
42#include <process.h>
81d9e625
MW
43
44//----------------------------------------------------------------------------
a3c0d768 45// Sleep
81d9e625
MW
46//----------------------------------------------------------------------------
47
48void wxSleep(int nSecs)
49{
50 wxMilliSleep(1000 * nSecs);
51}
52
53void wxMilliSleep(unsigned long milliseconds)
54{
55#if HAVE_USLEEP || defined __DJGPP__
56 usleep(milliseconds * 1000);
57#elif defined __WATCOMC__
58 delay(milliseconds);
59#else
60 clock_t start = clock();
61 while ((clock() - start) * 1000 / CLOCKS_PER_SEC < (clock_t)milliseconds)
a3c0d768
MW
62 {
63 // yield if in a multitasking environment
64 // "Release Current Virtual Machine's Time Slice" in DPMI 1.0
65 REGS r;
66 memset(&r, 0, sizeof(r));
67 r.x.ax = 0x1680;
68 int386(0x2f, &r, &r);
69 }
81d9e625
MW
70#endif
71}
72
73void wxMicroSleep(unsigned long microseconds)
74{
75#if HAVE_USLEEP || defined __DJGPP__
76 usleep(microseconds);
77#else
78 wxMilliSleep(microseconds/1000);
79#endif
80}
81
a3c0d768
MW
82//----------------------------------------------------------------------------
83// Get/Set environment variables
84//----------------------------------------------------------------------------
81d9e625
MW
85
86bool wxGetEnv(const wxString& var, wxString *value)
87{
88 // wxGetenv is defined as getenv()
89 wxChar *p = wxGetenv(var);
90 if ( !p )
df91131c 91 return false;
81d9e625
MW
92
93 if ( value )
94 *value = p;
95
df91131c 96 return true;
81d9e625
MW
97}
98
99bool wxSetEnv(const wxString& variable, const wxChar *value)
100{
101 wxString s = variable;
102 if ( value )
103 s << _T('=') << value;
104
105 // transform to ANSI
106 const char *p = s.mb_str();
107
108 // the string will be free()d by libc
109 char *buf = (char *)malloc(strlen(p) + 1);
110 strcpy(buf, p);
111
112 return putenv(buf) == 0;
113}
114
a3c0d768
MW
115//----------------------------------------------------------------------------
116// Hostname, username, home directory
117//----------------------------------------------------------------------------
118
119// Based on the MSW implementation
120//
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 ".".
124//
81d9e625
MW
125const wxChar* wxGetHomeDir(wxString *home)
126{
a3c0d768 127 wxString& strDir = *home;
81d9e625 128
a3c0d768
MW
129 strDir.clear();
130
131 // try HOMEDRIVE/PATH
132 const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
133 if ( szHome != NULL )
134 strDir << szHome;
135 szHome = wxGetenv(wxT("HOMEPATH"));
136
137 if ( szHome != NULL )
138 {
139 strDir << szHome;
140
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 )
148 strDir.clear();
149 }
150
151 if ( strDir.empty() )
152 {
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"));
156
157 if ( szHome != NULL )
158 strDir = szHome;
159 }
160
161 if ( strDir.empty() )
162 {
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"));
166
167 if ( szHome != NULL )
168 {
169 strDir = szHome;
170 // when msys sets %HOME% it uses '/' (cygwin uses '\\')
171 strDir.Replace(_T("/"), _T("\\"));
172 }
173 }
174
175 if ( !strDir.empty() )
176 {
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);
180 }
181 else // fall back to the program directory
182 {
183 if ( wxTheApp )
184 {
185 wxString prog(wxTheApp->argv[0]);
186#ifdef __DJGPP__
187 // djgpp startup code switches the slashes around, so restore them
188 prog.Replace(_T("/"), _T("\\"));
189#endif
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);
193 }
194 if ( strDir.empty() )
195 {
196 strDir = _T(".");
197 }
198 }
199
200 return strDir.c_str();
81d9e625
MW
201}
202
a3c0d768 203wxChar *wxGetUserHome(const wxString& user)
81d9e625 204{
a3c0d768
MW
205 static wxString home;
206
207 if (user.empty() || user == wxGetUserId())
208 return wx_const_cast(wxChar*, wxGetHomeDir(&home));
209 else
210 return _T("");
81d9e625
MW
211}
212
a3c0d768
MW
213// returns %UserName%, $USER or just "user"
214//
215bool wxGetUserId(wxChar *buf, int n)
81d9e625 216{
a3c0d768
MW
217 const wxChar *user = wxGetenv(_T("UserName"));
218
219 if (!user)
220 user = wxGetenv(_T("USER"));
221
222 if (!user)
223 user = _T("user");
224
225 wxStrncpy(buf, user, n);
226 return true;
81d9e625
MW
227}
228
a3c0d768 229bool wxGetUserName(wxChar *buf, int n)
81d9e625 230{
a3c0d768 231 return wxGetUserId(buf, n);
81d9e625
MW
232}
233
a3c0d768
MW
234// returns %ComputerName%, or $HOSTNAME, or "host"
235//
236bool wxGetHostName(wxChar *buf, int n)
81d9e625 237{
a3c0d768 238 const wxChar *host = wxGetenv(_T("ComputerName"));
df91131c 239
a3c0d768
MW
240 if (!host)
241 host = wxGetenv(_T("HOSTNAME"));
242
243 if (!host)
244 host = _T("host");
245
246 wxStrncpy(buf, host, n);
247 return true;
81d9e625
MW
248}
249
a3c0d768
MW
250// adds %UserDnsDomain% to wxGetHostName()
251//
252bool wxGetFullHostName(wxChar *buf, int n)
253{
254 wxGetHostName(buf, n);
255
256 const wxChar *domain = wxGetenv(_T("UserDnsDomain"));
257
258 if (domain)
259 wxStrncat(wxStrncat(buf, _T("."), n), domain, n);
260
261 return true;
262}
263
264//----------------------------------------------------------------------------
265// Processes
266//----------------------------------------------------------------------------
267
268unsigned long wxGetProcessId()
81d9e625 269{
a3c0d768 270 return (unsigned long)getpid();
81d9e625
MW
271}
272
a3c0d768 273int wxKill(long pid, wxSignal sig, wxKillError *rc, int WXUNUSED(flags))
81d9e625 274{
a3c0d768
MW
275 int result = -1;
276
277 if (pid != (long)wxGetProcessId())
278 {
279 result = raise(sig);
280 if (rc)
281 *rc = result == 0 ? wxKILL_OK : wxKILL_BAD_SIGNAL;
282 }
283 else
284 {
285 wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
286 if (rc)
287 *rc = wxKILL_NO_PROCESS;
288 }
289
290 return result;
81d9e625
MW
291}
292
a3c0d768 293bool wxShell(const wxString& command /*=wxEmptyString*/)
81d9e625 294{
a3c0d768
MW
295 // FIXME: suspend/resume gui
296 int result = system(command);
297
298 if (result == -1)
299 wxLogSysError(_("can't execute '%s'"), command.c_str());
300
301 return result == 0;
81d9e625
MW
302}
303
a3c0d768 304long wxExecute(const wxString& command, int flags, wxProcess *process)
81d9e625 305{
a3c0d768
MW
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];
310
311 argv[n] = NULL;
312 while (n-- > 0)
313 argv[n] = wx_const_cast(wxChar*, args[n].c_str());
314
315 long result = wxExecute(argv, flags, process);
316
317 delete [] argv;
318 return result;
81d9e625
MW
319}
320
a3c0d768
MW
321#if wxUSE_STREAMS
322
323// A wxFFileInputStream that deletes the file in it's destructor
df91131c 324//
a3c0d768
MW
325class wxTempFileInStream : public wxFFileInputStream
326{
327public:
328 wxTempFileInStream(const wxString& name)
329 : wxFFileInputStream(name, _T("rt"))
330 { }
331
332 ~wxTempFileInStream()
333 {
334 m_file->Close();
335 wxRemoveFile(m_file->GetName());
336 }
337};
338
339// A file descriptor that can be redirected to a file
340//
341class wxRedirectableFd
342{
343public:
344 wxRedirectableFd(int fd) : m_fd(fd), m_dup(-1) { }
345 ~wxRedirectableFd();
346
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);
352
353 // un-redirect the redirected file descriptor, closing the file, and give
354 // away the filename without deleting it
355 wxString Release();
356
357private:
358 // un-redirect the descriptor, closing the file
359 void Restore();
360
361 int m_fd;
362 int m_dup;
363 wxString m_name;
364};
365
366wxRedirectableFd::~wxRedirectableFd()
367{
368 Restore();
369 if (!m_name.empty())
370 wxRemoveFile(m_name);
371}
372
373bool wxRedirectableFd::Reopen(const wxString& name, int flags)
374{
375 wxASSERT(m_dup == -1);
376 bool result = false;
377
378 // save a duplicate so that the descriptor can be closed now and
379 // restored later
380 m_dup = dup(m_fd);
381
382 if (m_dup != -1)
383 {
384 int tmp = open(name.mb_str(), flags);
385
386 if (tmp != -1)
387 {
388 close(m_fd);
389
390 if (flags & O_CREAT)
391 m_name = name;
392
393 result = dup2(tmp, m_fd) == m_fd;
394 close(tmp);
395 }
396 }
397
398 if (!result)
399 wxLogSysError(_("error opening '%s'"), name.c_str());
400
401 return result;
402}
403
404void wxRedirectableFd::Restore()
405{
406 if (m_dup != -1)
407 {
408 close(m_fd);
409 dup2(m_dup, m_fd);
410 close(m_dup);
411 m_dup = -1;
412 }
413}
414
415wxString wxRedirectableFd::Release()
416{
417 Restore();
418 wxString name = m_name;
419 m_name.clear();
420 return name;
421}
422
423#endif // wxUSE_STREAMS
424
425// wxExecute implementation
426//
427long wxExecute(wxChar **argv, int flags, wxProcess *process)
428{
429#if wxUSE_STREAMS
430 const int STDIN = 0;
431 const int STDOUT = 1;
432 const int STDERR = 2;
433
434 wxRedirectableFd in(STDIN), out(STDOUT), err(STDERR);
435 bool redirect = process && process->IsRedirected() && (flags & wxEXEC_SYNC);
436
437 if (redirect)
438 {
439 // close stdin/out/err and reopen them as files
440 if (!in.Reopen(_T("NUL"), O_RDONLY | O_TEXT))
441 return -1;
442
443 if (!out.Reopen(wxFileName::CreateTempFileName(_T("out")),
444 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
445 return -1;
446
447 if (!err.Reopen(wxFileName::CreateTempFileName(_T("err")),
448 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
449 return -1;
450 }
451#endif // wxUSE_STREAMS
452
453 // FIXME: suspend/resume gui
454 int mode = flags & wxEXEC_SYNC ? P_WAIT : P_NOWAIT;
455 int result = spawnvp(mode, argv[0], argv);
456
457 if (result == -1)
458 wxLogSysError(_("can't execute '%s'"), argv[0]);
459
460#if wxUSE_STREAMS
461 if (redirect)
462 process->SetPipeStreams(new wxTempFileInStream(out.Release()),
463 new wxFFileOutputStream(_T("NUL"), _T("wt")),
464 new wxTempFileInStream(err.Release()));
465#endif // wxUSE_STREAMS
466
467 return result;
468}
469
470//----------------------------------------------------------------------------
471// Traits for console apps
472//----------------------------------------------------------------------------
473
81d9e625
MW
474wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
475{
476 static wxToolkitInfo info;
a3c0d768
MW
477 info.versionMajor = _osmajor;
478 info.versionMinor = _osminor;
81d9e625
MW
479 info.name = _T("wxBase");
480 info.os = wxDOS;
481 return info;
482}
b5d09a5f
MW
483
484//----------------------------------------------------------------------------
485// OS Description
486//----------------------------------------------------------------------------
487
488wxString wxGetOsDescription()
489{
490 wxString osname(_T("DOS"));
491 return osname;
492}