/* * $Id: win32_pipes.c,v 2.3 2006/02/14 09:02:57 radim Exp $ * **************************************************************************** * * LIBRARY: unix_socks.c -- Routines related to using UNIX domain * sockets for IPC mechanisms (such as XDRIVER). * * AUTHOR(S): Eric G. Miller * * PURPOSE: Historically GRASS has used FIFO for interprocess communic- * ations for display functions. Unfortunately, FIFO's are * not available on all target platforms. An attempt has been * made to use IPC message passing, but the semantics are * variable and it also isn't available on all target platforms. * UNIX sockets, or local or domain sockets, are much more * widely available and consistent. NOTE: This implementation * of UNIX sockets provides zero security checking so should * not be used from untrusted clients. * * COPYRIGHT: (C) 2000 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #ifndef __MINGW32__ /* TODO */ #ifdef __MINGW32__ #include #include #include #include #include #include #include #include #include #define PIPE_TIMEOUT 5000 #define BUFSIZE 2048 /* --------------------------------------------------------------------- * _get_make_pipe_path(), builds and tests the path for the socket * directory. Returns NULL on any failure, otherwise it returns the * directory path. The path will be like "/tmp/grass-$USER". * ---------------------------------------------------------------------*/ static char * _get_make_pipe_path (void) { char *path, *user; const char *prefix = "c:/grass-"; char *whoami = "mingw-anon-user"; int len, status; struct _stat theStat; user = G_whoami(); /* Don't G_free () return value ever! */ if (user == NULL) { user = whoami; } len = strlen(prefix) + strlen(user) + 1; path = G_malloc (len); sprintf (path, "%s%s", prefix, user); if ((status = lstat (path, &theStat)) != 0) { status = mkdir ( path ); } else { if (!S_ISDIR (theStat.st_mode)) { status = -1; /* not a directory ?? */ } else { status = chmod (path, S_IRWXU); /* fails if we don't own it */ } } if (status) /* something's wrong if non-zero */ { G_free (path); path = NULL; } return path; } /* ---------------------------------------------------------------------- * G_pipe_get_fname(), builds the full path for a UNIX socket. Caller * should G_free () the return value when it is no longer needed. Returns * NULL on failure. * ---------------------------------------------------------------------*/ char * G_pipe_get_fname (char *name) { char *path, *dirpath; int len; if (name == NULL) return NULL; dirpath = _get_make_pipe_path(); if (dirpath == NULL) return NULL; len = strlen (dirpath) + strlen(name) + 2; path = G_malloc (len); sprintf (path, "%s/%s", dirpath, name); G_free (dirpath); return path; } /* ------------------------------------------------------------------- * G_pipe_exists(char *): Returns 1 if path is to a UNIX socket that * already exists, 0 otherwise. * -------------------------------------------------------------------*/ int G_pipe_exists (char *name) { int rv = 0; HANDLE hFile = hFile = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile != INVALID_HANDLE_VALUE ) { if ( name == NULL || ( FILE_TYPE_PIPE != GetFileType ( hFile ) ) ) { rv = 0; } else { rv = 1; CloseFile ( hFile ); } } return ( rv ); } /* ----------------------------------------------------------------- * G_pipe_bind (char *): Takes the full pathname for a UNIX socket * and returns the file descriptor to the socket after a successful * call to bind(). On error, it returns -1. Check "errno" if you * want to find out why this failed (clear it before the call). * ----------------------------------------------------------------*/ HANDLE G_pipe_bind (char *name) { HANDLE hPipe; if ( name == NULL ) { return -1; } if ( G_pipe_exists ( name ) ) { /*errno = EADDRINUSE;*/ return -1; } hPipe = CreateNamedPipe ( name, // pipe name PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size BUFSIZE, // input buffer size PIPE_TIMEOUT, // client time-out NULL); // no security attribute if ( hPipe == INVALID_HANDLE_VALUE ) { return ( -1 ); } return ( hPipe ); } /* --------------------------------------------------------------------- * G_pipe_listen(int, unsigned int): Wrapper around the listen() * function. * --------------------------------------------------------------------*/ int G_pipe_listen ( HANDLE hPipe, unsigned int queue_len) { return ( 0 ); } /* ----------------------------------------------------------------------- * G_pipe_accept (int sockfd): * Wrapper around the accept() function. No client info is returned, but * that's not generally useful for local sockets anyway. Function returns * the file descriptor or an error code generated by accept(). Note, * this call will usually block until a connection arrives. You can use * select() for a time out on the call. * ---------------------------------------------------------------------*/ HANDLE G_pipe_accept ( HANDLE hPipe ) { BOOL fConnected; HANDLE rv = hPipe; fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if ( fConnected ) { rv = NULL; } return ( rv ); } /* ---------------------------------------------------------------------- * G_pipe_connect (char *name): Tries to connect to the unix socket * specified by "name". Returns the file descriptor if successful, or * -1 if unsuccessful. Global errno is set by connect() if return is -1 * (though you should zero errno first, since this function doesn't set * it for a couple conditions). * --------------------------------------------------------------------*/ HANDLE G_pipe_connect (char *name) { HANDLE hPipe = -1; if ( !G_pipe_exists ( name ) ) { return hPipe; } while (1) { hPipe = CreateFile ( name, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing NULL, // no security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL ); // no template file if ( hPipe != INVALID_HANDLE_VALUE ) { break; } if ( GetLastError() != ERROR_PIPE_BUSY ) { return (-1); } /* Wait for 5 seconds */ if (! WaitNamedPipe( name, PIPE_TIMEOUT ) ) { return ( -1 ); } } return ( hPipe ); } #endif /* __MINGW32__ */ #endif /* __MINGW32__ */