You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
8.9 KiB

24 years ago
24 years ago
25 years ago
25 years ago
25 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 4 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2002 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.02 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/2_02.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Daniel Beulshausen <daniel@php4win.de> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <fcntl.h>
  22. #include <io.h>
  23. #include <process.h>
  24. #include <time.h>
  25. #include "TSRM.h"
  26. #ifdef TSRM_WIN32
  27. #include <windows.h>
  28. #include "tsrm_win32.h"
  29. #ifdef ZTS
  30. static ts_rsrc_id win32_globals_id;
  31. #else
  32. static tsrm_win32_globals win32_globals;
  33. #endif
  34. static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
  35. {
  36. globals->process = NULL;
  37. globals->shm = NULL;
  38. globals->process_size = 0;
  39. globals->shm_size = 0;
  40. globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
  41. }
  42. static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
  43. {
  44. shm_pair *ptr;
  45. if (globals->process) {
  46. free(globals->process);
  47. }
  48. if (globals->shm) {
  49. for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
  50. UnmapViewOfFile(ptr->addr);
  51. CloseHandle(ptr->segment);
  52. UnmapViewOfFile(ptr->descriptor);
  53. CloseHandle(ptr->info);
  54. }
  55. free(globals->shm);
  56. }
  57. free(globals->comspec);
  58. }
  59. TSRM_API void tsrm_win32_startup(void)
  60. {
  61. #ifdef ZTS
  62. ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
  63. #else
  64. tsrm_win32_ctor(&win32_globals TSRMLS_CC);
  65. #endif
  66. }
  67. TSRM_API void tsrm_win32_shutdown(void)
  68. {
  69. #ifndef ZTS
  70. tsrm_win32_dtor(&win32_globals TSRMLS_CC);
  71. #endif
  72. }
  73. static process_pair *process_get(FILE *stream TSRMLS_DC)
  74. {
  75. process_pair *ptr;
  76. process_pair *newptr;
  77. for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
  78. if (ptr->stream == stream) {
  79. break;
  80. }
  81. }
  82. if (ptr < (TWG(process) + TWG(process_size))) {
  83. return ptr;
  84. }
  85. newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
  86. if (newptr == NULL) {
  87. return NULL;
  88. }
  89. TWG(process) = newptr;
  90. ptr = newptr + TWG(process_size);
  91. TWG(process_size)++;
  92. return ptr;
  93. }
  94. static shm_pair *shm_get(int key, void *addr)
  95. {
  96. shm_pair *ptr;
  97. shm_pair *newptr;
  98. TSRMLS_FETCH();
  99. for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
  100. if (!ptr->descriptor) {
  101. continue;
  102. }
  103. if (!addr && ptr->descriptor->shm_perm.key == key) {
  104. break;
  105. } else if (ptr->addr == addr) {
  106. break;
  107. }
  108. }
  109. if (ptr < (TWG(shm) + TWG(shm_size))) {
  110. return ptr;
  111. }
  112. newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
  113. if (newptr == NULL) {
  114. return NULL;
  115. }
  116. TWG(shm) = newptr;
  117. ptr = newptr + TWG(shm_size);
  118. TWG(shm_size)++;
  119. return ptr;
  120. }
  121. static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
  122. HANDLE copy, self = GetCurrentProcess();
  123. if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
  124. return NULL;
  125. }
  126. return copy;
  127. }
  128. TSRM_API FILE *popen(const char *command, const char *type)
  129. {
  130. FILE *stream = NULL;
  131. int fno, str_len = strlen(type), read, mode;
  132. STARTUPINFO startup;
  133. PROCESS_INFORMATION process;
  134. SECURITY_ATTRIBUTES security;
  135. HANDLE in, out;
  136. char *cmd;
  137. process_pair *proc;
  138. TSRMLS_FETCH();
  139. security.nLength = sizeof(SECURITY_ATTRIBUTES);
  140. security.bInheritHandle = TRUE;
  141. security.lpSecurityDescriptor = NULL;
  142. if (!str_len || !CreatePipe(&in, &out, &security, 2048L)) {
  143. return NULL;
  144. }
  145. memset(&startup, 0, sizeof(STARTUPINFO));
  146. memset(&process, 0, sizeof(PROCESS_INFORMATION));
  147. startup.cb = sizeof(STARTUPINFO);
  148. startup.dwFlags = STARTF_USESTDHANDLES;
  149. startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  150. read = (type[0] == 'r') ? TRUE : FALSE;
  151. mode = ((str_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
  152. if (read) {
  153. in = dupHandle(in, FALSE);
  154. startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  155. startup.hStdOutput = out;
  156. } else {
  157. out = dupHandle(out, FALSE);
  158. startup.hStdInput = in;
  159. startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  160. }
  161. cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));
  162. sprintf(cmd, "%s /c %s", TWG(comspec), command);
  163. if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &process)) {
  164. return NULL;
  165. }
  166. free(cmd);
  167. CloseHandle(process.hThread);
  168. proc = process_get(NULL TSRMLS_CC);
  169. if (read) {
  170. fno = _open_osfhandle((long)in, _O_RDONLY | mode);
  171. CloseHandle(out);
  172. } else {
  173. fno = _open_osfhandle((long)out, _O_WRONLY | mode);
  174. CloseHandle(in);
  175. }
  176. stream = _fdopen(fno, type);
  177. proc->prochnd = process.hProcess;
  178. proc->stream = stream;
  179. return stream;
  180. }
  181. TSRM_API int pclose(FILE *stream)
  182. {
  183. DWORD termstat = 0;
  184. process_pair *process;
  185. TSRMLS_FETCH();
  186. if ((process = process_get(stream TSRMLS_CC)) == NULL) {
  187. return 0;
  188. }
  189. fflush(process->stream);
  190. fclose(process->stream);
  191. WaitForSingleObject(process->prochnd, INFINITE);
  192. GetExitCodeProcess(process->prochnd, &termstat);
  193. process->stream = NULL;
  194. CloseHandle(process->prochnd);
  195. return termstat;
  196. }
  197. TSRM_API int shmget(int key, int size, int flags)
  198. {
  199. shm_pair *shm;
  200. char shm_segment[26], shm_info[29];
  201. HANDLE shm_handle, info_handle;
  202. BOOL created = FALSE;
  203. if (size < 0) {
  204. return -1;
  205. }
  206. sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
  207. sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
  208. shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
  209. info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
  210. if ((!shm_handle && !info_handle)) {
  211. if (flags & IPC_EXCL) {
  212. return -1;
  213. }
  214. if (flags & IPC_CREAT) {
  215. shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
  216. info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
  217. created = TRUE;
  218. }
  219. if ((!shm_handle || !info_handle)) {
  220. return -1;
  221. }
  222. }
  223. shm = shm_get(key, NULL);
  224. shm->segment = shm_handle;
  225. shm->info = info_handle;
  226. shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  227. if (created) {
  228. shm->descriptor->shm_perm.key = key;
  229. shm->descriptor->shm_segsz = size;
  230. shm->descriptor->shm_ctime = time(NULL);
  231. shm->descriptor->shm_cpid = getpid();
  232. shm->descriptor->shm_perm.mode = flags;
  233. shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
  234. shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
  235. shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
  236. shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
  237. shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
  238. }
  239. if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
  240. CloseHandle(shm->segment);
  241. UnmapViewOfFile(shm->descriptor);
  242. CloseHandle(shm->info);
  243. return -1;
  244. }
  245. return key;
  246. }
  247. TSRM_API void *shmat(int key, const void *shmaddr, int flags)
  248. {
  249. shm_pair *shm = shm_get(key, NULL);
  250. if (!shm->segment) {
  251. return (void*)-1;
  252. }
  253. shm->descriptor->shm_atime = time(NULL);
  254. shm->descriptor->shm_lpid = getpid();
  255. shm->descriptor->shm_nattch++;
  256. shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  257. return shm->addr;
  258. }
  259. TSRM_API int shmdt(const void *shmaddr)
  260. {
  261. shm_pair *shm = shm_get(0, (void*)shmaddr);
  262. if (!shm->segment) {
  263. return -1;
  264. }
  265. shm->descriptor->shm_dtime = time(NULL);
  266. shm->descriptor->shm_lpid = getpid();
  267. shm->descriptor->shm_nattch--;
  268. return UnmapViewOfFile(shm->addr) ? 0 : -1;
  269. }
  270. TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
  271. shm_pair *shm = shm_get(key, NULL);
  272. if (!shm->segment) {
  273. return -1;
  274. }
  275. switch (cmd) {
  276. case IPC_STAT:
  277. memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
  278. return 0;
  279. case IPC_SET:
  280. shm->descriptor->shm_ctime = time(NULL);
  281. shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
  282. shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
  283. shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
  284. return 0;
  285. case IPC_RMID:
  286. if (shm->descriptor->shm_nattch < 1) {
  287. shm->descriptor->shm_perm.key = -1;
  288. }
  289. return 0;
  290. default:
  291. return -1;
  292. }
  293. }
  294. #endif