GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
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 * ---------------------------------------------------------------------*/
48static 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 * ---------------------------------------------------------------------*/
90char *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
117int 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
148HANDLE 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
183int 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
197HANDLE 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
219HANDLE 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__ */
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
#define NULL
Definition: ccmath.h:32
#define TRUE
Definition: dbfopen.c:183
const char * name
Definition: named_colr.c:7
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:16
const char * G_whoami(void)
Gets user's name.
Definition: whoami.c:35