win32_pipes.c

Go to the documentation of this file.
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__ */

Generated on Sat Jul 22 22:06:15 2006 for GRASS by  doxygen 1.4.7