2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /************************************************
22 * IPC between gliv processes to reuse a window *
23 ************************************************/
25 #include <unistd.h> /* unlink(), close(), write() */
26 #include <sys/types.h> /* struct sockaddr */
27 #include <sys/socket.h> /* socket(), ... */
28 #include <sys/un.h> /* AF_LOCAL */
29 #include <string.h> /* strncpy() */
30 #include <stdio.h> /* perror(), fread(), stdin */
36 #include "files_list.h"
37 #include "next_image.h"
39 static GIOChannel
*make_channel(gint fd
)
44 channel
= g_io_channel_unix_new(fd
);
45 g_io_channel_set_close_on_unref(channel
, TRUE
);
46 g_io_channel_set_encoding(channel
, NULL
, &err
);
48 g_printerr("%s\n", err
->message
);
50 g_io_channel_unref(channel
);
57 /*** Where do we keep this socket? ***/
59 static gchar
*get_socket_name(void)
61 gchar
*user_name
, *repl
, *res
;
63 /* Do people have '/' in their user names. */
64 repl
= user_name
= g_strdup(g_get_user_name());
66 while ((repl
= strchr(repl
, '/')) != NULL
)
69 res
= g_strdup_printf("%s/.19830128gliv_%s", g_get_tmp_dir(), user_name
);
75 /*** State encoding by the client for the server. ***/
77 #define PARAM(func, param) \
82 func(channel, (gpointer) param, sizeof(gboolean), &bytes, &err); \
83 if (bytes != sizeof(gboolean) && err != NULL) { \
84 g_printerr("%s\n", err->message); \
90 static gboolean
write_params(GIOChannel
* channel
, gboolean recursive
,
91 gboolean shuffle
, gboolean sort
)
99 PARAM(g_io_channel_write_chars
, &recursive
);
100 PARAM(g_io_channel_write_chars
, &shuffle
);
101 PARAM(g_io_channel_write_chars
, &sort
);
103 current_dir
= g_get_current_dir();
104 length
= strlen(current_dir
) + 1;
106 g_io_channel_write_chars(channel
, current_dir
, length
, &bytes
, &err
);
107 if (bytes
!= length
) {
110 g_printerr("%s\n", err
->message
);
120 static gboolean
read_params(GIOChannel
* channel
, gchar
** client_dir
,
121 gboolean
* recursive
,
122 gboolean
* shuffle
, gboolean
* sort
)
126 struct stat client_stat
, server_stat
;
129 PARAM(g_io_channel_read_chars
, recursive
);
130 PARAM(g_io_channel_read_chars
, shuffle
);
131 PARAM(g_io_channel_read_chars
, sort
);
134 g_io_channel_read_line(channel
, client_dir
, &size
, NULL
, &err
);
136 g_printerr("%s\n", err
->message
);
141 server_dir
= g_get_current_dir();
142 if (stat(*client_dir
, &client_stat
) < 0 ||
143 stat(server_dir
, &server_stat
) < 0) {
150 if (client_stat
.st_dev
== server_stat
.st_dev
&&
151 client_stat
.st_ino
== server_stat
.st_ino
) {
153 * The client and server are in the same directory, we can use relative
154 * filenames without problems.
166 static gint
create_server_socket(void)
168 struct sockaddr_un name
;
173 sock
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
179 name
.sun_family
= AF_LOCAL
;
181 filename
= get_socket_name();
182 strncpy(name
.sun_path
, filename
, sizeof(name
.sun_path
) - 1);
183 name
.sun_path
[sizeof(name
.sun_path
) - 1] = '\0';
185 /* The latest launched gliv is the server. */
189 size
= SUN_LEN(&name
);
191 if (bind(sock
, (struct sockaddr
*) &name
, size
) < 0) {
195 } else if (listen(sock
, 5) < 0) {
204 /* Put the '\0' separated strings in an array. */
205 static gchar
**rebuild_args_array(gchar
* data
, gint length
, gint
* count
,
209 gchar
*last
= data
+ length
, *ptr
= data
;
212 /* How many strings? */
215 ptr
+= strlen(ptr
) + 1;
220 tab
= g_new(gchar
*, *count
);
221 for (i
= 0; i
< *count
; i
++) {
222 if (client_dir
== NULL
|| data
[0] == '/')
223 tab
[i
] = g_strdup(data
);
225 tab
[i
] = g_build_filename(client_dir
, data
, NULL
);
227 data
+= strlen(data
) + 1;
233 /* Add the filenames and open the next image. */
234 static void process_data(gchar
* data
, gint length
, gchar
* client_dir
,
235 gboolean recursive
, gboolean shuffle
, gboolean sort
)
237 gint i
, count
, nb_inserted
;
240 tab
= rebuild_args_array(data
, length
, &count
, client_dir
);
241 nb_inserted
= insert_after_current(tab
, count
, recursive
, shuffle
, sort
);
244 open_next_image(nb_inserted
== 1);
246 for (i
= 0; i
< count
; i
++)
252 /* Called when there is something to read. */
253 static gboolean
handle_connect(GIOChannel
* source
, GIOCondition unused1
,
260 gboolean recursive
, shuffle
, sort
;
263 fd
= accept(g_io_channel_unix_get_fd(source
), NULL
, &length
);
269 channel
= make_channel(fd
);
273 /* Fill the flags. */
274 if (read_params(channel
, &client_dir
, &recursive
, &shuffle
, &sort
) == FALSE
) {
275 g_io_channel_unref(channel
);
279 g_io_channel_read_to_end(channel
, &data
, &length
, &err
);
281 g_printerr("%s\n", err
->message
);
283 g_io_channel_unref(channel
);
287 process_data(data
, length
, client_dir
, recursive
, shuffle
, sort
);
288 g_io_channel_unref(channel
);
292 void start_server(void)
297 socket
= create_server_socket();
301 channel
= make_channel(socket
);
305 /* Let GTK+ inform us about clients. */
306 g_io_add_watch(channel
, G_IO_IN
, (GIOFunc
) handle_connect
, NULL
);
311 static gint
create_client_socket(void)
313 struct sockaddr_un name
;
318 sock
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
324 name
.sun_family
= AF_LOCAL
;
326 filename
= get_socket_name();
327 strncpy(name
.sun_path
, filename
, sizeof(name
.sun_path
) - 1);
328 name
.sun_path
[sizeof(name
.sun_path
) - 1] = '\0';
331 size
= SUN_LEN(&name
);
332 if (connect(sock
, (struct sockaddr
*) &name
, size
) < 0) {
341 /* Used when we read the filenames from stdin. */
342 static void send_filenames(GIOChannel
* channel
)
347 while ((size
= fread(buffer
, 1, sizeof(buffer
), stdin
)) > 0)
348 g_io_channel_write_chars(channel
, buffer
, size
, NULL
, NULL
);
351 gboolean
connect_server(gint argc
, gchar
** argv
)
354 struct gengetopt_args_info ggo
;
357 fd
= create_client_socket();
361 cmdline_parser(argc
, argv
, &ggo
);
363 channel
= make_channel(fd
);
367 if (write_params(channel
, ggo
.recursive_flag
,
368 ggo
.shuffle_flag
, ggo
.sort_flag
) == FALSE
) {
369 g_io_channel_unref(channel
);
374 send_filenames(channel
);
376 for (i
= 0; i
< ggo
.inputs_num
; i
++) {
378 gint length
= strlen(ggo
.inputs
[i
]);
381 g_io_channel_write_chars(channel
, ggo
.inputs
[i
], length
, &size
, &err
);
383 g_printerr("%s\n", err
->message
);
385 g_io_channel_unref(channel
);
390 g_io_channel_unref(channel
);