win32_pipes.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. ****************************************************************************
  3. *
  4. * LIBRARY: unix_socks.c -- Routines related to using UNIX domain
  5. * sockets for IPC mechanisms (such as XDRIVER).
  6. *
  7. * AUTHOR(S): Eric G. Miller
  8. *
  9. * PURPOSE: Historically GRASS has used FIFO for interprocess communic-
  10. * ations for display functions. Unfortunately, FIFO's are
  11. * not available on all target platforms. An attempt has been
  12. * made to use IPC message passing, but the semantics are
  13. * variable and it also isn't available on all target platforms.
  14. * UNIX sockets, or local or domain sockets, are much more
  15. * widely available and consistent. NOTE: This implementation
  16. * of UNIX sockets provides zero security checking so should
  17. * not be used from untrusted clients.
  18. *
  19. * COPYRIGHT: (C) 2000 by the GRASS Development Team
  20. *
  21. * This program is free software under the GNU General Public
  22. * License (>=v2). Read the file COPYING that comes with GRASS
  23. * for details.
  24. *
  25. *****************************************************************************/
  26. #ifndef __MINGW32__ /* TODO */
  27. #ifdef __MINGW32__
  28. #include <grass/gis.h>
  29. #include <windows.h>
  30. #include <io.h>
  31. #include <errno.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34. #include <stddef.h>
  35. #include <stdlib.h>
  36. #include <sys/stat.h>
  37. #define PIPE_TIMEOUT 5000
  38. #define BUFSIZE 2048
  39. /* ---------------------------------------------------------------------
  40. * _get_make_pipe_path(), builds and tests the path for the socket
  41. * directory. Returns NULL on any failure, otherwise it returns the
  42. * directory path. The path will be like "/tmp/grass-$USER".
  43. * ---------------------------------------------------------------------*/
  44. static char *_get_make_pipe_path(void)
  45. {
  46. char *path, *user;
  47. const char *prefix = "c:/grass-";
  48. char *whoami = "mingw-anon-user";
  49. int len, status;
  50. struct _stat theStat;
  51. user = G_whoami(); /* Don't G_free () return value ever! */
  52. if (user == NULL) {
  53. user = whoami;
  54. }
  55. len = strlen(prefix) + strlen(user) + 1;
  56. path = G_malloc(len);
  57. sprintf(path, "%s%s", prefix, user);
  58. if ((status = G_lstat(path, &theStat)) != 0) {
  59. status = G_mkdir(path);
  60. }
  61. else {
  62. if (!S_ISDIR(theStat.st_mode)) {
  63. status = -1; /* not a directory ?? */
  64. }
  65. else {
  66. status = chmod(path, S_IRWXU); /* fails if we don't own it */
  67. }
  68. }
  69. if (status) { /* something's wrong if non-zero */
  70. G_free(path);
  71. path = NULL;
  72. }
  73. return path;
  74. }
  75. /* ----------------------------------------------------------------------
  76. * G_pipe_get_fname(), builds the full path for a UNIX socket. Caller
  77. * should G_free () the return value when it is no longer needed. Returns
  78. * NULL on failure.
  79. * ---------------------------------------------------------------------*/
  80. char *G_pipe_get_fname(char *name)
  81. {
  82. char *path, *dirpath;
  83. int len;
  84. if (name == NULL)
  85. return NULL;
  86. dirpath = _get_make_pipe_path();
  87. if (dirpath == NULL)
  88. return NULL;
  89. len = strlen(dirpath) + strlen(name) + 2;
  90. path = G_malloc(len);
  91. sprintf(path, "%s/%s", dirpath, name);
  92. G_free(dirpath);
  93. return path;
  94. }
  95. /* -------------------------------------------------------------------
  96. * G_pipe_exists(char *): Returns 1 if path is to a UNIX socket that
  97. * already exists, 0 otherwise.
  98. * -------------------------------------------------------------------*/
  99. int G_pipe_exists(char *name)
  100. {
  101. int rv = 0;
  102. HANDLE hFile = hFile = CreateFile(name,
  103. GENERIC_READ,
  104. FILE_SHARE_READ,
  105. NULL,
  106. OPEN_EXISTING,
  107. FILE_ATTRIBUTE_NORMAL,
  108. NULL);
  109. if (hFile != INVALID_HANDLE_VALUE) {
  110. if (name == NULL || (FILE_TYPE_PIPE != GetFileType(hFile))) {
  111. rv = 0;
  112. }
  113. else {
  114. rv = 1;
  115. CloseFile(hFile);
  116. }
  117. }
  118. return (rv);
  119. }
  120. /* -----------------------------------------------------------------
  121. * G_pipe_bind (char *): Takes the full pathname for a UNIX socket
  122. * and returns the file descriptor to the socket after a successful
  123. * call to bind(). On error, it returns -1. Check "errno" if you
  124. * want to find out why this failed (clear it before the call).
  125. * ----------------------------------------------------------------*/
  126. HANDLE G_pipe_bind(char *name)
  127. {
  128. HANDLE hPipe;
  129. if (name == NULL) {
  130. return -1;
  131. }
  132. if (G_pipe_exists(name)) {
  133. /*errno = EADDRINUSE; */
  134. return -1;
  135. }
  136. hPipe = CreateNamedPipe(name, // pipe name
  137. PIPE_ACCESS_DUPLEX, // read/write access
  138. PIPE_TYPE_MESSAGE | // message type pipe
  139. PIPE_READMODE_MESSAGE | // message-read mode
  140. PIPE_WAIT, // blocking mode
  141. PIPE_UNLIMITED_INSTANCES, // max. instances
  142. BUFSIZE, // output buffer size
  143. BUFSIZE, // input buffer size
  144. PIPE_TIMEOUT, // client time-out
  145. NULL); // no security attribute
  146. if (hPipe == INVALID_HANDLE_VALUE) {
  147. return (-1);
  148. }
  149. return (hPipe);
  150. }
  151. /* ---------------------------------------------------------------------
  152. * G_pipe_listen(int, unsigned int): Wrapper around the listen()
  153. * function.
  154. * --------------------------------------------------------------------*/
  155. int G_pipe_listen(HANDLE hPipe, unsigned int queue_len)
  156. {
  157. return (0);
  158. }
  159. /* -----------------------------------------------------------------------
  160. * G_pipe_accept (int sockfd):
  161. * Wrapper around the accept() function. No client info is returned, but
  162. * that's not generally useful for local sockets anyway. Function returns
  163. * the file descriptor or an error code generated by accept(). Note,
  164. * this call will usually block until a connection arrives. You can use
  165. * select() for a time out on the call.
  166. * ---------------------------------------------------------------------*/
  167. HANDLE G_pipe_accept(HANDLE hPipe)
  168. {
  169. BOOL fConnected;
  170. HANDLE rv = hPipe;
  171. fConnected = ConnectNamedPipe(hPipe, NULL) ?
  172. TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
  173. if (fConnected) {
  174. rv = NULL;
  175. }
  176. return (rv);
  177. }
  178. /* ----------------------------------------------------------------------
  179. * G_pipe_connect (char *name): Tries to connect to the unix socket
  180. * specified by "name". Returns the file descriptor if successful, or
  181. * -1 if unsuccessful. Global errno is set by connect() if return is -1
  182. * (though you should zero errno first, since this function doesn't set
  183. * it for a couple conditions).
  184. * --------------------------------------------------------------------*/
  185. HANDLE G_pipe_connect(char *name)
  186. {
  187. HANDLE hPipe = -1;
  188. if (!G_pipe_exists(name)) {
  189. return hPipe;
  190. }
  191. while (1) {
  192. hPipe = CreateFile(name, // pipe name
  193. GENERIC_READ | // read and write access
  194. GENERIC_WRITE, 0, // no sharing
  195. NULL, // no security attributes
  196. OPEN_EXISTING, // opens existing pipe
  197. 0, // default attributes
  198. NULL); // no template file
  199. if (hPipe != INVALID_HANDLE_VALUE) {
  200. break;
  201. }
  202. if (GetLastError() != ERROR_PIPE_BUSY) {
  203. return (-1);
  204. }
  205. /* Wait for 5 seconds */
  206. if (!WaitNamedPipe(name, PIPE_TIMEOUT)) {
  207. return (-1);
  208. }
  209. }
  210. return (hPipe);
  211. }
  212. #endif /* __MINGW32__ */
  213. #endif /* __MINGW32__ */