123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- ****************************************************************************
- *
- * 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 <grass/gis.h>
- #include <windows.h>
- #include <io.h>
- #include <errno.h>
- #include <string.h>
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- #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 = G_lstat(path, &theStat)) != 0) {
- status = G_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__ */
|