GRASS Programmer's Manual 6.4.1(2011)
|
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__ */