summaryrefslogtreecommitdiff
path: root/TSRM
diff options
context:
space:
mode:
Diffstat (limited to 'TSRM')
-rw-r--r--TSRM/tsrm_win32.c183
-rw-r--r--TSRM/tsrm_win32.h70
2 files changed, 238 insertions, 15 deletions
diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c
index 5dfc2d60f8..daf7d606b1 100644
--- a/TSRM/tsrm_win32.c
+++ b/TSRM/tsrm_win32.c
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <io.h>
#include <process.h>
+#include <time.h>
#include "TSRM.h"
@@ -39,15 +40,30 @@ static tsrm_win32_globals win32_globals;
static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
{
globals->process = NULL;
+ globals->shm = NULL;
globals->process_size = 0;
+ globals->shm_size = 0;
globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
}
static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
{
- if (globals->process != NULL) {
+ shm_pair *ptr;
+
+ if (globals->process) {
free(globals->process);
}
+
+ if (globals->shm) {
+ for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
+ UnmapViewOfFile(ptr->addr);
+ CloseHandle(ptr->segment);
+ UnmapViewOfFile(ptr->descriptor);
+ CloseHandle(ptr->info);
+ }
+ free(globals->shm);
+ }
+
free(globals->comspec);
}
@@ -67,10 +83,10 @@ TSRM_API void tsrm_win32_shutdown(void)
#endif
}
-static ProcessPair* process_get(FILE *stream TSRMLS_DC)
+static process_pair *process_get(FILE *stream TSRMLS_DC)
{
- ProcessPair* ptr;
- ProcessPair* newptr;
+ process_pair *ptr;
+ process_pair *newptr;
for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
if (ptr->stream == stream) {
@@ -82,7 +98,7 @@ static ProcessPair* process_get(FILE *stream TSRMLS_DC)
return ptr;
}
- newptr = (ProcessPair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(ProcessPair));
+ newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
if (newptr == NULL) {
return NULL;
}
@@ -93,6 +109,38 @@ static ProcessPair* process_get(FILE *stream TSRMLS_DC)
return ptr;
}
+static shm_pair *shm_get(int key, void *addr)
+{
+ shm_pair *ptr;
+ shm_pair *newptr;
+ TSRMLS_FETCH();
+
+ for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
+ if (!ptr->descriptor) {
+ continue;
+ }
+ if (!addr && ptr->descriptor->shm_perm.key == key) {
+ break;
+ } else if (ptr->addr == addr) {
+ break;
+ }
+ }
+
+ if (ptr < (TWG(shm) + TWG(shm_size))) {
+ return ptr;
+ }
+
+ newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
+ if (newptr == NULL) {
+ return NULL;
+ }
+
+ TWG(shm) = newptr;
+ ptr = newptr + TWG(shm_size);
+ TWG(shm_size)++;
+ return ptr;
+}
+
static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
HANDLE copy, self = GetCurrentProcess();
if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
@@ -110,7 +158,7 @@ TSRM_API FILE *popen(const char *command, const char *type)
SECURITY_ATTRIBUTES security;
HANDLE in, out;
char *cmd;
- ProcessPair *proc;
+ process_pair *proc;
TSRMLS_FETCH();
security.nLength = sizeof(SECURITY_ATTRIBUTES);
@@ -169,7 +217,7 @@ TSRM_API FILE *popen(const char *command, const char *type)
TSRM_API int pclose(FILE *stream)
{
DWORD termstat = 0;
- ProcessPair* process;
+ process_pair *process;
TSRMLS_FETCH();
if ((process = process_get(stream TSRMLS_CC)) == NULL) {
@@ -187,4 +235,125 @@ TSRM_API int pclose(FILE *stream)
return termstat;
}
+TSRM_API int shmget(int key, int size, int flags)
+{
+ shm_pair *shm;
+ char shm_segment[26], shm_info[29];
+ HANDLE shm_handle, info_handle;
+ BOOL created = FALSE;
+
+ if (size < 0) {
+ return -1;
+ }
+
+ sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
+ sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
+
+ shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
+ info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
+
+ if ((!shm_handle && !info_handle)) {
+ if (flags & IPC_EXCL) {
+ return -1;
+ }
+ if (flags & IPC_CREAT) {
+ shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
+ info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
+ created = TRUE;
+ }
+ if ((!shm_handle || !info_handle)) {
+ return -1;
+ }
+ }
+
+ shm = shm_get(key, NULL);
+ shm->segment = shm_handle;
+ shm->info = info_handle;
+ shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
+
+ if (created) {
+ shm->descriptor->shm_perm.key = key;
+ shm->descriptor->shm_segsz = size;
+ shm->descriptor->shm_ctime = time(NULL);
+ shm->descriptor->shm_cpid = getpid();
+ shm->descriptor->shm_perm.mode = flags;
+
+ shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
+ shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
+ shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
+ shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
+ shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
+ }
+
+ if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
+ CloseHandle(shm->segment);
+ UnmapViewOfFile(shm->descriptor);
+ CloseHandle(shm->info);
+ return -1;
+ }
+
+ return key;
+}
+
+TSRM_API void *shmat(int key, const void *shmaddr, int flags)
+{
+ shm_pair *shm = shm_get(key, NULL);
+
+ if (!shm->segment) {
+ return (void*)-1;
+ }
+
+ shm->descriptor->shm_atime = time(NULL);
+ shm->descriptor->shm_lpid = getpid();
+ shm->descriptor->shm_nattch++;
+
+ shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
+
+ return shm->addr;
+}
+
+TSRM_API int shmdt(const void *shmaddr)
+{
+ shm_pair *shm = shm_get(0, (void*)shmaddr);
+
+ if (!shm->segment) {
+ return -1;
+ }
+
+ shm->descriptor->shm_dtime = time(NULL);
+ shm->descriptor->shm_lpid = getpid();
+ shm->descriptor->shm_nattch--;
+
+ return UnmapViewOfFile(shm->addr) ? 0 : -1;
+}
+
+TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
+ shm_pair *shm = shm_get(key, NULL);
+
+ if (!shm->segment) {
+ return -1;
+ }
+
+ switch (cmd) {
+ case IPC_STAT:
+ memcpy(buf, shm->descriptor, sizeof(shm->descriptor));
+ return 0;
+
+ case IPC_SET:
+ shm->descriptor->shm_ctime = time(NULL);
+ shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
+ shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
+ shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
+ return 0;
+
+ case IPC_RMID:
+ if (shm->descriptor->shm_nattch < 1) {
+ shm->descriptor->shm_perm.key = -1;
+ }
+ return 0;
+
+ default:
+ return -1;
+ }
+}
#endif \ No newline at end of file
diff --git a/TSRM/tsrm_win32.h b/TSRM/tsrm_win32.h
index cb09786682..08e7c7a509 100644
--- a/TSRM/tsrm_win32.h
+++ b/TSRM/tsrm_win32.h
@@ -26,15 +26,45 @@
#ifdef TSRM_WIN32
#include <windows.h>
+struct ipc_perm {
+ int key;
+ unsigned short uid;
+ unsigned short gid;
+ unsigned short cuid;
+ unsigned short cgid;
+ unsigned short mode;
+ unsigned short seq;
+};
+
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ int shm_segsz;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+ unsigned short shm_cpid;
+ unsigned short shm_lpid;
+ short shm_nattch;
+};
+
+typedef struct {
+ FILE *stream;
+ HANDLE prochnd;
+} process_pair;
+
typedef struct {
- FILE *stream;
- HANDLE prochnd;
-} ProcessPair;
+ void *addr;
+ HANDLE info;
+ HANDLE segment;
+ struct shmid_ds *descriptor;
+} shm_pair;
typedef struct {
- ProcessPair *process;
- int process_size;
- char *comspec;
+ process_pair *process;
+ shm_pair *shm;
+ int process_size;
+ int shm_size;
+ char *comspec;
} tsrm_win32_globals;
#ifdef ZTS
@@ -45,9 +75,33 @@ typedef struct {
#endif
+#define IPC_PRIVATE 0
+#define IPC_CREAT 00001000
+#define IPC_EXCL 00002000
+#define IPC_NOWAIT 00004000
+
+#define IPC_RMID 0
+#define IPC_SET 1
+#define IPC_STAT 2
+#define IPC_INFO 3
+
+#define SHM_R PAGE_READONLY
+#define SHM_W PAGE_READWRITE
+
+#define SHM_RDONLY FILE_MAP_READ
+#define SHM_RND FILE_MAP_WRITE
+#define SHM_REMAP FILE_MAP_COPY
+
+
TSRM_API void tsrm_win32_startup(void);
TSRM_API void tsrm_win32_shutdown(void);
-TSRM_API FILE* popen(const char *command, const char *type);
-TSRM_API int pclose(FILE* stream);
+
+TSRM_API FILE *popen(const char *command, const char *type);
+TSRM_API int pclose(FILE *stream);
+
+TSRM_API int shmget(int key, int size, int flags);
+TSRM_API void *shmat(int key, const void *shmaddr, int flags);
+TSRM_API int shmdt(const void *shmaddr);
+TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf);
#endif \ No newline at end of file