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