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
00081
00082
00083
00084
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();
00095 if (user == NULL)
00096 return NULL;
00097 else if (user[0] == '?') {
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;
00115 }
00116 else {
00117 status = chmod(path, S_IRWXU);
00118 }
00119 }
00120
00121 if (status) {
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
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
00294
00295
00296
00297 if (G_sock_exists(name)) {
00298 errno = EADDRINUSE;
00299 return -1;
00300 }
00301
00302
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
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