GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
win32_pipes.c
Go to the documentation of this file.
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 
27 #ifndef __MINGW32__ /* TODO */
28 #ifdef __MINGW32__
29 
30 #include <grass/gis.h>
31 #include <windows.h>
32 #include <io.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <sys/stat.h>
39 
40 #define PIPE_TIMEOUT 5000
41 #define BUFSIZE 2048
42 
43 /* ---------------------------------------------------------------------
44  * _get_make_pipe_path(), builds and tests the path for the socket
45  * directory. Returns NULL on any failure, otherwise it returns the
46  * directory path. The path will be like "/tmp/grass-$USER".
47  * ---------------------------------------------------------------------*/
48 static char *_get_make_pipe_path(void)
49 {
50  char *path, *user;
51  const char *prefix = "c:/grass-";
52  char *whoami = "mingw-anon-user";
53  int len, status;
54  struct _stat theStat;
55 
56  user = G_whoami(); /* Don't G_free () return value ever! */
57  if (user == NULL) {
58  user = whoami;
59  }
60  len = strlen(prefix) + strlen(user) + 1;
61  path = G_malloc(len);
62  sprintf(path, "%s%s", prefix, user);
63 
64  if ((status = G_lstat(path, &theStat)) != 0) {
65  status = G_mkdir(path);
66  }
67  else {
68  if (!S_ISDIR(theStat.st_mode)) {
69  status = -1; /* not a directory ?? */
70  }
71  else {
72  status = chmod(path, S_IRWXU); /* fails if we don't own it */
73  }
74  }
75 
76  if (status) { /* something's wrong if non-zero */
77  G_free(path);
78  path = NULL;
79  }
80 
81  return path;
82 }
83 
84 
85  /* ----------------------------------------------------------------------
86  * G_pipe_get_fname(), builds the full path for a UNIX socket. Caller
87  * should G_free () the return value when it is no longer needed. Returns
88  * NULL on failure.
89  * ---------------------------------------------------------------------*/
90 char *G_pipe_get_fname(char *name)
91 {
92  char *path, *dirpath;
93  int len;
94 
95  if (name == NULL)
96  return NULL;
97 
98  dirpath = _get_make_pipe_path();
99 
100  if (dirpath == NULL)
101  return NULL;
102 
103  len = strlen(dirpath) + strlen(name) + 2;
104  path = G_malloc(len);
105  sprintf(path, "%s/%s", dirpath, name);
106  G_free(dirpath);
107 
108  return path;
109 }
110 
111 
112 /* -------------------------------------------------------------------
113  * G_pipe_exists(char *): Returns 1 if path is to a UNIX socket that
114  * already exists, 0 otherwise.
115  * -------------------------------------------------------------------*/
116 
117 int G_pipe_exists(char *name)
118 {
119  int rv = 0;
120  HANDLE hFile = hFile = CreateFile(name,
121  GENERIC_READ,
122  FILE_SHARE_READ,
123  NULL,
124  OPEN_EXISTING,
125  FILE_ATTRIBUTE_NORMAL,
126  NULL);
127 
128  if (hFile != INVALID_HANDLE_VALUE) {
129  if (name == NULL || (FILE_TYPE_PIPE != GetFileType(hFile))) {
130  rv = 0;
131  }
132  else {
133  rv = 1;
134  CloseFile(hFile);
135  }
136  }
137  return (rv);
138 }
139 
140 
141 /* -----------------------------------------------------------------
142  * G_pipe_bind (char *): Takes the full pathname for a UNIX socket
143  * and returns the file descriptor to the socket after a successful
144  * call to bind(). On error, it returns -1. Check "errno" if you
145  * want to find out why this failed (clear it before the call).
146  * ----------------------------------------------------------------*/
147 
148 HANDLE G_pipe_bind(char *name)
149 {
150  HANDLE hPipe;
151 
152  if (name == NULL) {
153  return -1;
154  }
155  if (G_pipe_exists(name)) {
156  /*errno = EADDRINUSE; */
157  return -1;
158  }
159 
160  hPipe = CreateNamedPipe(name, // pipe name
161  PIPE_ACCESS_DUPLEX, // read/write access
162  PIPE_TYPE_MESSAGE | // message type pipe
163  PIPE_READMODE_MESSAGE | // message-read mode
164  PIPE_WAIT, // blocking mode
165  PIPE_UNLIMITED_INSTANCES, // max. instances
166  BUFSIZE, // output buffer size
167  BUFSIZE, // input buffer size
168  PIPE_TIMEOUT, // client time-out
169  NULL); // no security attribute
170 
171  if (hPipe == INVALID_HANDLE_VALUE) {
172  return (-1);
173  }
174  return (hPipe);
175 }
176 
177 
178 /* ---------------------------------------------------------------------
179  * G_pipe_listen(int, unsigned int): Wrapper around the listen()
180  * function.
181  * --------------------------------------------------------------------*/
182 
183 int G_pipe_listen(HANDLE hPipe, unsigned int queue_len)
184 {
185  return (0);
186 }
187 
188 /* -----------------------------------------------------------------------
189  * G_pipe_accept (int sockfd):
190  * Wrapper around the accept() function. No client info is returned, but
191  * that's not generally useful for local sockets anyway. Function returns
192  * the file descriptor or an error code generated by accept(). Note,
193  * this call will usually block until a connection arrives. You can use
194  * select() for a time out on the call.
195  * ---------------------------------------------------------------------*/
196 
197 HANDLE G_pipe_accept(HANDLE hPipe)
198 {
199  BOOL fConnected;
200  HANDLE rv = hPipe;
201 
202  fConnected = ConnectNamedPipe(hPipe, NULL) ?
203  TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
204  if (fConnected) {
205  rv = NULL;
206  }
207  return (rv);
208 }
209 
210 
211 /* ----------------------------------------------------------------------
212  * G_pipe_connect (char *name): Tries to connect to the unix socket
213  * specified by "name". Returns the file descriptor if successful, or
214  * -1 if unsuccessful. Global errno is set by connect() if return is -1
215  * (though you should zero errno first, since this function doesn't set
216  * it for a couple conditions).
217  * --------------------------------------------------------------------*/
218 
219 HANDLE G_pipe_connect(char *name)
220 {
221  HANDLE hPipe = -1;
222 
223  if (!G_pipe_exists(name)) {
224  return hPipe;
225  }
226 
227  while (1) {
228  hPipe = CreateFile(name, // pipe name
229  GENERIC_READ | // read and write access
230  GENERIC_WRITE, 0, // no sharing
231  NULL, // no security attributes
232  OPEN_EXISTING, // opens existing pipe
233  0, // default attributes
234  NULL); // no template file
235 
236  if (hPipe != INVALID_HANDLE_VALUE) {
237  break;
238  }
239  if (GetLastError() != ERROR_PIPE_BUSY) {
240  return (-1);
241  }
242  /* Wait for 5 seconds */
243  if (!WaitNamedPipe(name, PIPE_TIMEOUT)) {
244  return (-1);
245  }
246  }
247  return (hPipe);
248 }
249 
250 #endif /* __MINGW32__ */
251 #endif /* __MINGW32__ */
#define TRUE
Definition: gis.h:59
#define G_malloc(n)
Definition: defs/gis.h:112
const char * G_whoami(void)
Gets user&#39;s name.
Definition: gis/whoami.c:35
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
#define NULL
Definition: ccmath.h:32
Definition: path.h:16
int G_mkdir(const char *)
Creates a new directory.
Definition: paths.c:27
const char * name
Definition: named_colr.c:7
int G_lstat(const char *, struct stat *)
Get file status.
Definition: paths.c:145