GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
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 * ---------------------------------------------------------------------*/
47static 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 * ---------------------------------------------------------------------*/
88char *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
114int 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
140HANDLE 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
174int 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
188HANDLE 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
210HANDLE 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__ */
243extern int dummy_for_iso_compilers; /* suppress -Wempty-translation-unit */
244#endif /* __MINGW32__ */
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
#define NULL
Definition ccmath.h:32
#define TRUE
Definition dbfopen.c:75
const char * name
Definition named_colr.c:6
int G_mkdir(const char *path)
Creates a new directory.
Definition paths.c:27
int G_lstat(const char *file_name, struct stat *buf)
Get file status.
Definition paths.c:145
Definition path.h:15
const char * G_whoami(void)
Gets user's name.
Definition whoami.c:35
int dummy_for_iso_compilers