2000-10-01 23:06:04 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| PHP version 4.0 |
|
|
|
|
+----------------------------------------------------------------------+
|
2001-02-26 14:11:02 +08:00
|
|
|
| Copyright (c) 1997-2001 The PHP Group |
|
2000-10-01 23:06:04 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| 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) |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
2001-06-05 21:12:10 +08:00
|
|
|
/* $Id$ */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
2001-05-24 18:07:29 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2000-10-01 23:06:04 +08:00
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
|
|
|
#include "php_shmop.h"
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#include <sys/shm.h>
|
|
|
|
|
|
|
|
#if HAVE_SHMOP
|
|
|
|
|
2000-12-02 21:43:50 +08:00
|
|
|
#include "ext/standard/info.h"
|
|
|
|
|
2000-10-01 23:06:04 +08:00
|
|
|
#ifdef ZTS
|
|
|
|
int shmop_globals_id;
|
|
|
|
#else
|
|
|
|
php_shmop_globals shmop_globals;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int shm_type;
|
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ shmop_functions[]
|
|
|
|
*/
|
2000-10-01 23:06:04 +08:00
|
|
|
function_entry shmop_functions[] = {
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FE(shmop_open, NULL)
|
|
|
|
PHP_FE(shmop_read, NULL)
|
|
|
|
PHP_FE(shmop_close, NULL)
|
|
|
|
PHP_FE(shmop_size, NULL)
|
|
|
|
PHP_FE(shmop_write, NULL)
|
|
|
|
PHP_FE(shmop_delete, NULL)
|
2000-10-01 23:06:04 +08:00
|
|
|
{NULL, NULL, NULL} /* Must be the last line in shmop_functions[] */
|
|
|
|
};
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ shmop_module_entry
|
|
|
|
*/
|
2000-10-01 23:06:04 +08:00
|
|
|
zend_module_entry shmop_module_entry = {
|
|
|
|
"shmop",
|
|
|
|
shmop_functions,
|
|
|
|
PHP_MINIT(shmop),
|
|
|
|
PHP_MSHUTDOWN(shmop),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
PHP_MINFO(shmop),
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
|
|
|
#ifdef COMPILE_DL_SHMOP
|
|
|
|
ZEND_GET_MODULE(shmop)
|
|
|
|
#endif
|
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ rsclean
|
|
|
|
*/
|
2000-10-21 02:25:16 +08:00
|
|
|
static void rsclean(zend_rsrc_list_entry *rsrc)
|
|
|
|
{
|
|
|
|
struct php_shmop *shmop = (struct php_shmop *)rsrc->ptr;
|
2001-07-30 09:56:43 +08:00
|
|
|
|
2000-10-21 02:25:16 +08:00
|
|
|
shmdt(shmop->addr);
|
|
|
|
efree(shmop);
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-08 04:46:30 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MINIT_FUNCTION
|
|
|
|
*/
|
2000-10-01 23:06:04 +08:00
|
|
|
PHP_MINIT_FUNCTION(shmop)
|
|
|
|
{
|
2000-10-26 01:44:02 +08:00
|
|
|
shm_type = zend_register_list_destructors_ex(rsclean, NULL, "shmop", module_number);
|
2000-10-01 23:06:04 +08:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MSHUTDOWN_FUNCTION
|
|
|
|
*/
|
2000-10-01 23:06:04 +08:00
|
|
|
PHP_MSHUTDOWN_FUNCTION(shmop)
|
|
|
|
{
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MINFO_FUNCTION
|
|
|
|
*/
|
2000-10-01 23:06:04 +08:00
|
|
|
PHP_MINFO_FUNCTION(shmop)
|
|
|
|
{
|
|
|
|
php_info_print_table_start();
|
2000-12-10 22:45:42 +08:00
|
|
|
php_info_print_table_row(2, "shmop support", "enabled");
|
2000-10-01 23:06:04 +08:00
|
|
|
php_info_print_table_end();
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-01 23:06:04 +08:00
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto int shmop_open (int key, int flags, int mode, int size)
|
2000-10-20 07:14:51 +08:00
|
|
|
gets and attaches a shared memory segment */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_open)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto string shmop_read (int shmid, int start, int count)
|
2000-10-20 07:14:51 +08:00
|
|
|
reads from a shm segment */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_read)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto void shmop_close (int shmid)
|
2000-10-20 07:14:51 +08:00
|
|
|
closes a shared memory segment */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_close)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto int shmop_size (int shmid)
|
2000-10-20 07:14:51 +08:00
|
|
|
returns the shm size */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_size)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto int shmop_write (int shmid, string data, int offset)
|
2000-10-20 07:14:51 +08:00
|
|
|
writes to a shared memory segment */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_write)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-10-20 06:50:41 +08:00
|
|
|
/* {{{ proto bool shmop_delete (int shmid)
|
2000-10-20 07:14:51 +08:00
|
|
|
mark segment for deletion */
|
2000-10-20 06:50:41 +08:00
|
|
|
PHP_FUNCTION(shmop_delete)
|
2000-10-01 23:06:04 +08:00
|
|
|
{
|
|
|
|
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:
|
2001-06-06 21:06:12 +08:00
|
|
|
* vim600: sw=4 ts=4 tw=78 fdm=marker
|
|
|
|
* vim<600: sw=4 ts=4 tw=78
|
2000-10-01 23:06:04 +08:00
|
|
|
*/
|