From 42081b7fa62ec6f3fe9da4c3aa47bfaf81405ba7 Mon Sep 17 00:00:00 2001 From: g Date: Thu, 25 Sep 2003 15:17:52 +0000 Subject: [PATCH] The client should give some state information to the server. git-svn-id: file:///srv/svn/gliv/trunk@102 dbf4865f-1ec6-0310-8412-f61adeb1ccb1 committer: g --- src/ipc.c | 196 +++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 142 insertions(+), 54 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 620c4f8..593b35b 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -28,6 +28,7 @@ #include /* AF_LOCAL */ #include /* strncpy() */ #include /* perror(), fread(), stdin */ +#include #include "gliv.h" #include "ipc.h" @@ -35,6 +36,24 @@ #include "files_list.h" #include "next_image.h" +static GIOChannel *make_channel(gint fd) +{ + GIOChannel *channel; + GError *err = NULL; + + channel = g_io_channel_unix_new(fd); + g_io_channel_set_close_on_unref(channel, TRUE); + g_io_channel_set_encoding(channel, NULL, &err); + if (err != NULL) { + g_printerr("%s\n", err->message); + g_error_free(err); + g_io_channel_unref(channel); + channel = NULL; + } + + return channel; +} + /*** Where do we keep this socket? ***/ static gchar *get_socket_name(void) @@ -47,37 +66,98 @@ static gchar *get_socket_name(void) while ((repl = strchr(repl, '/')) != NULL) *repl = '_'; - res = g_strdup_printf("%s/gliv_%s", g_get_tmp_dir(), user_name); + res = g_strdup_printf("%s/.19830128gliv_%s", g_get_tmp_dir(), user_name); g_free(user_name); return res; } -/*** Recursive, shuffle and sort flags encodings ***/ - -#define PARAM(func, param) \ - do { \ - if (func(fd, ¶m, sizeof(gboolean)) != sizeof(gboolean)) \ - return FALSE; \ +/*** State encoding by the client for the server. ***/ + +#define PARAM(func, param) \ + do { \ + gsize bytes = 0; \ + GError *err = NULL; \ + \ + func(channel, (gpointer) param, sizeof(gboolean), &bytes, &err); \ + if (bytes != sizeof(gboolean) && err != NULL) { \ + g_printerr("%s\n", err->message); \ + g_error_free(err); \ + return FALSE; \ + } \ } while (0) -static gboolean write_params(gint fd, gboolean recursive, +static gboolean write_params(GIOChannel * channel, gboolean recursive, gboolean shuffle, gboolean sort) { - PARAM(write, recursive); - PARAM(write, shuffle); - PARAM(write, sort); + gchar *current_dir; + gint length; + gboolean res = TRUE; + gsize bytes = 0; + GError *err = NULL; - return TRUE; + PARAM(g_io_channel_write_chars, &recursive); + PARAM(g_io_channel_write_chars, &shuffle); + PARAM(g_io_channel_write_chars, &sort); + + current_dir = g_get_current_dir(); + length = strlen(current_dir) + 1; + + g_io_channel_write_chars(channel, current_dir, length, &bytes, &err); + if (bytes != length) { + res = FALSE; + if (err != NULL) { + g_printerr("%s\n", err->message); + g_error_free(err); + } + } + + g_free(current_dir); + + return res; } -static gboolean read_params(gint fd, gboolean * recursive, +static gboolean read_params(GIOChannel * channel, gchar ** client_dir, + gboolean * recursive, gboolean * shuffle, gboolean * sort) { - PARAM(read, recursive); - PARAM(read, shuffle); - PARAM(read, sort); + size_t size = 0; + gchar *server_dir; + struct stat client_stat, server_stat; + GError *err = NULL; + + PARAM(g_io_channel_read_chars, recursive); + PARAM(g_io_channel_read_chars, shuffle); + PARAM(g_io_channel_read_chars, sort); + + *client_dir = NULL; + g_io_channel_read_line(channel, client_dir, &size, NULL, &err); + if (err != NULL) { + g_printerr("%s\n", err->message); + g_error_free(err); + return FALSE; + } + + server_dir = g_get_current_dir(); + if (stat(*client_dir, &client_stat) < 0 || + stat(server_dir, &server_stat) < 0) { + + g_free(server_dir); + g_free(*client_dir); + return FALSE; + } + + if (client_stat.st_dev == server_stat.st_dev && + client_stat.st_ino == server_stat.st_ino) { + /* + * The client and server are in the same directory, we can use relative + * filenames without problems. + */ + g_free(*client_dir); + *client_dir = NULL; + } + g_free(server_dir); return TRUE; } @@ -122,7 +202,8 @@ static gint create_server_socket(void) } /* Put the '\0' separated strings in an array. */ -static gchar **rebuild_args_array(gchar * data, gint length, gint * count) +static gchar **rebuild_args_array(gchar * data, gint length, gint * count, + gchar * client_dir) { gint i; gchar *last = data + length, *ptr = data; @@ -137,27 +218,35 @@ static gchar **rebuild_args_array(gchar * data, gint length, gint * count) /* Cut them. */ tab = g_new(gchar *, *count); - for (i = 0; i < *count - 1; i++) { - tab[i] = data; + for (i = 0; i < *count; i++) { + if (client_dir == NULL || data[0] == '/') + tab[i] = g_strdup(data); + else + tab[i] = g_build_filename(client_dir, data, NULL); + data += strlen(data) + 1; } - tab[i] = data; return tab; } /* Add the filenames and open the next image. */ -static void process_data(gchar * data, gint length, gboolean recursive, - gboolean shuffle, gboolean sort) +static void process_data(gchar * data, gint length, gchar * client_dir, + gboolean recursive, gboolean shuffle, gboolean sort) { - gint count, nb_inserted; + gint i, count, nb_inserted; gchar **tab; - tab = rebuild_args_array(data, length, &count); + tab = rebuild_args_array(data, length, &count, client_dir); nb_inserted = insert_after_current(tab, count, recursive, shuffle, sort); if (nb_inserted > 0) open_next_image(nb_inserted == 1); + + for (i = 0; i < count; i++) + g_free(tab[i]); + + g_free(tab); } /* Called when there is something to read. */ @@ -169,6 +258,7 @@ static gboolean handle_connect(GIOChannel * source, GIOCondition unused1, GError *err = NULL; GIOChannel *channel; gboolean recursive, shuffle, sort; + gchar *client_dir; fd = accept(g_io_channel_unix_get_fd(source), NULL, &length); if (fd < 0) { @@ -176,17 +266,13 @@ static gboolean handle_connect(GIOChannel * source, GIOCondition unused1, return TRUE; } - /* Fill the flags. */ - if (read_params(fd, &recursive, &shuffle, &sort) == FALSE) + channel = make_channel(fd); + if (channel == NULL) return TRUE; - channel = g_io_channel_unix_new(fd); - g_io_channel_set_encoding(channel, NULL, &err); - if (err != NULL) { - g_printerr("%s\n", err->message); - g_error_free(err); + /* Fill the flags. */ + if (read_params(channel, &client_dir, &recursive, &shuffle, &sort) == FALSE) { g_io_channel_unref(channel); - close(fd); return TRUE; } @@ -195,11 +281,11 @@ static gboolean handle_connect(GIOChannel * source, GIOCondition unused1, g_printerr("%s\n", err->message); g_error_free(err); g_io_channel_unref(channel); - close(fd); return TRUE; } - process_data(data, length, recursive, shuffle, sort); + process_data(data, length, client_dir, recursive, shuffle, sort); + g_io_channel_unref(channel); return TRUE; } @@ -207,21 +293,14 @@ void start_server(void) { gint socket; GIOChannel *channel; - GError *err = NULL; socket = create_server_socket(); if (socket < 0) return; - channel = g_io_channel_unix_new(socket); - g_io_channel_set_encoding(channel, NULL, &err); - if (err != NULL) { - g_printerr("%s\n", err->message); - g_error_free(err); - g_io_channel_unref(channel); - close(socket); + channel = make_channel(socket); + if (channel == NULL) return; - } /* Let GTK+ inform us about clients. */ g_io_add_watch(channel, G_IO_IN, (GIOFunc) handle_connect, NULL); @@ -260,19 +339,20 @@ static gint create_client_socket(void) } /* Used when we read the filenames from stdin. */ -static void send_filenames(gint fd) +static void send_filenames(GIOChannel * channel) { gchar buffer[4096]; gint size; while ((size = fread(buffer, 1, sizeof(buffer), stdin)) > 0) - write(fd, buffer, size); + g_io_channel_write_chars(channel, buffer, size, NULL, NULL); } gboolean connect_server(gint argc, gchar ** argv) { gint fd, i; struct gengetopt_args_info ggo; + GIOChannel *channel; fd = create_client_socket(); if (fd < 0) @@ -280,25 +360,33 @@ gboolean connect_server(gint argc, gchar ** argv) cmdline_parser(argc, argv, &ggo); - if (write_params(fd, ggo.recursive_flag, + channel = make_channel(fd); + if (channel == NULL) + return TRUE; + + if (write_params(channel, ggo.recursive_flag, ggo.shuffle_flag, ggo.sort_flag) == FALSE) { - close(fd); + g_io_channel_unref(channel); return FALSE; } if (ggo.null_flag) - send_filenames(fd); + send_filenames(channel); for (i = 0; i < ggo.inputs_num; i++) { + gsize size; gint length = strlen(ggo.inputs[i]); - if (write(fd, ggo.inputs[i], length) != length) { - perror("write"); - close(fd); - return FALSE; + GError *err = NULL; + + g_io_channel_write_chars(channel, ggo.inputs[i], length, &size, &err); + if (err != NULL) { + g_printerr("%s\n", err->message); + g_error_free(err); + g_io_channel_unref(channel); + return TRUE; } } - close(fd); - + g_io_channel_unref(channel); return TRUE; } -- 2.11.4.GIT