Use gboolean pseudo type where applicable.
[geeqie.git] / src / remote.c
1 /*
2  * Geeqie
3  * (C) 2004 John Ellis
4  * Copyright (C) 2008 - 2009 The Geeqie Team
5  *
6  * Author: John Ellis
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13
14 #include "main.h"
15 #include "remote.h"
16
17 #include "collect.h"
18 #include "filedata.h"
19 #include "img-view.h"
20 #include "layout.h"
21 #include "layout_image.h"
22 #include "misc.h"
23 #include "slideshow.h"
24 #include "ui_fileops.h"
25
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <signal.h>
29 #include <errno.h>
30
31
32 #define SERVER_MAX_CLIENTS 8
33
34 #define REMOTE_SERVER_BACKLOG 4
35
36
37 #ifndef UNIX_PATH_MAX
38 #define UNIX_PATH_MAX 108
39 #endif
40
41
42 static RemoteConnection *remote_client_open(const gchar *path);
43 static gint remote_client_send(RemoteConnection *rc, const gchar *text);
44
45
46 typedef struct _RemoteClient RemoteClient;
47 struct _RemoteClient {
48         gint fd;
49         gint channel_id;
50         RemoteConnection *rc;
51 };
52
53 typedef struct _RemoteData RemoteData;
54 struct _RemoteData {
55         CollectionData *command_collection;
56 };
57
58
59 static gboolean remote_server_client_cb(GIOChannel *source, GIOCondition condition, gpointer data)
60 {
61         RemoteClient *client = data;
62         RemoteConnection *rc;
63         GIOStatus status = G_IO_STATUS_NORMAL;
64
65         rc = client->rc;
66
67         if (condition & G_IO_IN)
68                 {
69                 GList *queue = NULL;
70                 GList *work;
71                 gchar *buffer = NULL;
72                 GError *error = NULL;
73                 gsize termpos;
74
75                 while ((status = g_io_channel_read_line(source, &buffer, NULL, &termpos, &error)) == G_IO_STATUS_NORMAL)
76                         {
77                         if (buffer)
78                                 {
79                                 buffer[termpos] = '\0';
80
81                                 if (strlen(buffer) > 0)
82                                         {
83                                         queue = g_list_append(queue, buffer);
84                                         }
85                                 else
86                                         {
87                                         g_free(buffer);
88                                         }
89
90                                 buffer = NULL;
91                                 }
92                         }
93
94                 if (error)
95                         {
96                         log_printf("error reading socket: %s\n", error->message);
97                         g_error_free(error);
98                         }
99
100                 work = queue;
101                 while (work)
102                         {
103                         gchar *command = work->data;
104                         work = work->next;
105
106                         if (rc->read_func) rc->read_func(rc, command, rc->read_data);
107                         g_free(command);
108                         }
109
110                 g_list_free(queue);
111                 }
112
113         if (condition & G_IO_HUP || status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
114                 {
115                 rc->clients = g_list_remove(rc->clients, client);
116
117                 DEBUG_1("HUP detected, closing client.");
118                 DEBUG_1("client count %d", g_list_length(rc->clients));
119                 
120                 g_source_remove(client->channel_id);
121                 close(client->fd);
122                 g_free(client);
123                 }
124
125         return TRUE;
126 }
127
128 static void remote_server_client_add(RemoteConnection *rc, gint fd)
129 {
130         RemoteClient *client;
131         GIOChannel *channel;
132
133         if (g_list_length(rc->clients) > SERVER_MAX_CLIENTS)
134                 {
135                 log_printf("maximum remote clients of %d exceeded, closing connection\n", SERVER_MAX_CLIENTS);
136                 close(fd);
137                 return;
138                 }
139
140         client = g_new0(RemoteClient, 1);
141         client->rc = rc;
142         client->fd = fd;
143
144         channel = g_io_channel_unix_new(fd);
145         client->channel_id = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_HUP,
146                                                  remote_server_client_cb, client, NULL);
147         g_io_channel_unref(channel);
148
149         rc->clients = g_list_append(rc->clients, client);
150         DEBUG_1("client count %d", g_list_length(rc->clients));
151 }
152
153 static void remote_server_clients_close(RemoteConnection *rc)
154 {
155         while (rc->clients)
156                 {
157                 RemoteClient *client = rc->clients->data;
158
159                 rc->clients = g_list_remove(rc->clients, client);
160
161                 g_source_remove(client->channel_id);
162                 close(client->fd);
163                 g_free(client);
164                 }
165 }
166
167 static gboolean remote_server_read_cb(GIOChannel *source, GIOCondition condition, gpointer data)
168 {
169         RemoteConnection *rc = data;
170         gint fd;
171         guint alen;
172
173         fd = accept(rc->fd, NULL, &alen);
174         if (fd == -1)
175                 {
176                 log_printf("error accepting socket: %s\n", strerror(errno));
177                 return TRUE;
178                 }
179
180         remote_server_client_add(rc, fd);
181
182         return TRUE;
183 }
184
185 static gint remote_server_exists(const gchar *path)
186 {
187         RemoteConnection *rc;
188
189         /* verify server up */
190         rc = remote_client_open(path);
191         remote_close(rc);
192
193         if (rc) return TRUE;
194
195         /* unable to connect, remove socket file to free up address */
196         unlink(path);
197         return FALSE;
198 }
199
200 static RemoteConnection *remote_server_open(const gchar *path)
201 {
202         RemoteConnection *rc;
203         struct sockaddr_un addr;
204         gint sun_path_len;
205         gint fd;
206         GIOChannel *channel;
207
208         if (remote_server_exists(path))
209                 {
210                 log_printf("Address already in use: %s\n", path);
211                 return NULL;
212                 }
213
214         fd = socket(PF_UNIX, SOCK_STREAM, 0);
215         if (fd == -1) return NULL;
216
217         addr.sun_family = AF_UNIX;
218         sun_path_len = MIN(strlen(path) + 1, UNIX_PATH_MAX);
219         strncpy(addr.sun_path, path, sun_path_len);
220         if (bind(fd, &addr, sizeof(addr)) == -1 ||
221             listen(fd, REMOTE_SERVER_BACKLOG) == -1)
222                 {
223                 log_printf("error subscribing to socket: %s\n", strerror(errno));
224                 close(fd);
225                 return NULL;
226                 }
227
228         rc = g_new0(RemoteConnection, 1);
229         
230         rc->server = TRUE;
231         rc->fd = fd;
232         rc->path = g_strdup(path);
233
234         channel = g_io_channel_unix_new(rc->fd);
235         g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL); 
236         
237         rc->channel_id = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_IN,
238                                              remote_server_read_cb, rc, NULL);
239         g_io_channel_unref(channel);
240
241         return rc;
242 }
243
244 static void remote_server_subscribe(RemoteConnection *rc, RemoteReadFunc *func, gpointer data)
245 {
246         if (!rc || !rc->server) return;
247
248         rc->read_func = func;
249         rc->read_data = data;
250 }
251
252
253 static RemoteConnection *remote_client_open(const gchar *path)
254 {
255         RemoteConnection *rc;
256         struct stat st;
257         struct sockaddr_un addr;
258         gint sun_path_len;
259         gint fd;
260
261         if (stat(path, &st) != 0 || !S_ISSOCK(st.st_mode)) return NULL;
262
263         fd = socket(PF_UNIX, SOCK_STREAM, 0);
264         if (fd == -1) return NULL;
265
266         addr.sun_family = AF_UNIX;
267         sun_path_len = MIN(strlen(path) + 1, UNIX_PATH_MAX);
268         strncpy(addr.sun_path, path, sun_path_len);
269         if (connect(fd, &addr, sizeof(addr)) == -1)
270                 {
271                 DEBUG_1("error connecting to socket: %s", strerror(errno));
272                 close(fd);
273                 return NULL;
274                 }
275
276         rc = g_new0(RemoteConnection, 1);
277         rc->server = FALSE;
278         rc->fd = fd;
279         rc->path = g_strdup(path);
280
281         /* this might fix the freezes on freebsd, solaris, etc. - completely untested */
282         remote_client_send(rc, "\n");
283
284         return rc;
285 }
286
287 static sig_atomic_t sigpipe_occured = FALSE;
288
289 static void sighandler_sigpipe(gint sig)
290 {
291         sigpipe_occured = TRUE;
292 }
293
294 static gint remote_client_send(RemoteConnection *rc, const gchar *text)
295 {
296         struct sigaction new_action, old_action;
297         gint ret = FALSE;
298
299         if (!rc || rc->server) return FALSE;
300         if (!text) return TRUE;
301
302         sigpipe_occured = FALSE;
303
304         new_action.sa_handler = sighandler_sigpipe;
305         sigemptyset(&new_action.sa_mask);
306         new_action.sa_flags = 0;
307
308         /* setup our signal handler */
309         sigaction(SIGPIPE, &new_action, &old_action);
310
311         if (write(rc->fd, text, strlen(text)) == -1 ||
312             write(rc->fd, "\n", 1) == -1)
313                 {
314                 if (sigpipe_occured)
315                         {
316                         log_printf("SIGPIPE writing to socket: %s\n", rc->path);
317                         }
318                 else
319                         {
320                         log_printf("error writing to socket: %s\n", strerror(errno));
321                         }
322                 ret = FALSE;;
323                 }
324         else
325                 {
326                 ret = TRUE;
327                 }
328
329         /* restore the original signal handler */
330         sigaction(SIGPIPE, &old_action, NULL);
331
332         return ret;
333 }
334
335 void remote_close(RemoteConnection *rc)
336 {
337         if (!rc) return;
338
339         if (rc->server)
340                 {
341                 remote_server_clients_close(rc);
342
343                 g_source_remove(rc->channel_id);
344                 unlink(rc->path);
345                 }
346
347         if (rc->read_data)
348                 g_free(rc->read_data);
349
350         close(rc->fd);
351
352         g_free(rc->path);
353         g_free(rc);
354 }
355
356 /*
357  *-----------------------------------------------------------------------------
358  * remote functions
359  *-----------------------------------------------------------------------------
360  */
361
362 static void gr_image_next(const gchar *text, gpointer data)
363 {
364         layout_image_next(NULL);
365 }
366
367 static void gr_image_prev(const gchar *text, gpointer data)
368 {
369         layout_image_prev(NULL);
370 }
371
372 static void gr_image_first(const gchar *text, gpointer data)
373 {
374         layout_image_first(NULL);
375 }
376
377 static void gr_image_last(const gchar *text, gpointer data)
378 {
379         layout_image_last(NULL);
380 }
381
382 static void gr_fullscreen_toggle(const gchar *text, gpointer data)
383 {
384         layout_image_full_screen_toggle(NULL);
385 }
386
387 static void gr_fullscreen_start(const gchar *text, gpointer data)
388 {
389         layout_image_full_screen_start(NULL);
390 }
391
392 static void gr_fullscreen_stop(const gchar *text, gpointer data)
393 {
394         layout_image_full_screen_stop(NULL);
395 }
396
397 static void gr_slideshow_start_rec(const gchar *text, gpointer data)
398 {
399         GList *list;
400         FileData *dir_fd = file_data_new_simple(text);
401         list = filelist_recursive(dir_fd);
402         file_data_unref(dir_fd);
403         if (!list) return;
404 //printf("length: %d\n", g_list_length(list));
405         layout_image_slideshow_stop(NULL);
406         layout_image_slideshow_start_from_list(NULL, list);
407 }
408
409 static void gr_slideshow_toggle(const gchar *text, gpointer data)
410 {
411         layout_image_slideshow_toggle(NULL);
412 }
413
414 static void gr_slideshow_start(const gchar *text, gpointer data)
415 {
416         layout_image_slideshow_start(NULL);
417 }
418
419 static void gr_slideshow_stop(const gchar *text, gpointer data)
420 {
421         layout_image_slideshow_stop(NULL);
422 }
423
424 static void gr_slideshow_delay(const gchar *text, gpointer data)
425 {
426         gdouble n;
427
428         n = g_ascii_strtod(text, NULL);
429         if (n < SLIDESHOW_MIN_SECONDS || n > SLIDESHOW_MAX_SECONDS)
430                 {
431                 printf_term("Remote slideshow delay out of range (%.1f to %.1f)\n",
432                             SLIDESHOW_MIN_SECONDS, SLIDESHOW_MAX_SECONDS);
433                 return;
434                 }
435         options->slideshow.delay = (gint)(n * 10.0 + 0.01);
436 }
437
438 static void gr_tools_show(const gchar *text, gpointer data)
439 {
440         gboolean popped;
441         gboolean hidden;
442
443         if (layout_tools_float_get(NULL, &popped, &hidden) && hidden)
444                 {
445                 layout_tools_float_set(NULL, popped, FALSE);
446                 }
447 }
448
449 static void gr_tools_hide(const gchar *text, gpointer data)
450 {
451         gboolean popped;
452         gboolean hidden;
453
454         if (layout_tools_float_get(NULL, &popped, &hidden) && !hidden)
455                 {
456                 layout_tools_float_set(NULL, popped, TRUE);
457                 }
458 }
459
460 static gint gr_quit_idle_cb(gpointer data)
461 {
462         exit_program();
463
464         return FALSE;
465 }
466
467 static void gr_quit(const gchar *text, gpointer data)
468 {
469         /* schedule exit when idle, if done from within a
470          * remote handler remote_close will crash
471          */
472         g_idle_add(gr_quit_idle_cb, NULL);
473 }
474
475 static void gr_file_load(const gchar *text, gpointer data)
476 {
477         gchar *filename = expand_tilde(text);
478
479         if (isfile(filename))
480                 {
481                 if (file_extension_match(filename, GQ_COLLECTION_EXT))
482                         {
483                         collection_window_new(filename);
484                         }
485                 else
486                         {
487                         layout_set_path(NULL, filename);
488                         }
489                 }
490         else if (isdir(filename))
491                 {
492                 layout_set_path(NULL, filename);
493                 }
494         else
495                 {
496                 log_printf("remote sent filename that does not exist:\"%s\"\n", filename);
497                 }
498
499         g_free(filename);
500 }
501
502 static void gr_file_view(const gchar *text, gpointer data)
503 {
504         gchar *filename = expand_tilde(text);
505
506         view_window_new(file_data_new_simple(filename));
507         g_free(filename);
508 }
509
510 static void gr_list_clear(const gchar *text, gpointer data)
511 {
512         RemoteData *remote_data = data;
513
514         if (remote_data->command_collection)
515                 {
516                 collection_unref(remote_data->command_collection);
517                 remote_data->command_collection = NULL;
518                 }
519 }
520
521 static void gr_list_add(const gchar *text, gpointer data)
522 {
523         RemoteData *remote_data = data;
524         gint new = TRUE;
525
526         if (!remote_data->command_collection)
527                 {
528                 CollectionData *cd;
529
530                 cd = collection_new("");
531
532                 g_free(cd->path);
533                 cd->path = NULL;
534                 g_free(cd->name);
535                 cd->name = g_strdup(_("Command line"));
536
537                 remote_data->command_collection = cd;
538                 }
539         else
540                 {
541                 new = (!collection_get_first(remote_data->command_collection));
542                 }
543
544         if (collection_add(remote_data->command_collection, file_data_new_simple(text), FALSE) && new)
545                 {
546                 layout_image_set_collection(NULL, remote_data->command_collection,
547                                             collection_get_first(remote_data->command_collection));
548                 }
549 }
550
551 static void gr_raise(const gchar *text, gpointer data)
552 {
553         LayoutWindow *lw = NULL;
554
555         if (layout_valid(&lw))
556                 {
557                 gtk_window_present(GTK_WINDOW(lw->window));
558                 }
559 }
560
561 typedef struct _RemoteCommandEntry RemoteCommandEntry;
562 struct _RemoteCommandEntry {
563         gchar *opt_s;
564         gchar *opt_l;
565         void (*func)(const gchar *text, gpointer data);
566         gint needs_extra;
567         gint prefer_command_line;
568         gchar *description;
569 };
570
571 static RemoteCommandEntry remote_commands[] = {
572         /* short, long                  callback,               extra, prefer,description */
573         { "-n", "--next",               gr_image_next,          FALSE, FALSE, N_("next image") },
574         { "-b", "--back",               gr_image_prev,          FALSE, FALSE, N_("previous image") },
575         { NULL, "--first",              gr_image_first,         FALSE, FALSE, N_("first image") },
576         { NULL, "--last",               gr_image_last,          FALSE, FALSE, N_("last image") },
577         { "-f", "--fullscreen",         gr_fullscreen_toggle,   FALSE, TRUE,  N_("toggle full screen") },
578         { "-fs","--fullscreen-start",   gr_fullscreen_start,    FALSE, FALSE, N_("start full screen") },
579         { "-fS","--fullscreen-stop",    gr_fullscreen_stop,     FALSE, FALSE, N_("stop full screen") },
580         { "-s", "--slideshow",          gr_slideshow_toggle,    FALSE, TRUE,  N_("toggle slide show") },
581         { "-ss","--slideshow-start",    gr_slideshow_start,     FALSE, FALSE, N_("start slide show") },
582         { "-sS","--slideshow-stop",     gr_slideshow_stop,      FALSE, FALSE, N_("stop slide show") },
583         { "-sr","--slideshow-recurse",  gr_slideshow_start_rec, TRUE,  FALSE, N_("start recursive slide show") },
584         { "-d", "--delay=",             gr_slideshow_delay,     TRUE,  FALSE, N_("set slide show delay in seconds") },
585         { "+t", "--tools-show",         gr_tools_show,          FALSE, TRUE,  N_("show tools") },
586         { "-t", "--tools-hide",         gr_tools_hide,          FALSE, TRUE,  N_("hide tools") },
587         { "-q", "--quit",               gr_quit,                FALSE, FALSE, N_("quit") },
588         { NULL, "file:",                gr_file_load,           TRUE,  FALSE, N_("open file") },
589         { NULL, "view:",                gr_file_view,           TRUE,  FALSE, N_("open file in new window") },
590         { NULL, "--list-clear",         gr_list_clear,          FALSE, FALSE, NULL },
591         { NULL, "--list-add:",          gr_list_add,            TRUE,  FALSE, NULL },
592         { NULL, "raise",                gr_raise,               FALSE, FALSE, NULL },
593         { NULL, NULL, NULL, FALSE, FALSE, NULL }
594 };
595
596 static RemoteCommandEntry *remote_command_find(const gchar *text, const gchar **offset)
597 {
598         gint match = FALSE;
599         gint i;
600
601         i = 0;
602         while (!match && remote_commands[i].func != NULL)
603                 {
604                 if (remote_commands[i].needs_extra)
605                         {
606                         if (remote_commands[i].opt_s &&
607                             strncmp(remote_commands[i].opt_s, text, strlen(remote_commands[i].opt_s)) == 0)
608                                 {
609                                 if (offset) *offset = text + strlen(remote_commands[i].opt_s);
610                                 return &remote_commands[i];
611                                 }
612                         else if (remote_commands[i].opt_l &&
613                                  strncmp(remote_commands[i].opt_l, text, strlen(remote_commands[i].opt_l)) == 0)
614                                 {
615                                 if (offset) *offset = text + strlen(remote_commands[i].opt_l);
616                                 return &remote_commands[i];
617                                 }
618                         }
619                 else
620                         {
621                         if ((remote_commands[i].opt_s && strcmp(remote_commands[i].opt_s, text) == 0) ||
622                             (remote_commands[i].opt_l && strcmp(remote_commands[i].opt_l, text) == 0))
623                                 {
624                                 if (offset) *offset = text;
625                                 return &remote_commands[i];
626                                 }
627                         }
628
629                 i++;
630                 }
631
632         return NULL;
633 }
634
635 static void remote_cb(RemoteConnection *rc, const gchar *text, gpointer data)
636 {
637         RemoteCommandEntry *entry;
638         const gchar *offset;
639
640         entry = remote_command_find(text, &offset);
641         if (entry && entry->func)
642                 {
643                 entry->func(offset, data);
644                 }
645         else
646                 {
647                 log_printf("unknown remote command:%s\n", text);
648                 }
649 }
650
651 void remote_help(void)
652 {
653         gint i;
654
655         print_term(_("Remote command list:\n"));
656
657         i = 0;
658         while (remote_commands[i].func != NULL)
659                 {
660                 if (remote_commands[i].description)
661                         {
662                         printf_term("  %-3s%s %-20s %s\n",
663                                     (remote_commands[i].opt_s) ? remote_commands[i].opt_s : "",
664                                     (remote_commands[i].opt_s && remote_commands[i].opt_l) ? "," : " ",
665                                     (remote_commands[i].opt_l) ? remote_commands[i].opt_l : "",
666                                     _(remote_commands[i].description));
667                         }
668                 i++;
669                 }
670 }
671
672 GList *remote_build_list(GList *list, gint argc, gchar *argv[], GList **errors)
673 {
674         gint i;
675
676         i = 1;
677         while (i < argc)
678                 {
679                 RemoteCommandEntry *entry;
680
681                 entry = remote_command_find(argv[i], NULL);
682                 if (entry)
683                         {
684                         list = g_list_append(list, argv[i]);
685                         }
686                 else if (errors)
687                         {
688                         *errors = g_list_append(*errors, argv[i]);
689                         }
690                 i++;
691                 }
692
693         return list;
694 }
695
696 void remote_control(const gchar *arg_exec, GList *remote_list, const gchar *path,
697                     GList *cmd_list, GList *collection_list)
698 {
699         RemoteConnection *rc;
700         gint started = FALSE;
701         gchar *buf;
702
703         buf = g_build_filename(get_rc_dir(), ".command", NULL);
704         rc = remote_client_open(buf);
705         if (!rc)
706                 {
707                 GString *command;
708                 GList *work;
709                 gint retry_count = 12;
710                 gint blank = FALSE;
711
712                 printf_term(_("Remote %s not running, starting..."), GQ_APPNAME);
713
714                 command = g_string_new(arg_exec);
715
716                 work = remote_list;
717                 while (work)
718                         {
719                         gchar *text;
720                         RemoteCommandEntry *entry;
721
722                         text = work->data;
723                         work = work->next;
724
725                         entry = remote_command_find(text, NULL);
726                         if (entry)
727                                 {
728                                 if (entry->prefer_command_line)
729                                         {
730                                         remote_list = g_list_remove(remote_list, text);
731                                         g_string_append(command, " ");
732                                         g_string_append(command, text);
733                                         }
734                                 if (entry->opt_l && strcmp(entry->opt_l, "file:") == 0)
735                                         {
736                                         blank = TRUE;
737                                         }
738                                 }
739                         }
740
741                 if (blank || cmd_list || path) g_string_append(command, " --blank");
742                 if (get_debug_level()) g_string_append(command, " --debug");
743
744                 g_string_append(command, " &");
745                 runcmd(command->str);
746                 g_string_free(command, TRUE);
747
748                 while (!rc && retry_count > 0)
749                         {
750                         usleep((retry_count > 10) ? 500000 : 1000000);
751                         rc = remote_client_open(buf);
752                         if (!rc) print_term(".");
753                         retry_count--;
754                         }
755
756                 print_term("\n");
757
758                 started = TRUE;
759                 }
760         g_free(buf);
761
762         if (rc)
763                 {
764                 GList *work;
765                 const gchar *prefix;
766                 gint use_path = TRUE;
767                 gint sent = FALSE;
768
769                 work = remote_list;
770                 while (work)
771                         {
772                         gchar *text;
773                         RemoteCommandEntry *entry;
774
775                         text = work->data;
776                         work = work->next;
777
778                         entry = remote_command_find(text, NULL);
779                         if (entry &&
780                             entry->opt_l &&
781                             strcmp(entry->opt_l, "file:") == 0) use_path = FALSE;
782
783                         remote_client_send(rc, text);
784
785                         sent = TRUE;
786                         }
787
788                 if (cmd_list && cmd_list->next)
789                         {
790                         prefix = "--list-add:";
791                         remote_client_send(rc, "--list-clear");
792                         }
793                 else
794                         {
795                         prefix = "file:";
796                         }
797
798                 work = cmd_list;
799                 while (work)
800                         {
801                         FileData *fd;
802                         gchar *text;
803
804                         fd = work->data;
805                         work = work->next;
806
807                         text = g_strconcat(prefix, fd->path, NULL);
808                         remote_client_send(rc, text);
809                         g_free(text);
810
811                         sent = TRUE;
812                         }
813
814                 if (path && !cmd_list && use_path)
815                         {
816                         gchar *text;
817
818                         text = g_strdup_printf("file:%s", path);
819                         remote_client_send(rc, text);
820                         g_free(text);
821
822                         sent = TRUE;
823                         }
824
825                 work = collection_list;
826                 while (work)
827                         {
828                         const gchar *name;
829                         gchar *text;
830
831                         name = work->data;
832                         work = work->next;
833
834                         text = g_strdup_printf("file:%s", name);
835                         remote_client_send(rc, text);
836                         g_free(text);
837
838                         sent = TRUE;
839                         }
840
841                 if (!started && !sent)
842                         {
843                         remote_client_send(rc, "raise");
844                         }
845                 }
846         else
847                 {
848                 print_term(_("Remote not available\n"));
849                 }
850
851         _exit(0);
852 }
853
854 RemoteConnection *remote_server_init(gchar *path, CollectionData *command_collection)
855 {
856         RemoteConnection *remote_connection = remote_server_open(path);
857         RemoteData *remote_data = g_new(RemoteData, 1);
858         
859         remote_data->command_collection = command_collection;
860
861         remote_server_subscribe(remote_connection, remote_cb, remote_data);
862         return remote_connection;
863 }
864 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */