summaryrefslogtreecommitdiff
path: root/ext/shmop
diff options
context:
space:
mode:
authorDerick Rethans <derick@php.net>2000-10-01 15:06:04 +0000
committerDerick Rethans <derick@php.net>2000-10-01 15:06:04 +0000
commit58294f67d2ca0842d9d60fe1c26891da85201870 (patch)
treec9c28e41cef3f4f4dd853c4586de4de509a25a9b /ext/shmop
parent9ccc11ce50f5bd01fb348c56a81d5dac5a895356 (diff)
downloadphp-git-58294f67d2ca0842d9d60fe1c26891da85201870.tar.gz
@- Added the shmop extension. It allows more general ways of shared memory
@ access. (thanks to Ilia Alshanestky <iliaa@home.com> and Slava Poliakov @ <slavapl@mailandnews.com> (Derick)
Diffstat (limited to 'ext/shmop')
-rw-r--r--ext/shmop/Makefile.in8
-rw-r--r--ext/shmop/README65
-rw-r--r--ext/shmop/config.m48
-rw-r--r--ext/shmop/php_shmop.h83
-rw-r--r--ext/shmop/setup.stub5
-rw-r--r--ext/shmop/shmop.c333
6 files changed, 502 insertions, 0 deletions
diff --git a/ext/shmop/Makefile.in b/ext/shmop/Makefile.in
new file mode 100644
index 0000000000..0748ec799f
--- /dev/null
+++ b/ext/shmop/Makefile.in
@@ -0,0 +1,8 @@
+# $Id$
+
+LTLIBRARY_NAME = libshmop.la
+LTLIBRARY_SOURCES = shmop.c
+LTLIBRARY_SHARED_NAME = shmop.la
+LTLIBRARY_SHARED_LIBADD = $(SHMOP_SHARED_LIBADD)
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/shmop/README b/ext/shmop/README
new file mode 100644
index 0000000000..8ddd407d22
--- /dev/null
+++ b/ext/shmop/README
@@ -0,0 +1,65 @@
+last update sept 3, 2000 (slavapl@mailandnews.com/iliaa@home.com)
+
+Shared Memory Operations Extention to PHP4
+
+ While developing a search deamon we needed the php based front end
+ to communicate the deamon via SHM. Now, PHP already had a shared memory
+ extention (sysvshm) written by Christian Cartus <cartus@atrior.de>,
+ unfortunatly this extention was designed with PHP only in mind, and
+ offers high level features which are extremly bothersome for basic SHM
+ we had in mind. After spending a day trying to reverse engeener figure
+ out the format of sysvshm we decided that it would be much easier to
+ add our own extention to php for simple SHM operations, we were right :)).
+
+the functions are:
+
+int shm_open(int key, string flags, int mode, int size)
+
+ key - the key of/for the shared memory block
+ flags - 2 flags are avalible
+ a for access (sets IPC_EXCL)
+ c for create (sets IPC_CREATE)
+ mode - acsess mode same as for a file (0644) for example
+ size - size of the block in bytes
+
+ returns an indentifier
+
+
+char shm_read(int shmid, int start, int count)
+
+ shmid - shmid from which to read
+ start - offset from which to start reading
+ count - how many bytes to read
+
+ returns the data read
+
+int shm_write(int shmid, string data, int offset)
+
+ shmid - shmid from which to read
+ data - string to put into shared memory
+ offset - offset in shm to write from
+
+ returns bytes written
+
+int shm_size(int shmid)
+
+ shmid - shmid for which to return the size
+
+ returns the size in bytes of the shm segment
+
+
+int shm_delete(int shmid)
+
+ marks the segment for deletion, the segment will be deleted when all processes mapping it will detach
+
+ shmid - shmid which to mark for deletion
+
+ returns 1 if all ok, zero on failure
+
+int shm_close(int shmid)
+
+ shmid - shmid which to close
+
+ returns zero
+
+
diff --git a/ext/shmop/config.m4 b/ext/shmop/config.m4
new file mode 100644
index 0000000000..532256d9a9
--- /dev/null
+++ b/ext/shmop/config.m4
@@ -0,0 +1,8 @@
+dnl $Id$
+PHP_ARG_ENABLE(shmop, whether to enable shmop support,
+[ --enable-shmop Enable shmop support])
+
+if test "$PHP_SHMOP" != "no"; then
+ AC_DEFINE(HAVE_SHMOP, 1, [ ])
+ PHP_EXTENSION(shmop, $ext_shared)
+fi
diff --git a/ext/shmop/php_shmop.h b/ext/shmop/php_shmop.h
new file mode 100644
index 0000000000..f3fee5c6f1
--- /dev/null
+++ b/ext/shmop/php_shmop.h
@@ -0,0 +1,83 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000 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: Slava Poliakov (slavapl@mailandnews.com) |
+ | Ilia Alshanetsky (iliaa@home.com) |
+ +----------------------------------------------------------------------+
+ */
+#ifndef PHP_SHMOP_H
+#define PHP_SHMOP_H
+
+#if HAVE_SHMOP
+
+extern zend_module_entry shmop_module_entry;
+#define phpext_shmop_ptr &shmop_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_SHMOP_API __declspec(dllexport)
+#else
+#define PHP_SHMOP_API
+#endif
+
+PHP_MINIT_FUNCTION(shmop);
+PHP_MSHUTDOWN_FUNCTION(shmop);
+PHP_RINIT_FUNCTION(shmop);
+PHP_RSHUTDOWN_FUNCTION(shmop);
+PHP_MINFO_FUNCTION(shmop);
+
+PHP_FUNCTION(shm_open);
+PHP_FUNCTION(shm_read);
+PHP_FUNCTION(shm_close);
+PHP_FUNCTION(shm_size);
+PHP_FUNCTION(shm_write);
+PHP_FUNCTION(shm_delete);
+
+struct php_shmop
+{
+ int shmid;
+ key_t key;
+ int shmflg;
+ char *addr;
+ int size;
+};
+
+static void rsclean(struct php_shmop *shmop);
+
+typedef struct {
+ int le_shmop;
+} php_shmop_globals;
+
+#ifdef ZTS
+#define SHMOPG(v) (shmop_globals->v)
+#define SHMOPLS_FETCH() php_shmop_globals *shmop_globals = ts_resource(gd_shmop_id)
+#else
+#define SHMOPG(v) (shmop_globals.v)
+#define SHMOPLS_FETCH()
+#endif
+
+#else
+
+#define phpext_shmop_ptr NULL
+
+#endif
+
+#endif /* PHP_SHMOP_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/shmop/setup.stub b/ext/shmop/setup.stub
new file mode 100644
index 0000000000..e35c532988
--- /dev/null
+++ b/ext/shmop/setup.stub
@@ -0,0 +1,5 @@
+# $Source$
+# $Id$
+
+define_option enable-shmop 'System V shmop suppport? ' yesno no \
+' Whether to use the System V shmop (currently only Solaris and Linux).'
diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c
new file mode 100644
index 0000000000..7234eed748
--- /dev/null
+++ b/ext/shmop/shmop.c
@@ -0,0 +1,333 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000 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: Slava Poliakov (slavapl@mailandnews.com) |
+ | Ilia Alshanetsky (iliaa@home.com) |
+ +----------------------------------------------------------------------+
+ */
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_shmop.h"
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#if HAVE_SHMOP
+
+#ifdef ZTS
+int shmop_globals_id;
+#else
+php_shmop_globals shmop_globals;
+#endif
+
+int shm_type;
+
+/* Every user visible function must have an entry in shmop_functions[].
+*/
+function_entry shmop_functions[] = {
+ PHP_FE(shm_open, NULL)
+ PHP_FE(shm_read, NULL)
+ PHP_FE(shm_close, NULL)
+ PHP_FE(shm_size, NULL)
+ PHP_FE(shm_write, NULL)
+ PHP_FE(shm_delete, NULL)
+ {NULL, NULL, NULL} /* Must be the last line in shmop_functions[] */
+};
+
+zend_module_entry shmop_module_entry = {
+ "shmop",
+ shmop_functions,
+ PHP_MINIT(shmop),
+ PHP_MSHUTDOWN(shmop),
+ NULL,
+ NULL,
+ PHP_MINFO(shmop),
+ STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_SHMOP
+ZEND_GET_MODULE(shmop)
+#endif
+
+PHP_MINIT_FUNCTION(shmop)
+{
+ shm_type = register_list_destructors(rsclean, NULL);
+
+ return SUCCESS;
+}
+
+static void rsclean(struct php_shmop *shmop)
+{
+ shmdt(shmop->addr);
+ efree(shmop);
+}
+
+PHP_MSHUTDOWN_FUNCTION(shmop)
+{
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(shmop)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "shmop support", "enabled");
+ php_info_print_table_end();
+}
+
+/* {{{ void shm_open (int key, int flags, int mode, int size)
+ shm_open - gets and attaches an shared memory segment */
+PHP_FUNCTION(shm_open)
+{
+ zval **key, **flags, **mode, **size;
+ struct php_shmop *shmop;
+ struct shmid_ds shm;
+ int rsid;
+ int shmflg=0;
+
+ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &key, &flags, &mode, &size) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long_ex(key);
+ convert_to_string_ex(flags);
+ convert_to_long_ex(mode);
+ convert_to_long_ex(size);
+
+ shmop = emalloc(sizeof(struct php_shmop));
+ memset(shmop, 0, sizeof(struct php_shmop));
+
+ shmop->key = (*key)->value.lval;
+ shmop->shmflg |= (*mode)->value.lval;
+
+ if (memchr((*flags)->value.str.val, 'a', (*flags)->value.str.len)) {
+ shmflg = SHM_RDONLY;
+ shmop->shmflg |= IPC_EXCL;
+ }
+ else if (memchr((*flags)->value.str.val, 'c', (*flags)->value.str.len)) {
+ shmop->shmflg |= IPC_CREAT;
+ shmop->size = (*size)->value.lval;
+ }
+ else {
+ php_error(E_WARNING, "shmopen: access mode invalid");
+ efree(shmop);
+ RETURN_FALSE;
+ }
+
+ shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
+ if (shmop->shmid == -1) {
+ php_error(E_WARNING, "shmopen: can't get the block");
+ efree(shmop);
+ RETURN_FALSE;
+ }
+
+ if (shmctl(shmop->shmid, IPC_STAT, &shm)) {
+ efree(shmop);
+ php_error(E_WARNING, "shmopen: can't get information on the block");
+ RETURN_FALSE;
+ }
+
+ shmop->addr = shmat(shmop->shmid, 0, shmflg);
+ if (shmop->addr == (char*) -1) {
+ efree(shmop);
+ php_error(E_WARNING, "shmopen: can't attach the memory block");
+ RETURN_FALSE;
+ }
+
+ shmop->size = shm.shm_segsz;
+
+ rsid = zend_list_insert(shmop, shm_type);
+ RETURN_LONG(rsid);
+}
+/* }}} */
+
+
+/* {{{ string shm_read (int shmid, int start, int count)
+ shm_read - reads from an shm segment */
+PHP_FUNCTION(shm_read)
+{
+ zval **shmid, **start, **count;
+ struct php_shmop *shmop;
+ int type;
+ char *startaddr;
+ int bytes;
+ char *return_string;
+
+ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &shmid, &start, &count) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long_ex(shmid);
+ convert_to_long_ex(start);
+ convert_to_long_ex(count);
+
+ shmop = zend_list_find((*shmid)->value.lval, &type);
+
+ if (!shmop) {
+ php_error(E_WARNING, "shmread: can't find this segment");
+ RETURN_FALSE;
+ }
+
+ if ((*start)->value.lval < 0 || (*start)->value.lval > shmop->size) {
+ php_error(E_WARNING, "shmread: start is out of range");
+ RETURN_FALSE;
+ }
+
+ if (((*start)->value.lval+(*count)->value.lval) > shmop->size) {
+ php_error(E_WARNING, "shmread: count is out of range");
+ RETURN_FALSE;
+ }
+
+ if ((*count)->value.lval < 0 ){
+ php_error(E_WARNING, "shmread: count is out of range");
+ RETURN_FALSE;
+ }
+
+ startaddr = shmop->addr + (*start)->value.lval;
+ bytes = (*count)->value.lval ? (*count)->value.lval : shmop->size-(*start)->value.lval;
+
+ return_string = emalloc(bytes);
+ memcpy(return_string, startaddr, bytes);
+
+ RETURN_STRINGL(return_string, bytes, 0);
+}
+/* }}} */
+
+
+/* {{{ void shm_close (int shmid)
+ shm_close - closes a shared memory segment */
+PHP_FUNCTION(shm_close)
+{
+ zval **shmid;
+ struct php_shmop *shmop;
+ int type;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &shmid) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ shmop = zend_list_find((*shmid)->value.lval, &type);
+
+ if (!shmop) {
+ php_error(E_WARNING, "shmclose: no such shmid");
+ RETURN_FALSE;
+ }
+ zend_list_delete((*shmid)->value.lval);
+
+ RETURN_LONG(0);
+}
+/* }}} */
+
+
+/* {{{ int shm_size (int shmid)
+ shm_size - returns the shm size */
+PHP_FUNCTION(shm_size)
+{
+ zval **shmid;
+ struct php_shmop *shmop;
+ int type;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &shmid) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long_ex(shmid);
+
+ shmop = zend_list_find((*shmid)->value.lval, &type);
+
+ if (!shmop) {
+ php_error(E_WARNING, "shmsize: no such segment");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(shmop->size);
+}
+/* }}} */
+
+
+/* {{{ int shm_write (int shmid, string data, int offset)
+ shm_write - writes to a shared memory segment */
+PHP_FUNCTION(shm_write)
+{
+ zval **shmid, **data, **offset;
+ struct php_shmop *shmop;
+ int type;
+ int writesize;
+
+ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &shmid, &data, &offset) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long_ex(shmid);
+ convert_to_string_ex(data);
+ convert_to_long_ex(offset);
+
+ shmop = zend_list_find((*shmid)->value.lval, &type);
+
+ if (!shmop) {
+ php_error(E_WARNING, "shmwrite: error no such segment");
+ RETURN_FALSE;
+ }
+
+ if ( (*offset)->value.lval > shmop->size ) {
+ php_error(E_WARNING, "shmwrite: offset out of range");
+ RETURN_FALSE;
+ }
+
+ writesize = ((*data)->value.str.len<shmop->size-(*offset)->value.lval) ? (*data)->value.str.len : shmop->size-(*offset)->value.lval;
+ memcpy(shmop->addr+(*offset)->value.lval, (*data)->value.str.val, writesize);
+
+ RETURN_LONG(writesize);
+}
+/* }}} */
+
+
+/* {{{ bool shm_delete (int shmid)
+ shm_delete - mark segment for deletion */
+PHP_FUNCTION(shm_delete)
+{
+ zval **shmid;
+ struct php_shmop *shmop;
+ int type;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &shmid) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long_ex(shmid);
+
+ shmop = zend_list_find((*shmid)->value.lval, &type);
+
+ if (!shmop) {
+ php_error(E_WARNING, "shmdelete: error no such segment");
+ RETURN_FALSE;
+ }
+
+ if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
+ php_error(E_WARNING, "shmdelete: can't mark segment for deletion (are you the owner?)");
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+#endif /* HAVE_SHMOP */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */