win32_pipes.c

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

Generated on Fri Nov 21 11:02:18 2008 for GRASS by  doxygen 1.5.1