00001 /* 00002 * $Id: win32_pipes.c,v 2.0 2004/11/09 12:23:11 bernhard Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * LIBRARY: unix_socks.c -- Routines related to using UNIX domain 00007 * sockets for IPC mechanisms (such as XDRIVER). 00008 * 00009 * AUTHOR(S): Eric G. Miller 00010 * 00011 * PURPOSE: Historically GRASS has used FIFO for interprocess communic- 00012 * ations for display functions. Unfortunately, FIFO's are 00013 * not available on all target platforms. An attempt has been 00014 * made to use IPC message passing, but the semantics are 00015 * variable and it also isn't available on all target platforms. 00016 * UNIX sockets, or local or domain sockets, are much more 00017 * widely available and consistent. NOTE: This implementation 00018 * of UNIX sockets provides zero security checking so should 00019 * not be used from untrusted clients. 00020 * 00021 * COPYRIGHT: (C) 2000 by the GRASS Development Team 00022 * 00023 * This program is free software under the GNU General Public 00024 * License (>=v2). Read the file COPYING that comes with GRASS 00025 * for details. 00026 * 00027 *****************************************************************************/ 00028 00029 #ifdef __MINGW32__ 00030 00031 #include "gis.h" 00032 #include <windows.h> 00033 #include <io.h> 00034 #include <errno.h> 00035 #include <string.h> 00036 #include <stdio.h> 00037 #include <stddef.h> 00038 #include <stdlib.h> 00039 #include <sys/stat.h> 00040 00041 #define PIPE_TIMEOUT 5000 00042 #define BUFSIZE 2048 00043 00044 /* --------------------------------------------------------------------- 00045 * _get_make_pipe_path(), builds and tests the path for the socket 00046 * directory. Returns NULL on any failure, otherwise it returns the 00047 * directory path. The path will be like "/tmp/grass-$USER". 00048 * ---------------------------------------------------------------------*/ 00049 static char * 00050 _get_make_pipe_path (void) 00051 { 00052 char *path, *user; 00053 const char *prefix = "c:/grass-"; 00054 char *whoami = "mingw-anon-user"; 00055 int len, status; 00056 struct _stat theStat; 00057 00058 user = G_whoami(); /* Don't free() return value ever! */ 00059 if (user == NULL) { 00060 user = whoami; 00061 } 00062 len = strlen(prefix) + strlen(user) + 1; 00063 path = G_malloc (len); 00064 sprintf (path, "%s%s", prefix, user); 00065 00066 if ((status = lstat (path, &theStat)) != 0) 00067 { 00068 status = mkdir ( path ); 00069 } 00070 else 00071 { 00072 if (!S_ISDIR (theStat.st_mode)) 00073 { 00074 status = -1; /* not a directory ?? */ 00075 } 00076 else 00077 { 00078 status = chmod (path, S_IRWXU); /* fails if we don't own it */ 00079 } 00080 } 00081 00082 if (status) /* something's wrong if non-zero */ 00083 { 00084 G_free (path); 00085 path = NULL; 00086 } 00087 00088 return path; 00089 } 00090 00091 00092 /* ---------------------------------------------------------------------- 00093 * G_pipe_get_fname(), builds the full path for a UNIX socket. Caller 00094 * should free() the return value when it is no longer needed. Returns 00095 * NULL on failure. 00096 * ---------------------------------------------------------------------*/ 00097 char * 00098 G_pipe_get_fname (char *name) 00099 { 00100 char *path, *dirpath; 00101 int len; 00102 00103 if (name == NULL) 00104 return NULL; 00105 00106 dirpath = _get_make_pipe_path(); 00107 00108 if (dirpath == NULL) 00109 return NULL; 00110 00111 len = strlen (dirpath) + strlen(name) + 2; 00112 path = G_malloc (len); 00113 sprintf (path, "%s/%s", dirpath, name); 00114 G_free (dirpath); 00115 00116 return path; 00117 } 00118 00119 00120 /* ------------------------------------------------------------------- 00121 * G_pipe_exists(char *): Returns 1 if path is to a UNIX socket that 00122 * already exists, 0 otherwise. 00123 * -------------------------------------------------------------------*/ 00124 00125 int 00126 G_pipe_exists (char *name) 00127 { 00128 int rv = 0; 00129 HANDLE hFile = hFile = CreateFile( name, 00130 GENERIC_READ, 00131 FILE_SHARE_READ, 00132 NULL, 00133 OPEN_EXISTING, 00134 FILE_ATTRIBUTE_NORMAL, 00135 NULL ); 00136 00137 if ( hFile != INVALID_HANDLE_VALUE ) { 00138 if ( name == NULL || ( FILE_TYPE_PIPE != GetFileType ( hFile ) ) ) { 00139 rv = 0; 00140 } else { 00141 rv = 1; 00142 CloseFile ( hFile ); 00143 } 00144 } 00145 return ( rv ); 00146 } 00147 00148 00149 /* ----------------------------------------------------------------- 00150 * G_pipe_bind (char *): Takes the full pathname for a UNIX socket 00151 * and returns the file descriptor to the socket after a successful 00152 * call to bind(). On error, it returns -1. Check "errno" if you 00153 * want to find out why this failed (clear it before the call). 00154 * ----------------------------------------------------------------*/ 00155 00156 HANDLE 00157 G_pipe_bind (char *name) 00158 { 00159 HANDLE hPipe; 00160 if ( name == NULL ) { 00161 return -1; 00162 } 00163 if ( G_pipe_exists ( name ) ) { 00164 /*errno = EADDRINUSE;*/ 00165 return -1; 00166 } 00167 00168 hPipe = CreateNamedPipe ( name, // pipe name 00169 PIPE_ACCESS_DUPLEX, // read/write access 00170 PIPE_TYPE_MESSAGE | // message type pipe 00171 PIPE_READMODE_MESSAGE | // message-read mode 00172 PIPE_WAIT, // blocking mode 00173 PIPE_UNLIMITED_INSTANCES, // max. instances 00174 BUFSIZE, // output buffer size 00175 BUFSIZE, // input buffer size 00176 PIPE_TIMEOUT, // client time-out 00177 NULL); // no security attribute 00178 00179 if ( hPipe == INVALID_HANDLE_VALUE ) { 00180 return ( -1 ); 00181 } 00182 return ( hPipe ); 00183 } 00184 00185 00186 /* --------------------------------------------------------------------- 00187 * G_pipe_listen(int, unsigned int): Wrapper around the listen() 00188 * function. 00189 * --------------------------------------------------------------------*/ 00190 00191 int 00192 G_pipe_listen ( HANDLE hPipe, unsigned int queue_len) 00193 { 00194 return ( 0 ); 00195 } 00196 00197 /* ----------------------------------------------------------------------- 00198 * G_pipe_accept (int sockfd): 00199 * Wrapper around the accept() function. No client info is returned, but 00200 * that's not generally useful for local sockets anyway. Function returns 00201 * the file descriptor or an error code generated by accept(). Note, 00202 * this call will usually block until a connection arrives. You can use 00203 * select() for a time out on the call. 00204 * ---------------------------------------------------------------------*/ 00205 00206 HANDLE 00207 G_pipe_accept ( HANDLE hPipe ) 00208 { 00209 BOOL fConnected; 00210 HANDLE rv = hPipe; 00211 fConnected = ConnectNamedPipe(hPipe, NULL) ? 00212 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 00213 if ( fConnected ) { 00214 rv = NULL; 00215 } 00216 return ( rv ); 00217 } 00218 00219 00220 /* ---------------------------------------------------------------------- 00221 * G_pipe_connect (char *name): Tries to connect to the unix socket 00222 * specified by "name". Returns the file descriptor if successful, or 00223 * -1 if unsuccessful. Global errno is set by connect() if return is -1 00224 * (though you should zero errno first, since this function doesn't set 00225 * it for a couple conditions). 00226 * --------------------------------------------------------------------*/ 00227 00228 HANDLE 00229 G_pipe_connect (char *name) 00230 { 00231 HANDLE hPipe = -1; 00232 00233 if ( !G_pipe_exists ( name ) ) { 00234 return hPipe; 00235 } 00236 00237 while (1) { 00238 hPipe = CreateFile ( name, // pipe name 00239 GENERIC_READ | // read and write access 00240 GENERIC_WRITE, 00241 0, // no sharing 00242 NULL, // no security attributes 00243 OPEN_EXISTING, // opens existing pipe 00244 0, // default attributes 00245 NULL ); // no template file 00246 00247 if ( hPipe != INVALID_HANDLE_VALUE ) { 00248 break; 00249 } 00250 if ( GetLastError() != ERROR_PIPE_BUSY ) { 00251 return (-1); 00252 } 00253 /* Wait for 5 seconds */ 00254 if (! WaitNamedPipe( name, PIPE_TIMEOUT ) ) { 00255 return ( -1 ); 00256 } 00257 } 00258 return ( hPipe ); 00259 } 00260 00261 #endif /* __MINGW32__ */