2 * socket.c - - this file is part of vomak - a very simple IRC bot
4 * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <sys/types.h>
25 #include <sys/socket.h>
27 #include <netinet/in.h>
29 #include <glib/gstdio.h>
37 #define SOCKET_IS_VALID(s) ((s) >= 0)
38 #define INVALID_SOCKET (-1)
41 /* (Unix domain) socket (taken from Geany, originally taken from Sylpheed, thanks) */
44 static gint
socket_fd_open_unix (const gchar
*path
);
45 static gint
socket_fd_check_io (gint fd
, GIOCondition cond
);
46 static gint
socket_fd_read (gint sock
, gchar
*buf
, gint len
);
47 static gint
socket_fd_recv (gint fd
, gchar
*buf
, gint len
, gint flags
);
48 static gint
socket_fd_connect_unix (const gchar
*path
);
52 static void remove_socket_link_full(socket_info_t
*si
)
54 g_unlink(si
->file_name
);
58 void socket_init(socket_info_t
*si
, const gchar
*filename
)
62 if (si
->file_name
== NULL
)
63 si
->file_name
= g_strdup(filename
);
65 sock
= socket_fd_connect_unix(si
->file_name
);
68 remove_socket_link_full(si
); /* deletes the socket file and the symlink */
69 si
->lock_socket
= socket_fd_open_unix(si
->file_name
);
73 si
->lock_socket
= sock
;
78 gint
socket_finalize(socket_info_t
*si
)
80 if (si
->lock_socket
< 0) return -1;
82 if (si
->lock_socket_tag
> 0)
83 g_source_remove(si
->lock_socket_tag
);
86 g_io_channel_shutdown(si
->read_ioc
, FALSE
, NULL
);
87 g_io_channel_unref(si
->read_ioc
);
91 if (si
->file_name
!= NULL
)
93 remove_socket_link_full(si
); /* deletes the socket file and the symlink */
94 g_free(si
->file_name
);
101 static gint
socket_fd_connect_unix(const gchar
*path
)
104 struct sockaddr_un addr
;
106 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
109 perror("socket_fd_connect_unix(): socket");
113 memset(&addr
, 0, sizeof(addr
));
114 addr
.sun_family
= AF_UNIX
;
115 strncpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
) - 1);
117 if (connect(sock
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)
119 socket_fd_close(sock
);
127 static gint
socket_fd_open_unix(const gchar
*path
)
130 struct sockaddr_un addr
;
133 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
137 perror("sock_open_unix(): socket");
142 if (setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(val
)) < 0)
144 perror("setsockopt");
145 socket_fd_close(sock
);
149 memset(&addr
, 0, sizeof(addr
));
150 addr
.sun_family
= AF_UNIX
;
151 strncpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
) - 1);
153 if (bind(sock
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)
156 socket_fd_close(sock
);
160 if (listen(sock
, 1) < 0)
163 socket_fd_close(sock
);
171 gint
socket_fd_close(gint fd
)
180 gint
socket_fd_gets(gint fd
, gchar
*buf
, gint len
)
182 gchar
*newline
, *bp
= buf
;
189 if ((n
= socket_fd_recv(fd
, bp
, len
, MSG_PEEK
)) <= 0)
191 if ((newline
= memchr(bp
, '\n', n
)) != NULL
)
192 n
= newline
- bp
+ 1;
193 if ((n
= socket_fd_read(fd
, bp
, n
)) < 0)
197 } while (! newline
&& len
);
204 static gint
socket_fd_recv(gint fd
, gchar
*buf
, gint len
, gint flags
)
206 if (socket_fd_check_io(fd
, G_IO_IN
) < 0)
209 return recv(fd
, buf
, len
, flags
);
213 static gint
socket_fd_read(gint fd
, gchar
*buf
, gint len
)
215 if (socket_fd_check_io(fd
, G_IO_IN
) < 0)
218 return read(fd
, buf
, len
);
222 static gint
socket_fd_check_io(gint fd
, GIOCondition cond
)
224 struct timeval timeout
;
234 /* checking for non-blocking mode */
235 flags
= fcntl(fd
, F_GETFL
, 0);
242 if ((flags
& O_NONBLOCK
) != 0)
250 select(fd
+ 1, &fds
, NULL
, NULL
, &timeout
);
254 select(fd
+ 1, NULL
, &fds
, NULL
, &timeout
);
257 if (FD_ISSET(fd
, &fds
))
263 g_print("Socket IO timeout\n");