From: SVN Migration Date: Fri, 12 Jul 2002 13:02:46 +0000 (+0000) Subject: This commit was manufactured by cvs2svn to create branch 'PHP_4_2_0'. X-Git-Tag: php-4.2.3RC1~76 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5f6e25342f99916bc045bc649c20d1b707651c03;p=php This commit was manufactured by cvs2svn to create branch 'PHP_4_2_0'. --- diff --git a/TSRM/tsrm_config.nw.h b/TSRM/tsrm_config.nw.h new file mode 100644 index 0000000000..0681852c7d --- /dev/null +++ b/TSRM/tsrm_config.nw.h @@ -0,0 +1,9 @@ +#ifndef TSRM_CONFIG_NW_H +#define TSRM_CONFIG_NW_H + +#define HAVE_UTIME 1 + +/* Though we have alloca(), this seems to be causing some problem with the stack pointer -- hence not using it */ +/* #define HAVE_ALLOCA 1 */ + +#endif diff --git a/TSRM/tsrm_nw.c b/TSRM/tsrm_nw.c new file mode 100644 index 0000000000..c0f69adb5d --- /dev/null +++ b/TSRM/tsrm_nw.c @@ -0,0 +1,260 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Venkat Raghavan S | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include +#include +#include + +#include "TSRM.h" + +#ifdef NETWARE + +#ifdef USE_MKFIFO +#include +#elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */ +#include +#endif + +#include +#include + +#include + +#include "mktemp.h" + +/* strtok() call in LibC is abending when used in a different address space -- hence using + PHP's version itself for now : Venkat (30/4/02) */ +#include "tsrm_strtok_r.h" +#define tsrm_strtok_r(a,b,c) strtok((a),(b)) + +#define WHITESPACE " \t" +#define MAX_ARGS 10 + + +TSRM_API FILE* popen(const char *commandline, const char *type) +{ + char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL; + char *tempName = "sys:/php/temp/phpXXXXXX.tmp"; + char *filePath = NULL; + char *ptr = NULL; + int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0; + FILE *stream = NULL; +#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) + int pipe_handle; + int mode = O_RDONLY; +#else + NXHandle_t pipe_handle; + NXMode_t mode = NX_O_RDONLY; +#endif + NXExecEnvSpec_t envSpec; + NXNameSpec_t nameSpec; + NXVmId_t newVM = 0; + + /* Check for validity of input parameters */ + if (!commandline || !type) + return NULL; + + /* Get temporary file name */ + filePath = mktemp(tempName); +/*consoleprintf ("PHP | popen: file path = %s, mode = %s\n", filePath, type);*/ + if (!filePath) + return NULL; + + /* Set pipe mode according to type -- for now allow only "r" or "w" */ + if (strcmp(type, "r") == 0) +#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) + mode = O_RDONLY; +#else + mode = NX_O_RDONLY; +#endif + else if (strcmp(type, "w") == 0) +#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) + mode = O_WRONLY; +#else + mode = NX_O_WRONLY; +#endif + else + return NULL; + +#ifdef USE_PIPE_OPEN + pipe_handle = pipe_open(filePath, mode); +/*consoleprintf ("PHP | popen: pipe_open() returned %d\n", pipe_handle);*/ + if (pipe_handle == -1) + return NULL; +#elif defined(USE_MKFIFO) + pipe_handle = mkfifo(filePath, mode); +consoleprintf ("PHP | popen: mkfifo() returned %d\n", pipe_handle); + if (pipe_handle == -1) + return NULL; +#else + /* + - NetWare doesn't require first parameter + - Allowing LibC to choose the buffer size for now + */ + err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle); +/*consoleprintf ("PHP | popen: NXFifoOpen() returned %d\n", err);*/ + if (err) + return NULL; +#endif + + /* Copy the environment variables in preparation for the spawn call */ + + envCount = NXGetEnvCount() + 1; /* add one for NULL */ + env = (char**)NXMemAlloc(sizeof(char*) * envCount, 0); + if (!env) + return NULL; + + err = NXCopyEnv(env, envCount); +consoleprintf ("PHP | popen: NXCopyEnv() returned %d\n", err); + if (err) + { + NXMemFree (env); + return NULL; + } + + /* Separate commandline string into words */ +consoleprintf ("PHP | popen: commandline = %s\n", commandline); + ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL); + ptrLen = strlen(ptr); + + command = (char*)malloc(ptrLen + 1); + if (!command) + { + NXMemFree (env); + return NULL; + } + + strcpy (command, ptr); + + ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL); + while (ptr && (argc < MAX_ARGS)) + { + ptrLen = strlen(ptr); + + argv[argc] = (char*)malloc(ptrLen + 1); + if (!argv[argc]) + { + NXMemFree (env); + + if (command) + free (command); + + for (i = 0; i < argc; i++) + { + if (argv[i]) + free (argv[i]); + } + + return NULL; + } + + strcpy (argv[argc], ptr); + + argc++; + + ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL); + } +consoleprintf ("PHP | popen: commandline string parsed into tokens\n"); + /* Setup the execution environment and spawn new process */ + + envSpec.esFlags = 0; /* Not used */ + envSpec.esArgc = argc; + envSpec.esArgv = (void**)argv; + envSpec.esEnv = (void**)env; + + envSpec.esStdin.ssType = + envSpec.esStdout.ssType = NX_OBJ_FIFO; + envSpec.esStderr.ssType = NX_OBJ_FILE; +/* + envSpec.esStdin.ssHandle = + envSpec.esStdout.ssHandle = + envSpec.esStderr.ssHandle = -1; +*/ + envSpec.esStdin.ssPathCtx = + envSpec.esStdout.ssPathCtx = + envSpec.esStderr.ssPathCtx = NULL; + +#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) + if (mode == O_RDONLY) +#else + if (mode == NX_O_RDONLY) +#endif + { + envSpec.esStdin.ssPath = filePath; + envSpec.esStdout.ssPath = stdout; + } + else /* Write Only */ + { + envSpec.esStdin.ssPath = stdin; + envSpec.esStdout.ssPath = filePath; + } + + envSpec.esStderr.ssPath = stdout; + + nameSpec.ssType = NX_OBJ_FIFO; +/* nameSpec.ssHandle = 0; */ /* Not used */ + nameSpec.ssPathCtx = NULL; /* Not used */ + nameSpec.ssPath = argv[0]; +consoleprintf ("PHP | popen: environment setup\n"); + err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM); +consoleprintf ("PHP | popen: NXVmSpawn() returned %d\n", err); + if (!err) + /* Get file pointer corresponding to the pipe (file) opened */ + stream = fdopen(pipe_handle, type); + + /* Clean-up */ + + if (env) + NXMemFree (env); + + if (pipe_handle) +#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) + close(pipe_handle); +#else + NXClose(pipe_handle); +#endif + + if (command) + free (command); + + for (i = 0; i < argc; i++) + { + if (argv[i]) + free (argv[i]); + } +consoleprintf ("PHP | popen: all clean-up done, returning...\n"); + return stream; +} + +TSRM_API int pclose(FILE* stream) +{ + int err = 0; + NXHandle_t fd = 0; + + /* Get the process associated with this pipe (file) handle and terminate it */ + fd = fileno(stream); + NXClose (fd); + + err = fclose(stream); + + return err; +} + +#endif diff --git a/TSRM/tsrm_nw.h b/TSRM/tsrm_nw.h new file mode 100644 index 0000000000..3ced3f299b --- /dev/null +++ b/TSRM/tsrm_nw.h @@ -0,0 +1,28 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Venkat Raghavan S | + +----------------------------------------------------------------------+ +*/ + + +#ifndef TSRM_NW_H +#define TSRM_NW_H + +#include "TSRM.h" + +TSRM_API FILE* popen(const char *command, const char *type); +TSRM_API int pclose(FILE* stream); + +#endif diff --git a/ext/com/dispatch.c b/ext/com/dispatch.c new file mode 100644 index 0000000000..23c3b0dd91 --- /dev/null +++ b/ext/com/dispatch.c @@ -0,0 +1,627 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* + * This module is used to export PHP objects to COM and DOTNET by exposing + * them as objects implementing IDispatch. + * */ + +#include "php.h" +#include "php_COM.h" +#include "php_VARIANT.h" +#include "conversion.h" +#include "variant.h" + +#define COBJMACROS +#include /* IDispatch */ +#include /* IDispatchEx */ + + +typedef struct { + /* This first part MUST match the declaration + * of interface IDispatchEx */ + CONST_VTBL struct IDispatchExVtbl *lpVtbl; + + /* now the PHP stuff */ + + THREAD_T engine_thread; /* for sanity checking */ + zval *object; /* the object exported */ + LONG refcount; /* COM reference count */ + + HashTable *dispid_to_name; /* keep track of dispid -> name mappings */ + HashTable *name_to_dispid; /* keep track of name -> dispid mappings */ + + GUID sinkid; /* iid that we "implement" for event sinking */ + + int id; +} php_dispatchex; + +static void disp_destructor(php_dispatchex *disp); + +static void dispatch_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + php_dispatchex *disp = (php_dispatchex *)rsrc->ptr; + disp_destructor(disp); +} + +static int le_dispatch; +int php_COM_dispatch_init(int module_number TSRMLS_DC) +{ + le_dispatch = zend_register_list_destructors_ex(dispatch_dtor, NULL, "COM:Dispatch", module_number); + return le_dispatch; +} + + +/* {{{ trace */ +static inline void trace(char *fmt, ...) +{ + va_list ap; + char buf[4096]; + + sprintf(buf, "T=%08x ", tsrm_thread_id()); + OutputDebugString(buf); + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + + OutputDebugString(buf); + + va_end(ap); +} +/* }}} */ + +#define FETCH_DISP(methname) \ + php_dispatchex *disp = (php_dispatchex*)This; \ + trace(" PHP:%s %s\n", Z_OBJCE_P(disp->object)->name, methname); \ + if (tsrm_thread_id() != disp->engine_thread) \ + return E_UNEXPECTED; + + +static HRESULT STDMETHODCALLTYPE disp_queryinterface( + IDispatchEx *This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject) +{ + FETCH_DISP("QueryInterface"); + + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IDispatch, riid) || + IsEqualGUID(&IID_IDispatchEx, riid) || + IsEqualGUID(&disp->sinkid, riid)) { + *ppvObject = This; + InterlockedIncrement(&disp->refcount); + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE disp_addref(IDispatchEx *This) +{ + FETCH_DISP("AddRef"); + + return InterlockedIncrement(&disp->refcount); +} + +static ULONG STDMETHODCALLTYPE disp_release(IDispatchEx *This) +{ + ULONG ret; + TSRMLS_FETCH(); + FETCH_DISP("Release"); + + ret = InterlockedDecrement(&disp->refcount); + trace("-- refcount now %d\n", ret); + if (ret == 0) { + /* destroy it */ + if (disp->id) + zend_list_delete(disp->id); + } + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_gettypeinfocount( + IDispatchEx *This, + /* [out] */ UINT *pctinfo) +{ + FETCH_DISP("GetTypeInfoCount"); + + *pctinfo = 0; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE disp_gettypeinfo( + IDispatchEx *This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo) +{ + FETCH_DISP("GetTypeInfo"); + + *ppTInfo = NULL; + return DISP_E_BADINDEX; +} + +static HRESULT STDMETHODCALLTYPE disp_getidsofnames( + IDispatchEx *This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId) +{ + UINT i; + HRESULT ret = S_OK; + TSRMLS_FETCH(); + FETCH_DISP("GetIDsOfNames"); + + for (i = 0; i < cNames; i++) { + char *name; + unsigned int namelen; + zval **tmp; + + name = php_OLECHAR_to_char(rgszNames[i], &namelen, CP_ACP TSRMLS_CC); + + /* Lookup the name in the hash */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == FAILURE) { + ret = DISP_E_UNKNOWNNAME; + rgDispId[i] = 0; + } else { + rgDispId[i] = Z_LVAL_PP(tmp); + } + + efree(name); + + } + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_invoke( + IDispatchEx *This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr) +{ + return This->lpVtbl->InvokeEx(This, dispIdMember, + lcid, wFlags, pDispParams, + pVarResult, pExcepInfo, NULL); +} + +static HRESULT STDMETHODCALLTYPE disp_getdispid( + IDispatchEx *This, + /* [in] */ BSTR bstrName, + /* [in] */ DWORD grfdex, + /* [out] */ DISPID *pid) +{ + HRESULT ret = DISP_E_UNKNOWNNAME; + char *name; + unsigned int namelen; + zval **tmp; + TSRMLS_FETCH(); + FETCH_DISP("GetDispID"); + + name = php_OLECHAR_to_char(bstrName, &namelen, CP_ACP TSRMLS_CC); + + /* Lookup the name in the hash */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) { + *pid = Z_LVAL_PP(tmp); + ret = S_OK; + } + + efree(name); + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_invokeex( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [in] */ DISPPARAMS *pdp, + /* [out] */ VARIANT *pvarRes, + /* [out] */ EXCEPINFO *pei, + /* [unique][in] */ IServiceProvider *pspCaller) +{ + zval **name; + UINT i; + int codepage = CP_ACP; + zval *retval = NULL; + zval ***params = NULL; + HRESULT ret = DISP_E_MEMBERNOTFOUND; + TSRMLS_FETCH(); + FETCH_DISP("InvokeEx"); + + if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { + /* TODO: add support for overloaded objects */ + + trace("-- Invoke: %d %20s flags=%08x args=%d\n", id, Z_STRVAL_PP(name), wFlags, pdp->cArgs); + + /* convert args into zvals. + * Args are in reverse order */ + params = (zval ***)emalloc(sizeof(zval **) * pdp->cArgs); + for (i = 0; i < pdp->cArgs; i++) { + VARIANT *arg; + zval *zarg; + + arg = &pdp->rgvarg[ pdp->cArgs - 1 - i]; + + trace("alloc zval for arg %d VT=%08x\n", i, V_VT(arg)); + + ALLOC_INIT_ZVAL(zarg); + + if (V_VT(arg) == VT_DISPATCH) { + trace("arg %d is dispatchable\n", i); + if (NULL == php_COM_object_from_dispatch(V_DISPATCH(arg), zarg TSRMLS_CC)) { + trace("failed to convert arg %d to zval\n", i); + ZVAL_NULL(zarg); + } + } else { + // arg can't be an idispatch, so we don't care for the implicit AddRef() call here + if (FAILURE == php_variant_to_pval(arg, zarg, codepage TSRMLS_CC)) { + trace("failed to convert arg %d to zval\n", i); + ZVAL_NULL(zarg); + } + } + + params[i] = &zarg; + } + + trace("arguments processed, prepare to do some work\n"); + + if (wFlags & DISPATCH_PROPERTYGET) { + trace("trying to get a property\n"); + zend_hash_find(Z_OBJPROP_P(disp->object), Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, (void**)&retval); + } else if (wFlags & DISPATCH_PROPERTYPUT) { + trace("trying to set a property\n"); + add_property_zval(disp->object, Z_STRVAL_PP(name), *params[0]); + } else if (wFlags & DISPATCH_METHOD) { + trace("Trying to call user function\n"); + if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name, + &retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) { + ret = S_OK; + } else { + ret = DISP_E_EXCEPTION; + } + } else { + trace("Don't know how to handle this invocation %08x\n", wFlags); + } + + /* release arguments */ + for (i = 0; i < pdp->cArgs; i++) + zval_ptr_dtor(params[i]); + efree(params); + + /* return value */ + if (retval) { + if (pvarRes) { + if (Z_TYPE_P(retval) == IS_OBJECT) { + /* export the object using a dispatch like ourselves */ + VariantInit(pvarRes); + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = php_COM_export_object(retval TSRMLS_CC); + } else { + php_pval_to_variant(retval, pvarRes, codepage TSRMLS_CC); + } + } + zval_ptr_dtor(&retval); + } else if (pvarRes) { + VariantInit(pvarRes); + } + + } else { + trace("InvokeEx: I don't support DISPID=%d\n", id); + } + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_deletememberbyname( + IDispatchEx *This, + /* [in] */ BSTR bstrName, + /* [in] */ DWORD grfdex) +{ + FETCH_DISP("DeleteMemberByName"); + + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_deletememberbydispid( + IDispatchEx *This, + /* [in] */ DISPID id) +{ + FETCH_DISP("DeleteMemberByDispID"); + + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_getmemberproperties( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [in] */ DWORD grfdexFetch, + /* [out] */ DWORD *pgrfdex) +{ + FETCH_DISP("GetMemberProperties"); + + return DISP_E_UNKNOWNNAME; +} + +static HRESULT STDMETHODCALLTYPE disp_getmembername( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [out] */ BSTR *pbstrName) +{ + zval *name; + TSRMLS_FETCH(); + FETCH_DISP("GetMemberName"); + + if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { + OLECHAR *olestr = php_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP TSRMLS_CC); + *pbstrName = SysAllocString(olestr); + efree(olestr); + return S_OK; + } else { + return DISP_E_UNKNOWNNAME; + } +} + +static HRESULT STDMETHODCALLTYPE disp_getnextdispid( + IDispatchEx *This, + /* [in] */ DWORD grfdex, + /* [in] */ DISPID id, + /* [out] */ DISPID *pid) +{ + ulong next = id+1; + FETCH_DISP("GetNextDispID"); + + while(!zend_hash_index_exists(disp->dispid_to_name, next)) + next++; + + if (zend_hash_index_exists(disp->dispid_to_name, next)) { + *pid = next; + return S_OK; + } + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_getnamespaceparent( + IDispatchEx *This, + /* [out] */ IUnknown **ppunk) +{ + FETCH_DISP("GetNameSpaceParent"); + + *ppunk = NULL; + return E_NOTIMPL; +} + +static struct IDispatchExVtbl php_dispatch_vtbl = { + disp_queryinterface, + disp_addref, + disp_release, + disp_gettypeinfocount, + disp_gettypeinfo, + disp_getidsofnames, + disp_invoke, + disp_getdispid, + disp_invokeex, + disp_deletememberbyname, + disp_deletememberbydispid, + disp_getmemberproperties, + disp_getmembername, + disp_getnextdispid, + disp_getnamespaceparent +}; + + +/* enumerate functions and properties of the object and assign + * dispatch ids */ +static void generate_dispids(php_dispatchex *disp TSRMLS_DC) +{ + HashPosition pos; + char *name = NULL; + zval *tmp; + int namelen; + int keytype; + ulong pid; + + if (disp->dispid_to_name == NULL) { + ALLOC_HASHTABLE(disp->dispid_to_name); + ALLOC_HASHTABLE(disp->name_to_dispid); + zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(disp->dispid_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); + } + + /* properties */ + zend_hash_internal_pointer_reset_ex(Z_OBJPROP_PP(&disp->object), &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(Z_OBJPROP_PP(&disp->object), &name, &namelen, &pid, 0, &pos))) { + char namebuf[32]; + if (keytype == HASH_KEY_IS_LONG) { + sprintf(namebuf, "%d", pid); + name = namebuf; + namelen = strlen(namebuf); + } + + zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); + + /* Find the existing id */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) + continue; + + /* add the mappings */ + MAKE_STD_ZVAL(tmp); + ZVAL_STRINGL(tmp, name, namelen, 1); + zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); + + } + + /* functions */ + zend_hash_internal_pointer_reset_ex(&Z_OBJCE_PP(&disp->object)->function_table, &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(&Z_OBJCE_PP(&disp->object)->function_table, &name, &namelen, &pid, 0, &pos))) { + + char namebuf[32]; + if (keytype == HASH_KEY_IS_LONG) { + sprintf(namebuf, "%d", pid); + name = namebuf; + namelen = strlen(namebuf); + } + + zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); + + /* Find the existing id */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) + continue; + + /* add the mappings */ + MAKE_STD_ZVAL(tmp); + ZVAL_STRINGL(tmp, name, namelen, 1); + zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); + } +} + +static php_dispatchex *disp_constructor(zval *object TSRMLS_DC) +{ + php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex)); + + trace("constructing a COM proxy\n"); + + if (disp == NULL) + return NULL; + + memset(disp, 0, sizeof(php_dispatchex)); + + disp->engine_thread = tsrm_thread_id(); + disp->lpVtbl = &php_dispatch_vtbl; + disp->refcount = 1; + + + if (object) + ZVAL_ADDREF(object); + disp->object = object; + + disp->id = zend_list_insert(disp, le_dispatch); + + return disp; +} + +static void disp_destructor(php_dispatchex *disp) +{ + TSRMLS_FETCH(); + + trace("destroying COM wrapper for PHP object %s\n", Z_OBJCE_P(disp->object)->name); + + disp->id = 0; + + if (disp->refcount > 0) + CoDisconnectObject((IUnknown*)disp, 0); + + zend_hash_destroy(disp->dispid_to_name); + zend_hash_destroy(disp->name_to_dispid); + FREE_HASHTABLE(disp->dispid_to_name); + FREE_HASHTABLE(disp->name_to_dispid); + + if (disp->object) + zval_ptr_dtor(&disp->object); + + + CoTaskMemFree(disp); +} + +PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC) +{ + php_dispatchex *disp = disp_constructor(val TSRMLS_CC); + HashPosition pos; + char *name = NULL; + zval *tmp, **ntmp; + int namelen; + int keytype; + ulong pid; + + disp->dispid_to_name = id_to_name; + + memcpy(&disp->sinkid, sinkid, sizeof(disp->sinkid)); + + /* build up the reverse mapping */ + ALLOC_HASHTABLE(disp->name_to_dispid); + zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); + + zend_hash_internal_pointer_reset_ex(id_to_name, &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(id_to_name, &name, &namelen, &pid, 0, &pos))) { + + if (keytype == HASH_KEY_IS_LONG) { + + zend_hash_get_current_data_ex(id_to_name, (void**)&ntmp, &pos); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, Z_STRVAL_PP(ntmp), Z_STRLEN_PP(ntmp)+1, (void*)&tmp, sizeof(zval *), NULL); + } + + zend_hash_move_forward_ex(id_to_name, &pos); + } + + return (IDispatch*)disp; +} + +PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC) +{ + php_dispatchex *disp = NULL; + + if (Z_TYPE_P(val) != IS_OBJECT) + return NULL; + + if (Z_OBJCE_P(val) == &COM_class_entry || !strcmp(Z_OBJCE_P(val)->name, "COM")) { + /* pass back it's IDispatch directly */ + zval **tmp; + comval *obj; + int type; + + zend_hash_index_find(Z_OBJPROP_P(val), 0, (void**)&tmp); + obj = (comval *)zend_list_find(Z_LVAL_PP(tmp), &type); + if (type != IS_COM) + return NULL; + + C_DISPATCH(obj)->lpVtbl->AddRef(C_DISPATCH(obj)); + return C_DISPATCH(obj); + } + + disp = disp_constructor(val TSRMLS_CC); + generate_dispids(disp TSRMLS_CC); + + return (IDispatch*)disp; +} + + diff --git a/ext/mysql/mysql.mak b/ext/mysql/mysql.mak new file mode 100644 index 0000000000..8dd34ec601 --- /dev/null +++ b/ext/mysql/mysql.mak @@ -0,0 +1,168 @@ +# Temporarily here -- later may go into some batch file +# which will set this as an environment variable +PROJECT_ROOT = ..\.. + +# Module details +MODULE_NAME = phpmysql +MODULE_DESC = "PHP MySQL Extension" +VMAJ = 0 +VMIN = 60 +VREV = 0 + +#include the common settings +include $(PROJECT_ROOT)/netware/common.mif + +# MYSQL stuff +MYSQL_DIR = P:/APPS/script/sw/mysql + +# Build type defaults to 'release' +ifndef BUILD +BUILD = release +endif + +# Extensions of all input and output files +.SUFFIXES: +.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d + +# Source files +C_SRC = php_mysql.c \ + start.c + +CPP_SRC_NODIR = $(notdir $(CPP_SRC)) +C_SRC_NODIR = $(notdir $(C_SRC)) +SRC_DIR = $(dir $(CPP_SRC) $(C_SRC)) + +# Library files +LIBRARY = $(MYSQL_DIR)/lib/libmysqlclient.lib + +# Destination directories and files +OBJ_DIR = $(BUILD) +FINAL_DIR = $(BUILD) +OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC_NODIR:.c=.obj) $(C_SRC_NODIR:.c=.obj)) +DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC_NODIR:.c=.d) $(C_SRC_NODIR:.c=.d)) + +# Binary file +ifndef BINARY + BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm +endif + +# Compile flags +C_FLAGS = -c -maxerrors 25 -msgstyle gcc -wchar_t on -bool on -processor Pentium -align 1 +C_FLAGS += -nostdinc -nosyspath +C_FLAGS += -DNETWARE -DZTS -DNEW_LIBC -DUSE_OLD_FUNCTIONS -DCOMPILE_DL=1 +C_FLAGS += -I. -I$(PROJECT_ROOT)/main -I$(PROJECT_ROOT)/ext/standard -I$(PROJECT_ROOT) -I$(PROJECT_ROOT)/netware +C_FLAGS += -I$(PROJECT_ROOT)/zend -I$(PROJECT_ROOT)/tsrm +C_FLAGS += -I- -I$(SDK_DIR)/include -I$(MWCIncludes) +C_FLAGS += -I$(MYSQL_DIR)/include -DCOMPILE_DL_MYSQL=1 +C_FLAGS += -I$(WINSOCK_DIR)/include/nlm -I$(WINSOCK_DIR)/include + + +# Extra stuff based on debug / release builds +ifeq '$(BUILD)' 'debug' + SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym + C_FLAGS += -inline smart -sym on -sym codeview4 -opt off -opt intrinsics -DDEBUGGING -DDKFBPON + C_FLAGS += -exc cw -DZEND_DEBUG=1 + LD_FLAGS += -sym on -sym codeview4 -osym $(SYM_FILE) + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib +else + C_FLAGS += -opt speed -inline on -inline smart -inline auto -sym off -opt intrinsics + C_FLAGS += -opt level=4 -DZEND_DEBUG=0 + LD_FLAGS += -sym off + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib +endif + + +# Dependencies +MODULE = LibC \ + phplib +IMPORT = @$(SDK_DIR)/imports/libc.imp \ + @$(SDK_DIR)/imports/ws2nlm.imp \ + @$(MPK_DIR)/import/mpkOrg.imp \ + @$(PROJECT_ROOT)/netware/phplib.imp + +#EXPORT = mysql_functions \ +# mysql_module_entry \ +# ($(MODULE_NAME).nlm) get_module +EXPORT = ($(MODULE_NAME)) get_module +API = OutputToScreen + +# Virtual paths +vpath %.cpp . +vpath %.c . ..\..\netware +vpath %.obj $(OBJ_DIR) + + +all: prebuild project + +.PHONY: all + +prebuild: + @if not exist $(OBJ_DIR) md $(OBJ_DIR) + +project: $(BINARY) + @echo Build complete. + +$(OBJ_DIR)/%.d: %.cpp + @echo Building Dependencies for $( $(basename $@).def +ifdef API + @echo Import $(API) >> $(basename $@).def +endif + @echo Module $(MODULE) >> $(basename $@).def +ifdef EXPORT + @echo Export $(EXPORT) >> $(basename $@).def +endif + @echo AutoUnload >> $(basename $@).def +ifeq '$(BUILD)' 'debug' + @echo Debug >> $(basename $@).def +endif + @echo Flag_On 0x00000008 >> $(basename $@).def + @echo Start _NonAppStart >> $(basename $@).def + @echo Exit _NonAppStop >> $(basename $@).def + + @echo Linking $@... + @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link + @echo $(LIBRARY) $(OBJECTS) >> $(basename $@).link + @$(LINK) @$(basename $@).link + + +.PHONY: clean +clean: cleand cleanobj cleanbin + +.PHONY: cleand +cleand: + @echo Deleting all dependency files... + -@del "$(OBJ_DIR)\*.d" + +.PHONY: cleanobj +cleanobj: + @echo Deleting all object files... + -@del "$(OBJ_DIR)\*.obj" + +.PHONY: cleanbin +cleanbin: + @echo Deleting binary files... + -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" + @echo Deleting MAP, DEF files, etc.... + -@del "$(FINAL_DIR)\$(MODULE_NAME).map" + -@del "$(FINAL_DIR)\$(MODULE_NAME).def" + -@del "$(FINAL_DIR)\$(MODULE_NAME).link" +ifeq '$(BUILD)' 'debug' + -@del $(FINAL_DIR)\$(MODULE_NAME).sym +endif diff --git a/ext/rpc/com/dispatch.c b/ext/rpc/com/dispatch.c new file mode 100644 index 0000000000..23c3b0dd91 --- /dev/null +++ b/ext/rpc/com/dispatch.c @@ -0,0 +1,627 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* + * This module is used to export PHP objects to COM and DOTNET by exposing + * them as objects implementing IDispatch. + * */ + +#include "php.h" +#include "php_COM.h" +#include "php_VARIANT.h" +#include "conversion.h" +#include "variant.h" + +#define COBJMACROS +#include /* IDispatch */ +#include /* IDispatchEx */ + + +typedef struct { + /* This first part MUST match the declaration + * of interface IDispatchEx */ + CONST_VTBL struct IDispatchExVtbl *lpVtbl; + + /* now the PHP stuff */ + + THREAD_T engine_thread; /* for sanity checking */ + zval *object; /* the object exported */ + LONG refcount; /* COM reference count */ + + HashTable *dispid_to_name; /* keep track of dispid -> name mappings */ + HashTable *name_to_dispid; /* keep track of name -> dispid mappings */ + + GUID sinkid; /* iid that we "implement" for event sinking */ + + int id; +} php_dispatchex; + +static void disp_destructor(php_dispatchex *disp); + +static void dispatch_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + php_dispatchex *disp = (php_dispatchex *)rsrc->ptr; + disp_destructor(disp); +} + +static int le_dispatch; +int php_COM_dispatch_init(int module_number TSRMLS_DC) +{ + le_dispatch = zend_register_list_destructors_ex(dispatch_dtor, NULL, "COM:Dispatch", module_number); + return le_dispatch; +} + + +/* {{{ trace */ +static inline void trace(char *fmt, ...) +{ + va_list ap; + char buf[4096]; + + sprintf(buf, "T=%08x ", tsrm_thread_id()); + OutputDebugString(buf); + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + + OutputDebugString(buf); + + va_end(ap); +} +/* }}} */ + +#define FETCH_DISP(methname) \ + php_dispatchex *disp = (php_dispatchex*)This; \ + trace(" PHP:%s %s\n", Z_OBJCE_P(disp->object)->name, methname); \ + if (tsrm_thread_id() != disp->engine_thread) \ + return E_UNEXPECTED; + + +static HRESULT STDMETHODCALLTYPE disp_queryinterface( + IDispatchEx *This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject) +{ + FETCH_DISP("QueryInterface"); + + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IDispatch, riid) || + IsEqualGUID(&IID_IDispatchEx, riid) || + IsEqualGUID(&disp->sinkid, riid)) { + *ppvObject = This; + InterlockedIncrement(&disp->refcount); + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE disp_addref(IDispatchEx *This) +{ + FETCH_DISP("AddRef"); + + return InterlockedIncrement(&disp->refcount); +} + +static ULONG STDMETHODCALLTYPE disp_release(IDispatchEx *This) +{ + ULONG ret; + TSRMLS_FETCH(); + FETCH_DISP("Release"); + + ret = InterlockedDecrement(&disp->refcount); + trace("-- refcount now %d\n", ret); + if (ret == 0) { + /* destroy it */ + if (disp->id) + zend_list_delete(disp->id); + } + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_gettypeinfocount( + IDispatchEx *This, + /* [out] */ UINT *pctinfo) +{ + FETCH_DISP("GetTypeInfoCount"); + + *pctinfo = 0; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE disp_gettypeinfo( + IDispatchEx *This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo) +{ + FETCH_DISP("GetTypeInfo"); + + *ppTInfo = NULL; + return DISP_E_BADINDEX; +} + +static HRESULT STDMETHODCALLTYPE disp_getidsofnames( + IDispatchEx *This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId) +{ + UINT i; + HRESULT ret = S_OK; + TSRMLS_FETCH(); + FETCH_DISP("GetIDsOfNames"); + + for (i = 0; i < cNames; i++) { + char *name; + unsigned int namelen; + zval **tmp; + + name = php_OLECHAR_to_char(rgszNames[i], &namelen, CP_ACP TSRMLS_CC); + + /* Lookup the name in the hash */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == FAILURE) { + ret = DISP_E_UNKNOWNNAME; + rgDispId[i] = 0; + } else { + rgDispId[i] = Z_LVAL_PP(tmp); + } + + efree(name); + + } + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_invoke( + IDispatchEx *This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr) +{ + return This->lpVtbl->InvokeEx(This, dispIdMember, + lcid, wFlags, pDispParams, + pVarResult, pExcepInfo, NULL); +} + +static HRESULT STDMETHODCALLTYPE disp_getdispid( + IDispatchEx *This, + /* [in] */ BSTR bstrName, + /* [in] */ DWORD grfdex, + /* [out] */ DISPID *pid) +{ + HRESULT ret = DISP_E_UNKNOWNNAME; + char *name; + unsigned int namelen; + zval **tmp; + TSRMLS_FETCH(); + FETCH_DISP("GetDispID"); + + name = php_OLECHAR_to_char(bstrName, &namelen, CP_ACP TSRMLS_CC); + + /* Lookup the name in the hash */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) { + *pid = Z_LVAL_PP(tmp); + ret = S_OK; + } + + efree(name); + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_invokeex( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [in] */ DISPPARAMS *pdp, + /* [out] */ VARIANT *pvarRes, + /* [out] */ EXCEPINFO *pei, + /* [unique][in] */ IServiceProvider *pspCaller) +{ + zval **name; + UINT i; + int codepage = CP_ACP; + zval *retval = NULL; + zval ***params = NULL; + HRESULT ret = DISP_E_MEMBERNOTFOUND; + TSRMLS_FETCH(); + FETCH_DISP("InvokeEx"); + + if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { + /* TODO: add support for overloaded objects */ + + trace("-- Invoke: %d %20s flags=%08x args=%d\n", id, Z_STRVAL_PP(name), wFlags, pdp->cArgs); + + /* convert args into zvals. + * Args are in reverse order */ + params = (zval ***)emalloc(sizeof(zval **) * pdp->cArgs); + for (i = 0; i < pdp->cArgs; i++) { + VARIANT *arg; + zval *zarg; + + arg = &pdp->rgvarg[ pdp->cArgs - 1 - i]; + + trace("alloc zval for arg %d VT=%08x\n", i, V_VT(arg)); + + ALLOC_INIT_ZVAL(zarg); + + if (V_VT(arg) == VT_DISPATCH) { + trace("arg %d is dispatchable\n", i); + if (NULL == php_COM_object_from_dispatch(V_DISPATCH(arg), zarg TSRMLS_CC)) { + trace("failed to convert arg %d to zval\n", i); + ZVAL_NULL(zarg); + } + } else { + // arg can't be an idispatch, so we don't care for the implicit AddRef() call here + if (FAILURE == php_variant_to_pval(arg, zarg, codepage TSRMLS_CC)) { + trace("failed to convert arg %d to zval\n", i); + ZVAL_NULL(zarg); + } + } + + params[i] = &zarg; + } + + trace("arguments processed, prepare to do some work\n"); + + if (wFlags & DISPATCH_PROPERTYGET) { + trace("trying to get a property\n"); + zend_hash_find(Z_OBJPROP_P(disp->object), Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, (void**)&retval); + } else if (wFlags & DISPATCH_PROPERTYPUT) { + trace("trying to set a property\n"); + add_property_zval(disp->object, Z_STRVAL_PP(name), *params[0]); + } else if (wFlags & DISPATCH_METHOD) { + trace("Trying to call user function\n"); + if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name, + &retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) { + ret = S_OK; + } else { + ret = DISP_E_EXCEPTION; + } + } else { + trace("Don't know how to handle this invocation %08x\n", wFlags); + } + + /* release arguments */ + for (i = 0; i < pdp->cArgs; i++) + zval_ptr_dtor(params[i]); + efree(params); + + /* return value */ + if (retval) { + if (pvarRes) { + if (Z_TYPE_P(retval) == IS_OBJECT) { + /* export the object using a dispatch like ourselves */ + VariantInit(pvarRes); + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = php_COM_export_object(retval TSRMLS_CC); + } else { + php_pval_to_variant(retval, pvarRes, codepage TSRMLS_CC); + } + } + zval_ptr_dtor(&retval); + } else if (pvarRes) { + VariantInit(pvarRes); + } + + } else { + trace("InvokeEx: I don't support DISPID=%d\n", id); + } + + return ret; +} + +static HRESULT STDMETHODCALLTYPE disp_deletememberbyname( + IDispatchEx *This, + /* [in] */ BSTR bstrName, + /* [in] */ DWORD grfdex) +{ + FETCH_DISP("DeleteMemberByName"); + + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_deletememberbydispid( + IDispatchEx *This, + /* [in] */ DISPID id) +{ + FETCH_DISP("DeleteMemberByDispID"); + + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_getmemberproperties( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [in] */ DWORD grfdexFetch, + /* [out] */ DWORD *pgrfdex) +{ + FETCH_DISP("GetMemberProperties"); + + return DISP_E_UNKNOWNNAME; +} + +static HRESULT STDMETHODCALLTYPE disp_getmembername( + IDispatchEx *This, + /* [in] */ DISPID id, + /* [out] */ BSTR *pbstrName) +{ + zval *name; + TSRMLS_FETCH(); + FETCH_DISP("GetMemberName"); + + if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { + OLECHAR *olestr = php_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP TSRMLS_CC); + *pbstrName = SysAllocString(olestr); + efree(olestr); + return S_OK; + } else { + return DISP_E_UNKNOWNNAME; + } +} + +static HRESULT STDMETHODCALLTYPE disp_getnextdispid( + IDispatchEx *This, + /* [in] */ DWORD grfdex, + /* [in] */ DISPID id, + /* [out] */ DISPID *pid) +{ + ulong next = id+1; + FETCH_DISP("GetNextDispID"); + + while(!zend_hash_index_exists(disp->dispid_to_name, next)) + next++; + + if (zend_hash_index_exists(disp->dispid_to_name, next)) { + *pid = next; + return S_OK; + } + return S_FALSE; +} + +static HRESULT STDMETHODCALLTYPE disp_getnamespaceparent( + IDispatchEx *This, + /* [out] */ IUnknown **ppunk) +{ + FETCH_DISP("GetNameSpaceParent"); + + *ppunk = NULL; + return E_NOTIMPL; +} + +static struct IDispatchExVtbl php_dispatch_vtbl = { + disp_queryinterface, + disp_addref, + disp_release, + disp_gettypeinfocount, + disp_gettypeinfo, + disp_getidsofnames, + disp_invoke, + disp_getdispid, + disp_invokeex, + disp_deletememberbyname, + disp_deletememberbydispid, + disp_getmemberproperties, + disp_getmembername, + disp_getnextdispid, + disp_getnamespaceparent +}; + + +/* enumerate functions and properties of the object and assign + * dispatch ids */ +static void generate_dispids(php_dispatchex *disp TSRMLS_DC) +{ + HashPosition pos; + char *name = NULL; + zval *tmp; + int namelen; + int keytype; + ulong pid; + + if (disp->dispid_to_name == NULL) { + ALLOC_HASHTABLE(disp->dispid_to_name); + ALLOC_HASHTABLE(disp->name_to_dispid); + zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(disp->dispid_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); + } + + /* properties */ + zend_hash_internal_pointer_reset_ex(Z_OBJPROP_PP(&disp->object), &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(Z_OBJPROP_PP(&disp->object), &name, &namelen, &pid, 0, &pos))) { + char namebuf[32]; + if (keytype == HASH_KEY_IS_LONG) { + sprintf(namebuf, "%d", pid); + name = namebuf; + namelen = strlen(namebuf); + } + + zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); + + /* Find the existing id */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) + continue; + + /* add the mappings */ + MAKE_STD_ZVAL(tmp); + ZVAL_STRINGL(tmp, name, namelen, 1); + zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); + + } + + /* functions */ + zend_hash_internal_pointer_reset_ex(&Z_OBJCE_PP(&disp->object)->function_table, &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(&Z_OBJCE_PP(&disp->object)->function_table, &name, &namelen, &pid, 0, &pos))) { + + char namebuf[32]; + if (keytype == HASH_KEY_IS_LONG) { + sprintf(namebuf, "%d", pid); + name = namebuf; + namelen = strlen(namebuf); + } + + zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); + + /* Find the existing id */ + if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) + continue; + + /* add the mappings */ + MAKE_STD_ZVAL(tmp); + ZVAL_STRINGL(tmp, name, namelen, 1); + zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); + } +} + +static php_dispatchex *disp_constructor(zval *object TSRMLS_DC) +{ + php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex)); + + trace("constructing a COM proxy\n"); + + if (disp == NULL) + return NULL; + + memset(disp, 0, sizeof(php_dispatchex)); + + disp->engine_thread = tsrm_thread_id(); + disp->lpVtbl = &php_dispatch_vtbl; + disp->refcount = 1; + + + if (object) + ZVAL_ADDREF(object); + disp->object = object; + + disp->id = zend_list_insert(disp, le_dispatch); + + return disp; +} + +static void disp_destructor(php_dispatchex *disp) +{ + TSRMLS_FETCH(); + + trace("destroying COM wrapper for PHP object %s\n", Z_OBJCE_P(disp->object)->name); + + disp->id = 0; + + if (disp->refcount > 0) + CoDisconnectObject((IUnknown*)disp, 0); + + zend_hash_destroy(disp->dispid_to_name); + zend_hash_destroy(disp->name_to_dispid); + FREE_HASHTABLE(disp->dispid_to_name); + FREE_HASHTABLE(disp->name_to_dispid); + + if (disp->object) + zval_ptr_dtor(&disp->object); + + + CoTaskMemFree(disp); +} + +PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC) +{ + php_dispatchex *disp = disp_constructor(val TSRMLS_CC); + HashPosition pos; + char *name = NULL; + zval *tmp, **ntmp; + int namelen; + int keytype; + ulong pid; + + disp->dispid_to_name = id_to_name; + + memcpy(&disp->sinkid, sinkid, sizeof(disp->sinkid)); + + /* build up the reverse mapping */ + ALLOC_HASHTABLE(disp->name_to_dispid); + zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); + + zend_hash_internal_pointer_reset_ex(id_to_name, &pos); + while (HASH_KEY_NON_EXISTANT != (keytype = + zend_hash_get_current_key_ex(id_to_name, &name, &namelen, &pid, 0, &pos))) { + + if (keytype == HASH_KEY_IS_LONG) { + + zend_hash_get_current_data_ex(id_to_name, (void**)&ntmp, &pos); + + MAKE_STD_ZVAL(tmp); + ZVAL_LONG(tmp, pid); + zend_hash_update(disp->name_to_dispid, Z_STRVAL_PP(ntmp), Z_STRLEN_PP(ntmp)+1, (void*)&tmp, sizeof(zval *), NULL); + } + + zend_hash_move_forward_ex(id_to_name, &pos); + } + + return (IDispatch*)disp; +} + +PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC) +{ + php_dispatchex *disp = NULL; + + if (Z_TYPE_P(val) != IS_OBJECT) + return NULL; + + if (Z_OBJCE_P(val) == &COM_class_entry || !strcmp(Z_OBJCE_P(val)->name, "COM")) { + /* pass back it's IDispatch directly */ + zval **tmp; + comval *obj; + int type; + + zend_hash_index_find(Z_OBJPROP_P(val), 0, (void**)&tmp); + obj = (comval *)zend_list_find(Z_LVAL_PP(tmp), &type); + if (type != IS_COM) + return NULL; + + C_DISPATCH(obj)->lpVtbl->AddRef(C_DISPATCH(obj)); + return C_DISPATCH(obj); + } + + disp = disp_constructor(val TSRMLS_CC); + generate_dispids(disp TSRMLS_CC); + + return (IDispatch*)disp; +} + + diff --git a/ext/standard/tests/file/002.phpt b/ext/standard/tests/file/002.phpt new file mode 100644 index 0000000000..4642bac366 --- /dev/null +++ b/ext/standard/tests/file/002.phpt @@ -0,0 +1,54 @@ +--TEST-- +File/Stream functions +--POST-- +--GET-- +--FILE-- + +--EXPECT-- +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah diff --git a/main/config.nw.h b/main/config.nw.h new file mode 100644 index 0000000000..b2c15b56b0 --- /dev/null +++ b/main/config.nw.h @@ -0,0 +1,274 @@ +/* config.nw.h. Configure file for NetWare platform */ + + +/**** + +Need to carefully look into each constant and either define or undef it w.r.t. NetWare. + +****/ + + +/* Define if PHP to setup it's own SIGCHLD handler (not needed on NetWare) */ +#define PHP_SIGCHILD 0 + +/* dns functions found in resolv.lib */ +#define HAVE_LIBBIND 1 + +#define HAVE_GETSERVBYNAME 1 +#define HAVE_GETSERVBYPORT 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETPROTOBYNUMBER 1 + +/* set to enable bcmath */ +#define WITH_BCMATH 1 + +/* set to enable mysql */ +#define HAVE_MYSQL 1 + +/* set to enable FTP support */ +#define HAVE_FTP 1 + +/* set to enable bundled PCRE library */ +#define HAVE_BUNDLED_PCRE 1 + +/* set to enable bundled expat library */ +/* #define HAVE_LIBEXPAT 1 */ /* For now */ +#define HAVE_WDDX 0 + +/* set to enable the crypt command */ +/* #define HAVE_CRYPT 1 */ +/* #define HAVE_CRYPT_H 1 */ + +/* set to enable force cgi redirect */ +#define FORCE_CGI_REDIRECT 0 + +/* should be added to runtime config*/ +#define PHP_URL_FOPEN 1 + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +/* ---------------------------------------------------------------- + The following are defaults for run-time configuration + ---------------------------------------------------------------*/ + +#define PHP_SAFE_MODE 0 +#define MAGIC_QUOTES 0 +/* This is the default configuration file to read */ +#define CONFIGURATION_FILE_PATH "php.ini" +#define USE_CONFIG_FILE 1 + +#define PHP_INCLUDE_PATH NULL + + +/* Undefine if you want stricter XML/SGML compliance by default */ +/* this disables "" and "" */ +#define DEFAULT_SHORT_OPEN_TAG "1" + + +/* ---------------------------------------------------------------- + The following defines are for those modules which require + external libraries to compile. These will be removed from + here in a future beta, as these modules will be moved out to dll's + ---------------------------------------------------------------*/ +#define HAVE_ERRMSG_H 0 /*needed for mysql 3.21.17 and up*/ +#undef HAVE_ADABAS +#undef HAVE_SOLID + + +/* ---------------------------------------------------------------- + The following may or may not be (or need to be) ported to the + windows environment. + ---------------------------------------------------------------*/ + +/* Define if you have the link function. */ +#undef HAVE_LINK + +/* Define if you have the symlink function. */ +#undef HAVE_SYMLINK + +/* Define if you have the usleep function. */ +#undef HAVE_USLEEP + +#define HAVE_GETCWD 1 +/* #define HAVE_POSIX_READDIR_R 1 */ /* We will use readdir() from LibC */ + +#define NEED_ISBLANK 1 + +/* ---------------------------------------------------------------- + The following should never need to be played with + Functions defined to 0 or remarked out are either already + handled by the standard VC libraries, or are no longer needed, or + simply will/can not be ported. + + DONT TOUCH!!!!! Unless you realy know what your messing with! + ---------------------------------------------------------------*/ + +#define DISCARD_PATH 0 +#undef HAVE_SETITIMER +#undef HAVE_IODBC +#define HAVE_UODBC 1 +#define HAVE_LIBDL 1 +#define HAVE_SENDMAIL 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_PUTENV 1 +#define HAVE_LIMITS_H 1 + +#define HAVE_TZSET 1 +#define HAVE_TZNAME 1 + +/* Define if you have the flock function. */ +#undef HAVE_FLOCK + +/* Define if you have alloca, as a function or macro. */ +/* Though we have alloca(), this seems to be causing some problem with the stack pointer -- hence not using it */ +/* #define HAVE_ALLOCA 1 */ + +/* Define if you have */ +#undef HAVE_SYS_TIME_H + +/* Define if you have */ +#define HAVE_SIGNAL_H 1 + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if utime(file, NULL) sets file's timestamp to the present. */ +#define HAVE_UTIME_NULL 1 + +/* Define if you have the vprintf function. */ +#define HAVE_VPRINTF 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define both of these if you want the bundled REGEX library */ +#define REGEX 1 +#define HSREGEX 1 + +#define HAVE_PCRE 1 + +#define HAVE_LDAP 1 + +/* Define if you have the gcvt function. */ +/* #define HAVE_GCVT 1 */ + +/* Define if you have the getlogin function. */ +/* #define HAVE_GETLOGIN 1 */ + +/* Define if you have the gettimeofday function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE 1 + +/* Define if you have the putenv function. */ +/* #define HAVE_PUTENV 1 */ /* Why are such things defined in more than one place ? */ + +/* Define if you have the regcomp function. */ +/* #define HAVE_REGCOMP 1 */ + +/* Define if you have the setlocale function. */ +/* #define HAVE_SETLOCALE 1 */ /* LibC doesn't seem to be supporting fully -- hence commenting for now */ + +#define HAVE_LOCALECONV 1 + +#define HAVE_LOCALE_H 1 + +/* Define if you have the setvbuf function. */ +#ifndef HAVE_LIBBIND +#define HAVE_SETVBUF 1 +#endif + +/* Define if you have the snprintf function. */ +#define HAVE_SNPRINTF 1 +#define HAVE_VSNPRINTF 1 +/* Define if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the tempnam function. */ +#define HAVE_TEMPNAM 1 + +/* Define if you have the utime function. */ +#define HAVE_UTIME 1 + +/* Define if you have the header file. */ +#define HAVE_DIRENT_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 0 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 /* Added '1' for '#if' to work */ + +/* Define if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have the header file. */ +/* #define HAVE_SYSLOG_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 /* Added '1' for '#if' to work */ + +/* Define if you have the dl library (-ldl). */ +#define HAVE_LIBDL 1 + +/* Define if you have the m library (-lm). */ +#define HAVE_LIBM 1 + +/* Define if you have the cuserid function. */ +#define HAVE_CUSERID 0 + +/* Define if you have the rint function. */ +#undef HAVE_RINT + +#define HAVE_STRFTIME 1 + +/* Default directory for loading extensions. */ +#define PHP_EXTENSION_DIR "sys:/php/ext" + +#define SIZEOF_INT 4 + +/* Define directory constants for php and pear */ + +/* Venkat (20/12/01) */ +#define APACHE_MODULE_DIR "sys:/apache/modules" +#define PHP_BINDIR "sys:/php" +#define PHP_LIBDIR PHP_BINDIR +#define PHP_DATADIR PHP_BINDIR +#define PHP_SYSCONFDIR PHP_BINDIR +#define PHP_LOCALSTATEDIR PHP_BINDIR +#define PHP_CONFIG_FILE_PATH "sys:/php" +#define PEAR_INSTALLDIR "sys:/php/pear" + diff --git a/netware/build.bat b/netware/build.bat new file mode 100755 index 0000000000..5c8e310a53 --- /dev/null +++ b/netware/build.bat @@ -0,0 +1,21 @@ +@echo off + +cd ..\%1 + +if "%2" == "clean" make -f ..\netware\%1.mak clean +if "%2" == "/?" goto USAGE + +if "%1" == "zend" call ..\netware\BisonFlexZend +if "%1" == "ZendEngine2" call ..\netware\BisonFlexZend + +REM Build command +make -f ..\netware\%1.mak +goto EXIT + +:USAGE + @echo on + @echo Usage: build moduleName [clean] + @echo clean - delete all object files and binaries before building + +:EXIT +cd ..\netware \ No newline at end of file diff --git a/netware/buildext.bat b/netware/buildext.bat new file mode 100755 index 0000000000..6cea5530cc --- /dev/null +++ b/netware/buildext.bat @@ -0,0 +1,18 @@ +@echo off + +cd ..\ext\%1 + +if "%2" == "clean" make -f %1.mak clean +if "%2" == "/?" goto USAGE + +REM Build command +make -f %1.mak +goto EXIT + +:USAGE + @echo on + @echo Usage: buildext extension_name [clean] + @echo clean - delete all object files and binaries before building + +:EXIT +cd ..\..\netware diff --git a/netware/buildsapi.bat b/netware/buildsapi.bat new file mode 100755 index 0000000000..57498cbf89 --- /dev/null +++ b/netware/buildsapi.bat @@ -0,0 +1,18 @@ +@echo off + +cd ..\sapi\%1 + +if "%2" == "clean" make -f ..\..\netware\php4%1.mak clean +if "%2" == "/?" goto USAGE + +REM Build command +make -f ..\..\netware\php4%1.mak +goto EXIT + +:USAGE + @echo on + @echo Usage: buildsapi SAPI_Module_Name [clean] + @echo clean - delete all object files and binaries before building + +:EXIT +cd ..\..\netware diff --git a/netware/common.mif b/netware/common.mif new file mode 100644 index 0000000000..d09026fd21 --- /dev/null +++ b/netware/common.mif @@ -0,0 +1,73 @@ +# +# common include file for PHP build +# include this in every make file +# + +# Set following directories based on your setting + +# Path to CodeWarrior installation +CW_PATH = P:/APPS/SCRIPT/SW/CW71-4 + +# NWSDK directories +ifndef SDK_DIR +SDK_DIR = R:/script/common/libc +endif + +# MPK related directory +ifndef MPK_DIR +MPK_DIR = p:/apps/script/mpk +endif + +#ifndef CLIB_DIR +#CLIB_DIR = p:/apps/ndk0601/nwsdk +#endif + +# Winsock stuff +WINSOCK_DIR = P:/APPS/script/sw/Winsock2 + +# LDAP stuff +LDAP_DIR = P:/APPS/script/sw/cldapsdk + +# Apache directory +ifndef APACHE_DIR +APACHE_DIR = P:/APPS/script/sw/Apache1.3.xSource +endif + + +# CW includes, libraries and tools +export MWCIncludes=$(CW_PATH)/include +export MWLibraries=$(CW_PATH)/lib + +# Compiler and linker tools +CC = mwccnlm +LINK = mwldnlm + +# Build type defaults to 'release' +ifndef BUILD +BUILD = release +endif +#BUILD = debug + +OBJ_DIR = $(BUILD) +FINAL_DIR = $(BUILD) +MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map + +ifndef STACK_SIZE +STACK_SIZE=65536 +endif + +ifndef COPYRIGHT +#COPYRIGHT = "Copyright (c) 1997-2002 The PHP Group. All Rights Reserved." +COPYRIGHT = "Copyright (c) 1999\, 2000 The PHP Group. All rights reserved." +endif + +# Link flags +LD_FLAGS = -stacksize $(STACK_SIZE) -type generic -zerobss +LD_FLAGS += -o $(BINARY) -map $(MAP_FILE) -nlmversion $(VMAJ),$(VMIN),$(VREV) + +# Module details +LD_FLAGS += -desc $(MODULE_DESC) +LD_FLAGS += -copy $(COPYRIGHT) +LD_FLAGS += -screenname Default +LD_FLAGS += -threadname $(MODULE_NAME)__p + diff --git a/netware/mktemp.h b/netware/mktemp.h new file mode 100644 index 0000000000..b370438246 --- /dev/null +++ b/netware/mktemp.h @@ -0,0 +1 @@ +char* mktemp(char* templateStr); diff --git a/netware/php4apache.mak b/netware/php4apache.mak new file mode 100644 index 0000000000..0fb977841d --- /dev/null +++ b/netware/php4apache.mak @@ -0,0 +1,161 @@ +# Temporarily here -- later may go into some batch file +# which will set this as an environment variable +PROJECT_ROOT = ../.. + +# Module details +MODULE_NAME = mod_php +MODULE_DESC = "PHP 4.x.x for NetWare - mod_php" +VMAJ = 0 +VMIN = 90 +VREV = 0 + +#include the common settings +include $(PROJECT_ROOT)/netware/common.mif + +# Extensions of all input and output files +.SUFFIXES: +.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d + +# Source files +C_SRC = mod_php4.c \ + php_apache.c \ + sapi_apache.c + +# Destination directories and files +OBJ_DIR = $(BUILD) +FINAL_DIR = $(BUILD) +MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map +OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) +DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) + +# Binary file +ifndef BINARY +BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm +endif + + +# Compile flags +C_FLAGS = -c -maxerrors 25 -msgstyle gcc +C_FLAGS += -wchar_t on -bool on +C_FLAGS += -processor Pentium -align 1 +C_FLAGS += -w nounusedarg -msext on +C_FLAGS += -nostdinc +C_FLAGS += -DNETWARE -D__GNUC__ +C_FLAGS += -DZTS +C_FLAGS += -DNLM_PLATFORM +C_FLAGS += -DN_PLAT_NLM -DNLM=1 -D__NO_MATH_OPS +C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -DAPACHE_OS_H -DNO_USE_SIGACTION -DMULTITHREAD +C_FLAGS += -DCLIB_STAT_PATCH +C_FLAGS += -DNEW_LIBC +#C_FLAGS += -DUSE_WINSOCK_DIRECTLY=1 +C_FLAGS += -I. -I- -I. -I../../netware -I$(SDK_DIR)/include # ../../netware added for special SYS/STAT.H +C_FLAGS += -I$(MWCIncludes) +C_FLAGS += -I$(APACHE_DIR)/include -I$(APACHE_DIR)/os/netware +C_FLAGS += -I- -I../../main -I../../Zend -I../../TSRM -I../../ext/standard +C_FLAGS += -I../../ -I../../netware -I$(PROJECT_ROOT)/regex +C_FLAGS += -I$(WINSOCK_DIR)/include/nlm -I$(WINSOCK_DIR)/include + + +# Extra stuff based on debug / release builds +ifeq '$(BUILD)' 'debug' + SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym + C_FLAGS += -inline smart -sym on -sym codeview4 -opt off -opt intrinsics -sym internal -DDEBUGGING -DDKFBPON + C_FLAGS += -r -DZEND_DEBUG + C_FLAGS += -exc cw + LD_FLAGS += -sym on -sym codeview4 -sym internal -osym $(SYM_FILE) + LD_FLAGS += -msgstyle std + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib +else + C_FLAGS += -opt speed -inline on -inline smart -inline auto -sym off -DZEND_DEBUG=0 + C_FLAGS += -opt intrinsics + C_FLAGS += -opt level=4 + LD_FLAGS += -sym off + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib +endif + +# Dependencies +MODULE = LibC \ + phplib +IMPORT = @$(SDK_DIR)/imports/libc.imp \ + @$(APACHE_DIR)/os/netware/apachecore.imp \ + @$(PROJECT_ROOT)/netware/phplib.imp +EXPORT = php4_module + + +# Virtual paths +vpath %.cpp . +vpath %.c . +vpath %.obj $(OBJ_DIR) + + +all: prebuild project + +.PHONY: all + +prebuild: + @if not exist $(OBJ_DIR) md $(OBJ_DIR) + +project: $(BINARY) $(MESSAGE) + @echo Build complete. + + +$(OBJ_DIR)/%.d: %.c + @echo Building Dependencies for $( $(basename $@).def +ifdef API + @echo Import $(API) >> $(basename $@).def +endif + @echo Module $(MODULE) >> $(basename $@).def +ifdef EXPORT + @echo Export $(EXPORT) >> $(basename $@).def +endif + @echo AutoUnload >> $(basename $@).def +ifeq '$(BUILD)' 'debug' + @echo Debug >> $(basename $@).def +endif + @echo Flag_On 0x00000008 >> $(basename $@).def + @echo Start _lib_start >> $(basename $@).def + @echo Exit _lib_stop >> $(basename $@).def + + @echo Linking $@... + @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link +ifdef LIBRARY + @echo $(LIBRARY) >> $(basename $@).link +endif + @echo $(OBJECTS) $(APACHE_DIR)/os/netware/libpre.obj >> $(basename $@).link + + @$(LINK) @$(basename $@).link + + +.PHONY: clean +clean: cleand cleanobj cleanbin + +.PHONY: cleand +cleand: + @echo Deleting all dependency files... + -@del "$(OBJ_DIR)\*.d" + +.PHONY: cleanobj +cleanobj: + @echo Deleting all object files... + -@del "$(OBJ_DIR)\*.obj" + +.PHONY: cleanbin +cleanbin: + @echo Deleting binary files... + -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" + @echo Deleting MAP, DEF files, etc.... + -@del "$(FINAL_DIR)\$(MODULE_NAME).map" + -@del "$(FINAL_DIR)\$(MODULE_NAME).def" + -@del "$(FINAL_DIR)\$(MODULE_NAME).link" +ifeq '$(BUILD)' 'debug' + -@del $(FINAL_DIR)\$(MODULE_NAME).sym +endif diff --git a/netware/pwd.h b/netware/pwd.h new file mode 100644 index 0000000000..2a6ee7373b --- /dev/null +++ b/netware/pwd.h @@ -0,0 +1,49 @@ +/* pwd.h - Try to approximate UN*X's getuser...() functions under MS-DOS. + Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +/* This 'implementation' is conjectured from the use of this functions in + the RCS and BASH distributions. Of course these functions don't do too + much useful things under MS-DOS, but using them avoids many "#ifdef + MSDOS" in ported UN*X code ... */ + +#ifndef PWD_H +#define PWD_H + +/* + Not available in LibC / SDK header or CodeWarrior header files; so taking from Winsock + definitions, which should be OK +*/ +typedef unsigned int DWORD; + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* encrypted password */ + int pw_uid; /* user uid */ + int pw_gid; /* user gid */ + char *pw_comment; /* comment */ + char *pw_gecos; /* Honeywell login info */ + char *pw_dir; /* home directory */ + char *pw_shell; /* default shell */ +}; + +extern struct passwd *getpwuid(int); +extern struct passwd *getpwnam(char *name); +extern char *getlogin(void); + +#endif diff --git a/netware/sys/stat.h b/netware/sys/stat.h new file mode 100644 index 0000000000..dc1ab91347 --- /dev/null +++ b/netware/sys/stat.h @@ -0,0 +1,138 @@ +#ifndef __sys_stat_h__ +#define __sys_stat_h__ +/*============================================================================ += Novell Software Development Kit += += Copyright (C) 1999-2002 Novell, Inc. All Rights Reserved. += += This work is subject to U.S. and international copyright laws and treaties. += Use and redistribution of this work is subject to the license agreement += accompanying the software development kit (SDK) that contains this work. += However, no part of this work may be revised and/or modified without the += prior written consent of Novell, Inc. Any use or exploitation of this work += without authorization could subject the perpetrator to criminal and civil += liability. += += Source(s): ISO/IEC (POSIX) 9845:1996 += += sys/stat.h +============================================================================== +*/ +#include +#include +#include +#include + +#include + +#ifdef CLIB_STAT_PATCH /* Venkat (7/2/02) */ +/***************** stat structure taken from CLib and modified ***************/ +struct stat +{ + long st_dev; /* volume number */ /* dev_t replaced by long : Venkat (19/3/02) */ + MACHINE_WORD st_ino; /* directory entry number of the st_name */ /* ino_t replaced by MACHINE_WORD : Venkat (19/3/02) */ + unsigned short st_mode; /* emulated file mode */ + unsigned short st_pad1; /* reserved for alignment */ + unsigned long st_nlink; /* count of hard links (always 1) */ + unsigned long st_uid; /* object id of owner */ + unsigned long st_gid; /* group-id (always 0) */ + long st_rdev; /* device type (always 0) */ /* dev_t replaced by long : Venkat (19/3/02) */ + off_t st_size; /* total file size--files only */ + time_t st_atime; /* last access date--files only */ + time_t st_mtime; /* last modify date and time */ + time_t st_ctime; /* POSIX: last status change time... */ + /* ...NetWare: creation date/time */ + time_t st_btime; /* last archived date and time */ + unsigned long st_attr; /* file attributes */ + unsigned long st_archivedID; /* user/object ID of last archive */ + unsigned long st_updatedID; /* user/object ID of last update */ + unsigned short st_inheritedRightsMask; /* inherited rights mask */ + unsigned short st_pad2; /* reserved for alignment */ + unsigned int st_originatingNameSpace; /* namespace of creation */ + size_t st_blksize; /* block size for allocation--files only */ + size_t st_blocks; /* count of blocks allocated to file */ + unsigned int st_flags; /* user-defined flags */ + unsigned long st_spare[4]; /* for future use */ + unsigned char st_name[255+1];/* TARGET_NAMESPACE name */ +}; +/***************** stat structure taken from CLib and modified ***************/ + +struct stat_libc +{ + uint32_t st_userspec; /* untouched by stat() */ + uint32_t st_flags; /* flags for this entry */ + mode_t st_mode; /* emulated file mode */ + uint32_t st_spare1; + uint64_t st_gen; /* generation number of inode */ + ino_t st_ino; /* directory entry number */ + dev_t st_dev; /* volume number */ + dev_t st_rdev; /* device type (always 0) */ + off64_t st_size; /* total file size */ + uint64_t st_spare2; + blkcnt_t st_blocks; /* count of blocks allocated to file */ + blksize_t st_blksize; /* block size for allocation--files only */ + nlink_t st_nlink; /* count of hard links (always 1) */ + uint32_t st_spare3[3]; + uid_t st_uid; /* owner (object) identity */ + gid_t st_gid; /* group-id (always 0) */ + uid_t st_bid; /* identity of last archiver */ + uid_t st_mid; /* identity of last updator */ + timespec_t st_atime; /* last access date--files only */ + timespec_t st_mtime; /* last modify date and time */ + timespec_t st_ctime; /* last file attributes modification */ + timespec_t st_btime; /* last archived date and time */ + uint64_t st_spare4[44]; +}; /* sizeof(struct dirent) == 0x200 (512.) */ + +#else +struct stat +{ + uint32_t st_userspec; /* untouched by stat() */ + uint32_t st_flags; /* flags for this entry */ + mode_t st_mode; /* emulated file mode */ + uint32_t st_spare1; + uint64_t st_gen; /* generation number of inode */ + ino_t st_ino; /* directory entry number */ + dev_t st_dev; /* volume number */ + dev_t st_rdev; /* device type (always 0) */ + off64_t st_size; /* total file size */ + uint64_t st_spare2; + blkcnt_t st_blocks; /* count of blocks allocated to file */ + blksize_t st_blksize; /* block size for allocation--files only */ + nlink_t st_nlink; /* count of hard links (always 1) */ + uint32_t st_spare3[3]; + uid_t st_uid; /* owner (object) identity */ + gid_t st_gid; /* group-id (always 0) */ + uid_t st_bid; /* identity of last archiver */ + uid_t st_mid; /* identity of last updator */ + timespec_t st_atime; /* last access date--files only */ + timespec_t st_mtime; /* last modify date and time */ + timespec_t st_ctime; /* last file attributes modification */ + timespec_t st_btime; /* last archived date and time */ + uint64_t st_spare4[44]; +}; /* sizeof(struct dirent) == 0x200 (512.) */ +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +int chmod ( const char *path, mode_t mode ); +int fchmod( int fildes, mode_t mode ); +int fstat ( int fildes, struct stat *buf ); +int mkdir ( const char *pathname, mode_t mode ); +int mkfifo( const char *pathname, mode_t mode ); +int stat ( const char *path, struct stat *buf ); +mode_t umask ( mode_t cmask ); + +#ifdef __cplusplus +} +#endif + +#define stat64 stat /* same structure and function do both */ +#define fstat64 fstat /* same function does both */ + +#endif diff --git a/netware/tsrm.mak b/netware/tsrm.mak new file mode 100644 index 0000000000..94603934dc --- /dev/null +++ b/netware/tsrm.mak @@ -0,0 +1,108 @@ +# Temporarily here -- later may go into some batch file +# which will set this as an environment variable +PROJECT_ROOT = .. + +# Module details +MODULE_NAME = TSRM + +#MODULE_ROOT = $(PROJECT_ROOT)\\$(MODULE_NAME) + +#include the common settings +include $(PROJECT_ROOT)/netware/common.mif + +# Extensions of all input and output files +.SUFFIXES: +.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d + +# Source files +CPP_SRC = +C_SRC = TSRM.c \ + tsrm_strtok_r.c \ + tsrm_virtual_cwd.c \ + tsrm_nw.c + +# Destination directories and files +OBJ_DIR = $(BUILD) +FINAL_DIR = $(BUILD) +OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) +DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) + +# Binary file +ifndef BINARY + BINARY=$(FINAL_DIR)\$(MODULE_NAME).lib +endif + +# Compile flags +C_FLAGS = -c -maxerrors 25 -msgstyle gcc +C_FLAGS += -wchar_t on -bool on +C_FLAGS += -processor Pentium -align 1 +C_FLAGS += -nostdinc +C_FLAGS += -DZTS -DNETWARE -DHAVE_DIRENT_H +#C_FLAGS += -DUSE_PIPE_OPEN +C_FLAGS += -DUSE_MKFIFO +C_FLAGS += -DCLIB_STAT_PATCH -DUSE_MPK +C_FLAGS += -I. -I- -I../netware -I$(SDK_DIR)/include # ../netware added for special SYS/STAT.H +C_FLAGS += -I$(MPK_DIR)/include1 +C_FLAGS += -I$(MWCIncludes) + +# Link flags +LD_FLAGS = -type library +LD_FLAGS += -o $(BINARY) + +# Extra stuff based on debug / release builds +ifeq '$(BUILD)' 'debug' + C_FLAGS += -inline smart -sym on -sym codeview4 -sym internal -opt off -opt intrinsics -DTSRM_DEBUG=1 + LD_FLAGS += -sym codeview4 -sym internal + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib +else + C_FLAGS += -opt speed -inline smart -inline auto -sym off -DTSRM_DEBUG=0 + LD_FLAGS += -sym off + export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib +endif + +# Virtual paths +vpath %.cpp . +vpath %.c . +vpath %.obj $(OBJ_DIR) + + +all: prebuild project + +.PHONY: all + +prebuild: + @if not exist $(OBJ_DIR) md $(OBJ_DIR) + +project: $(BINARY) $(MESSAGE) + @echo Build complete. + +$(OBJ_DIR)/%.d: %.c + @echo Building Dependencies for $(