1
diff -Naur pcmanfm-20101030_10ae31a.orig/src/Makefile.am pcmanfm-20101030_10ae31a/src/Makefile.am
2
--- pcmanfm-20101030_10ae31a.orig/src/Makefile.am 2010-10-30 20:36:02.000000000 +0200
3
+++ pcmanfm-20101030_10ae31a/src/Makefile.am 2010-10-31 09:13:48.000000000 +0100
8
- single-inst.c single-inst.h \
12
diff -Naur pcmanfm-20101030_10ae31a.orig/src/pcmanfm.c pcmanfm-20101030_10ae31a/src/pcmanfm.c
13
--- pcmanfm-20101030_10ae31a.orig/src/pcmanfm.c 2010-10-30 20:36:02.000000000 +0200
14
+++ pcmanfm-20101030_10ae31a/src/pcmanfm.c 2010-10-31 09:25:45.000000000 +0100
17
/* socket is used to keep single instance */
18
#include <sys/types.h>
19
+#include <sys/socket.h>
22
#include <unistd.h> /* for getcwd */
25
#include "volume-manager.h"
28
-#include "single-inst.h"
31
+GIOChannel* io_channel = NULL;
33
static int signal_pipe[2] = {-1, -1};
34
gboolean daemon_mode = FALSE;
36
static char** files_to_open = NULL;
37
-static int n_files_to_open = 0;
38
static char* profile = NULL;
39
static gboolean no_desktop = FALSE;
40
static gboolean show_desktop = FALSE;
45
-/* single instance command id */
61
static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"};
63
+static gboolean single_instance_check();
64
+static void single_instance_finalize();
65
+static void get_socket_name(char* buf, int len);
66
static gboolean pcmanfm_run();
67
+static gboolean on_socket_event(GIOChannel* ioc, GIOCondition cond, gpointer data);
69
/* it's not safe to call gtk+ functions in unix signal handler
70
* since the process is interrupted here and the state of gtk+ is unpredictable. */
75
-static gboolean on_single_inst_command(int cmd, SingleInstCmdData* data)
81
- ipc_cwd = single_inst_get_str(data, NULL);
87
- single_inst_get_bool(data, &show_desktop);
89
- case CMD_DESKTOP_OFF:
90
- single_inst_get_bool(data, &desktop_off);
92
- case CMD_DAEMON_MODE:
95
- case CMD_DESKTOP_PREF:
96
- single_inst_get_bool(data, &desktop_pref);
98
- case CMD_SET_WALLPAPER:
99
- g_free(set_wallpaper);
100
- set_wallpaper = single_inst_get_str(data, NULL);
102
- case CMD_WALLPAPER_MODE:
103
- g_free(wallpaper_mode);
104
- wallpaper_mode = single_inst_get_str(data, NULL);
106
- case CMD_SHOW_PREF:
107
- single_inst_get_int(data, &show_pref);
109
- case CMD_FILES_TO_OPEN:
111
- g_strfreev(files_to_open);
112
- n_files_to_open = 0;
113
- files_to_open = single_inst_get_strv(data, &n_files_to_open);
119
- /* canonicalize filename if needed. */
120
- for(i = 0; i < n_files_to_open; ++i)
122
- char* file = files_to_open[i];
123
- char* scheme = g_uri_parse_scheme(file);
124
- if(scheme) /* a valid URI */
126
- /* FIXME: should we canonicalize URIs? and how about file:///? */
129
- else /* a file path */
131
- files_to_open[i] = fm_canonicalize_filename(file, ipc_cwd);
136
- /* handle the parsed result and run the main program */
144
-/* we're not the first instance. pass the argv to the existing one. */
145
-static void pass_args_to_existing_instance()
147
- /* send our current working dir to existing instance via IPC. */
148
- ipc_cwd = g_get_current_dir();
149
- single_inst_send_str(CMD_CWD, ipc_cwd);
152
- single_inst_send_bool(CMD_DESKTOP, show_desktop);
153
- single_inst_send_bool(CMD_DESKTOP_OFF, desktop_off);
154
- single_inst_send_bool(CMD_DESKTOP_PREF, desktop_pref);
155
- single_inst_send_str(CMD_SET_WALLPAPER, set_wallpaper);
156
- single_inst_send_str(CMD_WALLPAPER_MODE, wallpaper_mode);
157
- single_inst_send_int(CMD_SHOW_PREF, show_pref);
158
- /* single_inst_send_bool(CMD_FIND_FILES, find_files); */
160
- single_inst_send_strv(CMD_FILES_TO_OPEN, files_to_open);
161
- single_inst_send_bool(CMD_EOF, TRUE); /* all args have been sent. */
163
- single_inst_finalize();
166
int main(int argc, char** argv)
169
@@ -230,17 +130,10 @@
173
- /* ensure that there is only one instance of pcmanfm. */
174
- switch(single_inst_init("pcmanfm", on_single_inst_command))
176
- case SINGLE_INST_CLIENT: /* we're not the first instance. */
177
- pass_args_to_existing_instance();
178
- gdk_notify_startup_complete();
180
- case SINGLE_INST_ERROR: /* error happened. */
181
- single_inst_finalize();
184
+ /* ensure that there is only one instance of pcmanfm.
185
+ if there is an existing instance, command line arguments
186
+ will be passed to the existing instance, and exit() will be called here. */
187
+ single_instance_check();
189
if(pipe(signal_pipe) == 0)
191
@@ -274,13 +167,240 @@
192
fm_volume_manager_finalize();
195
- single_inst_finalize();
196
+ single_instance_finalize();
200
g_object_unref(config);
204
+inline static void buf_append_str(GByteArray* buf, const char* str)
209
+ len = strlen(str) + 1;
210
+ g_byte_array_append(buf, (guint8*)&len, sizeof(len));
211
+ g_byte_array_append(buf, (guint8*)str, len);
216
+ g_byte_array_append(buf, (guint8*)&len, sizeof(len));
220
+inline static GByteArray* args_to_ipc_buf()
223
+ GByteArray* buf = g_byte_array_sized_new(4096);
224
+ /* send our current working dir to existing instance via IPC. */
225
+ ipc_cwd = g_get_current_dir();
226
+ buf_append_str(buf, ipc_cwd);
229
+ /* g_byte_array_append(buf, (guint8*)&new_tab, sizeof(new_tab)); */
230
+ g_byte_array_append(buf, (guint8*)&show_desktop, sizeof(show_desktop));
231
+ g_byte_array_append(buf, (guint8*)&desktop_off, sizeof(desktop_off));
232
+ g_byte_array_append(buf, (guint8*)&desktop_pref, sizeof(desktop_pref));
233
+ buf_append_str(buf, set_wallpaper);
234
+ buf_append_str(buf, wallpaper_mode);
235
+ g_byte_array_append(buf, (guint8*)&show_pref, sizeof(show_pref));
236
+ g_byte_array_append(buf, (guint8*)&find_files, sizeof(find_files));
237
+ g_byte_array_append(buf, (guint8*)&no_desktop, sizeof(no_desktop));
239
+ len = files_to_open ? g_strv_length(files_to_open) : 0;
240
+ g_byte_array_append(buf, (guint8*)&len, sizeof(len));
241
+ for(i = 0; i < len; ++i)
242
+ buf_append_str(buf, files_to_open[i]);
247
+inline static gboolean buf_read_bool(const char**p)
250
+ memcpy(&ret, *p, sizeof(ret));
255
+inline static int buf_read_int(const char**p)
258
+ memcpy(&ret, *p, sizeof(ret));
263
+inline static char* buf_read_str(const char**p)
266
+ int len = buf_read_int(p);
269
+ ret = g_malloc(len);
270
+ memcpy(ret, *p, len);
278
+inline static void ipc_buf_to_args(GByteArray* buf)
281
+ char* p = buf->data;
282
+ char* cwd = buf_read_str(&p);
283
+ /* new_tab = buf_read_bool(&p); */
284
+ show_desktop = buf_read_bool(&p);
285
+ desktop_off = buf_read_bool(&p);
286
+ desktop_pref = buf_read_bool(&p);
287
+ g_free(set_wallpaper);
288
+ set_wallpaper = buf_read_str(&p);
289
+ g_free(wallpaper_mode);
290
+ wallpaper_mode = buf_read_str(&p);
291
+ show_pref = buf_read_int(&p);
292
+ find_files = buf_read_bool(&p);
293
+ no_desktop = buf_read_bool(&p);
295
+ len = buf_read_int(&p);
296
+ /* g_debug("len = %d", len); */
299
+ files_to_open = g_new(char*, len + 1);
300
+ for(i = 0; i < len; ++i)
302
+ char* file = buf_read_str(&p);
303
+ char* scheme = g_uri_parse_scheme(file);
304
+ if(scheme) /* a valid URI */
306
+ /* FIXME: should we canonicalize URIs? and how about file:///? */
307
+ files_to_open[i] = file;
310
+ else /* a file path */
312
+ files_to_open[i] = fm_canonicalize_filename(file, cwd);
316
+ files_to_open[i] = NULL;
319
+ files_to_open = NULL;
323
+gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data )
326
+ socklen_t addr_len = 0;
327
+ struct sockaddr_un client_addr ={ 0 };
328
+ static char buf[ 1024 ];
331
+ if ( cond & G_IO_IN )
333
+ client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len );
334
+ if ( client != -1 )
336
+ args = g_byte_array_sized_new(4096);
337
+ while( (r = read( client, buf, sizeof(buf) )) > 0 )
338
+ g_byte_array_append( args, (guint8*)buf, r);
339
+ shutdown( client, 2 );
341
+ ipc_buf_to_args(args);
342
+ g_byte_array_free( args, TRUE );
349
+void get_socket_name( char* buf, int len )
351
+ char* dpy = gdk_get_display();
352
+ g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", dpy, g_get_user_name() );
356
+gboolean single_instance_check()
358
+ struct sockaddr_un addr;
363
+ if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
369
+ /* FIXME: use abstract socket */
370
+ addr.sun_family = AF_UNIX;
371
+ get_socket_name(addr.sun_path, sizeof( addr.sun_path ));
373
+ addr_len = SUN_LEN(&addr);
375
+ addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family );
378
+ /* try to connect to existing instance */
379
+ if(connect(sock, (struct sockaddr*)&addr, addr_len) == 0)
381
+ /* connected successfully */
382
+ GByteArray* buf = args_to_ipc_buf();
383
+ write(sock, buf->data, buf->len);
384
+ g_byte_array_free(buf, TRUE);
386
+ shutdown( sock, 2 );
392
+ /* There is no existing server, and we are in the first instance. */
393
+ unlink( addr.sun_path ); /* delete old socket file if it exists. */
395
+ ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) );
396
+ if(bind(sock, (struct sockaddr*)&addr, addr_len) == -1)
402
+ io_channel = g_io_channel_unix_new(sock);
403
+ g_io_channel_set_encoding(io_channel, NULL, NULL);
404
+ g_io_channel_set_buffered(io_channel, FALSE);
405
+ g_io_add_watch(io_channel, G_IO_IN,
406
+ (GIOFunc)on_socket_event, NULL);
407
+ if(listen(sock, 5) == -1)
416
+ gdk_notify_startup_complete();
420
+void single_instance_finalize()
422
+ char lock_file[256];
424
+ g_io_channel_unref(io_channel);
426
+ get_socket_name(lock_file, sizeof( lock_file ));
430
static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data)
432
if(err->domain == G_IO_ERROR)