diff options
author | Gurusamy Sarathy <gsar@cpan.org> | 1998-01-30 09:23:36 +0000 |
---|---|---|
committer | Gurusamy Sarathy <gsar@cpan.org> | 1998-01-30 09:23:36 +0000 |
commit | 76e3520e1f6b7df33cd381a2cf4f1fce3d69c8a4 (patch) | |
tree | 1d4e5f5653fd9def6bd71cc0cb536400223f4d3e /win32 | |
parent | 6ad3d225cec2692b410002582f5558652eea32c8 (diff) | |
download | perl-76e3520e1f6b7df33cd381a2cf4f1fce3d69c8a4.tar.gz |
[asperl] added AS patch#2
p4raw-id: //depot/asperl@443
Diffstat (limited to 'win32')
-rw-r--r-- | win32/Makefile | 10 | ||||
-rw-r--r-- | win32/config_H.bc | 2 | ||||
-rw-r--r-- | win32/config_H.vc | 40 | ||||
-rw-r--r-- | win32/dl_win32.xs | 10 | ||||
-rw-r--r-- | win32/include/sys/socket.h | 2 | ||||
-rw-r--r-- | win32/ipdir.c | 186 | ||||
-rw-r--r-- | win32/ipenv.c | 62 | ||||
-rw-r--r-- | win32/iplio.c | 307 | ||||
-rw-r--r-- | win32/ipmem.c | 39 | ||||
-rw-r--r-- | win32/ipproc.c | 620 | ||||
-rw-r--r-- | win32/ipsock.c | 681 | ||||
-rw-r--r-- | win32/ipstdio.c | 447 | ||||
-rw-r--r-- | win32/ipstdiowin.h | 22 | ||||
-rw-r--r-- | win32/makedef.pl | 2 | ||||
-rw-r--r-- | win32/perlobj.def | 4 | ||||
-rw-r--r-- | win32/runperl.c | 172 | ||||
-rw-r--r-- | win32/win32iop.h | 9 |
17 files changed, 2603 insertions, 12 deletions
diff --git a/win32/Makefile b/win32/Makefile index 12410e21fb..b5413bdf46 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -21,6 +21,10 @@ BUILDOPT=-DUSE_THREADS #CCTYPE=MSVC20 # +# uncomment next line if you want to use the perl object +#OBJECT=-DPERL_OBJECT + +# # uncomment next line if you want debug version of perl (big,slow) #CFG=Debug @@ -70,7 +74,7 @@ RUNTIME = -MD !ENDIF INCLUDES = -I.\include -I. -I.. #PCHFLAGS = -Fp"$(INTDIR)/modules.pch" -YX -DEFINES = -DWIN32 -D_CONSOLE $(BUILDOPT) $(CRYPT_FLAG) +DEFINES = -DWIN32 -D_CONSOLE $(BUILDOPT) $(CRYPT_FLAG) $(OBJECT) LOCDEFS = -DPERLDLL -DPERL_CORE SUBSYS = console @@ -104,7 +108,11 @@ LIBFILES = $(CRYPT_LIB) oldnames.lib kernel32.lib user32.lib gdi32.lib \ oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \ version.lib odbc32.lib odbccp32.lib +!IF "$(OBJECT)" == "-DPERL_OBJECT" +CFLAGS = -nologo -Gf -W3 -TP $(INCLUDES) $(DEFINES) $(LOCDEFS) $(PCHFLAGS) $(OPTIMIZE) +!ELSE CFLAGS = -nologo -Gf -W3 $(INCLUDES) $(DEFINES) $(LOCDEFS) $(PCHFLAGS) $(OPTIMIZE) +!ENDIF LINK_FLAGS = -nologo $(LINK_DBG) -machine:$(PROCESSOR_ARCHITECTURE) OBJOUT_FLAG = -Fo EXEOUT_FLAG = -Fe diff --git a/win32/config_H.bc b/win32/config_H.bc index f587e019c8..6cdae5d536 100644 --- a/win32/config_H.bc +++ b/win32/config_H.bc @@ -1686,7 +1686,9 @@ /* MYMALLOC: * This symbol, if defined, indicates that we're using our own malloc. */ +#ifndef PERL_OBJECT #define MYMALLOC /**/ +#endif /* OLDARCHLIB: * This variable, if defined, holds the name of the directory in diff --git a/win32/config_H.vc b/win32/config_H.vc index 42578bad8e..4124b6188f 100644 --- a/win32/config_H.vc +++ b/win32/config_H.vc @@ -18,6 +18,14 @@ #ifndef _config_h_ #define _config_h_ +#ifdef PERL_OBJECT +#ifdef PERL_GLOBAL_STRUCT +#error PERL_GLOBAL_STRUCT cannot be defined with PERL_OBJECT +#endif +#define win32_perllib_path PerlEnv_lib_path +#endif + + /* MEM_ALIGNBYTES: * This symbol contains the number of bytes required to align a * double. Usual values are 2, 4 and 8. @@ -57,8 +65,8 @@ * This symbol is the filename expanded version of the BIN symbol, for * programs that do not want to deal with that at run-time. */ -#define BIN "c:\\perl\\bin" /**/ -#define BIN_EXP "c:\\perl\\bin" /**/ +#define BIN "c:\\perl5004.5x\\bin" /**/ +#define BIN_EXP "c:\\perl5004.5x\\bin" /**/ /* CAT2: * This macro catenates 2 tokens together. @@ -548,6 +556,12 @@ */ /*#define HAS_POLL /**/ +/* HAS_PTHREAD_YIELD: + * This symbol, if defined, indicates that the pthread_yield routine is + * available to yield the execution of the current thread. + */ +#undef HAS_PTHREAD_YIELD + /* HAS_READDIR: * This symbol, if defined, indicates that the readdir routine is * available to read directory entries. You may have to include @@ -555,6 +569,12 @@ */ #define HAS_READDIR /**/ +/* HAS_SCHED_YIELD: + * This symbol, if defined, indicates that the sched_yield + * routine is available to yield the execution of the current thread. + */ +#undef HAS_SCHED_YIELD + /* HAS_SEEKDIR: * This symbol, if defined, indicates that the seekdir routine is * available. You may have to include <dirent.h>. See I_DIRENT. @@ -1466,7 +1486,7 @@ * This symbol contains the ~name expanded version of ARCHLIB, to be used * in programs that are not prepared to deal with ~ expansion at run-time. */ -#define ARCHLIB "c:\\perl\\lib\\MSWin32-x86-thread" /**/ +#define ARCHLIB "c:\\perl5004.5x\\lib" /**/ #define ARCHLIB_EXP (win32_perllib_path(ARCHNAME,NULL)) /**/ /* BINCOMPAT3: @@ -1606,6 +1626,12 @@ */ /*#define USE_SFIO /**/ +/* PTHREADS_CREATED_JOINABLE: + * This symbol, if defined, indicates that pthreads are created + * in the joinable (aka undetached) state. + */ +/*#define PTHREADS_CREATED_JOINABLE /**/ + /* Sigjmp_buf: * This is the buffer type to be used with Sigsetjmp and Siglongjmp. */ @@ -1686,7 +1712,9 @@ /* MYMALLOC: * This symbol, if defined, indicates that we're using our own malloc. */ +#ifndef PERL_OBJECT #define MYMALLOC /**/ +#endif /* OLDARCHLIB: * This variable, if defined, holds the name of the directory in @@ -1713,7 +1741,7 @@ * This symbol contains the ~name expanded version of PRIVLIB, to be used * in programs that are not prepared to deal with ~ expansion at run-time. */ -#define PRIVLIB "c:\\perl\\lib" /**/ +#define PRIVLIB "c:\\perl5004.5x\\lib" /**/ #define PRIVLIB_EXP (win32_perllib_path(NULL)) /**/ /* SH_PATH: @@ -1769,7 +1797,7 @@ * This symbol contains the ~name expanded version of SITEARCH, to be used * in programs that are not prepared to deal with ~ expansion at run-time. */ -#define SITEARCH "c:\\perl\\lib\\site" /**/ +#define SITEARCH "c:\\perl5004.5x\\lib\\site" /**/ #define SITEARCH_EXP (win32_perllib_path("site",ARCHNAME,NULL)) /**/ /* SITELIB: @@ -1785,7 +1813,7 @@ * This symbol contains the ~name expanded version of SITELIB, to be used * in programs that are not prepared to deal with ~ expansion at run-time. */ -#define SITELIB "c:\\perl\\lib\\site" /**/ +#define SITELIB "c:\\perl5004.5x\\lib\\site" /**/ #define SITELIB_EXP (win32_perllib_path("site",NULL)) /**/ /* STARTPERL: diff --git a/win32/dl_win32.xs b/win32/dl_win32.xs index 0f869e1f85..13d97211a3 100644 --- a/win32/dl_win32.xs +++ b/win32/dl_win32.xs @@ -57,12 +57,12 @@ dl_load_file(filename,flags=0) int flags PREINIT: CODE: - DLDEBUG(1,fprintf(stderr,"dl_load_file(%s):\n", filename)); + DLDEBUG(1,PerlIO_printf(PerlIO_stderr(),"dl_load_file(%s):\n", filename)); if (dl_static_linked(filename) == 0) RETVAL = (void*) LoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ) ; else RETVAL = (void*) GetModuleHandle(NULL); - DLDEBUG(2,fprintf(stderr," libref=%x\n", RETVAL)); + DLDEBUG(2,PerlIO_printf(PerlIO_stderr()," libref=%x\n", RETVAL)); ST(0) = sv_newmortal() ; if (RETVAL == NULL) SaveError("%d",GetLastError()) ; @@ -75,10 +75,10 @@ dl_find_symbol(libhandle, symbolname) void * libhandle char * symbolname CODE: - DLDEBUG(2,fprintf(stderr,"dl_find_symbol(handle=%x, symbol=%s)\n", + DLDEBUG(2,PerlIO_printf(PerlIO_stderr(),"dl_find_symbol(handle=%x, symbol=%s)\n", libhandle, symbolname)); RETVAL = (void*) GetProcAddress((HINSTANCE) libhandle, symbolname); - DLDEBUG(2,fprintf(stderr," symbolref = %x\n", RETVAL)); + DLDEBUG(2,PerlIO_printf(PerlIO_stderr()," symbolref = %x\n", RETVAL)); ST(0) = sv_newmortal() ; if (RETVAL == NULL) SaveError("%d",GetLastError()) ; @@ -100,7 +100,7 @@ dl_install_xsub(perl_name, symref, filename="$Package") void * symref char * filename CODE: - DLDEBUG(2,fprintf(stderr,"dl_install_xsub(name=%s, symref=%x)\n", + DLDEBUG(2,PerlIO_printf(PerlIO_stderr(),"dl_install_xsub(name=%s, symref=%x)\n", perl_name, symref)); ST(0)=sv_2mortal(newRV((SV*)newXS(perl_name, (void(*)(CV*))symref, filename))); diff --git a/win32/include/sys/socket.h b/win32/include/sys/socket.h index 40a5485343..6ffb0ac269 100644 --- a/win32/include/sys/socket.h +++ b/win32/include/sys/socket.h @@ -142,6 +142,7 @@ void win32_endprotoent(void); void win32_endservent(void); #ifndef WIN32SCK_IS_STDSCK +#ifndef PERL_OBJECT // // direct to our version // @@ -203,6 +204,7 @@ void win32_endservent(void); #define FD_ZERO(p) PERL_FD_ZERO(p) #endif /* USE_SOCKETS_AS_HANDLES */ +#endif /* PERL_OBJECT */ #endif /* WIN32SCK_IS_STDSCK */ #ifdef __cplusplus diff --git a/win32/ipdir.c b/win32/ipdir.c new file mode 100644 index 0000000000..29702c8f26 --- /dev/null +++ b/win32/ipdir.c @@ -0,0 +1,186 @@ +/* + + ipdir.c + Interface for perl directory functions + +*/ + +#include <ipdir.h> + +class CPerlDir : public IPerlDir +{ +public: + CPerlDir() { pPerl = NULL; }; + virtual int MKdir(const char *dirname, int mode, int &err); + virtual int Chdir(const char *dirname, int &err); + virtual int Rmdir(const char *dirname, int &err); + virtual int Close(DIR *dirp, int &err); + virtual DIR *Open(char *filename, int &err); + virtual struct direct *Read(DIR *dirp, int &err); + virtual void Rewind(DIR *dirp, int &err); + virtual void Seek(DIR *dirp, long loc, int &err); + virtual long Tell(DIR *dirp, int &err); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; +protected: + CPerlObj *pPerl; +}; + +int CPerlDir::MKdir(const char *dirname, int mode, int &err) +{ + return mkdir(dirname); /* just ignore mode */ +} + +int CPerlDir::Chdir(const char *dirname, int &err) +{ + return chdir(dirname); +} + +int CPerlDir::Rmdir(const char *dirname, int &err) +{ + return rmdir(dirname); +} + +#define PATHLEN 1024 +// The idea here is to read all the directory names into a string table +// (separated by nulls) and when one of the other dir functions is called +// return the pointer to the current file name. +DIR *CPerlDir::Open(char *filename, int &err) +{ + DIR *p; + long len; + long idx; + char scannamespc[PATHLEN]; + char *scanname = scannamespc; + struct stat sbuf; + WIN32_FIND_DATA FindData; + HANDLE fh; + + // Create the search pattern + strcpy(scanname, filename); + + len = strlen(scanname); + if(len > 1 && ((scanname[len-1] == '/') || (scanname[len-1] == '\\'))) + { + // allow directory names of 'x:\' to pass + if(!(len == 3 && scanname[1] == ':')) + scanname[len-1] = '\0'; + } + + // check to see if filename is a directory + if(stat(scanname, &sbuf) < 0 || sbuf.st_mode & _S_IFDIR == 0) + { + DWORD dTemp = GetFileAttributes(scanname); + if(dTemp == 0xffffffff || !(dTemp & FILE_ATTRIBUTE_DIRECTORY)) + { + return NULL; + } + } + + if((scanname[len-1] == '/') || (scanname[len-1] == '\\')) + scanname[len-1] = '\0'; + + strcat(scanname, "/*"); + + // Get a DIR structure + Newz(1501, p, 1, DIR); + if(p == NULL) + return NULL; + + // do the FindFirstFile call + fh = FindFirstFile(scanname, &FindData); + if(fh == INVALID_HANDLE_VALUE) + { + Safefree(p); + return NULL; + } + + // now allocate the first part of the string table for the filenames that we find. + idx = strlen(FindData.cFileName)+1; + New(1502, p->start, idx, char); + if(p->start == NULL) + { + FindClose(fh); + croak("opendir: malloc failed!\n"); + } + strcpy(p->start, FindData.cFileName); + p->nfiles++; + + // loop finding all the files that match the wildcard + // (which should be all of them in this directory!). + // the variable idx should point one past the null terminator + // of the previous string found. + // + while(FindNextFile(fh, &FindData)) + { + len = strlen(FindData.cFileName); + // bump the string table size by enough for the + // new name and it's null terminator + Renew(p->start, idx+len+1, char); + if(p->start == NULL) + { + FindClose(fh); + croak("opendir: malloc failed!\n"); + } + strcpy(&p->start[idx], FindData.cFileName); + p->nfiles++; + idx += len+1; + } + FindClose(fh); + p->size = idx; + p->curr = p->start; + return p; +} + +int CPerlDir::Close(DIR *dirp, int &err) +{ + Safefree(dirp->start); + Safefree(dirp); + return 1; +} + +// Readdir just returns the current string pointer and bumps the +// string pointer to the next entry. +struct direct *CPerlDir::Read(DIR *dirp, int &err) +{ + int len; + static int dummy = 0; + + if(dirp->curr) + { // first set up the structure to return + len = strlen(dirp->curr); + strcpy(dirp->dirstr.d_name, dirp->curr); + dirp->dirstr.d_namlen = len; + + // Fake an inode + dirp->dirstr.d_ino = dummy++; + + // Now set up for the next call to readdir + dirp->curr += len + 1; + if(dirp->curr >= (dirp->start + dirp->size)) + { + dirp->curr = NULL; + } + + return &(dirp->dirstr); + } + else + return NULL; +} + +void CPerlDir::Rewind(DIR *dirp, int &err) +{ + dirp->curr = dirp->start; +} + +void CPerlDir::Seek(DIR *dirp, long loc, int &err) +{ + dirp->curr = (char *)loc; +} + +long CPerlDir::Tell(DIR *dirp, int &err) +{ + return (long) dirp->curr; +} + + diff --git a/win32/ipenv.c b/win32/ipenv.c new file mode 100644 index 0000000000..9033b55138 --- /dev/null +++ b/win32/ipenv.c @@ -0,0 +1,62 @@ +/* + + ipenv.c + Interface for perl environment functions + +*/ + +#include <ipenv.h> +#include <stdlib.h> + +class CPerlEnv : public IPerlEnv +{ +public: + CPerlEnv() { w32_perldll_handle = INVALID_HANDLE_VALUE; pPerl = NULL; }; + virtual char *Getenv(const char *varname, int &err); + virtual int Putenv(const char *envstring, int &err); + virtual char* LibPath(char *sfx, ...); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; +protected: + char w32_perllib_root[MAX_PATH+1]; + HANDLE w32_perldll_handle; + CPerlObj *pPerl; +}; + +char *CPerlEnv::Getenv(const char *varname, int &err) +{ + return getenv(varname); +} + +int CPerlEnv::Putenv(const char *envstring, int &err) +{ + return _putenv(envstring); +} + +char* CPerlEnv::LibPath(char *sfx, ...) +{ + va_list ap; + char *end; + va_start(ap,sfx); + GetModuleFileName((w32_perldll_handle == INVALID_HANDLE_VALUE) + ? GetModuleHandle(NULL) + : w32_perldll_handle, + w32_perllib_root, + sizeof(w32_perllib_root)); + *(end = strrchr(w32_perllib_root, '\\')) = '\0'; + if (stricmp(end-4,"\\bin") == 0) + end -= 4; + strcpy(end,"\\lib"); + while (sfx) + { + strcat(end,"\\"); + strcat(end,sfx); + sfx = va_arg(ap,char *); + } + va_end(ap); + return (w32_perllib_root); +} + + + + diff --git a/win32/iplio.c b/win32/iplio.c new file mode 100644 index 0000000000..3522284219 --- /dev/null +++ b/win32/iplio.c @@ -0,0 +1,307 @@ +/* + + iplio.c + Interface for perl Low IO functions + +*/ + +#include <iplio.h> +#include <sys/utime.h> + + +class CPerlLIO : public IPerlLIO +{ +public: + CPerlLIO() { w32_platform = (-1); pPerl = NULL; pSock = NULL; pStdIO = NULL; }; + + virtual int Access(const char *path, int mode, int &err); + virtual int Chmod(const char *filename, int pmode, int &err); + virtual int Chsize(int handle, long size, int &err); + virtual int Close(int handle, int &err); + virtual int Dup(int handle, int &err); + virtual int Dup2(int handle1, int handle2, int &err); + virtual int Flock(int fd, int oper, int &err); + virtual int FStat(int handle, struct stat *buffer, int &err); + virtual int IOCtl(int i, unsigned int u, char *data, int &err); + virtual int Isatty(int handle, int &err); + virtual long Lseek(int handle, long offset, int origin, int &err); + virtual int Lstat(const char *path, struct stat *buffer, int &err); + virtual char *Mktemp(char *Template, int &err); + virtual int Open(const char *filename, int oflag, int &err); + virtual int Open(const char *filename, int oflag, int pmode, int &err); + virtual int Read(int handle, void *buffer, unsigned int count, int &err); + virtual int Rename(const char *oldname, const char *newname, int &err); + virtual int Setmode(int handle, int mode, int &err); + virtual int STat(const char *path, struct stat *buffer, int &err); + virtual char *Tmpnam(char *string, int &err); + virtual int Umask(int pmode, int &err); + virtual int Unlink(const char *filename, int &err); + virtual int Utime(char *filename, struct utimbuf *times, int &err); + virtual int Write(int handle, const void *buffer, unsigned int count, int &err); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; + inline void SetSockCtl(CPerlSock *p) { pSock = p; }; + inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; }; +protected: + inline int IsWin95(void) + { + return (os_id() == VER_PLATFORM_WIN32_WINDOWS); + }; + inline int IsWinNT(void) + { + return (os_id() == VER_PLATFORM_WIN32_NT); + }; + int GetOSfhandle(int filenum) + { + return pStdIO->GetOSfhandle(filenum); + }; + DWORD os_id(void) + { + if((-1) == w32_platform) + { + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(OSVERSIONINFO)); + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osver); + w32_platform = osver.dwPlatformId; + } + return (w32_platform); + } + + DWORD w32_platform; + CPerlObj *pPerl; + CPerlSock *pSock; + IPerlStdIOWin *pStdIO; +}; + +#define CALLFUNCRET(x)\ + int ret = x;\ + if(ret)\ + err = errno;\ + return ret; + +#define CALLFUNCERR(x)\ + int ret = x;\ + if(errno)\ + err = errno;\ + return ret; + +#define LCALLFUNCERR(x)\ + long ret = x;\ + if(errno)\ + err = errno;\ + return ret; + +int CPerlLIO::Access(const char *path, int mode, int &err) +{ + CALLFUNCRET(access(path, mode)) +} + +int CPerlLIO::Chmod(const char *filename, int pmode, int &err) +{ + CALLFUNCRET(chmod(filename, pmode)) +} + +int CPerlLIO::Chsize(int handle, long size, int &err) +{ + CALLFUNCRET(chsize(handle, size)) +} + +int CPerlLIO::Close(int fd, int &err) +{ + CALLFUNCRET(close(fd)) +} + +int CPerlLIO::Dup(int fd, int &err) +{ + CALLFUNCERR(dup(fd)) +} + +int CPerlLIO::Dup2(int handle1, int handle2, int &err) +{ + CALLFUNCERR(dup2(handle1, handle2)) +} + + +#define LK_ERR(f,i) ((f) ? (i = 0) : (err = GetLastError())) +#define LK_LEN 0xffff0000 +#define LOCK_SH 1 +#define LOCK_EX 2 +#define LOCK_NB 4 +#define LOCK_UN 8 + +int CPerlLIO::Flock(int fd, int oper, int &err) +{ + OVERLAPPED o; + int i = -1; + HANDLE fh; + + if (!IsWinNT()) { + croak("flock() unimplemented on this platform"); + return -1; + } + fh = (HANDLE)GetOSfhandle(fd); + memset(&o, 0, sizeof(o)); + + switch(oper) { + case LOCK_SH: /* shared lock */ + LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i); + break; + case LOCK_EX: /* exclusive lock */ + LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i); + break; + case LOCK_SH|LOCK_NB: /* non-blocking shared lock */ + LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i); + break; + case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */ + LK_ERR(LockFileEx(fh, + LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, + 0, LK_LEN, 0, &o),i); + break; + case LOCK_UN: /* unlock lock */ + LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i); + break; + default: /* unknown */ + err = EINVAL; + break; + } + return i; +} + +int CPerlLIO::FStat(int fd, struct stat *sbufptr, int &err) +{ + int ret = fstat(fd, sbufptr); + if(errno) + err = errno; + return ret; +} + +int CPerlLIO::IOCtl(int i, unsigned int u, char *data, int &err) +{ + return pSock->IoctlSocket((SOCKET)i, (long)u, (u_long*)data, err); +} + +int CPerlLIO::Isatty(int fd, int &err) +{ + return isatty(fd); +} + +long CPerlLIO::Lseek(int fd, long offset, int origin, int &err) +{ + LCALLFUNCERR(lseek(fd, offset, origin)) +} + +int CPerlLIO::Lstat(const char *path, struct stat *sbufptr, int &err) +{ + return stat(path, sbufptr); +} + +char *CPerlLIO::Mktemp(char *Template, int &err) +{ + return mktemp(Template); +} + +int CPerlLIO::Open(const char *filename, int oflag, int &err) +{ + CALLFUNCERR(open(filename, oflag)) +} + +int CPerlLIO::Open(const char *filename, int oflag, int pmode, int &err) +{ + CALLFUNCERR(open(filename, oflag, pmode)) +} + +int CPerlLIO::Read(int fd, void *buffer, unsigned int cnt, int &err) +{ + CALLFUNCERR(read(fd, buffer, cnt)) +} + +int CPerlLIO::Rename(const char *OldFileName, const char *newname, int &err) +{ + char szNewWorkName[MAX_PATH+1]; + WIN32_FIND_DATA fdOldFile, fdNewFile; + HANDLE handle; + char *ptr; + + if((strchr(OldFileName, '\\') || strchr(OldFileName, '/')) + && strchr(newname, '\\') == NULL + && strchr(newname, '/') == NULL) + { + strcpy(szNewWorkName, OldFileName); + if((ptr = strrchr(szNewWorkName, '\\')) == NULL) + ptr = strrchr(szNewWorkName, '/'); + strcpy(++ptr, newname); + } + else + strcpy(szNewWorkName, newname); + + if(stricmp(OldFileName, szNewWorkName) != 0) + { // check that we're not being fooled by relative paths + // and only delete the new file + // 1) if it exists + // 2) it is not the same file as the old file + // 3) old file exist + // GetFullPathName does not return the long file name on some systems + handle = FindFirstFile(OldFileName, &fdOldFile); + if(handle != INVALID_HANDLE_VALUE) + { + FindClose(handle); + + handle = FindFirstFile(szNewWorkName, &fdNewFile); + + if(handle != INVALID_HANDLE_VALUE) + FindClose(handle); + else + fdNewFile.cFileName[0] = '\0'; + + if(strcmp(fdOldFile.cAlternateFileName, fdNewFile.cAlternateFileName) != 0 + && strcmp(fdOldFile.cFileName, fdNewFile.cFileName) != 0) + { // file exists and not same file + DeleteFile(szNewWorkName); + } + } + } + int ret = rename(OldFileName, szNewWorkName); + if(ret) + err = errno; + + return ret; +} + +int CPerlLIO::Setmode(int fd, int mode, int &err) +{ + CALLFUNCRET(setmode(fd, mode)) +} + +int CPerlLIO::STat(const char *path, struct stat *sbufptr, int &err) +{ + return stat(path, sbufptr); +} + +char *CPerlLIO::Tmpnam(char *string, int &err) +{ + return tmpnam(string); +} + +int CPerlLIO::Umask(int pmode, int &err) +{ + return umask(pmode); +} + +int CPerlLIO::Unlink(const char *filename, int &err) +{ + chmod(filename, _S_IREAD | _S_IWRITE); + CALLFUNCRET(unlink(filename)) +} + +int CPerlLIO::Utime(char *filename, struct utimbuf *times, int &err) +{ + CALLFUNCRET(utime(filename, times)) +} + +int CPerlLIO::Write(int fd, const void *buffer, unsigned int cnt, int &err) +{ + CALLFUNCERR(write(fd, buffer, cnt)) +} + diff --git a/win32/ipmem.c b/win32/ipmem.c new file mode 100644 index 0000000000..62e72ab8db --- /dev/null +++ b/win32/ipmem.c @@ -0,0 +1,39 @@ +/* + + ipmem.c + Interface for perl memory allocation + +*/ + +#include <ipmem.h> + +class CPerlMem : public IPerlMem +{ +public: + CPerlMem() { pPerl = NULL; }; + virtual void* Malloc(size_t); + virtual void* Realloc(void*, size_t); + virtual void Free(void*); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; +protected: + CPerlObj *pPerl; +}; + +void* CPerlMem::Malloc(size_t size) +{ + return malloc(size); +} + +void* CPerlMem::Realloc(void* ptr, size_t size) +{ + return realloc(ptr, size); +} + +void CPerlMem::Free(void* ptr) +{ + free(ptr); +} + + + diff --git a/win32/ipproc.c b/win32/ipproc.c new file mode 100644 index 0000000000..f6445291d1 --- /dev/null +++ b/win32/ipproc.c @@ -0,0 +1,620 @@ +/* + + ipproc.c + Interface for perl process functions + +*/ + +#include <ipproc.h> +#include <stdlib.h> +#include <fcntl.h> + +#define EXECF_EXEC 1 +#define EXECF_SPAWN 2 +#define EXECF_SPAWN_NOWAIT 3 + +class CPerlProc : public IPerlProc +{ +public: + CPerlProc() + { + pPerl = NULL; + w32_perlshell_tokens = NULL; + w32_perlshell_items = -1; + w32_platform = -1; +#ifndef __BORLANDC__ + w32_num_children = 0; +#endif + }; + virtual void Abort(void); + virtual void Exit(int status); + virtual void _Exit(int status); + virtual int Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3); + virtual int Execv(const char *cmdname, const char *const *argv); + virtual int Execvp(const char *cmdname, const char *const *argv); + virtual uid_t Getuid(void); + virtual uid_t Geteuid(void); + virtual gid_t Getgid(void); + virtual gid_t Getegid(void); + virtual char *Getlogin(void); + virtual int Kill(int pid, int sig); + virtual int Killpg(int pid, int sig); + virtual int PauseProc(void); + virtual PerlIO* Popen(const char *command, const char *mode); + virtual int Pclose(PerlIO *stream); + virtual int Pipe(int *phandles); + virtual int Setuid(uid_t u); + virtual int Setgid(gid_t g); + virtual int Sleep(unsigned int); + virtual int Times(struct tms *timebuf); + virtual int Wait(int *status); + virtual Sighandler_t Signal(int sig, Sighandler_t subcode); + virtual void GetSysMsg(char*& msg, DWORD& dwLen, DWORD dwErr); + virtual void FreeBuf(char* msg); + virtual BOOL DoCmd(char *cmd); + virtual int Spawn(char*cmds); + virtual int Spawnvp(int mode, const char *cmdname, const char *const *argv); + virtual int ASpawn(void *vreally, void **vmark, void **vsp); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; +protected: + int Spawn(char *cmd, int exectype); + void GetShell(void); + long Tokenize(char *str, char **dest, char ***destv); + + inline int IsWin95(void) + { + return (os_id() == VER_PLATFORM_WIN32_WINDOWS); + }; + inline int IsWinNT(void) + { + return (os_id() == VER_PLATFORM_WIN32_NT); + }; + + inline 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; + }; + + DWORD os_id(void) + { + if((-1) == w32_platform) + { + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(OSVERSIONINFO)); + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osver); + w32_platform = osver.dwPlatformId; + } + return (w32_platform); + }; + + DWORD w32_platform; + char szLoginNameStr[128]; + char *w32_perlshell_tokens; + long w32_perlshell_items; + char **w32_perlshell_vec; +#ifndef __BORLANDC__ + long w32_num_children; + HANDLE w32_child_pids[MAXIMUM_WAIT_OBJECTS]; +#endif + CPerlObj *pPerl; +}; + + +static BOOL +has_redirection(char *ptr) +{ + int inquote = 0; + char quote = '\0'; + + /* + * Scan string looking for redirection (< or >) or pipe + * characters (|) that are not in a quoted string + */ + while(*ptr) { + switch(*ptr) { + case '\'': + case '\"': + if(inquote) { + if(quote == *ptr) { + inquote = 0; + quote = '\0'; + } + } + else { + quote = *ptr; + inquote++; + } + break; + case '>': + case '<': + case '|': + if(!inquote) + return TRUE; + default: + break; + } + ++ptr; + } + return FALSE; +} + +/* 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 + * backslash (the backslash will be stripped). + * Returns number of words in result buffer. + */ +long +CPerlProc::Tokenize(char *str, char **dest, char ***destv) +{ + char *retstart = Nullch; + char **retvstart = 0; + int items = -1; + if (str) { + int slen = strlen(str); + register char *ret; + register char **retv; + New(1307, ret, slen+2, char); + New(1308, retv, (slen+3)/2, char*); + + retstart = ret; + retvstart = retv; + *retv = ret; + items = 0; + while (*str) { + *ret = *str++; + if (*ret == '\\' && *str) + *ret = *str++; + else if (*ret == ' ') { + while (*str == ' ') + str++; + if (ret == retstart) + ret--; + else { + *ret = '\0'; + ++items; + if (*str) + *++retv = ret+1; + } + } + else if (!*str) + ++items; + ret++; + } + retvstart[items] = Nullch; + *ret++ = '\0'; + *ret = '\0'; + } + *dest = retstart; + *destv = retvstart; + return items; +} + + +void +CPerlProc::GetShell(void) +{ + if (!w32_perlshell_tokens) { + /* we don't use COMSPEC here for two reasons: + * 1. the same reason perl on UNIX doesn't use SHELL--rampant and + * uncontrolled unportability of the ensuing scripts. + * 2. PERL5SHELL could be set to a shell that may not be fit for + * interactive use (which is what most programs look in COMSPEC + * for). + */ + char* defaultshell = (IsWinNT() ? "cmd.exe /x/c" : "command.com /c"); + char* usershell = getenv("PERL5SHELL"); + w32_perlshell_items = Tokenize(usershell ? usershell : defaultshell, + &w32_perlshell_tokens, + &w32_perlshell_vec); + } +} + +int +CPerlProc::ASpawn(void *vreally, void **vmark, void **vsp) +{ + SV *really = (SV*)vreally; + SV **mark = (SV**)vmark; + SV **sp = (SV**)vsp; + char **argv; + char *str; + int status; + int flag = P_WAIT; + int index = 0; + + if (sp <= mark) + return -1; + + GetShell(); + New(1306, argv, (sp - mark) + w32_perlshell_items + 2, char*); + + if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) { + ++mark; + flag = SvIVx(*mark); + } + + while(++mark <= sp) { + if (*mark && (str = SvPV(*mark, na))) + argv[index++] = str; + else + argv[index++] = ""; + } + argv[index++] = 0; + + status = Spawnvp(flag, + (really ? SvPV(really,na) : argv[0]), + (const char* const*)argv); + + if (status < 0 && errno == ENOEXEC) { + /* possible shell-builtin, invoke with shell */ + int sh_items; + sh_items = w32_perlshell_items; + while (--index >= 0) + argv[index+sh_items] = argv[index]; + while (--sh_items >= 0) + argv[sh_items] = w32_perlshell_vec[sh_items]; + + status = Spawnvp(flag, + (really ? SvPV(really,na) : argv[0]), + (const char* const*)argv); + } + + if (status < 0) { + if (pPerl->Perl_dowarn) + warn("Can't spawn \"%s\": %s", argv[0], strerror(errno)); + status = 255 * 256; + } + else if (flag != P_NOWAIT) + status *= 256; + Safefree(argv); + return (pPerl->Perl_statusvalue = status); +} + + +int +CPerlProc::Spawn(char *cmd, int exectype) +{ + char **a; + char *s; + char **argv; + int status = -1; + BOOL needToTry = TRUE; + char *cmd2; + + /* Save an extra exec if possible. See if there are shell + * metacharacters in it */ + if(!has_redirection(cmd)) { + New(1301,argv, strlen(cmd) / 2 + 2, char*); + New(1302,cmd2, strlen(cmd) + 1, char); + strcpy(cmd2, cmd); + a = argv; + for (s = cmd2; *s;) { + while (*s && isspace(*s)) + s++; + if (*s) + *(a++) = s; + while(*s && !isspace(*s)) + s++; + if(*s) + *s++ = '\0'; + } + *a = Nullch; + if (argv[0]) { + switch (exectype) { + case EXECF_SPAWN: + status = Spawnvp(P_WAIT, argv[0], + (const char* const*)argv); + break; + case EXECF_SPAWN_NOWAIT: + status = Spawnvp(P_NOWAIT, argv[0], + (const char* const*)argv); + break; + case EXECF_EXEC: + status = Execvp(argv[0], (const char* const*)argv); + break; + } + if (status != -1 || errno == 0) + needToTry = FALSE; + } + Safefree(argv); + Safefree(cmd2); + } + if (needToTry) { + char **argv; + int i = -1; + GetShell(); + New(1306, argv, w32_perlshell_items + 2, char*); + while (++i < w32_perlshell_items) + argv[i] = w32_perlshell_vec[i]; + argv[i++] = cmd; + argv[i] = Nullch; + switch (exectype) { + case EXECF_SPAWN: + status = Spawnvp(P_WAIT, argv[0], + (const char* const*)argv); + break; + case EXECF_SPAWN_NOWAIT: + status = Spawnvp(P_NOWAIT, argv[0], + (const char* const*)argv); + break; + case EXECF_EXEC: + status = Execvp(argv[0], (const char* const*)argv); + break; + } + cmd = argv[0]; + Safefree(argv); + } + if (status < 0) { + if (pPerl->Perl_dowarn) + warn("Can't %s \"%s\": %s", + (exectype == EXECF_EXEC ? "exec" : "spawn"), + cmd, strerror(errno)); + status = 255 * 256; + } + else if (exectype != EXECF_SPAWN_NOWAIT) + status *= 256; + return (pPerl->Perl_statusvalue = status); +} + + +void CPerlProc::Abort(void) +{ + abort(); +} + +void CPerlProc::Exit(int status) +{ + exit(status); +} + +void CPerlProc::_Exit(int status) +{ + _exit(status); +} + +int CPerlProc::Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3) +{ + return execl(cmdname, arg0, arg1, arg2, arg3); +} + +int CPerlProc::Execv(const char *cmdname, const char *const *argv) +{ + return execv(cmdname, argv); +} + +int CPerlProc::Execvp(const char *cmdname, const char *const *argv) +{ + return execvp(cmdname, argv); +} + +#define ROOT_UID ((uid_t)0) +#define ROOT_GID ((gid_t)0) + +uid_t CPerlProc::Getuid(void) +{ + return ROOT_UID; +} + +uid_t CPerlProc::Geteuid(void) +{ + return ROOT_UID; +} + +gid_t CPerlProc::Getgid(void) +{ + return ROOT_GID; +} + +gid_t CPerlProc::Getegid(void) +{ + return ROOT_GID; +} + + +char *CPerlProc::Getlogin(void) +{ + char unknown[] = "<Unknown>"; + unsigned long len; + + len = sizeof(szLoginNameStr); + if(!GetUserName(szLoginNameStr, &len)) + { + strcpy(szLoginNameStr, unknown); + } + return szLoginNameStr; +} + +int CPerlProc::Kill(int pid, int sig) +{ + HANDLE hProcess; + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); + if(hProcess == NULL) + croak("kill process failed!\n"); + + if(TerminateProcess(hProcess, 0) == FALSE) + croak("kill process failed!\n"); + + CloseHandle(hProcess); + return 0; +} + +int CPerlProc::Killpg(int pid, int sig) +{ + croak("killpg not implemented!\n"); + return 0; +} + +int CPerlProc::PauseProc(void) +{ + Sleep((unsigned int)((32767L << 16) + 32767)); + return 0; +} + +PerlIO* CPerlProc::Popen(const char *command, const char *mode) +{ + return (PerlIO*)_popen(command, mode); +} + +int CPerlProc::Pclose(PerlIO *pf) +{ + return _pclose((FILE*)pf); +} + +int CPerlProc::Pipe(int *phandles) +{ + return _pipe(phandles, 512, O_BINARY); +} + +int CPerlProc::Sleep(unsigned int s) +{ + ::Sleep(s*1000); + return 0; +} + +int CPerlProc::Times(struct tms *timebuf) +{ + FILETIME user; + FILETIME kernel; + FILETIME dummy; + if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, + &kernel,&user)) { + timebuf->tms_utime = filetime_to_clock(&user); + timebuf->tms_stime = filetime_to_clock(&kernel); + timebuf->tms_cutime = 0; + timebuf->tms_cstime = 0; + + } else { + /* That failed - e.g. Win95 fallback to clock() */ + clock_t t = clock(); + timebuf->tms_utime = t; + timebuf->tms_stime = 0; + timebuf->tms_cutime = 0; + timebuf->tms_cstime = 0; + } + return 0; +} + +int CPerlProc::Wait(int *status) +{ +#ifdef __BORLANDC__ + return wait(status); +#else + /* XXX this wait emulation only knows about processes + * spawned via win32_spawnvp(P_NOWAIT, ...). + */ + int i, retval; + DWORD exitcode, waitcode; + + if (!w32_num_children) { + errno = ECHILD; + return -1; + } + + /* if a child exists, wait for it to die */ + waitcode = WaitForMultipleObjects(w32_num_children, + w32_child_pids, + FALSE, + INFINITE); + if (waitcode != WAIT_FAILED) { + if (waitcode >= WAIT_ABANDONED_0 + && waitcode < WAIT_ABANDONED_0 + w32_num_children) + i = waitcode - WAIT_ABANDONED_0; + else + i = waitcode - WAIT_OBJECT_0; + if (GetExitCodeProcess(w32_child_pids[i], &exitcode) ) { + CloseHandle(w32_child_pids[i]); + *status = (int)((exitcode & 0xff) << 8); + retval = (int)w32_child_pids[i]; + Copy(&w32_child_pids[i+1], &w32_child_pids[i], + (w32_num_children-i-1), HANDLE); + w32_num_children--; + return retval; + } + } + +FAILED: + errno = GetLastError(); + return -1; + +#endif +} + +int CPerlProc::Setuid(uid_t u) +{ + return (u == ROOT_UID ? 0 : -1); +} + +int CPerlProc::Setgid(gid_t g) +{ + return (g == ROOT_GID ? 0 : -1); +} + +Sighandler_t CPerlProc::Signal(int sig, Sighandler_t subcode) +{ + return 0; +} + +void CPerlProc::GetSysMsg(char*& sMsg, DWORD& dwLen, DWORD dwErr) +{ + dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS + |FORMAT_MESSAGE_FROM_SYSTEM, NULL, + dwErr, 0, (char *)&sMsg, 1, NULL); + if (0 < dwLen) { + while (0 < dwLen && isspace(sMsg[--dwLen])) + ; + if ('.' != sMsg[dwLen]) + dwLen++; + sMsg[dwLen]= '\0'; + } + if (0 == dwLen) { + sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/); + dwLen = sprintf(sMsg, + "Unknown error #0x%lX (lookup 0x%lX)", + dwErr, GetLastError()); + } +} + +void CPerlProc::FreeBuf(char* sMsg) +{ + LocalFree(sMsg); +} + +BOOL CPerlProc::DoCmd(char *cmd) +{ + Spawn(cmd, EXECF_EXEC); + return FALSE; +} + +int CPerlProc::Spawn(char* cmd) +{ + return Spawn(cmd, EXECF_SPAWN); +} + +int CPerlProc::Spawnvp(int mode, const char *cmdname, const char *const *argv) +{ + int status; + + status = spawnvp(mode, cmdname, (char * const *)argv); +#ifndef __BORLANDC__ + /* XXX For the P_NOWAIT case, Borland RTL returns pinfo.dwProcessId + * while VC RTL returns pinfo.hProcess. For purposes of the custom + * implementation of win32_wait(), we assume the latter. + */ + if (mode == P_NOWAIT && status >= 0) + w32_child_pids[w32_num_children++] = (HANDLE)status; +#endif + return status; +} + + + + diff --git a/win32/ipsock.c b/win32/ipsock.c new file mode 100644 index 0000000000..a6510b9d83 --- /dev/null +++ b/win32/ipsock.c @@ -0,0 +1,681 @@ +/* + + ipsock.c + Interface for perl socket functions + +*/ + +#include <ipsock.h> +#include <fcntl.h> + +#define USE_SOCKETS_AS_HANDLES + +class CPerlSock : public IPerlSock +{ +public: + CPerlSock(); + ~CPerlSock(); + virtual u_long Htonl(u_long hostlong); + virtual u_short Htons(u_short hostshort); + virtual u_long Ntohl(u_long netlong); + virtual u_short Ntohs(u_short netshort); + virtual SOCKET Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err); + virtual int Bind(SOCKET s, const struct sockaddr* name, int namelen, int &err); + virtual int Connect(SOCKET s, const struct sockaddr* name, int namelen, int &err); + virtual void Endhostent(int &err); + virtual void Endnetent(int &err); + virtual void Endprotoent(int &err); + virtual void Endservent(int &err); + virtual struct hostent* Gethostbyaddr(const char* addr, int len, int type, int &err); + virtual struct hostent* Gethostbyname(const char* name, int &err); + virtual struct hostent* Gethostent(int &err); + virtual int Gethostname(char* name, int namelen, int &err); + virtual struct netent *Getnetbyaddr(long net, int type, int &err); + virtual struct netent *Getnetbyname(const char *, int &err); + virtual struct netent *Getnetent(int &err); + virtual int Getpeername(SOCKET s, struct sockaddr* name, int* namelen, int &err); + virtual struct protoent* Getprotobyname(const char* name, int &err); + virtual struct protoent* Getprotobynumber(int number, int &err); + virtual struct protoent* Getprotoent(int &err); + virtual struct servent* Getservbyname(const char* name, const char* proto, int &err); + virtual struct servent* Getservbyport(int port, const char* proto, int &err); + virtual struct servent* Getservent(int &err); + virtual int Getsockname(SOCKET s, struct sockaddr* name, int* namelen, int &err); + virtual int Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err); + virtual unsigned long InetAddr(const char* cp, int &err); + virtual char* InetNtoa(struct in_addr in, int &err); + virtual int IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err); + virtual int Listen(SOCKET s, int backlog, int &err); + virtual int Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err); + virtual int Select(int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout, int &err); + virtual int Send(SOCKET s, const char* buffer, int len, int flags, int &err); + virtual int Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err); + virtual void Sethostent(int stayopen, int &err); + virtual void Setnetent(int stayopen, int &err); + virtual void Setprotoent(int stayopen, int &err); + virtual void Setservent(int stayopen, int &err); + virtual int Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err); + virtual int Shutdown(SOCKET s, int how, int &err); + virtual SOCKET Socket(int af, int type, int protocol, int &err); + virtual int Socketpair(int domain, int type, int protocol, int* fds, int &err); + + void CloseSocket(int fh, int& err); + void* GetAddress(HINSTANCE hInstance, char *lpFunctionName); + void LoadWinSock(void); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; + inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; }; +protected: + void Start(void); + + inline int OpenOSfhandle(long osfhandle) + { + return pStdIO->OpenOSfhandle(osfhandle, O_RDWR|O_BINARY); + }; + int GetOSfhandle(int filenum) + { + return pStdIO->GetOSfhandle(filenum); + }; + + inline void StartSockets(void) + { + if(!bStarted) + Start(); + }; + + BOOL bStarted; + CPerlObj *pPerl; + IPerlStdIOWin *pStdIO; +}; + + +#define SOCKETAPI PASCAL + +typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *); +typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int); +typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET); +typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int); +typedef unsigned long (SOCKETAPI *LPINETADDR)(const char *); +typedef char* (SOCKETAPI *LPINETNTOA)(struct in_addr); +typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *); +typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *); +typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *); +typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *); +typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long); +typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short); +typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int); +typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long); +typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short); +typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int); +typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *); +typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *); +typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int); +typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int); +typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int); +typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int); +typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int); + +/* Database function prototypes */ +typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int); +typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *); +typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int); +typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *); +typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *); +typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int); +typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *); + +/* Microsoft Windows Extension function prototypes */ +typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA); +typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void); +typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void); +typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *); + +static HINSTANCE hWinSockDll = 0; + +static LPSOCKACCEPT paccept = 0; +static LPSOCKBIND pbind = 0; +static LPSOCKCLOSESOCKET pclosesocket = 0; +static LPSOCKCONNECT pconnect = 0; +static LPINETADDR pinet_addr = 0; +static LPINETNTOA pinet_ntoa = 0; +static LPSOCKIOCTLSOCKET pioctlsocket = 0; +static LPSOCKGETPEERNAME pgetpeername = 0; +static LPSOCKGETSOCKNAME pgetsockname = 0; +static LPSOCKGETSOCKOPT pgetsockopt = 0; +static LPSOCKHTONL phtonl = 0; +static LPSOCKHTONS phtons = 0; +static LPSOCKLISTEN plisten = 0; +static LPSOCKNTOHL pntohl = 0; +static LPSOCKNTOHS pntohs = 0; +static LPSOCKRECV precv = 0; +static LPSOCKRECVFROM precvfrom = 0; +static LPSOCKSELECT pselect = 0; +static LPSOCKSEND psend = 0; +static LPSOCKSENDTO psendto = 0; +static LPSOCKSETSOCKOPT psetsockopt = 0; +static LPSOCKSHUTDOWN pshutdown = 0; +static LPSOCKSOCKET psocket = 0; +static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0; +static LPSOCKGETHOSTBYNAME pgethostbyname = 0; +static LPSOCKGETHOSTNAME pgethostname = 0; +static LPSOCKGETSERVBYPORT pgetservbyport = 0; +static LPSOCKGETSERVBYNAME pgetservbyname = 0; +static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0; +static LPSOCKGETPROTOBYNAME pgetprotobyname = 0; +static LPSOCKWSASTARTUP pWSAStartup = 0; +static LPSOCKWSACLEANUP pWSACleanup = 0; +static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0; +static LPWSAFDIsSet pWSAFDIsSet = 0; + +void* CPerlSock::GetAddress(HINSTANCE hInstance, char *lpFunctionName) +{ + char buffer[512]; + FARPROC proc = GetProcAddress(hInstance, lpFunctionName); + if(proc == 0) + { + sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName); + croak(buffer); + } + return proc; +} + +void CPerlSock::LoadWinSock(void) +{ + if(hWinSockDll == NULL) + { + HINSTANCE hLib = LoadLibrary("WSock32.DLL"); + if(hLib == NULL) + croak("Could not load WSock32.dll\n"); + + paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept"); + pbind = (LPSOCKBIND)GetAddress(hLib, "bind"); + pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket"); + pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect"); + pinet_addr = (LPINETADDR)GetAddress(hLib, "inet_addr"); + pinet_ntoa = (LPINETNTOA)GetAddress(hLib, "inet_ntoa"); + pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket"); + pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername"); + pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname"); + pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt"); + phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl"); + phtons = (LPSOCKHTONS)GetAddress(hLib, "htons"); + plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen"); + pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl"); + pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs"); + precv = (LPSOCKRECV)GetAddress(hLib, "recv"); + precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom"); + pselect = (LPSOCKSELECT)GetAddress(hLib, "select"); + psend = (LPSOCKSEND)GetAddress(hLib, "send"); + psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto"); + psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt"); + pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown"); + psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket"); + pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr"); + pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname"); + pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname"); + pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport"); + pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname"); + pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber"); + pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname"); + pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup"); + pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup"); + pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError"); + pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet"); + hWinSockDll = hLib; + } +} + + +CPerlSock::CPerlSock() +{ + bStarted = FALSE; + pPerl = NULL; + pStdIO = NULL; +} + +CPerlSock::~CPerlSock() +{ + if(bStarted) + pWSACleanup(); +} + +void +CPerlSock::Start(void) +{ + unsigned short version; + WSADATA retdata; + int ret; + int iSockOpt = SO_SYNCHRONOUS_NONALERT; + + LoadWinSock(); + /* + * initalize the winsock interface and insure that it is + * cleaned up at exit. + */ + version = 0x101; + if(ret = pWSAStartup(version, &retdata)) + croak("Unable to locate winsock library!\n"); + if(retdata.wVersion != version) + croak("Could not find version 1.1 of winsock dll\n"); + + /* atexit((void (*)(void)) EndSockets); */ + +#ifdef USE_SOCKETS_AS_HANDLES + /* + * Enable the use of sockets as filehandles + */ + psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, + (char *)&iSockOpt, sizeof(iSockOpt)); +#endif /* USE_SOCKETS_AS_HANDLES */ + bStarted = TRUE; +} + + +u_long +CPerlSock::Htonl(u_long hostlong) +{ + StartSockets(); + return phtonl(hostlong); +} + +u_short +CPerlSock::Htons(u_short hostshort) +{ + StartSockets(); + return phtons(hostshort); +} + +u_long +CPerlSock::Ntohl(u_long netlong) +{ + StartSockets(); + return pntohl(netlong); +} + +u_short +CPerlSock::Ntohs(u_short netshort) +{ + StartSockets(); + return pntohs(netshort); +} + + +/* thanks to Beverly Brown (beverly@datacube.com) */ +#ifdef USE_SOCKETS_AS_HANDLES +# define OPEN_SOCKET(x) OpenOSfhandle(x) +# define TO_SOCKET(x) GetOSfhandle(x) +#else +# define OPEN_SOCKET(x) (x) +# define TO_SOCKET(x) (x) +#endif /* USE_SOCKETS_AS_HANDLES */ + +#define SOCKET_TEST(x, y) \ + STMT_START { \ + StartSockets(); \ + if((x) == (y)) \ + err = pWSAGetLastError(); \ + } STMT_END + +#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) + +SOCKET +CPerlSock::Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) +{ + SOCKET r; + + SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); + return OPEN_SOCKET(r); +} + +int +CPerlSock::Bind(SOCKET s, const struct sockaddr* addr, int addrlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen)); + return r; +} + +void +CPerlSock::CloseSocket(int fh, int& err) +{ + SOCKET_TEST_ERROR(pclosesocket(TO_SOCKET(fh))); +} + +int +CPerlSock::Connect(SOCKET s, const struct sockaddr* addr, int addrlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen)); + return r; +} + +void CPerlSock::Endhostent(int &err) +{ + croak("endhostent not implemented!\n"); +} + +void CPerlSock::Endnetent(int &err) +{ + croak("endnetent not implemented!\n"); +} + +void CPerlSock::Endprotoent(int &err) +{ + croak("endprotoent not implemented!\n"); +} + +void CPerlSock::Endservent(int &err) +{ + croak("endservent not implemented!\n"); +} + +struct hostent* +CPerlSock::Gethostbyaddr(const char* addr, int len, int type, int &err) +{ + struct hostent *r; + + SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL); + return r; +} + +struct hostent* +CPerlSock::Gethostbyname(const char* name, int &err) +{ + struct hostent *r; + + SOCKET_TEST(r = pgethostbyname(name), NULL); + return r; +} + +struct hostent* CPerlSock::Gethostent(int &err) +{ + croak("gethostent not implemented!\n"); + return NULL; +} + +int +CPerlSock::Gethostname(char* name, int len, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pgethostname(name, len)); + return r; +} + +struct netent *CPerlSock::Getnetbyaddr(long net, int type, int &err) +{ + croak("getnetbyaddr not implemented!\n"); + return NULL; +} + +struct netent *CPerlSock::Getnetbyname(const char *, int &err) +{ + croak("getnetbyname not implemented!\n"); + return NULL; +} + +struct netent *CPerlSock::Getnetent(int &err) +{ + croak("getnetent not implemented!\n"); + return NULL; +} + +int +CPerlSock::Getpeername(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen)); + return r; +} + +struct protoent* +CPerlSock::Getprotobyname(const char* name, int &err) +{ + struct protoent *r; + + SOCKET_TEST(r = pgetprotobyname(name), NULL); + return r; +} + +struct protoent* +CPerlSock::Getprotobynumber(int number, int &err) +{ + struct protoent *r; + + SOCKET_TEST(r = pgetprotobynumber(number), NULL); + return r; +} + +struct protoent* CPerlSock::Getprotoent(int &err) +{ + croak("getprotoent not implemented!\n"); + return NULL; +} + +struct servent* +CPerlSock::Getservbyname(const char* name, const char* proto, int &err) +{ + struct servent *r; + dTHR; + + SOCKET_TEST(r = pgetservbyname(name, proto), NULL); +// if (r) { +// r = win32_savecopyservent(&myservent, r, proto); +// } + return r; +} + +struct servent* +CPerlSock::Getservbyport(int port, const char* proto, int &err) +{ + struct servent *r; + dTHR; + + SOCKET_TEST(r = pgetservbyport(port, proto), NULL); +// if (r) { +// r = win32_savecopyservent(&myservent, r, proto); +// } + return r; +} + +struct servent* CPerlSock::Getservent(int &err) +{ + croak("getservent not implemented!\n"); + return NULL; +} + +int +CPerlSock::Getsockname(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen)); + return r; +} + +int +CPerlSock::Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); + return r; +} + +unsigned long +CPerlSock::InetAddr(const char* cp, int &err) +{ + unsigned long r; + + SOCKET_TEST(r = pinet_addr(cp), INADDR_NONE); + return r; +} + +char* +CPerlSock::InetNtoa(struct in_addr in, int &err) +{ + char* r; + + SOCKET_TEST(r = pinet_ntoa(in), NULL); + return r; +} + +int +CPerlSock::IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err) +{ + int r; + + SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp)); + return r; +} + +int +CPerlSock::Listen(SOCKET s, int backlog, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog)); + return r; +} + +int +CPerlSock::Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buffer, len, flags, from, fromlen)); + return r; +} + +int +CPerlSock::Select(int nfds, char* rd, char* wr, char* ex, const struct timeval* timeout, int &err) +{ + long r; + int i, fd, bit, offset; + FD_SET nrd, nwr, nex; + + FD_ZERO(&nrd); + FD_ZERO(&nwr); + FD_ZERO(&nex); + for (i = 0; i < nfds; i++) + { + fd = TO_SOCKET(i); + bit = 1L<<(i % (sizeof(char)*8)); + offset = i / (sizeof(char)*8); + if(rd != NULL && (rd[offset] & bit)) + FD_SET(fd, &nrd); + if(wr != NULL && (wr[offset] & bit)) + FD_SET(fd, &nwr); + if(ex != NULL && (ex[offset] & bit)) + FD_SET(fd, &nex); + } + SOCKET_TEST_ERROR(r = pselect(nfds, &nrd, &nwr, &nex, timeout)); + + for(i = 0; i < nfds; i++) + { + fd = TO_SOCKET(i); + bit = 1L<<(i % (sizeof(char)*8)); + offset = i / (sizeof(char)*8); + if(rd != NULL && (rd[offset] & bit)) + { + if(!pWSAFDIsSet(fd, &nrd)) + rd[offset] &= ~bit; + } + if(wr != NULL && (wr[offset] & bit)) + { + if(!pWSAFDIsSet(fd, &nwr)) + wr[offset] &= ~bit; + } + if(ex != NULL && (ex[offset] & bit)) + { + if(!pWSAFDIsSet(fd, &nex)) + ex[offset] &= ~bit; + } + } + return r; +} + +int +CPerlSock::Send(SOCKET s, const char* buffer, int len, int flags, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buffer, len, flags)); + return r; +} + +int +CPerlSock::Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buffer, len, flags, to, tolen)); + return r; +} + +void CPerlSock::Sethostent(int stayopen, int &err) +{ + croak("sethostent not implemented!\n"); +} + +void CPerlSock::Setnetent(int stayopen, int &err) +{ + croak("setnetent not implemented!\n"); +} + +void CPerlSock::Setprotoent(int stayopen, int &err) +{ + croak("setprotoent not implemented!\n"); +} + +void CPerlSock::Setservent(int stayopen, int &err) +{ + croak("setservent not implemented!\n"); +} + +int +CPerlSock::Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); + return r; +} + +int +CPerlSock::Shutdown(SOCKET s, int how, int &err) +{ + int r; + + SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how)); + return r; +} + +SOCKET +CPerlSock::Socket(int af, int type, int protocol, int &err) +{ + SOCKET s; + +#ifdef USE_SOCKETS_AS_HANDLES + StartSockets(); + if((s = psocket(af, type, protocol)) == INVALID_SOCKET) + err = pWSAGetLastError(); + else + s = OPEN_SOCKET(s); +#else + SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET); +#endif /* USE_SOCKETS_AS_HANDLES */ + + return s; +} + +int CPerlSock::Socketpair(int domain, int type, int protocol, int* fds, int &err) +{ + croak("socketpair not implemented!\n"); + return 0; +} + + diff --git a/win32/ipstdio.c b/win32/ipstdio.c new file mode 100644 index 0000000000..7d37373b9a --- /dev/null +++ b/win32/ipstdio.c @@ -0,0 +1,447 @@ +/* + + ipstdio.c + Interface for perl stdio functions + +*/ + +#include "ipstdiowin.h" +#include <stdio.h> + +class CPerlStdIO : public IPerlStdIOWin +{ +public: + CPerlStdIO() + { + pPerl = NULL; + pSock = NULL; + w32_platform = -1; + }; + virtual PerlIO* Stdin(void); + virtual PerlIO* Stdout(void); + virtual PerlIO* Stderr(void); + virtual PerlIO* Open(const char *, const char *, int &err); + virtual int Close(PerlIO*, int &err); + virtual int Eof(PerlIO*, int &err); + virtual int Error(PerlIO*, int &err); + virtual void Clearerr(PerlIO*, int &err); + virtual int Getc(PerlIO*, int &err); + virtual char* GetBase(PerlIO *, int &err); + virtual int GetBufsiz(PerlIO *, int &err); + virtual int GetCnt(PerlIO *, int &err); + virtual char* GetPtr(PerlIO *, int &err); + virtual int Putc(PerlIO*, int, int &err); + virtual int Puts(PerlIO*, const char *, int &err); + virtual int Flush(PerlIO*, int &err); + virtual int Ungetc(PerlIO*,int, int &err); + virtual int Fileno(PerlIO*, int &err); + virtual PerlIO* Fdopen(int, const char *, int &err); + virtual SSize_t Read(PerlIO*,void *,Size_t, int &err); + virtual SSize_t Write(PerlIO*,const void *,Size_t, int &err); + virtual void SetCnt(PerlIO *, int, int &err); + virtual void SetPtrCnt(PerlIO *, char *, int, int& err); + virtual void Setlinebuf(PerlIO*, int &err); + virtual int Printf(PerlIO*, int &err, const char *,...); + virtual int Vprintf(PerlIO*, int &err, const char *, va_list); + virtual long Tell(PerlIO*, int &err); + virtual int Seek(PerlIO*, off_t, int, int &err); + virtual void Rewind(PerlIO*, int &err); + virtual PerlIO* Tmpfile(int &err); + virtual int Getpos(PerlIO*, Fpos_t *, int &err); + virtual int Setpos(PerlIO*, const Fpos_t *, int &err); + virtual void Init(int &err); + virtual void InitOSExtras(void* p); + virtual int OpenOSfhandle(long osfhandle, int flags); + virtual int GetOSfhandle(int filenum); + + void ShutDown(void); + + inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; + inline void SetSockCtl(CPerlSock *p) { pSock = p; }; +protected: + inline int IsWin95(void) + { + return (os_id() == VER_PLATFORM_WIN32_WINDOWS); + }; + inline int IsWinNT(void) + { + return (os_id() == VER_PLATFORM_WIN32_NT); + }; + inline void AddToSocketTable(int fh) + { + if(fh < _NSTREAM_) + bSocketTable[fh] = TRUE; + }; + inline BOOL InSocketTable(int fh) + { + if(fh < _NSTREAM_) + return bSocketTable[fh]; + return FALSE; + }; + inline void RemoveFromSocketTable(int fh) + { + if(fh < _NSTREAM_) + bSocketTable[fh] = FALSE; + }; + DWORD os_id(void) + { + if((-1) == w32_platform) + { + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(OSVERSIONINFO)); + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osver); + w32_platform = osver.dwPlatformId; + } + return (w32_platform); + }; + + + CPerlObj *pPerl; + CPerlSock *pSock; + DWORD w32_platform; + BOOL bSocketTable[_NSTREAM_]; +}; + +void CPerlStdIO::ShutDown(void) +{ + int i, err; + for(i = 0; i < _NSTREAM_; ++i) + { + if(InSocketTable(i)) + pSock->CloseSocket(i, err); + } +}; + +#ifdef _X86_ +extern "C" int __cdecl _alloc_osfhnd(void); +extern "C" int __cdecl _set_osfhnd(int fh, long value); +extern "C" void __cdecl _unlock(int); + +#if (_MSC_VER >= 1000) +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 */ +} ioinfo; +extern "C" ioinfo * __pioinfo[]; +#define IOINFO_L2E 5 +#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) +#define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) +#define _osfile(i) (_pioinfo(i)->osfile) +#else +extern "C" extern char _osfile[]; +#endif // (_MSC_VER >= 1000) + +#define FOPEN 0x01 // file handle open +#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 _STREAM_LOCKS 26 // Table of stream locks +#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) // Last stream lock +#define _FH_LOCKS (_LAST_STREAM_LOCK+1) // Table of fh locks +#endif // _X86_ + +int CPerlStdIO::OpenOSfhandle(long osfhandle, int flags) +{ + int fh; + +#ifdef _X86_ + if(IsWin95()) + { + // all this is here to handle Win95's GetFileType bug. + char fileflags; // _osfile flags + + // copy relevant flags from second parameter + fileflags = FDEV; + + if(flags & _O_APPEND) + fileflags |= FAPPEND; + + if(flags & _O_TEXT) + fileflags |= FTEXT; + + // attempt to allocate a C Runtime file handle + if((fh = _alloc_osfhnd()) == -1) + { + errno = EMFILE; // too many open files + _doserrno = 0L; // not an OS error + return -1; // return error to caller + } + + // the file is open. now, set the info in _osfhnd array + _set_osfhnd(fh, osfhandle); + + fileflags |= FOPEN; // mark as open + +#if (_MSC_VER >= 1000) + _osfile(fh) = fileflags; // set osfile entry +#else + _osfile[fh] = fileflags; // set osfile entry +#endif + } + else +#endif // _X86_ + fh = _open_osfhandle(osfhandle, flags); + + if(fh >= 0) + AddToSocketTable(fh); + + return fh; // return handle +} + +int CPerlStdIO::GetOSfhandle(int filenum) +{ + return _get_osfhandle(filenum); +} + +PerlIO* CPerlStdIO::Stdin(void) +{ + return (PerlIO*)(&_iob[0]); +} + +PerlIO* CPerlStdIO::Stdout(void) +{ + return (PerlIO*)(&_iob[1]); +} + +PerlIO* CPerlStdIO::Stderr(void) +{ + return (PerlIO*)(&_iob[2]); +} + +PerlIO* CPerlStdIO::Open(const char *path, const char *mode, int &err) +{ + PerlIO* ret = NULL; + if(*path != '\0') + { + ret = (PerlIO*)fopen(path, mode); + if(errno) + err = errno; + } + else + err = EINVAL; + return ret; +} + +extern "C" int _free_osfhnd(int fh); +int CPerlStdIO::Close(PerlIO* pf, int &err) +{ + int ret = 0, fileNo = fileno((FILE*)pf); + if(InSocketTable(fileNo)) + { + RemoveFromSocketTable(fileNo); + pSock->CloseSocket(fileNo, err); + _free_osfhnd(fileNo); + fclose((FILE*)pf); + } + else + ret = fclose((FILE*)pf); + + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Eof(PerlIO* pf, int &err) +{ + int ret = feof((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Error(PerlIO* pf, int &err) +{ + int ret = ferror((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +void CPerlStdIO::Clearerr(PerlIO* pf, int &err) +{ + clearerr((FILE*)pf); + err = 0; +} + +int CPerlStdIO::Getc(PerlIO* pf, int &err) +{ + int ret = fgetc((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Putc(PerlIO* pf, int c, int &err) +{ + int ret = fputc(c, (FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Puts(PerlIO* pf, const char *s, int &err) +{ + int ret = fputs(s, (FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Flush(PerlIO* pf, int &err) +{ + int ret = fflush((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Ungetc(PerlIO* pf,int c, int &err) +{ + int ret = ungetc(c, (FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Fileno(PerlIO* pf, int &err) +{ + int ret = fileno((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +PerlIO* CPerlStdIO::Fdopen(int fh, const char *mode, int &err) +{ + PerlIO* ret = (PerlIO*)fdopen(fh, mode); + if(errno) + err = errno; + return ret; +} + +SSize_t CPerlStdIO::Read(PerlIO* pf, void * buffer, Size_t count, int &err) +{ + size_t ret = fread(buffer, 1, count, (FILE*)pf); + if(errno) + err = errno; + return ret; +} + +SSize_t CPerlStdIO::Write(PerlIO* pf, const void * buffer, Size_t count, int &err) +{ + size_t ret = fwrite(buffer, 1, count, (FILE*)pf); + if(errno) + err = errno; + return ret; +} + +void CPerlStdIO::Setlinebuf(PerlIO*, int &err) +{ + croak("setlinebuf not implemented!\n"); +} + +int CPerlStdIO::Printf(PerlIO* pf, int &err, const char *format, ...) +{ + va_list(arglist); + va_start(arglist, format); + int ret = Vprintf(pf, err, format, arglist); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Vprintf(PerlIO* pf, int &err, const char * format, va_list arg) +{ + int ret = vfprintf((FILE*)pf, format, arg); + if(errno) + err = errno; + return ret; +} + +long CPerlStdIO::Tell(PerlIO* pf, int &err) +{ + long ret = ftell((FILE*)pf); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Seek(PerlIO* pf, off_t offset, int origin, int &err) +{ + int ret = fseek((FILE*)pf, offset, origin); + if(errno) + err = errno; + return ret; +} + +void CPerlStdIO::Rewind(PerlIO* pf, int &err) +{ + rewind((FILE*)pf); +} + +PerlIO* CPerlStdIO::Tmpfile(int &err) +{ + return (PerlIO*)tmpfile(); +} + +int CPerlStdIO::Getpos(PerlIO* pf, Fpos_t *p, int &err) +{ + int ret = fgetpos((FILE*)pf, (fpos_t*)p); + if(errno) + err = errno; + return ret; +} + +int CPerlStdIO::Setpos(PerlIO* pf, const Fpos_t *p, int &err) +{ + int ret = fsetpos((FILE*)pf, (fpos_t*)p); + if(errno) + err = errno; + return ret; +} + +char* CPerlStdIO::GetBase(PerlIO *pf, int &err) +{ + return ((FILE*)pf)->_base; +} + +int CPerlStdIO::GetBufsiz(PerlIO *pf, int &err) +{ + return ((FILE*)pf)->_bufsiz; +} + +int CPerlStdIO::GetCnt(PerlIO *pf, int &err) +{ + return ((FILE*)pf)->_cnt; +} + +char* CPerlStdIO::GetPtr(PerlIO *pf, int &err) +{ + return ((FILE*)pf)->_ptr; +} + +void CPerlStdIO::SetCnt(PerlIO *pf, int n, int &err) +{ + ((FILE*)pf)->_cnt = n; +} + +void CPerlStdIO::SetPtrCnt(PerlIO *pf, char *ptr, int n, int& err) +{ + ((FILE*)pf)->_ptr = ptr; + ((FILE*)pf)->_cnt = n; +} + +void CPerlStdIO::Init(int &err) +{ +} + +void CPerlStdIO::InitOSExtras(void* p) +{ +} + + diff --git a/win32/ipstdiowin.h b/win32/ipstdiowin.h new file mode 100644 index 0000000000..e4895272c0 --- /dev/null +++ b/win32/ipstdiowin.h @@ -0,0 +1,22 @@ +/* + + ipstdiowin.h + Interface for perl stdio functions + +*/ + +#ifndef __Inc__IPerlStdIOWin___ +#define __Inc__IPerlStdIOWin___ + +#include <ipstdio.h> + + +class IPerlStdIOWin : public IPerlStdIO +{ +public: + virtual int OpenOSfhandle(long osfhandle, int flags) = 0; + virtual int GetOSfhandle(int filenum) = 0; +}; + +#endif /* __Inc__IPerlStdIOWin___ */ + diff --git a/win32/makedef.pl b/win32/makedef.pl index ddf01fdab8..b4097d5c23 100644 --- a/win32/makedef.pl +++ b/win32/makedef.pl @@ -104,6 +104,7 @@ Perl_dump_packsubs Perl_dump_pm Perl_dump_sub Perl_expectterm +Perl_error_no Perl_fetch_gv Perl_fetch_io Perl_force_ident @@ -156,6 +157,7 @@ Perl_scan_trans Perl_scan_word Perl_setenv_getix Perl_skipspace +Perl_sort_mutex Perl_sublex_done Perl_sublex_start Perl_sv_ref diff --git a/win32/perlobj.def b/win32/perlobj.def new file mode 100644 index 0000000000..6b0f65dad8 --- /dev/null +++ b/win32/perlobj.def @@ -0,0 +1,4 @@ +LIBRARY Perl500 +DESCRIPTION 'Perl interpreter' +EXPORTS + perl_alloc diff --git a/win32/runperl.c b/win32/runperl.c index 954460739f..76f9ea0b93 100644 --- a/win32/runperl.c +++ b/win32/runperl.c @@ -1,3 +1,173 @@ + +#ifdef PERL_OBJECT +#define USE_SOCKETS_AS_HANDLES +#include "EXTERN.h" +#include "perl.h" + +#include "XSUB.H" + +#include <ipdir.h> +#include <ipenv.h> +#include <ipsock.h> +#include <iplio.h> +#include <ipmem.h> +#include <ipproc.h> + +#include "ipstdiowin.h" +#include "ipdir.c" +#include "ipenv.c" +#include "ipsock.c" +#include "iplio.c" +#include "ipmem.c" +#include "ipproc.c" +#include "ipstdio.c" + +static void xs_init _((CPERLarg)); +#define stderr (&_iob[2]) +#undef fprintf +#undef environ + +class CPerlHost +{ +public: + CPerlHost() { pPerl = NULL; }; + inline BOOL PerlCreate(void) + { + try + { + pPerl = perl_alloc(&perlMem, + &perlEnv, + &perlStdIO, + &perlLIO, + &perlDir, + &perlSock, + &perlProc); + if(pPerl != NULL) + { + perlDir.SetPerlObj(pPerl); + perlEnv.SetPerlObj(pPerl); + perlLIO.SetPerlObj(pPerl); + perlLIO.SetSockCtl(&perlSock); + perlLIO.SetStdObj(&perlStdIO); + perlMem.SetPerlObj(pPerl); + perlProc.SetPerlObj(pPerl); + perlSock.SetPerlObj(pPerl); + perlSock.SetStdObj(&perlStdIO); + perlStdIO.SetPerlObj(pPerl); + perlStdIO.SetSockCtl(&perlSock); + try + { + pPerl->perl_construct(); + } + catch(...) + { + fprintf(stderr, "%s\n", "Error: Unable to construct data structures"); + pPerl->perl_free(); + pPerl = NULL; + } + } + } + catch(...) + { + fprintf(stderr, "%s\n", "Error: Unable to allocate memory"); + pPerl = NULL; + } + return (pPerl != NULL); + }; + inline int PerlParse(int argc, char** argv, char** env) + { + char* environ = NULL; + int retVal; + try + { + retVal = pPerl->perl_parse(xs_init, argc, argv, (env == NULL || *env == NULL ? &environ : env)); + } + catch(int x) + { + // this is where exit() should arrive + retVal = x; + } + catch(...) + { + fprintf(stderr, "Error: Parse exception\n"); + retVal = -1; + } + return retVal; + }; + inline int PerlRun(void) + { + int retVal; + try + { + retVal = pPerl->perl_run(); + } + catch(int x) + { + // this is where exit() should arrive + retVal = x; + } + catch(...) + { + fprintf(stderr, "Error: Runtime exception\n"); + retVal = -1; + } + return retVal; + }; + inline void PerlDestroy(void) + { + try + { + pPerl->perl_destruct(); + pPerl->perl_free(); + } + catch(...) + { + } + }; + +protected: + CPerlObj *pPerl; + CPerlDir perlDir; + CPerlEnv perlEnv; + CPerlLIO perlLIO; + CPerlMem perlMem; + CPerlProc perlProc; + CPerlSock perlSock; + CPerlStdIO perlStdIO; +}; + +#undef PERL_SYS_INIT +#define PERL_SYS_INIT(a, c) + +int +main(int argc, char **argv, char **env) +{ + CPerlHost host; + int exitstatus = 1; + + if(!host.PerlCreate()) + exit(exitstatus); + + + exitstatus = host.PerlParse(argc, argv, env); + + if (!exitstatus) + { + exitstatus = host.PerlRun(); + } + + host.PerlDestroy(); + + return exitstatus; +} + + +static void xs_init(CPERLarg) +{ +} + +#else /* PERL_OBJECT */ + /* Say NO to CPP! Hallelujah! */ #ifdef __GNUC__ /* @@ -22,3 +192,5 @@ main(int argc, char **argv, char **env) { return RunPerl(argc, argv, env, (void*)0); } + +#endif /* PERL_OBJECT */ diff --git a/win32/win32iop.h b/win32/win32iop.h index e71bf3865e..98627e4c6b 100644 --- a/win32/win32iop.h +++ b/win32/win32iop.h @@ -151,6 +151,7 @@ END_EXTERN_C #undef fileno #endif +#ifndef PERL_OBJECT #define stderr win32_stderr() #define stdout win32_stdout() #define stdin win32_stdin() @@ -163,6 +164,7 @@ END_EXTERN_C /* * redirect to our own version */ +#undef fprintf #define fprintf win32_fprintf #define vfprintf win32_vfprintf #define printf win32_printf @@ -177,6 +179,7 @@ END_EXTERN_C #define fputs(s,f) win32_fputs(s,f) #define fputc(c,f) win32_fputc(c,f) #define ungetc(c,f) win32_ungetc(c,f) +#undef getc #define getc(f) win32_getc(f) #define fileno(f) win32_fileno(f) #define clearerr(f) win32_clearerr(f) @@ -218,9 +221,12 @@ END_EXTERN_C #define fgets win32_fgets #define gets win32_gets #define fgetc win32_fgetc +#undef putc #define putc win32_putc #define puts win32_puts +#undef getchar #define getchar win32_getchar +#undef putchar #define putchar win32_putchar #if !defined(MYMALLOC) || !defined(PERL_CORE) @@ -241,6 +247,7 @@ END_EXTERN_C #define alarm win32_alarm #define ioctl win32_ioctl #define wait win32_wait +#endif /* PERL_OBJECT */ #ifdef HAVE_DES_FCRYPT #undef crypt @@ -248,8 +255,10 @@ END_EXTERN_C #endif #ifndef USE_WIN32_RTL_ENV +#ifndef PERL_OBJECT #undef getenv #define getenv win32_getenv +#endif /* PERL_OBJECT */ #endif #endif /* WIN32IO_IS_STDIO */ |