diff options
Diffstat (limited to 'extra/pcmanfm/revert-new-IPC.patch')
-rw-r--r-- | extra/pcmanfm/revert-new-IPC.patch | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/extra/pcmanfm/revert-new-IPC.patch b/extra/pcmanfm/revert-new-IPC.patch new file mode 100644 index 000000000..fa64fde42 --- /dev/null +++ b/extra/pcmanfm/revert-new-IPC.patch @@ -0,0 +1,432 @@ +diff -Naur pcmanfm-20101030_10ae31a.orig/src/Makefile.am pcmanfm-20101030_10ae31a/src/Makefile.am +--- pcmanfm-20101030_10ae31a.orig/src/Makefile.am 2010-10-30 20:36:02.000000000 +0200 ++++ pcmanfm-20101030_10ae31a/src/Makefile.am 2010-10-31 09:13:48.000000000 +0100 +@@ -16,7 +16,6 @@ + pref.c pref.h \ + utils.c utils.h \ + gseal-gtk-compat.h \ +- single-inst.c single-inst.h \ + $(NULL) + + EXTRA_DIST= \ +diff -Naur pcmanfm-20101030_10ae31a.orig/src/pcmanfm.c pcmanfm-20101030_10ae31a/src/pcmanfm.c +--- pcmanfm-20101030_10ae31a.orig/src/pcmanfm.c 2010-10-30 20:36:02.000000000 +0200 ++++ pcmanfm-20101030_10ae31a/src/pcmanfm.c 2010-10-31 09:25:45.000000000 +0100 +@@ -31,6 +31,8 @@ + #include <string.h> + /* socket is used to keep single instance */ + #include <sys/types.h> ++#include <sys/socket.h> ++#include <sys/un.h> + #include <signal.h> + #include <unistd.h> /* for getcwd */ + +@@ -41,13 +43,14 @@ + #include "volume-manager.h" + #include "pref.h" + #include "pcmanfm.h" +-#include "single-inst.h" ++ ++static int sock; ++GIOChannel* io_channel = NULL; + + static int signal_pipe[2] = {-1, -1}; + gboolean daemon_mode = FALSE; + + static char** files_to_open = NULL; +-static int n_files_to_open = 0; + static char* profile = NULL; + static gboolean no_desktop = FALSE; + static gboolean show_desktop = FALSE; +@@ -80,25 +83,13 @@ + { NULL } + }; + +-/* single instance command id */ +-enum { +- CMD_INVALID, +- CMD_CWD, +- CMD_PROFILE, +- CMD_DESKTOP, +- CMD_DESKTOP_OFF, +- CMD_DAEMON_MODE, +- CMD_DESKTOP_PREF, +- CMD_SET_WALLPAPER, +- CMD_WALLPAPER_MODE, +- CMD_SHOW_PREF, +- CMD_FILES_TO_OPEN, +- CMD_EOF +-}; +- + static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"}; + ++static gboolean single_instance_check(); ++static void single_instance_finalize(); ++static void get_socket_name(char* buf, int len); + static gboolean pcmanfm_run(); ++static gboolean on_socket_event(GIOChannel* ioc, GIOCondition cond, gpointer data); + + /* it's not safe to call gtk+ functions in unix signal handler + * since the process is interrupted here and the state of gtk+ is unpredictable. */ +@@ -121,97 +112,6 @@ + return TRUE; + } + +-static gboolean on_single_inst_command(int cmd, SingleInstCmdData* data) +-{ +- switch(cmd) +- { +- case CMD_CWD: +- g_free(ipc_cwd); +- ipc_cwd = single_inst_get_str(data, NULL); +- break; +- case CMD_PROFILE: +- /* Not supported */ +- break; +- case CMD_DESKTOP: +- single_inst_get_bool(data, &show_desktop); +- break; +- case CMD_DESKTOP_OFF: +- single_inst_get_bool(data, &desktop_off); +- break; +- case CMD_DAEMON_MODE: +- /* Not supported */ +- break; +- case CMD_DESKTOP_PREF: +- single_inst_get_bool(data, &desktop_pref); +- break; +- case CMD_SET_WALLPAPER: +- g_free(set_wallpaper); +- set_wallpaper = single_inst_get_str(data, NULL); +- break; +- case CMD_WALLPAPER_MODE: +- g_free(wallpaper_mode); +- wallpaper_mode = single_inst_get_str(data, NULL); +- break; +- case CMD_SHOW_PREF: +- single_inst_get_int(data, &show_pref); +- break; +- case CMD_FILES_TO_OPEN: +- { +- g_strfreev(files_to_open); +- n_files_to_open = 0; +- files_to_open = single_inst_get_strv(data, &n_files_to_open); +- } +- break; +- case CMD_EOF: +- { +- int i; +- /* canonicalize filename if needed. */ +- for(i = 0; i < n_files_to_open; ++i) +- { +- char* file = files_to_open[i]; +- char* scheme = g_uri_parse_scheme(file); +- if(scheme) /* a valid URI */ +- { +- /* FIXME: should we canonicalize URIs? and how about file:///? */ +- g_free(scheme); +- } +- else /* a file path */ +- { +- files_to_open[i] = fm_canonicalize_filename(file, ipc_cwd); +- g_free(file); +- } +- } +- +- /* handle the parsed result and run the main program */ +- pcmanfm_run(); +- } +- break; +- } +- return TRUE; +-} +- +-/* we're not the first instance. pass the argv to the existing one. */ +-static void pass_args_to_existing_instance() +-{ +- /* send our current working dir to existing instance via IPC. */ +- ipc_cwd = g_get_current_dir(); +- single_inst_send_str(CMD_CWD, ipc_cwd); +- g_free(ipc_cwd); +- +- single_inst_send_bool(CMD_DESKTOP, show_desktop); +- single_inst_send_bool(CMD_DESKTOP_OFF, desktop_off); +- single_inst_send_bool(CMD_DESKTOP_PREF, desktop_pref); +- single_inst_send_str(CMD_SET_WALLPAPER, set_wallpaper); +- single_inst_send_str(CMD_WALLPAPER_MODE, wallpaper_mode); +- single_inst_send_int(CMD_SHOW_PREF, show_pref); +- /* single_inst_send_bool(CMD_FIND_FILES, find_files); */ +- +- single_inst_send_strv(CMD_FILES_TO_OPEN, files_to_open); +- single_inst_send_bool(CMD_EOF, TRUE); /* all args have been sent. */ +- +- single_inst_finalize(); +-} +- + int main(int argc, char** argv) + { + FmConfig* config; +@@ -230,17 +130,10 @@ + return 1; + } + +- /* ensure that there is only one instance of pcmanfm. */ +- switch(single_inst_init("pcmanfm", on_single_inst_command)) +- { +- case SINGLE_INST_CLIENT: /* we're not the first instance. */ +- pass_args_to_existing_instance(); +- gdk_notify_startup_complete(); +- return 0; +- case SINGLE_INST_ERROR: /* error happened. */ +- single_inst_finalize(); +- return 1; +- } ++ /* ensure that there is only one instance of pcmanfm. ++ if there is an existing instance, command line arguments ++ will be passed to the existing instance, and exit() will be called here. */ ++ single_instance_check(); + + if(pipe(signal_pipe) == 0) + { +@@ -274,13 +167,240 @@ + fm_volume_manager_finalize(); + } + +- single_inst_finalize(); ++ single_instance_finalize(); ++ + fm_gtk_finalize(); + + g_object_unref(config); + return 0; + } + ++inline static void buf_append_str(GByteArray* buf, const char* str) ++{ ++ int len; ++ if(G_LIKELY(str)) ++ { ++ len = strlen(str) + 1; ++ g_byte_array_append(buf, (guint8*)&len, sizeof(len)); ++ g_byte_array_append(buf, (guint8*)str, len); ++ } ++ else ++ { ++ len = 0; ++ g_byte_array_append(buf, (guint8*)&len, sizeof(len)); ++ } ++} ++ ++inline static GByteArray* args_to_ipc_buf() ++{ ++ int i, len; ++ GByteArray* buf = g_byte_array_sized_new(4096); ++ /* send our current working dir to existing instance via IPC. */ ++ ipc_cwd = g_get_current_dir(); ++ buf_append_str(buf, ipc_cwd); ++ g_free(ipc_cwd); ++ ++ /* g_byte_array_append(buf, (guint8*)&new_tab, sizeof(new_tab)); */ ++ g_byte_array_append(buf, (guint8*)&show_desktop, sizeof(show_desktop)); ++ g_byte_array_append(buf, (guint8*)&desktop_off, sizeof(desktop_off)); ++ g_byte_array_append(buf, (guint8*)&desktop_pref, sizeof(desktop_pref)); ++ buf_append_str(buf, set_wallpaper); ++ buf_append_str(buf, wallpaper_mode); ++ g_byte_array_append(buf, (guint8*)&show_pref, sizeof(show_pref)); ++ g_byte_array_append(buf, (guint8*)&find_files, sizeof(find_files)); ++ g_byte_array_append(buf, (guint8*)&no_desktop, sizeof(no_desktop)); ++ ++ len = files_to_open ? g_strv_length(files_to_open) : 0; ++ g_byte_array_append(buf, (guint8*)&len, sizeof(len)); ++ for(i = 0; i < len; ++i) ++ buf_append_str(buf, files_to_open[i]); ++ ++ return buf; ++} ++ ++inline static gboolean buf_read_bool(const char**p) ++{ ++ gboolean ret; ++ memcpy(&ret, *p, sizeof(ret)); ++ *p += sizeof(ret); ++ return ret; ++} ++ ++inline static int buf_read_int(const char**p) ++{ ++ int ret; ++ memcpy(&ret, *p, sizeof(ret)); ++ *p += sizeof(ret); ++ return ret; ++} ++ ++inline static char* buf_read_str(const char**p) ++{ ++ char* ret; ++ int len = buf_read_int(p); ++ if(len > 0) ++ { ++ ret = g_malloc(len); ++ memcpy(ret, *p, len); ++ *p += len; ++ } ++ else ++ ret = NULL; ++ return ret; ++} ++ ++inline static void ipc_buf_to_args(GByteArray* buf) ++{ ++ int i, len; ++ char* p = buf->data; ++ char* cwd = buf_read_str(&p); ++ /* new_tab = buf_read_bool(&p); */ ++ show_desktop = buf_read_bool(&p); ++ desktop_off = buf_read_bool(&p); ++ desktop_pref = buf_read_bool(&p); ++ g_free(set_wallpaper); ++ set_wallpaper = buf_read_str(&p); ++ g_free(wallpaper_mode); ++ wallpaper_mode = buf_read_str(&p); ++ show_pref = buf_read_int(&p); ++ find_files = buf_read_bool(&p); ++ no_desktop = buf_read_bool(&p); ++ ++ len = buf_read_int(&p); ++ /* g_debug("len = %d", len); */ ++ if(len > 0) ++ { ++ files_to_open = g_new(char*, len + 1); ++ for(i = 0; i < len; ++i) ++ { ++ char* file = buf_read_str(&p); ++ char* scheme = g_uri_parse_scheme(file); ++ if(scheme) /* a valid URI */ ++ { ++ /* FIXME: should we canonicalize URIs? and how about file:///? */ ++ files_to_open[i] = file; ++ g_free(scheme); ++ } ++ else /* a file path */ ++ { ++ files_to_open[i] = fm_canonicalize_filename(file, cwd); ++ g_free(file); ++ } ++ } ++ files_to_open[i] = NULL; ++ } ++ else ++ files_to_open = NULL; ++ g_free(cwd); ++} ++ ++gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data ) ++{ ++ int client, r; ++ socklen_t addr_len = 0; ++ struct sockaddr_un client_addr ={ 0 }; ++ static char buf[ 1024 ]; ++ GByteArray* args; ++ ++ if ( cond & G_IO_IN ) ++ { ++ client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len ); ++ if ( client != -1 ) ++ { ++ args = g_byte_array_sized_new(4096); ++ while( (r = read( client, buf, sizeof(buf) )) > 0 ) ++ g_byte_array_append( args, (guint8*)buf, r); ++ shutdown( client, 2 ); ++ close( client ); ++ ipc_buf_to_args(args); ++ g_byte_array_free( args, TRUE ); ++ pcmanfm_run(); ++ } ++ } ++ return TRUE; ++} ++ ++void get_socket_name( char* buf, int len ) ++{ ++ char* dpy = gdk_get_display(); ++ g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", dpy, g_get_user_name() ); ++ g_free( dpy ); ++} ++ ++gboolean single_instance_check() ++{ ++ struct sockaddr_un addr; ++ int addr_len; ++ int ret; ++ int reuse; ++ ++ if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) ++ { ++ ret = 1; ++ goto _exit; ++ } ++ ++ /* FIXME: use abstract socket */ ++ addr.sun_family = AF_UNIX; ++ get_socket_name(addr.sun_path, sizeof( addr.sun_path )); ++#ifdef SUN_LEN ++ addr_len = SUN_LEN(&addr); ++#else ++ addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family ); ++#endif ++ ++ /* try to connect to existing instance */ ++ if(connect(sock, (struct sockaddr*)&addr, addr_len) == 0) ++ { ++ /* connected successfully */ ++ GByteArray* buf = args_to_ipc_buf(); ++ write(sock, buf->data, buf->len); ++ g_byte_array_free(buf, TRUE); ++ ++ shutdown( sock, 2 ); ++ close( sock ); ++ ret = 0; ++ goto _exit; ++ } ++ ++ /* There is no existing server, and we are in the first instance. */ ++ unlink( addr.sun_path ); /* delete old socket file if it exists. */ ++ reuse = 1; ++ ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ); ++ if(bind(sock, (struct sockaddr*)&addr, addr_len) == -1) ++ { ++ ret = 1; ++ goto _exit; ++ } ++ ++ io_channel = g_io_channel_unix_new(sock); ++ g_io_channel_set_encoding(io_channel, NULL, NULL); ++ g_io_channel_set_buffered(io_channel, FALSE); ++ g_io_add_watch(io_channel, G_IO_IN, ++ (GIOFunc)on_socket_event, NULL); ++ if(listen(sock, 5) == -1) ++ { ++ ret = 1; ++ goto _exit; ++ } ++ return TRUE; ++ ++_exit: ++ ++ gdk_notify_startup_complete(); ++ exit( ret ); ++} ++ ++void single_instance_finalize() ++{ ++ char lock_file[256]; ++ shutdown(sock, 2); ++ g_io_channel_unref(io_channel); ++ close(sock); ++ get_socket_name(lock_file, sizeof( lock_file )); ++ unlink(lock_file); ++} ++ + static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data) + { + if(err->domain == G_IO_ERROR) |