GRASS Programmer's Manual 6.4.1(2011)
|
00001 00030 #include <grass/config.h> 00031 00032 #ifdef HAVE_SOCKET 00033 00034 #include <stdio.h> 00035 #include <stddef.h> 00036 #include <stdlib.h> 00037 #include <errno.h> 00038 #include <string.h> 00039 #include <unistd.h> 00040 #include <sys/types.h> 00041 #include <sys/stat.h> 00042 #ifdef __MINGW32__ 00043 #define USE_TCP 00044 #include <winsock2.h> 00045 #include <ws2tcpip.h> 00046 #define EADDRINUSE WSAEADDRINUSE 00047 #else 00048 #include <sys/socket.h> 00049 #include <sys/un.h> 00050 #include <netinet/in.h> 00051 #define INVALID_SOCKET (-1) 00052 #endif 00053 00054 #include <grass/gis.h> 00055 #include <grass/version.h> 00056 #include <grass/glocale.h> 00057 00062 static char *_get_make_sock_path(void); 00063 00064 static void init_sockets(void) 00065 { 00066 #ifdef __MINGW32__ 00067 static int ready; 00068 WSADATA wsadata; 00069 00070 if (ready) 00071 return; 00072 00073 ready = 1; 00074 00075 WSAStartup(0x0001, &wsadata); 00076 #endif 00077 } 00078 00079 /* --------------------------------------------------------------------- 00080 * _get_make_sock_path(), builds and tests the path for the socket 00081 * directory. Returns NULL on any failure, otherwise it returns the 00082 * directory path. The path will be like 00083 * "/tmp/grass6-$USER-$GIS_LOCK". 00084 * ($GIS_LOCK is set in lib/init/init.sh to PID) 00085 * ---------------------------------------------------------------------*/ 00086 00087 static char *_get_make_sock_path(void) 00088 { 00089 char *path, *user, *lock; 00090 const char *prefix = "/tmp/grass6"; 00091 int len, status; 00092 struct stat theStat; 00093 00094 user = G_whoami(); /* Don't G_free () return value ever! */ 00095 if (user == NULL) 00096 return NULL; 00097 else if (user[0] == '?') { /* why's it do that? */ 00098 return NULL; 00099 } 00100 00101 if ((lock = getenv("GIS_LOCK")) == NULL) 00102 G_fatal_error(_("Unable to get GIS_LOCK enviroment variable value")); 00103 00104 len = strlen(prefix) + strlen(user) + strlen(lock) + 3; 00105 path = G_malloc(len); 00106 00107 sprintf(path, "%s-%s-%s", prefix, user, lock); 00108 00109 if ((status = G_lstat(path, &theStat)) != 0) { 00110 status = G_mkdir(path); 00111 } 00112 else { 00113 if (!S_ISDIR(theStat.st_mode)) { 00114 status = -1; /* not a directory ?? */ 00115 } 00116 else { 00117 status = chmod(path, S_IRWXU); /* fails if we don't own it */ 00118 } 00119 } 00120 00121 if (status) { /* something's wrong if non-zero */ 00122 G_free(path); 00123 path = NULL; 00124 } 00125 00126 return path; 00127 } 00128 00129 #ifdef USE_TCP 00130 00131 #define PROTO PF_INET 00132 typedef struct sockaddr_in sockaddr_t; 00133 00134 static int set_port(const char *name, int port) 00135 { 00136 FILE *fp = fopen(name, "w"); 00137 00138 if (!fp) 00139 return -1; 00140 00141 fprintf(fp, "%d\n", port); 00142 00143 fclose(fp); 00144 00145 return 0; 00146 } 00147 00148 static int get_port(const char *name) 00149 { 00150 FILE *fp = fopen(name, "r"); 00151 int port; 00152 00153 if (!fp) 00154 return -1; 00155 00156 if (fscanf(fp, "%d", &port) != 1) 00157 port = -1; 00158 00159 fclose(fp); 00160 00161 return port; 00162 } 00163 00164 static int save_port(int sockfd, const char *name) 00165 { 00166 sockaddr_t addr; 00167 socklen_t size = sizeof(addr); 00168 00169 if (getsockname(sockfd, (struct sockaddr *)&addr, &size) != 0) 00170 return -1; 00171 00172 if (set_port(name, ntohs(addr.sin_port)) < 0) 00173 return -1; 00174 00175 return 0; 00176 } 00177 00178 static int make_address(sockaddr_t * addr, const char *name, int exists) 00179 { 00180 int port = exists ? get_port(name) : 0; 00181 00182 if (port < 0) 00183 return -1; 00184 00185 addr->sin_family = AF_INET; 00186 addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 00187 addr->sin_port = htons((unsigned short)port); 00188 00189 return 0; 00190 } 00191 00192 #else 00193 00194 #define PROTO PF_UNIX 00195 typedef struct sockaddr_un sockaddr_t; 00196 00197 static int make_address(sockaddr_t * addr, const char *name, int exists) 00198 { 00199 addr->sun_family = AF_UNIX; 00200 00201 /* The path to the unix socket must fit in sun_path[] */ 00202 if (sizeof(addr->sun_path) < strlen(name) + 1) 00203 return -1; 00204 00205 strncpy(addr->sun_path, name, sizeof(addr->sun_path) - 1); 00206 00207 return 0; 00208 } 00209 00210 #endif 00211 00223 char *G_sock_get_fname(const char *name) 00224 { 00225 char *path, *dirpath; 00226 int len; 00227 00228 if (name == NULL) 00229 return NULL; 00230 00231 dirpath = _get_make_sock_path(); 00232 00233 if (dirpath == NULL) 00234 return NULL; 00235 00236 len = strlen(dirpath) + strlen(name) + 2; 00237 path = G_malloc(len); 00238 sprintf(path, "%s/%s", dirpath, name); 00239 G_free(dirpath); 00240 00241 return path; 00242 } 00243 00244 00253 int G_sock_exists(const char *name) 00254 { 00255 struct stat theStat; 00256 00257 if (name == NULL || stat(name, &theStat) != 0) 00258 return 0; 00259 00260 #ifdef USE_TCP 00261 if (S_ISREG(theStat.st_mode)) 00262 #else 00263 if (S_ISSOCK(theStat.st_mode)) 00264 #endif 00265 return 1; 00266 else 00267 return 0; 00268 } 00269 00270 00282 int G_sock_bind(const char *name) 00283 { 00284 int sockfd; 00285 sockaddr_t addr; 00286 socklen_t size; 00287 00288 if (name == NULL) 00289 return -1; 00290 00291 init_sockets(); 00292 00293 /* Bind requires that the file does not exist. Force the caller 00294 * to make sure the socket is not in use. The only way to test, 00295 * is a call to connect(). 00296 */ 00297 if (G_sock_exists(name)) { 00298 errno = EADDRINUSE; 00299 return -1; 00300 } 00301 00302 /* must always zero socket structure */ 00303 memset(&addr, 0, sizeof(addr)); 00304 00305 size = sizeof(addr); 00306 00307 if (make_address(&addr, name, 0) < 0) 00308 return -1; 00309 00310 sockfd = socket(PROTO, SOCK_STREAM, 0); 00311 if (sockfd == INVALID_SOCKET) 00312 return -1; 00313 00314 if (bind(sockfd, (const struct sockaddr *)&addr, size) != 0) 00315 return -1; 00316 00317 #ifdef USE_TCP 00318 if (save_port(sockfd, name) < 0) 00319 return -1; 00320 #endif 00321 00322 return sockfd; 00323 } 00324 00334 int G_sock_listen(int sockfd, unsigned int queue_len) 00335 { 00336 return listen(sockfd, queue_len); 00337 } 00338 00339 00351 int G_sock_accept(int sockfd) 00352 { 00353 sockaddr_t addr; 00354 socklen_t len = sizeof(addr); 00355 00356 return accept(sockfd, (struct sockaddr *)&addr, &len); 00357 } 00358 00359 00368 int G_sock_connect(const char *name) 00369 { 00370 int sockfd; 00371 sockaddr_t addr; 00372 00373 init_sockets(); 00374 00375 if (!G_sock_exists(name)) 00376 return -1; 00377 00378 /* must always zero socket structure */ 00379 memset(&addr, 0, sizeof(addr)); 00380 00381 if (make_address(&addr, name, 1) < 0) 00382 return -1; 00383 00384 sockfd = socket(PROTO, SOCK_STREAM, 0); 00385 if (sockfd == INVALID_SOCKET) 00386 return -1; 00387 00388 if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) 00389 return -1; 00390 else 00391 return sockfd; 00392 } 00393 00394 #endif