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