summaryrefslogtreecommitdiff
path: root/win32/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/win32.c')
-rw-r--r--win32/win32.c756
1 files changed, 613 insertions, 143 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 6566f9a7f4..78955fc046 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -15,6 +15,8 @@
#define Win32_Winsock
#endif
#include <windows.h>
+#include <winnt.h>
+#include <io.h>
/* #include "config.h" */
@@ -95,11 +97,20 @@ static char * get_emd_part(SV **leading, char *trailing, ...);
static void remove_dead_process(long deceased);
static long find_pid(int pid);
static char * qualified_path(const char *cmd);
+#ifdef USE_ITHREADS
+static void remove_dead_pseudo_process(long child);
+static long find_pseudo_pid(int pid);
+#endif
+START_EXTERN_C
HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
char w32_module_name[MAX_PATH+1];
+END_EXTERN_C
+
static DWORD w32_platform = (DWORD)-1;
+#define ONE_K_BUFSIZE 1024
+
int
IsWin95(void)
{
@@ -165,12 +176,13 @@ get_emd_part(SV **prev_pathp, char *trailing_path, ...)
char *optr;
char *strip;
int oldsize, newsize;
+ STRLEN baselen;
va_start(ap, trailing_path);
strip = va_arg(ap, char *);
- sprintf(base, "%5.3f",
- (double)PERL_REVISION + ((double)PERL_VERSION / (double)1000));
+ sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
+ baselen = strlen(base);
if (!*w32_module_name) {
GetModuleFileName((HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
@@ -202,10 +214,10 @@ get_emd_part(SV **prev_pathp, char *trailing_path, ...)
/* avoid stripping component if there is no slash,
* or it doesn't match ... */
if (!ptr || stricmp(ptr+1, strip) != 0) {
- /* ... but not if component matches 5.00X* */
+ /* ... but not if component matches m|5\.$patchlevel.*| */
if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
- && strncmp(strip, base, 5) == 0
- && strncmp(ptr+1, base, 5) == 0))
+ && strncmp(strip, base, baselen) == 0
+ && strncmp(ptr+1, base, baselen) == 0))
{
*optr = '/';
ptr = optr;
@@ -272,12 +284,6 @@ win32_get_sitelib(char *pl)
* ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/site/$]/lib"; */
sprintf(pathstr, "site/%s/lib", pl);
(void)get_emd_part(&sv1, pathstr, ARCHNAME, "bin", pl, Nullch);
- if (!sv1 && strlen(pl) == 7) {
- /* pl may have been SUBVERSION-specific; try again without
- * SUBVERSION */
- sprintf(pathstr, "site/%.5s/lib", pl);
- (void)get_emd_part(&sv1, pathstr, ARCHNAME, "bin", pl, Nullch);
- }
/* $HKCU{'sitelib'} || $HKLM{'sitelib'} . ---; */
(void)get_regstr(sitelib, &sv2);
@@ -349,17 +355,17 @@ PerlIO *
Perl_my_popen(pTHX_ char *cmd, char *mode)
{
#ifdef FIXCMD
-#define fixcmd(x) { \
- char *pspace = strchr((x),' '); \
- if (pspace) { \
- char *p = (x); \
- while (p < pspace) { \
- if (*p == '/') \
- *p = '\\'; \
- p++; \
- } \
- } \
- }
+#define fixcmd(x) { \
+ char *pspace = strchr((x),' '); \
+ if (pspace) { \
+ char *p = (x); \
+ while (p < pspace) { \
+ if (*p == '/') \
+ *p = '\\'; \
+ p++; \
+ } \
+ } \
+ }
#else
#define fixcmd(x)
#endif
@@ -389,6 +395,17 @@ win32_os_id(void)
return (unsigned long)w32_platform;
}
+DllExport int
+win32_getpid(void)
+{
+#ifdef USE_ITHREADS
+ dTHXo;
+ if (w32_pseudo_id)
+ return -((int)w32_pseudo_id);
+#endif
+ return _getpid();
+}
+
/* Tokenize a string. Words are null-separated, and the list
* ends with a doubled null. Any character (except null and
* including backslash) may be escaped by preceding it with a
@@ -685,10 +702,10 @@ win32_opendir(char *filename)
/* do the FindFirstFile call */
if (USING_WIDE()) {
A2WHELPER(scanname, wbuffer, sizeof(wbuffer));
- fh = FindFirstFileW(wbuffer, &wFindData);
+ fh = FindFirstFileW(PerlDir_mapW(wbuffer), &wFindData);
}
else {
- fh = FindFirstFileA(scanname, &aFindData);
+ fh = FindFirstFileA(PerlDir_mapA(scanname), &aFindData);
}
dirp->handle = fh;
if (fh == INVALID_HANDLE_VALUE) {
@@ -911,8 +928,8 @@ static long
find_pid(int pid)
{
dTHXo;
- long child;
- for (child = 0 ; child < w32_num_children ; ++child) {
+ long child = w32_num_children;
+ while (--child >= 0) {
if (w32_child_pids[child] == pid)
return child;
}
@@ -933,18 +950,72 @@ remove_dead_process(long child)
}
}
+#ifdef USE_ITHREADS
+static long
+find_pseudo_pid(int pid)
+{
+ dTHXo;
+ long child = w32_num_pseudo_children;
+ while (--child >= 0) {
+ if (w32_pseudo_child_pids[child] == pid)
+ return child;
+ }
+ return -1;
+}
+
+static void
+remove_dead_pseudo_process(long child)
+{
+ if (child >= 0) {
+ dTHXo;
+ CloseHandle(w32_pseudo_child_handles[child]);
+ Copy(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
+ (w32_num_pseudo_children-child-1), HANDLE);
+ Copy(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
+ (w32_num_pseudo_children-child-1), DWORD);
+ w32_num_pseudo_children--;
+ }
+}
+#endif
+
DllExport int
win32_kill(int pid, int sig)
{
+ dTHXo;
HANDLE hProcess;
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
- if (hProcess && TerminateProcess(hProcess, sig))
- CloseHandle(hProcess);
- else {
- errno = EINVAL;
- return -1;
+#ifdef USE_ITHREADS
+ if (pid < 0) {
+ /* it is a pseudo-forked child */
+ long child = find_pseudo_pid(-pid);
+ if (child >= 0) {
+ hProcess = w32_pseudo_child_handles[child];
+ if (TerminateThread(hProcess, sig)) {
+ remove_dead_pseudo_process(child);
+ return 0;
+ }
+ }
}
- return 0;
+ else
+#endif
+ {
+ long child = find_pid(pid);
+ if (child >= 0) {
+ hProcess = w32_child_handles[child];
+ if (TerminateProcess(hProcess, sig)) {
+ remove_dead_process(child);
+ return 0;
+ }
+ }
+ else {
+ hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
+ if (hProcess && TerminateProcess(hProcess, sig)) {
+ CloseHandle(hProcess);
+ return 0;
+ }
+ }
+ }
+ errno = EINVAL;
+ return -1;
}
/*
@@ -995,9 +1066,11 @@ win32_stat(const char *path, struct stat *buffer)
/* This also gives us an opportunity to determine the number of links. */
if (USING_WIDE()) {
A2WHELPER(path, wbuffer, sizeof(wbuffer));
+ wcscpy(wbuffer, PerlDir_mapW(wbuffer));
handle = CreateFileW(wbuffer, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
}
else {
+ path = PerlDir_mapA(path);
handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
}
if (handle != INVALID_HANDLE_VALUE) {
@@ -1007,10 +1080,13 @@ win32_stat(const char *path, struct stat *buffer)
CloseHandle(handle);
}
- if (USING_WIDE())
+ /* wbuffer or path will be mapped correctly above */
+ if (USING_WIDE()) {
res = _wstat(wbuffer, (struct _stat *)buffer);
- else
+ }
+ else {
res = stat(path, buffer);
+ }
buffer->st_nlink = nlink;
if (res < 0) {
@@ -1213,9 +1289,9 @@ win32_putenv(const char *name)
New(1309,wCuritem,length,WCHAR);
A2WHELPER(name, wCuritem, length*sizeof(WCHAR));
wVal = wcschr(wCuritem, '=');
- if(wVal) {
+ if (wVal) {
*wVal++ = '\0';
- if(SetEnvironmentVariableW(wCuritem, *wVal ? wVal : NULL))
+ if (SetEnvironmentVariableW(wCuritem, *wVal ? wVal : NULL))
relval = 0;
}
Safefree(wCuritem);
@@ -1224,7 +1300,7 @@ win32_putenv(const char *name)
New(1309,curitem,strlen(name)+1,char);
strcpy(curitem, name);
val = strchr(curitem, '=');
- if(val) {
+ if (val) {
/* The sane way to deal with the environment.
* Has these advantages over putenv() & co.:
* * enables us to store a truly empty value in the
@@ -1240,7 +1316,7 @@ win32_putenv(const char *name)
* GSAR 97-06-07
*/
*val++ = '\0';
- if(SetEnvironmentVariableA(curitem, *val ? val : NULL))
+ if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
relval = 0;
}
Safefree(curitem);
@@ -1254,11 +1330,11 @@ win32_putenv(const char *name)
static long
filetime_to_clock(PFILETIME ft)
{
- __int64 qw = ft->dwHighDateTime;
- qw <<= 32;
- qw |= ft->dwLowDateTime;
- qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
- return (long) qw;
+ __int64 qw = ft->dwHighDateTime;
+ qw <<= 32;
+ qw |= ft->dwLowDateTime;
+ qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
+ return (long) qw;
}
DllExport int
@@ -1309,6 +1385,43 @@ filetime_from_time(PFILETIME pFileTime, time_t Time)
}
DllExport int
+win32_unlink(const char *filename)
+{
+ dTHXo;
+ int ret;
+ DWORD attrs;
+
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+
+ A2WHELPER(filename, wBuffer, sizeof(wBuffer));
+ wcscpy(wBuffer, PerlDir_mapW(wBuffer));
+ attrs = GetFileAttributesW(wBuffer);
+ if (attrs & FILE_ATTRIBUTE_READONLY) {
+ (void)SetFileAttributesW(wBuffer, attrs & ~FILE_ATTRIBUTE_READONLY);
+ ret = _wunlink(wBuffer);
+ if (ret == -1)
+ (void)SetFileAttributesW(wBuffer, attrs);
+ }
+ else
+ ret = _wunlink(wBuffer);
+ }
+ else {
+ filename = PerlDir_mapA(filename);
+ attrs = GetFileAttributesA(filename);
+ if (attrs & FILE_ATTRIBUTE_READONLY) {
+ (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
+ ret = unlink(filename);
+ if (ret == -1)
+ (void)SetFileAttributesA(filename, attrs);
+ }
+ else
+ ret = unlink(filename);
+ }
+ return ret;
+}
+
+DllExport int
win32_utime(const char *filename, struct utimbuf *times)
{
dTHXo;
@@ -1322,9 +1435,11 @@ win32_utime(const char *filename, struct utimbuf *times)
int rc;
if (USING_WIDE()) {
A2WHELPER(filename, wbuffer, sizeof(wbuffer));
+ wcscpy(wbuffer, PerlDir_mapW(wbuffer));
rc = _wutime(wbuffer, (struct _utimbuf*)times);
}
else {
+ filename = PerlDir_mapA(filename);
rc = utime(filename, times);
}
/* EACCES: path specifies directory or readonly file */
@@ -1458,8 +1573,27 @@ win32_waitpid(int pid, int *status, int flags)
{
dTHXo;
int retval = -1;
- if (pid == -1)
+ if (pid == -1) /* XXX threadid == 1 ? */
return win32_wait(status);
+#ifdef USE_ITHREADS
+ else if (pid < 0) {
+ long child = find_pseudo_pid(-pid);
+ if (child >= 0) {
+ HANDLE hThread = w32_pseudo_child_handles[child];
+ DWORD waitcode = WaitForSingleObject(hThread, INFINITE);
+ if (waitcode != WAIT_FAILED) {
+ if (GetExitCodeThread(hThread, &waitcode)) {
+ *status = (int)((waitcode & 0xff) << 8);
+ retval = (int)w32_pseudo_child_pids[child];
+ remove_dead_pseudo_process(child);
+ return retval;
+ }
+ }
+ else
+ errno = ECHILD;
+ }
+ }
+#endif
else {
long child = find_pid(pid);
if (child >= 0) {
@@ -1498,6 +1632,28 @@ win32_wait(int *status)
int i, retval;
DWORD exitcode, waitcode;
+#ifdef USE_ITHREADS
+ if (w32_num_pseudo_children) {
+ waitcode = WaitForMultipleObjects(w32_num_pseudo_children,
+ w32_pseudo_child_handles,
+ FALSE,
+ INFINITE);
+ if (waitcode != WAIT_FAILED) {
+ if (waitcode >= WAIT_ABANDONED_0
+ && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
+ i = waitcode - WAIT_ABANDONED_0;
+ else
+ i = waitcode - WAIT_OBJECT_0;
+ if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
+ *status = (int)((exitcode & 0xff) << 8);
+ retval = (int)w32_pseudo_child_pids[i];
+ remove_dead_pseudo_process(i);
+ return retval;
+ }
+ }
+ }
+#endif
+
if (!w32_num_children) {
errno = ECHILD;
return -1;
@@ -1903,9 +2059,9 @@ win32_fopen(const char *filename, const char *mode)
if (USING_WIDE()) {
A2WHELPER(mode, wMode, sizeof(wMode));
A2WHELPER(filename, wBuffer, sizeof(wBuffer));
- return _wfopen(wBuffer, wMode);
+ return _wfopen(PerlDir_mapW(wBuffer), wMode);
}
- return fopen(filename, mode);
+ return fopen(PerlDir_mapA(filename), mode);
}
#ifndef USE_SOCKETS_AS_HANDLES
@@ -1936,9 +2092,9 @@ win32_freopen(const char *path, const char *mode, FILE *stream)
if (USING_WIDE()) {
A2WHELPER(mode, wMode, sizeof(wMode));
A2WHELPER(path, wBuffer, sizeof(wBuffer));
- return _wfreopen(wBuffer, wMode, stream);
+ return _wfreopen(PerlDir_mapW(wBuffer), wMode, stream);
}
- return freopen(path, mode, stream);
+ return freopen(PerlDir_mapA(path), mode, stream);
}
DllExport int
@@ -2210,8 +2366,13 @@ Nt4CreateHardLinkW(
StreamId.dwStreamId = BACKUP_LINK;
StreamId.dwStreamAttributes = 0;
StreamId.dwStreamNameSize = 0;
+#if defined(__BORLANDC__) || defined(__MINGW32__)
+ StreamId.Size.u.HighPart = 0;
+ StreamId.Size.u.LowPart = dwLen;
+#else
StreamId.Size.HighPart = 0;
StreamId.Size.LowPart = dwLen;
+#endif
bSuccess = pfnBackupWrite(handle, (LPBYTE)&StreamId, dwSize, &dwWritten,
FALSE, FALSE, &lpContext);
@@ -2244,7 +2405,8 @@ win32_link(const char *oldname, const char *newname)
if ((A2WHELPER(oldname, wOldName, sizeof(wOldName))) &&
(A2WHELPER(newname, wNewName, sizeof(wNewName))) &&
- pfnCreateHardLinkW(wNewName, wOldName, NULL))
+ (wcscpy(wOldName, PerlDir_mapW(wOldName)),
+ pfnCreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
{
return 0;
}
@@ -2257,6 +2419,7 @@ win32_rename(const char *oname, const char *newname)
{
WCHAR wOldName[MAX_PATH];
WCHAR wNewName[MAX_PATH];
+ char szOldName[MAX_PATH];
BOOL bResult;
/* XXX despite what the documentation says about MoveFileEx(),
* it doesn't work under Windows95!
@@ -2266,11 +2429,13 @@ win32_rename(const char *oname, const char *newname)
if (USING_WIDE()) {
A2WHELPER(oname, wOldName, sizeof(wOldName));
A2WHELPER(newname, wNewName, sizeof(wNewName));
- bResult = MoveFileExW(wOldName,wNewName,
+ wcscpy(wOldName, PerlDir_mapW(wOldName));
+ bResult = MoveFileExW(wOldName,PerlDir_mapW(wNewName),
MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING);
}
else {
- bResult = MoveFileExA(oname,newname,
+ strcpy(szOldName, PerlDir_mapA(szOldName));
+ bResult = MoveFileExA(szOldName,PerlDir_mapA(newname),
MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING);
}
if (!bResult) {
@@ -2401,9 +2566,9 @@ win32_open(const char *path, int flag, ...)
if (USING_WIDE()) {
A2WHELPER(path, wBuffer, sizeof(wBuffer));
- return _wopen(wBuffer, flag, pmode);
+ return _wopen(PerlDir_mapW(wBuffer), flag, pmode);
}
- return open(path,flag,pmode);
+ return open(PerlDir_mapA(path), flag, pmode);
}
DllExport int
@@ -2430,10 +2595,240 @@ win32_dup2(int fd1,int fd2)
return dup2(fd1,fd2);
}
+#ifdef PERL_MSVCRT_READFIX
+
+#define LF 10 /* line feed */
+#define CR 13 /* carriage return */
+#define CTRLZ 26 /* ctrl-z means eof for text */
+#define FOPEN 0x01 /* file handle open */
+#define FEOFLAG 0x02 /* end of file has been encountered */
+#define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */
+#define FPIPE 0x08 /* file handle refers to a pipe */
+#define FAPPEND 0x20 /* file handle opened O_APPEND */
+#define FDEV 0x40 /* file handle refers to device */
+#define FTEXT 0x80 /* file handle is in text mode */
+#define MAX_DESCRIPTOR_COUNT (64*32) /* this is the maximun that MSVCRT can handle */
+
+/*
+ * Control structure for lowio file handles
+ */
+typedef struct {
+ long osfhnd; /* underlying OS file HANDLE */
+ char osfile; /* attributes of file (e.g., open in text mode?) */
+ char pipech; /* one char buffer for handles opened on pipes */
+ int lockinitflag;
+ CRITICAL_SECTION lock;
+} ioinfo;
+
+
+/*
+ * Array of arrays of control structures for lowio files.
+ */
+EXTERN_C _CRTIMP ioinfo* __pioinfo[];
+
+/*
+ * Definition of IOINFO_L2E, the log base 2 of the number of elements in each
+ * array of ioinfo structs.
+ */
+#define IOINFO_L2E 5
+
+/*
+ * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array
+ */
+#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
+
+/*
+ * Access macros for getting at an ioinfo struct and its fields from a
+ * file handle
+ */
+#define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)))
+#define _osfhnd(i) (_pioinfo(i)->osfhnd)
+#define _osfile(i) (_pioinfo(i)->osfile)
+#define _pipech(i) (_pioinfo(i)->pipech)
+
+int __cdecl _fixed_read(int fh, void *buf, unsigned cnt)
+{
+ int bytes_read; /* number of bytes read */
+ char *buffer; /* buffer to read to */
+ int os_read; /* bytes read on OS call */
+ char *p, *q; /* pointers into buffer */
+ char peekchr; /* peek-ahead character */
+ ULONG filepos; /* file position after seek */
+ ULONG dosretval; /* o.s. return value */
+
+ /* validate handle */
+ if (((unsigned)fh >= (unsigned)MAX_DESCRIPTOR_COUNT) ||
+ !(_osfile(fh) & FOPEN))
+ {
+ /* out of range -- return error */
+ errno = EBADF;
+ _doserrno = 0; /* not o.s. error */
+ return -1;
+ }
+
+ EnterCriticalSection(&(_pioinfo(fh)->lock)); /* lock file */
+
+ bytes_read = 0; /* nothing read yet */
+ buffer = (char*)buf;
+
+ if (cnt == 0 || (_osfile(fh) & FEOFLAG)) {
+ /* nothing to read or at EOF, so return 0 read */
+ goto functionexit;
+ }
+
+ if ((_osfile(fh) & (FPIPE|FDEV)) && _pipech(fh) != LF) {
+ /* a pipe/device and pipe lookahead non-empty: read the lookahead
+ * char */
+ *buffer++ = _pipech(fh);
+ ++bytes_read;
+ --cnt;
+ _pipech(fh) = LF; /* mark as empty */
+ }
+
+ /* read the data */
+
+ if (!ReadFile((HANDLE)_osfhnd(fh), buffer, cnt, (LPDWORD)&os_read, NULL))
+ {
+ /* ReadFile has reported an error. recognize two special cases.
+ *
+ * 1. map ERROR_ACCESS_DENIED to EBADF
+ *
+ * 2. just return 0 if ERROR_BROKEN_PIPE has occurred. it
+ * means the handle is a read-handle on a pipe for which
+ * all write-handles have been closed and all data has been
+ * read. */
+
+ if ((dosretval = GetLastError()) == ERROR_ACCESS_DENIED) {
+ /* wrong read/write mode should return EBADF, not EACCES */
+ errno = EBADF;
+ _doserrno = dosretval;
+ bytes_read = -1;
+ goto functionexit;
+ }
+ else if (dosretval == ERROR_BROKEN_PIPE) {
+ bytes_read = 0;
+ goto functionexit;
+ }
+ else {
+ bytes_read = -1;
+ goto functionexit;
+ }
+ }
+
+ bytes_read += os_read; /* update bytes read */
+
+ if (_osfile(fh) & FTEXT) {
+ /* now must translate CR-LFs to LFs in the buffer */
+
+ /* set CRLF flag to indicate LF at beginning of buffer */
+ /* if ((os_read != 0) && (*(char *)buf == LF)) */
+ /* _osfile(fh) |= FCRLF; */
+ /* else */
+ /* _osfile(fh) &= ~FCRLF; */
+
+ _osfile(fh) &= ~FCRLF;
+
+ /* convert chars in the buffer: p is src, q is dest */
+ p = q = (char*)buf;
+ while (p < (char *)buf + bytes_read) {
+ if (*p == CTRLZ) {
+ /* if fh is not a device, set ctrl-z flag */
+ if (!(_osfile(fh) & FDEV))
+ _osfile(fh) |= FEOFLAG;
+ break; /* stop translating */
+ }
+ else if (*p != CR)
+ *q++ = *p++;
+ else {
+ /* *p is CR, so must check next char for LF */
+ if (p < (char *)buf + bytes_read - 1) {
+ if (*(p+1) == LF) {
+ p += 2;
+ *q++ = LF; /* convert CR-LF to LF */
+ }
+ else
+ *q++ = *p++; /* store char normally */
+ }
+ else {
+ /* This is the hard part. We found a CR at end of
+ buffer. We must peek ahead to see if next char
+ is an LF. */
+ ++p;
+
+ dosretval = 0;
+ if (!ReadFile((HANDLE)_osfhnd(fh), &peekchr, 1,
+ (LPDWORD)&os_read, NULL))
+ dosretval = GetLastError();
+
+ if (dosretval != 0 || os_read == 0) {
+ /* couldn't read ahead, store CR */
+ *q++ = CR;
+ }
+ else {
+ /* peekchr now has the extra character -- we now
+ have several possibilities:
+ 1. disk file and char is not LF; just seek back
+ and copy CR
+ 2. disk file and char is LF; store LF, don't seek back
+ 3. pipe/device and char is LF; store LF.
+ 4. pipe/device and char isn't LF, store CR and
+ put char in pipe lookahead buffer. */
+ if (_osfile(fh) & (FDEV|FPIPE)) {
+ /* non-seekable device */
+ if (peekchr == LF)
+ *q++ = LF;
+ else {
+ *q++ = CR;
+ _pipech(fh) = peekchr;
+ }
+ }
+ else {
+ /* disk file */
+ if (peekchr == LF) {
+ /* nothing read yet; must make some
+ progress */
+ *q++ = LF;
+ /* turn on this flag for tell routine */
+ _osfile(fh) |= FCRLF;
+ }
+ else {
+ HANDLE osHandle; /* o.s. handle value */
+ /* seek back */
+ if ((osHandle = (HANDLE)_get_osfhandle(fh)) != (HANDLE)-1)
+ {
+ if ((filepos = SetFilePointer(osHandle, -1, NULL, FILE_CURRENT)) == -1)
+ dosretval = GetLastError();
+ }
+ if (peekchr != LF)
+ *q++ = CR;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* we now change bytes_read to reflect the true number of chars
+ in the buffer */
+ bytes_read = q - (char *)buf;
+ }
+
+functionexit:
+ LeaveCriticalSection(&(_pioinfo(fh)->lock)); /* unlock file */
+
+ return bytes_read;
+}
+
+#endif /* PERL_MSVCRT_READFIX */
+
DllExport int
win32_read(int fd, void *buf, unsigned int cnt)
{
+#ifdef PERL_MSVCRT_READFIX
+ return _fixed_read(fd, buf, cnt);
+#else
return read(fd, buf, cnt);
+#endif
}
DllExport int
@@ -2445,21 +2840,64 @@ win32_write(int fd, const void *buf, unsigned int cnt)
DllExport int
win32_mkdir(const char *dir, int mode)
{
- return mkdir(dir); /* just ignore mode */
+ dTHXo;
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+ A2WHELPER(dir, wBuffer, sizeof(wBuffer));
+ return _wmkdir(PerlDir_mapW(wBuffer));
+ }
+ return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
}
DllExport int
win32_rmdir(const char *dir)
{
- return rmdir(dir);
+ dTHXo;
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+ A2WHELPER(dir, wBuffer, sizeof(wBuffer));
+ return _wrmdir(PerlDir_mapW(wBuffer));
+ }
+ return rmdir(PerlDir_mapA(dir));
}
DllExport int
win32_chdir(const char *dir)
{
+ dTHXo;
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+ A2WHELPER(dir, wBuffer, sizeof(wBuffer));
+ return _wchdir(wBuffer);
+ }
return chdir(dir);
}
+DllExport int
+win32_access(const char *path, int mode)
+{
+ dTHXo;
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+ A2WHELPER(path, wBuffer, sizeof(wBuffer));
+ return _waccess(PerlDir_mapW(wBuffer), mode);
+ }
+ return access(PerlDir_mapA(path), mode);
+}
+
+DllExport int
+win32_chmod(const char *path, int mode)
+{
+ dTHXo;
+ if (USING_WIDE()) {
+ WCHAR wBuffer[MAX_PATH];
+ A2WHELPER(path, wBuffer, sizeof(wBuffer));
+ return _wchmod(PerlDir_mapW(wBuffer), mode);
+ }
+ return chmod(PerlDir_mapA(path), mode);
+}
+
+
static char *
create_command_line(const char* command, const char * const *args)
{
@@ -2592,12 +3030,28 @@ free_childenv(void* d)
char*
get_childdir(void)
{
- return NULL;
+ dTHXo;
+ char* ptr;
+ char szfilename[(MAX_PATH+1)*2];
+ if (USING_WIDE()) {
+ WCHAR wfilename[MAX_PATH+1];
+ GetCurrentDirectoryW(MAX_PATH+1, wfilename);
+ W2AHELPER(wfilename, szfilename, sizeof(szfilename));
+ }
+ else {
+ GetCurrentDirectoryA(MAX_PATH+1, szfilename);
+ }
+
+ New(0, ptr, strlen(szfilename)+1, char);
+ strcpy(ptr, szfilename);
+ return ptr;
}
void
free_childdir(char* d)
{
+ dTHXo;
+ Safefree(d);
}
@@ -2722,12 +3176,26 @@ RETVAL:
DllExport int
win32_execv(const char *cmdname, const char *const *argv)
{
+#ifdef USE_ITHREADS
+ dTHXo;
+ /* if this is a pseudo-forked child, we just want to spawn
+ * the new program, and return */
+ if (w32_pseudo_id)
+ return spawnv(P_WAIT, cmdname, (char *const *)argv);
+#endif
return execv(cmdname, (char *const *)argv);
}
DllExport int
win32_execvp(const char *cmdname, const char *const *argv)
{
+#ifdef USE_ITHREADS
+ dTHXo;
+ /* if this is a pseudo-forked child, we just want to spawn
+ * the new program, and return */
+ if (w32_pseudo_id)
+ return win32_spawnvp(P_WAIT, cmdname, (char *const *)argv);
+#endif
return execvp(cmdname, (char *const *)argv);
}
@@ -2927,44 +3395,14 @@ win32_dynaload(const char* filename)
if (USING_WIDE()) {
WCHAR wfilename[MAX_PATH];
A2WHELPER(filename, wfilename, sizeof(wfilename));
- hModule = LoadLibraryExW(wfilename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ hModule = LoadLibraryExW(PerlDir_mapW(wfilename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
else {
- hModule = LoadLibraryExA(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ hModule = LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
return hModule;
}
-DllExport int
-win32_add_host(char *nameId, void *data)
-{
- /*
- * This must be called before the script is parsed,
- * therefore no locking of threads is needed
- */
- dTHXo;
- struct host_link *link;
- New(1314, link, 1, struct host_link);
- link->host_data = data;
- link->nameId = nameId;
- link->next = w32_host_link;
- w32_host_link = link;
- return 1;
-}
-
-DllExport void *
-win32_get_host_data(char *nameId)
-{
- dTHXo;
- struct host_link *link = w32_host_link;
- while(link) {
- if(strEQ(link->nameId, nameId))
- return link->host_data;
- link = link->next;
- }
- return Nullch;
-}
-
/*
* Extras.
*/
@@ -2973,19 +3411,19 @@ static
XS(w32_GetCwd)
{
dXSARGS;
- SV *sv = sv_newmortal();
- /* Make one call with zero size - return value is required size */
- DWORD len = GetCurrentDirectory((DWORD)0,NULL);
- SvUPGRADE(sv,SVt_PV);
- SvGROW(sv,len);
- SvCUR(sv) = GetCurrentDirectory((DWORD) SvLEN(sv), SvPVX(sv));
+ /* Make the host for current directory */
+ char* ptr = PerlEnv_get_childdir();
/*
- * If result != 0
+ * If ptr != Nullch
* then it worked, set PV valid,
- * else leave it 'undef'
+ * else return 'undef'
*/
- EXTEND(SP,1);
- if (SvCUR(sv)) {
+ if (ptr) {
+ SV *sv = sv_newmortal();
+ sv_setpv(sv, ptr);
+ PerlEnv_free_childdir(ptr);
+
+ EXTEND(SP,1);
SvPOK_on(sv);
ST(0) = sv;
XSRETURN(1);
@@ -2999,7 +3437,7 @@ XS(w32_SetCwd)
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "usage: Win32::SetCurrentDirectory($cwd)");
- if (SetCurrentDirectory(SvPV_nolen(ST(0))))
+ if (!PerlDir_chdir(SvPV_nolen(ST(0))))
XSRETURN_YES;
XSRETURN_NO;
@@ -3122,7 +3560,7 @@ XS(w32_DomainName)
if (hNetApi32)
FreeLibrary(hNetApi32);
if (GetUserName(name,&size)) {
- char sid[1024];
+ char sid[ONE_K_BUFSIZE];
DWORD sidlen = sizeof(sid);
char dname[256];
DWORD dnamelen = sizeof(dname);
@@ -3161,19 +3599,34 @@ static
XS(w32_GetOSVersion)
{
dXSARGS;
- OSVERSIONINFO osver;
+ OSVERSIONINFOA osver;
- osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx(&osver)) {
+ if (USING_WIDE()) {
+ OSVERSIONINFOW osverw;
+ char szCSDVersion[sizeof(osverw.szCSDVersion)];
+ osverw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ if (!GetVersionExW(&osverw)) {
+ XSRETURN_EMPTY;
+ }
+ W2AHELPER(osverw.szCSDVersion, szCSDVersion, sizeof(szCSDVersion));
+ XPUSHs(newSVpvn(szCSDVersion, strlen(szCSDVersion)));
+ osver.dwMajorVersion = osverw.dwMajorVersion;
+ osver.dwMinorVersion = osverw.dwMinorVersion;
+ osver.dwBuildNumber = osverw.dwBuildNumber;
+ osver.dwPlatformId = osverw.dwPlatformId;
+ }
+ else {
+ osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+ if (!GetVersionExA(&osver)) {
+ XSRETURN_EMPTY;
+ }
XPUSHs(newSVpvn(osver.szCSDVersion, strlen(osver.szCSDVersion)));
- XPUSHs(newSViv(osver.dwMajorVersion));
- XPUSHs(newSViv(osver.dwMinorVersion));
- XPUSHs(newSViv(osver.dwBuildNumber));
- XPUSHs(newSViv(osver.dwPlatformId));
- PUTBACK;
- return;
}
- XSRETURN_EMPTY;
+ XPUSHs(newSViv(osver.dwMajorVersion));
+ XPUSHs(newSViv(osver.dwMinorVersion));
+ XPUSHs(newSViv(osver.dwBuildNumber));
+ XPUSHs(newSViv(osver.dwPlatformId));
+ PUTBACK;
}
static
@@ -3197,15 +3650,27 @@ XS(w32_FormatMessage)
{
dXSARGS;
DWORD source = 0;
- char msgbuf[1024];
+ char msgbuf[ONE_K_BUFSIZE];
if (items != 1)
Perl_croak(aTHX_ "usage: Win32::FormatMessage($errno)");
- if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
- &source, SvIV(ST(0)), 0,
- msgbuf, sizeof(msgbuf)-1, NULL))
- XSRETURN_PV(msgbuf);
+ if (USING_WIDE()) {
+ WCHAR wmsgbuf[ONE_K_BUFSIZE];
+ if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
+ &source, SvIV(ST(0)), 0,
+ wmsgbuf, ONE_K_BUFSIZE-1, NULL))
+ {
+ W2AHELPER(wmsgbuf, msgbuf, sizeof(msgbuf));
+ XSRETURN_PV(msgbuf);
+ }
+ }
+ else {
+ if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
+ &source, SvIV(ST(0)), 0,
+ msgbuf, sizeof(msgbuf)-1, NULL))
+ XSRETURN_PV(msgbuf);
+ }
XSRETURN_UNDEF;
}
@@ -3358,9 +3823,24 @@ static
XS(w32_CopyFile)
{
dXSARGS;
+ BOOL bResult;
if (items != 3)
Perl_croak(aTHX_ "usage: Win32::CopyFile($from, $to, $overwrite)");
- if (CopyFile(SvPV_nolen(ST(0)), SvPV_nolen(ST(1)), !SvTRUE(ST(2))))
+ if (USING_WIDE()) {
+ WCHAR wSourceFile[MAX_PATH];
+ WCHAR wDestFile[MAX_PATH];
+ A2WHELPER(SvPV_nolen(ST(0)), wSourceFile, sizeof(wSourceFile));
+ wcscpy(wSourceFile, PerlDir_mapW(wSourceFile));
+ A2WHELPER(SvPV_nolen(ST(1)), wDestFile, sizeof(wDestFile));
+ bResult = CopyFileW(wSourceFile, PerlDir_mapW(wDestFile), !SvTRUE(ST(2)));
+ }
+ else {
+ char szSourceFile[MAX_PATH];
+ strcpy(szSourceFile, PerlDir_mapA(SvPV_nolen(ST(0))));
+ bResult = CopyFileA(szSourceFile, PerlDir_mapA(SvPV_nolen(ST(1))), !SvTRUE(ST(2)));
+ }
+
+ if (bResult)
XSRETURN_YES;
XSRETURN_NO;
}
@@ -3377,6 +3857,12 @@ Perl_init_os_extras(void)
w32_fdpid = newAV(); /* XXX needs to be in Perl_win32_init()? */
New(1313, w32_children, 1, child_tab);
w32_num_children = 0;
+ w32_init_socktype = 0;
+#ifdef USE_ITHREADS
+ w32_pseudo_id = 0;
+ New(1313, w32_pseudo_children, 1, child_tab);
+ w32_num_pseudo_children = 0;
+#endif
/* these names are Activeware compatible */
newXS("Win32::GetCwd", w32_GetCwd, file);
@@ -3428,6 +3914,13 @@ Perl_win32_init(int *argcp, char ***argvp)
}
#ifdef USE_ITHREADS
+
+# ifdef PERL_OBJECT
+# undef Perl_sys_intern_dup
+# define Perl_sys_intern_dup CPerlObj::Perl_sys_intern_dup
+# define pPerl this
+# endif
+
void
Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
{
@@ -3435,34 +3928,11 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
dst->perlshell_vec = (char**)NULL;
dst->perlshell_items = 0;
dst->fdpid = newAV();
- New(1313, dst->children, 1, child_tab);
+ Newz(1313, dst->children, 1, child_tab);
+ Newz(1313, dst->pseudo_children, 1, child_tab);
+ dst->pseudo_id = 0;
dst->children->num = 0;
- dst->hostlist = src->hostlist; /* XXX */
dst->thr_intern.Winit_socktype = src->thr_intern.Winit_socktype;
}
#endif
-#ifdef USE_BINMODE_SCRIPTS
-
-void
-win32_strip_return(SV *sv)
-{
- char *s = SvPVX(sv);
- char *e = s+SvCUR(sv);
- char *d = s;
- while (s < e)
- {
- if (*s == '\r' && s[1] == '\n')
- {
- *d++ = '\n';
- s += 2;
- }
- else
- {
- *d++ = *s++;
- }
- }
- SvCUR_set(sv,d-SvPVX(sv));
-}
-
-#endif