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.

397 lines
9.7 KiB

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