GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
unix_socks.c
Go to the documentation of this file.
1 
30 #include <grass/config.h>
31 
32 #ifdef HAVE_SOCKET
33 
34 #include <stdio.h>
35 #include <stddef.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #ifdef __MINGW32__
43 #define USE_TCP
44 #include <winsock2.h>
45 #include <ws2tcpip.h>
46 #define EADDRINUSE WSAEADDRINUSE
47 #else
48 #include <sys/socket.h>
49 #include <sys/un.h>
50 #include <netinet/in.h>
51 #define INVALID_SOCKET (-1)
52 #endif
53 
54 #include <grass/gis.h>
55 #include <grass/version.h>
56 #include <grass/glocale.h>
57 
62 static char *_get_make_sock_path(void);
63 
64 static void init_sockets(void)
65 {
66 #ifdef __MINGW32__
67  static int ready;
68  WSADATA wsadata;
69 
70  if (ready)
71  return;
72 
73  ready = 1;
74 
75  WSAStartup(0x0001, &wsadata);
76 #endif
77 }
78 
79 /* ---------------------------------------------------------------------
80  * _get_make_sock_path(), builds and tests the path for the socket
81  * directory. Returns NULL on any failure, otherwise it returns the
82  * directory path. The path will be like
83  * "/tmp/grass6-$USER-$GIS_LOCK".
84  * ($GIS_LOCK is set in lib/init/init.sh to PID)
85  * ---------------------------------------------------------------------*/
86 
87 static char *_get_make_sock_path(void)
88 {
89  char *path, *user, *lock;
90  const char *prefix = "/tmp/grass6";
91  int len, status;
92  struct stat theStat;
93 
94  user = G_whoami(); /* Don't G_free () return value ever! */
95  if (user == NULL)
96  return NULL;
97  else if (user[0] == '?') { /* why's it do that? */
98  return NULL;
99  }
100 
101  if ((lock = getenv("GIS_LOCK")) == NULL)
102  G_fatal_error(_("Unable to get GIS_LOCK environment variable value"));
103 
104  len = strlen(prefix) + strlen(user) + strlen(lock) + 3;
105  path = G_malloc(len);
106 
107  sprintf(path, "%s-%s-%s", prefix, user, lock);
108 
109  if ((status = G_lstat(path, &theStat)) != 0) {
110  status = G_mkdir(path);
111  }
112  else {
113  if (!S_ISDIR(theStat.st_mode)) {
114  status = -1; /* not a directory ?? */
115  }
116  else {
117  status = chmod(path, S_IRWXU); /* fails if we don't own it */
118  }
119  }
120 
121  if (status) { /* something's wrong if non-zero */
122  G_free(path);
123  path = NULL;
124  }
125 
126  return path;
127 }
128 
129 #ifdef USE_TCP
130 
131 #define PROTO PF_INET
132 typedef struct sockaddr_in sockaddr_t;
133 
134 static int set_port(const char *name, int port)
135 {
136  FILE *fp = fopen(name, "w");
137 
138  if (!fp)
139  return -1;
140 
141  fprintf(fp, "%d\n", port);
142 
143  fclose(fp);
144 
145  return 0;
146 }
147 
148 static int get_port(const char *name)
149 {
150  FILE *fp = fopen(name, "r");
151  int port;
152 
153  if (!fp)
154  return -1;
155 
156  if (fscanf(fp, "%d", &port) != 1)
157  port = -1;
158 
159  fclose(fp);
160 
161  return port;
162 }
163 
164 static int save_port(int sockfd, const char *name)
165 {
166  sockaddr_t addr;
167  socklen_t size = sizeof(addr);
168 
169  if (getsockname(sockfd, (struct sockaddr *)&addr, &size) != 0)
170  return -1;
171 
172  if (set_port(name, ntohs(addr.sin_port)) < 0)
173  return -1;
174 
175  return 0;
176 }
177 
178 static int make_address(sockaddr_t * addr, const char *name, int exists)
179 {
180  int port = exists ? get_port(name) : 0;
181 
182  if (port < 0)
183  return -1;
184 
185  addr->sin_family = AF_INET;
186  addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
187  addr->sin_port = htons((unsigned short)port);
188 
189  return 0;
190 }
191 
192 #else
193 
194 #define PROTO PF_UNIX
195 typedef struct sockaddr_un sockaddr_t;
196 
197 static int make_address(sockaddr_t * addr, const char *name, int exists)
198 {
199  addr->sun_family = AF_UNIX;
200 
201  /* The path to the unix socket must fit in sun_path[] */
202  if (sizeof(addr->sun_path) < strlen(name) + 1)
203  return -1;
204 
205  strncpy(addr->sun_path, name, sizeof(addr->sun_path) - 1);
206 
207  return 0;
208 }
209 
210 #endif
211 
223 char *G_sock_get_fname(const char *name)
224 {
225  char *path, *dirpath;
226  int len;
227 
228  if (name == NULL)
229  return NULL;
230 
231  dirpath = _get_make_sock_path();
232 
233  if (dirpath == NULL)
234  return NULL;
235 
236  len = strlen(dirpath) + strlen(name) + 2;
237  path = G_malloc(len);
238  sprintf(path, "%s/%s", dirpath, name);
239  G_free(dirpath);
240 
241  return path;
242 }
243 
244 
253 int G_sock_exists(const char *name)
254 {
255  struct stat theStat;
256 
257  if (name == NULL || stat(name, &theStat) != 0)
258  return 0;
259 
260 #ifdef USE_TCP
261  if (S_ISREG(theStat.st_mode))
262 #else
263  if (S_ISSOCK(theStat.st_mode))
264 #endif
265  return 1;
266  else
267  return 0;
268 }
269 
270 
282 int G_sock_bind(const char *name)
283 {
284  int sockfd;
285  sockaddr_t addr;
286  socklen_t size;
287 
288  if (name == NULL)
289  return -1;
290 
291  init_sockets();
292 
293  /* Bind requires that the file does not exist. Force the caller
294  * to make sure the socket is not in use. The only way to test,
295  * is a call to connect().
296  */
297  if (G_sock_exists(name)) {
298  errno = EADDRINUSE;
299  return -1;
300  }
301 
302  /* must always zero socket structure */
303  memset(&addr, 0, sizeof(addr));
304 
305  size = sizeof(addr);
306 
307  if (make_address(&addr, name, 0) < 0)
308  return -1;
309 
310  sockfd = socket(PROTO, SOCK_STREAM, 0);
311  if (sockfd == INVALID_SOCKET)
312  return -1;
313 
314  if (bind(sockfd, (const struct sockaddr *)&addr, size) != 0)
315  return -1;
316 
317 #ifdef USE_TCP
318  if (save_port(sockfd, name) < 0)
319  return -1;
320 #endif
321 
322  return sockfd;
323 }
324 
334 int G_sock_listen(int sockfd, unsigned int queue_len)
335 {
336  return listen(sockfd, queue_len);
337 }
338 
339 
351 int G_sock_accept(int sockfd)
352 {
353  sockaddr_t addr;
354  socklen_t len = sizeof(addr);
355 
356  return accept(sockfd, (struct sockaddr *)&addr, &len);
357 }
358 
359 
368 int G_sock_connect(const char *name)
369 {
370  int sockfd;
371  sockaddr_t addr;
372 
373  init_sockets();
374 
375  if (!G_sock_exists(name))
376  return -1;
377 
378  /* must always zero socket structure */
379  memset(&addr, 0, sizeof(addr));
380 
381  if (make_address(&addr, name, 1) < 0)
382  return -1;
383 
384  sockfd = socket(PROTO, SOCK_STREAM, 0);
385  if (sockfd == INVALID_SOCKET)
386  return -1;
387 
388  if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
389  return -1;
390  else
391  return sockfd;
392 }
393 
394 #endif
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
tuple bind
Definition: tools.py:1407
int G_mkdir(const char *path)
Creates a new directory.
Definition: paths.c:17
string name
Definition: render.py:1314
int G_lstat(const char *file_name, struct stat *buf)
Get file status.
Definition: paths.c:135
tuple size
value.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
Definition: tools.py:2334
char * getenv()
int stat
Definition: g3dcolor.c:369
char * G_whoami(void)
Gets user&#39;s name.
Definition: gis/whoami.c:40
return NULL
Definition: dbfopen.c:1394
fclose(fd)
int errno
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.