/*
* doswin.cxx
*
* 16 bit implementation for MS-DOS and 16 bit Windows.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: doswin.cxx,v $
* Revision 1.10 1998/09/24 03:30:43 robertj
* Added open software license.
*
* Revision 1.9 1996/01/02 12:55:15 robertj
* Fixed copy of directories.
*
* Revision 1.8 1995/12/10 11:56:42 robertj
* Moved error code for specific WIN32 and MS-DOS versions.
*
* Revision 1.7 1995/08/24 12:41:10 robertj
* Changed PChannel so not a PContainer.
*
* Revision 1.6 1995/07/31 12:14:52 robertj
* Added semaphore class.
*
* Revision 1.5 1995/06/17 00:59:18 robertj
* Moved PPipeChannel::Execute from common dos/windows to individual files.
*
* Revision 1.4 1995/04/01 08:05:59 robertj
* Fixed yield for straight DOS and QUICKWIN systems.
*
* Revision 1.3 1995/03/25 02:09:11 robertj
* Added check for network login name.
*
// Revision 1.2 1995/03/14 13:31:36 robertj
// Implemented DOS pipe channel.
//
// Revision 1.1 1995/03/14 12:45:16 robertj
// Initial revision
//
*/
#include "ptlib.h"
#include <fcntl.h>
#include <sys/stat.h>
///////////////////////////////////////////////////////////////////////////////
// Directories
void PDirectory::Construct()
{
PString::operator=(CreateFullPath(*this, TRUE));
}
void PDirectory::CopyContents(const PDirectory & dir)
{
scanMask = dir.scanMask;
fileinfo = dir.fileinfo;
}
BOOL PDirectory::Open(int newScanMask)
{
scanMask = newScanMask;
if (_dos_findfirst(*this+"*.*", 0xff, &fileinfo) != 0)
return FALSE;
return Filtered() ? Next() : TRUE;
}
BOOL PDirectory::Next()
{
do {
if (_dos_findnext(&fileinfo) != 0)
return FALSE;
} while (Filtered());
return TRUE;
}
PCaselessString PDirectory::GetEntryName() const
{
return fileinfo.name;
}
BOOL PDirectory::IsSubDir() const
{
return (fileinfo.attrib&_A_SUBDIR) != 0;
}
void PDirectory::Close()
{
/* do nothing */
}
PCaselessString PDirectory::GetVolume() const
{
struct find_t finf;
if (_dos_findfirst(Left(3) + "*.*", _A_VOLID, &finf) != 0)
return PCaselessString();
return finf.name;
}
PString PDirectory::CreateFullPath(const PString & path, BOOL isDirectory)
{
PString curdir;
PAssert(getcwd(curdir.GetPointer(P_MAX_PATH),
P_MAX_PATH) != NULL, POperatingSystemError);
PString fullpath;
PINDEX offset;
if (path.GetLength() < 2 || path[1] != ':') {
fullpath = curdir(0,1);
offset = 0;
}
else {
fullpath = path(0,1).ToUpper();
offset = 2;
}
char slash = path[offset];
if (slash != '\\' && slash != '/') {
if (fullpath[0] == curdir[0])
fullpath += curdir(2, P_MAX_INDEX);
else if (_chdrive(fullpath[0]-'A'+1) == 0) {
PString otherdir;
PAssert(getcwd(otherdir.GetPointer(P_MAX_PATH),
P_MAX_PATH) != NULL, POperatingSystemError);
fullpath += otherdir(2, P_MAX_INDEX);
_chdrive(curdir[0]-'A'+1); // Put drive back
}
slash = fullpath[fullpath.GetLength()-1];
if (slash != '\\' && slash != '/')
fullpath += "\\";
}
fullpath += path(offset, P_MAX_INDEX);
slash = fullpath[fullpath.GetLength()-1];
if (isDirectory && slash != '\\' && slash != '/')
fullpath += "\\";
int pos;
while ((pos = fullpath.Find('/')) != P_MAX_INDEX)
fullpath[pos] = '\\';
while ((pos = fullpath.Find("\\.\\")) != P_MAX_INDEX)
fullpath = fullpath(0, pos) + fullpath(pos+3, P_MAX_INDEX);
while ((pos = fullpath.Find("\\..\\")) != P_MAX_INDEX)
fullpath = fullpath(0, fullpath.FindLast('\\', pos-1)) +
fullpath(pos+4, P_MAX_INDEX);
return fullpath.ToUpper();
}
///////////////////////////////////////////////////////////////////////////////
// PChannel
PString PChannel::GetErrorText() const
{
if (osError == 0)
return PString();
if (osError > 0 && osError < _sys_nerr && _sys_errlist[osError][0] != '\0')
return _sys_errlist[osError];
return psprintf("OS error %u", osError);
}
BOOL PChannel::ConvertOSError(int error)
{
if (error >= 0) {
lastError = NoError;
osError = 0;
return TRUE;
}
osError = errno;
switch (osError) {
case 0 :
lastError = NoError;
return TRUE;
case ENOENT :
lastError = NotFound;
break;
case EEXIST :
lastError = FileExists;
break;
case EACCES :
lastError = AccessDenied;
break;
case ENOMEM :
lastError = NoMemory;
break;
case ENOSPC :
lastError = DiskFull;
break;
case EINVAL :
lastError = BadParameter;
break;
case EBADF :
lastError = NotOpen;
break;
default :
lastError = Miscellaneous;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// PPipeChannel
void PPipeChannel::Construct(const PString & subProgram,
const char * const * arguments, OpenMode mode, BOOL searchPath)
{
hasRun = FALSE;
if (searchPath || subProgram.FindOneOf(":\\/") != P_MAX_INDEX)
subProgName = subProgram;
else
subProgName = ".\\" + subProgram;
if (arguments != NULL) {
while (*arguments != NULL) {
subProgName += " ";
if (strchr(*arguments, ' ') == NULL)
subProgName += *arguments;
else {
PString quote = '"';
subProgName += quote + *arguments + quote;
}
}
}
if (mode != ReadOnly) {
toChild = PFilePath("pw", NULL);
os_handle = _open(toChild, _O_WRONLY|_O_CREAT|_O_BINARY,S_IREAD|S_IWRITE);
if (!ConvertOSError(os_handle))
return;
subProgName += '<' + toChild;
}
if (mode != WriteOnly) {
fromChild = PFilePath("pw", NULL);
subProgName += '>' + fromChild;
}
if (mode == ReadOnly)
Execute();
}
PPipeChannel::~PPipeChannel()
{
Close();
}
BOOL PPipeChannel::Read(void * buffer, PINDEX amount)
{
if (!hasRun)
Execute();
flush();
lastReadCount = _read(GetHandle(), buffer, amount);
return ConvertOSError(lastReadCount) && lastReadCount > 0;
}
BOOL PPipeChannel::Write(const void * buffer, PINDEX amount)
{
if (hasRun) {
osError = EBADF;
lastError = NotOpen;
return FALSE;
}
flush();
lastWriteCount = _write(GetHandle(), buffer, amount);
return ConvertOSError(lastWriteCount) && lastWriteCount >= amount;
}
BOOL PPipeChannel::Close()
{
if (!hasRun)
Execute();
if (os_handle >= 0)
_close(os_handle);
PFile::Remove(toChild);
PFile::Remove(fromChild);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// PThread
PThread::~PThread()
{
Terminate();
_nfree(stackBase); // Give stack back to the near heap
}
void PThread::Block(BlockFunction isBlockFun, PObject * obj)
{
isBlocked = isBlockFun;
blocker = obj;
status = BlockedIO;
Yield();
}
///////////////////////////////////////////////////////////////////////////////
// PProcess
void PProcess::OperatingSystemYield()
{
#ifdef P_QUICKWIN
_wyield();
#endif
}
PString PProcess::GetUserName() const
{
/* ----- Microsoft LAN Manager, Windows for Workgroups, IBM LAN Server ----- */
#pragma pack(1)
static struct {
char _far *computername;
char _far *username;
char _far *langroup;
unsigned char ver_major;
unsigned char ver_minor;
char _far *logon_domain;
char _far *oth_domains;
char filler[32];
} NEAR wksta;
#pragma pack()
union REGS r;
r.x.ax = 0x5F44;
r.x.bx = 10;
r.x.cx = sizeof(wksta);
r.x.di = (WORD)&wksta;
struct SREGS sregs;
segread(&sregs);
sregs.es = sregs.ds;
int86x(0x21, &r, &r, &sregs);
if (r.x.ax == 0 || r.x.ax == 0x5F44) {
char name[32];
strcpy(name, wksta.username);
strlwr(name);
return name;
}
/* ----- Novell NetWare ----- Get Connection Information E3(16) */
#pragma pack(1)
static struct {
unsigned short len;
unsigned char func;
unsigned char number;
} NEAR gcireq;
static struct {
unsigned short len;
unsigned long objectID;
unsigned short objecttype;
char objectname[48];
unsigned char logintime[7];
unsigned char reserved[39];
} NEAR gcirep;
#pragma pack()
/* Load Get Connection Number function code. */
r.x.ax = 0xDC00;
int86x(0x21, &r, &r, &sregs);
if (r.h.al > 0 && r.h.al <= 100) {
/* If the connection number is in range 1-100,
* invoke Get Connection Information to get the user name. */
gcireq.len = sizeof(gcireq) - sizeof(gcireq.len);
gcireq.func = 0x16;
gcireq.number = r.h.al;
gcirep.len = sizeof(gcirep) - sizeof(gcirep.len);
r.h.ah = 0xE3;
r.x.si = (unsigned short) &gcireq;
r.x.di = (unsigned short) &gcirep;
int86x(0x21, &r, &r, &sregs);
if (r.h.al == 0) {
strlwr(gcirep.objectname);
return gcirep.objectname;
}
}
/* Give up and use environment variables */
const char * username = getenv("LOGNAME");
if (username == NULL) {
username = getenv("USER");
if (username == NULL)
username = "";
}
PAssert(*username != '\0', "Cannot determine user name, set LOGNAME.");
return username;
}
// End Of File ///////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1