/* perlhost.h
*
- * (c) 1999 Microsoft Corporation. All rights reserved.
+ * (c) 1999 Microsoft Corporation. All rights reserved.
* Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/
*
* You may distribute under the terms of either the GNU General Public
#include "vmem.h"
#include "vdir.h"
-#if !defined(PERL_OBJECT)
START_EXTERN_C
-#endif
extern char * g_win32_get_privlib(const char *pl);
extern char * g_win32_get_sitelib(const char *pl);
extern char * g_win32_get_vendorlib(const char *pl);
extern char * g_getlogin(void);
extern int do_spawn2(char *cmd, int exectype);
-#if !defined(PERL_OBJECT)
END_EXTERN_C
-#endif
-
-#ifdef PERL_OBJECT
-extern int g_do_aspawn(void *vreally, void **vmark, void **vsp);
-#define do_aspawn g_do_aspawn
-#endif
class CPerlHost
{
public:
+ /* Constructors */
CPerlHost(void);
CPerlHost(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared,
struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv,
void PerlDestroy(void);
/* IPerlMem */
+ /* Locks provided but should be unnecessary as this is private pool */
inline void* Malloc(size_t size) { return m_pVMem->Malloc(size); };
inline void* Realloc(void* ptr, size_t size) { return m_pVMem->Realloc(ptr, size); };
inline void Free(void* ptr) { m_pVMem->Free(ptr); };
inline int IsLocked(void) { return m_pVMem->IsLocked(); };
/* IPerlMemShared */
+ /* Locks used to serialize access to the pool */
+ inline void GetLockShared(void) { m_pVMemShared->GetLock(); };
+ inline void FreeLockShared(void) { m_pVMemShared->FreeLock(); };
+ inline int IsLockedShared(void) { return m_pVMemShared->IsLocked(); };
inline void* MallocShared(size_t size)
{
- return m_pVMemShared->Malloc(size);
+ void *result;
+ GetLockShared();
+ result = m_pVMemShared->Malloc(size);
+ FreeLockShared();
+ return result;
+ };
+ inline void* ReallocShared(void* ptr, size_t size)
+ {
+ void *result;
+ GetLockShared();
+ result = m_pVMemShared->Realloc(ptr, size);
+ FreeLockShared();
+ return result;
+ };
+ inline void FreeShared(void* ptr)
+ {
+ GetLockShared();
+ m_pVMemShared->Free(ptr);
+ FreeLockShared();
};
- inline void* ReallocShared(void* ptr, size_t size) { return m_pVMemShared->Realloc(ptr, size); };
- inline void FreeShared(void* ptr) { m_pVMemShared->Free(ptr); };
inline void* CallocShared(size_t num, size_t size)
{
size_t count = num*size;
ZeroMemory(lpVoid, count);
return lpVoid;
};
- inline void GetLockShared(void) { m_pVMem->GetLock(); };
- inline void FreeLockShared(void) { m_pVMem->FreeLock(); };
- inline int IsLockedShared(void) { return m_pVMem->IsLocked(); };
/* IPerlMemParse */
+ /* Assume something else is using locks to mangaging serialize
+ on a batch basis
+ */
+ inline void GetLockParse(void) { m_pVMemParse->GetLock(); };
+ inline void FreeLockParse(void) { m_pVMemParse->FreeLock(); };
+ inline int IsLockedParse(void) { return m_pVMemParse->IsLocked(); };
inline void* MallocParse(size_t size) { return m_pVMemParse->Malloc(size); };
inline void* ReallocParse(void* ptr, size_t size) { return m_pVMemParse->Realloc(ptr, size); };
inline void FreeParse(void* ptr) { m_pVMemParse->Free(ptr); };
ZeroMemory(lpVoid, count);
return lpVoid;
};
- inline void GetLockParse(void) { m_pVMem->GetLock(); };
- inline void FreeLockParse(void) { m_pVMem->FreeLock(); };
- inline int IsLockedParse(void) { return m_pVMem->IsLocked(); };
/* IPerlEnv */
char *Getenv(const char *varname);
DWORD m_dwEnvCount;
LPSTR* m_lppEnvList;
+ BOOL m_bTopLevel; // is this a toplevel host?
+ static long num_hosts;
+public:
+ inline int LastHost(void) { return num_hosts == 1L; };
};
+long CPerlHost::num_hosts = 0L;
+
#define STRUCT2PTR(x, y) (CPerlHost*)(((LPBYTE)x)-offsetof(CPerlHost, y))
win32_get_child_IO(ptr);
}
-struct IPerlEnv perlEnv =
+struct IPerlEnv perlEnv =
{
PerlEnvGetenv,
PerlEnvPutenv,
}
#endif
- /* it appears that the binmode is attached to the
+ /* it appears that the binmode is attached to the
* file descriptor so binmode files will be handled
* correctly
*/
return pfdup;
}
-struct IPerlStdIO perlStdIO =
+struct IPerlStdIO perlStdIO =
{
PerlStdIOStdin,
PerlStdIOStdout,
struct hostent*
PerlSockGethostent(struct IPerlSock* piPerl)
{
- dTHXo;
+ dTHX;
Perl_croak(aTHX_ "gethostent not implemented!\n");
return NULL;
}
int
PerlSockSocketpair(struct IPerlSock* piPerl, int domain, int type, int protocol, int* fds)
{
- dTHXo;
+ dTHX;
Perl_croak(aTHX_ "socketpair not implemented!\n");
return 0;
}
int
PerlProcKillpg(struct IPerlProc* piPerl, int pid, int sig)
{
- dTHXo;
+ dTHX;
Perl_croak(aTHX_ "killpg not implemented!\n");
return 0;
}
PerlIO*
PerlProcPopen(struct IPerlProc* piPerl, const char *command, const char *mode)
{
- dTHXo;
+ dTHX;
PERL_FLUSHALL_FOR_CHILD;
return win32_popen(command, mode);
}
+PerlIO*
+PerlProcPopenList(struct IPerlProc* piPerl, const char *mode, IV narg, SV **args)
+{
+ dTHX;
+ PERL_FLUSHALL_FOR_CHILD;
+ return win32_popenlist(mode, narg, args);
+}
+
int
PerlProcPclose(struct IPerlProc* piPerl, PerlIO *stream)
{
PerlInterpreter *my_perl = (PerlInterpreter*)arg;
GV *tmpgv;
int status;
-#ifdef PERL_OBJECT
- CPerlObj *pPerl = (CPerlObj*)my_perl;
-#endif
#ifdef PERL_SYNC_FORK
static long sync_fork_id = 0;
long id = ++sync_fork_id;
/* push a zero on the stack (we are the child) */
{
- djSP;
+ dSP;
dTARGET;
PUSHi(0);
PUTBACK;
int
PerlProcFork(struct IPerlProc* piPerl)
{
- dTHXo;
+ dTHX;
#ifdef USE_ITHREADS
DWORD id;
HANDLE handle;
return -1;
}
h = new CPerlHost(*(CPerlHost*)w32_internal_host);
- PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHXo, 1,
+ PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHX, 1,
h->m_pHostperlMem,
h->m_pHostperlMemShared,
h->m_pHostperlMemParse,
new_perl->Isys_intern.internal_host = h;
# ifdef PERL_SYNC_FORK
id = win32_start_child((LPVOID)new_perl);
- PERL_SET_THX(aTHXo);
+ PERL_SET_THX(aTHX);
# else
# ifdef USE_RTL_THREAD_API
handle = (HANDLE)_beginthreadex((void*)NULL, 0, win32_start_child,
handle = CreateThread(NULL, 0, win32_start_child,
(LPVOID)new_perl, 0, &id);
# endif
- PERL_SET_THX(aTHXo); /* XXX perl_clone*() set TLS */
+ PERL_SET_THX(aTHX); /* XXX perl_clone*() set TLS */
if (!handle) {
errno = EAGAIN;
return -1;
return do_aspawn(vreally, vmark, vsp);
}
+int
+PerlProcLastHost(struct IPerlProc* piPerl)
+{
+ dTHX;
+ CPerlHost *h = (CPerlHost*)w32_internal_host;
+ return h->LastHost();
+}
+
struct IPerlProc perlProc =
{
PerlProcAbort,
PerlProcSpawn,
PerlProcSpawnvp,
PerlProcASpawn,
+ PerlProcLastHost,
+ PerlProcPopenList
};
CPerlHost::CPerlHost(void)
{
+ /* Construct a host from scratch */
+ InterlockedIncrement(&num_hosts);
m_pvDir = new VDir();
m_pVMem = new VMem();
m_pVMemShared = new VMem();
m_dwEnvCount = 0;
m_lppEnvList = NULL;
+ m_bTopLevel = TRUE;
CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem));
CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared));
struct IPerlDir** ppDir, struct IPerlSock** ppSock,
struct IPerlProc** ppProc)
{
+ InterlockedIncrement(&num_hosts);
m_pvDir = new VDir(0);
m_pVMem = new VMem();
m_pVMemShared = new VMem();
m_dwEnvCount = 0;
m_lppEnvList = NULL;
+ m_bTopLevel = FALSE;
CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem));
CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared));
CPerlHost::CPerlHost(CPerlHost& host)
{
+ /* Construct a host from another host */
+ InterlockedIncrement(&num_hosts);
m_pVMem = new VMem();
m_pVMemShared = host.GetMemShared();
m_pVMemParse = host.GetMemParse();
m_dwEnvCount = 0;
m_lppEnvList = NULL;
+ m_bTopLevel = FALSE;
/* duplicate environment info */
LPSTR lpPtr;
CPerlHost::~CPerlHost(void)
{
// Reset();
+ InterlockedDecrement(&num_hosts);
delete m_pvDir;
m_pVMemParse->Release();
m_pVMemShared->Release();
if(c1 != c2) {
if(c1 < c2)
return -1; // string 1 < string 2
-
+
return 1; // string 1 > string 2
}
}
void
CPerlHost::Add(LPCSTR lpStr)
{
- dTHXo;
+ dTHX;
char szBuffer[1024];
LPSTR *lpPtr;
int index, length = strlen(lpStr)+1;
void
CPerlHost::FreeLocalEnvironmentStrings(LPSTR lpStr)
{
- dTHXo;
+ dTHX;
Safefree(lpStr);
}
char*
CPerlHost::GetChildDir(void)
{
- dTHXo;
+ dTHX;
int length;
char* ptr;
New(0, ptr, MAX_PATH+1, char);
if(ptr) {
m_pvDir->GetCurrentDirectoryA(MAX_PATH+1, ptr);
- length = strlen(ptr)-1;
- if(length > 0) {
- if((ptr[length] == '\\') || (ptr[length] == '/'))
- ptr[length] = 0;
+ length = strlen(ptr);
+ if (length > 3) {
+ if ((ptr[length-1] == '\\') || (ptr[length-1] == '/'))
+ ptr[length-1] = 0;
}
}
return ptr;
void
CPerlHost::FreeChildDir(char* pStr)
{
- dTHXo;
+ dTHX;
Safefree(pStr);
}
LPSTR
CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
{
- dTHXo;
+ dTHX;
LPSTR lpStr, lpPtr, lpEnvPtr, lpTmp, lpLocalEnv, lpAllocPtr;
DWORD dwSize, dwEnvIndex;
int nLength, compVal;
while(lpLocalEnv) {
// still have environment overrides to add
- // so copy the strings into place
- strcpy(lpStr, lpLocalEnv);
- nLength = strlen(lpLocalEnv) + 1;
- lpStr += nLength;
- lpEnvPtr += nLength;
+ // so copy the strings into place if not an override
+ char *ptr = strchr(lpLocalEnv, '=');
+ if(ptr && ptr[1]) {
+ strcpy(lpStr, lpLocalEnv);
+ lpStr += strlen(lpLocalEnv) + 1;
+ }
lpLocalEnv = GetIndex(dwEnvIndex);
}
void
CPerlHost::Reset(void)
{
- dTHXo;
+ dTHX;
if(m_lppEnvList != NULL) {
for(DWORD index = 0; index < m_dwEnvCount; ++index) {
Safefree(m_lppEnvList[index]);
void
CPerlHost::Clearenv(void)
{
+ dTHX;
char ch;
LPSTR lpPtr, lpStr, lpEnvPtr;
- if(m_lppEnvList != NULL) {
+ if (m_lppEnvList != NULL) {
/* set every entry to an empty string */
for(DWORD index = 0; index < m_dwEnvCount; ++index) {
char* ptr = strchr(m_lppEnvList[index], '=');
ch = *++lpPtr;
*lpPtr = 0;
Add(lpStr);
+ if (m_bTopLevel)
+ (void)win32_putenv(lpStr);
*lpPtr = ch;
}
lpStr += strlen(lpStr) + 1;
char*
CPerlHost::Getenv(const char *varname)
{
- char* pEnv = Find(varname);
- if(pEnv == NULL) {
- pEnv = win32_getenv(varname);
+ dTHX;
+ if (!m_bTopLevel) {
+ char *pEnv = Find(varname);
+ if (pEnv && *pEnv)
+ return pEnv;
}
- else {
- if(!*pEnv)
- pEnv = 0;
- }
-
- return pEnv;
+ return win32_getenv(varname);
}
int
CPerlHost::Putenv(const char *envstring)
{
+ dTHX;
Add(envstring);
+ if (m_bTopLevel)
+ return win32_putenv(envstring);
+
return 0;
}
int
CPerlHost::Chdir(const char *dirname)
{
- dTHXo;
+ dTHX;
int ret;
+ if (!dirname) {
+ errno = ENOENT;
+ return -1;
+ }
if (USING_WIDE()) {
WCHAR wBuffer[MAX_PATH];
A2WHELPER(dirname, wBuffer, sizeof(wBuffer));