static void send_open_command(gint sock, gint argc, gchar **argv) { gint i; gchar *filename; g_return_if_fail(argc > 1); geany_debug("using running instance of Geany"); if (cl_options.goto_line >= 0) { gchar *line = g_strdup_printf("%d\n", cl_options.goto_line); socket_fd_write_all(sock, "line\n", 5); socket_fd_write_all(sock, line, strlen(line)); socket_fd_write_all(sock, ".\n", 2); g_free(line); } if (cl_options.goto_column >= 0) { gchar *col = g_strdup_printf("%d\n", cl_options.goto_column); socket_fd_write_all(sock, "column\n", 7); socket_fd_write_all(sock, col, strlen(col)); socket_fd_write_all(sock, ".\n", 2); g_free(col); } socket_fd_write_all(sock, "open\n", 5); for (i = 1; i < argc && argv[i] != NULL; i++) { filename = main_get_argv_filename(argv[i]); /* if the filename is valid or if a new file should be opened is check on the other side */ if (filename != NULL) { socket_fd_write_all(sock, filename, strlen(filename)); socket_fd_write_all(sock, "\n", 1); } else { g_printerr(_("Could not find file '%s'."), filename); g_printerr("\n"); /* keep translation from open_cl_files() in main.c. */ } g_free(filename); } socket_fd_write_all(sock, ".\n", 2); }
/* (Unix domain) socket support; taken from Geany */ gint socket_init(gint argc, gchar **argv) { gint sock; if (socket_info.file_name == NULL) socket_info.file_name = g_strconcat ("/tmp/xarchiver_",g_get_user_name(),"_socket",NULL); sock = socket_fd_connect_unix(socket_info.file_name); if (sock < 0) { unlink(socket_info.file_name); return socket_fd_open_unix(socket_info.file_name); } // remote command mode, here we have another running instance and want to use it if (argc > 1) { gint i; gchar *filename; socket_fd_write_all(sock, "open\n", 5); for(i = 1; i < argc && argv[i] != NULL; i++) { filename = argv[i]; if (filename != NULL) { socket_fd_write_all(sock, filename, strlen(filename)); socket_fd_write_all(sock, "\n", 1); } } socket_fd_write_all(sock, ".\n", 2); } socket_fd_close(sock); return -1; }
static void socket_get_document_list(gint sock) { gchar doc_list[BUFFER_LENGTH]; gint doc_list_len; if (sock < 0) return; socket_fd_write_all(sock, "doclist\n", 8); doc_list_len = socket_fd_read(sock, doc_list, sizeof(doc_list)); if (doc_list_len >= BUFFER_LENGTH) doc_list_len = BUFFER_LENGTH -1; doc_list[doc_list_len] = '\0'; /* if we received ETX (end-of-text), there were no open files, so print only otherwise */ if (! utils_str_equal(doc_list, "\3")) printf("%s", doc_list); }
static void socket_get_document_list(gint sock) { gchar buf[BUFFER_LENGTH]; gint n_read; if (sock < 0) return; socket_fd_write_all(sock, "doclist\n", 8); do { n_read = socket_fd_read(sock, buf, BUFFER_LENGTH); /* if we received ETX (end-of-text), there is nothing else to read, so cut that * byte not to output it and to be sure not to validate the loop condition */ if (n_read > 0 && buf[n_read - 1] == '\3') n_read--; if (n_read > 0) fwrite(buf, 1, n_read, stdout); } while (n_read >= BUFFER_LENGTH); }
gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpointer data) { gint fd, sock; gchar buf[BUFFER_LENGTH]; gchar *command = NULL; struct sockaddr_in caddr; socklen_t caddr_len = sizeof(caddr); GtkWidget *window = data; gboolean popup = FALSE; fd = g_io_channel_unix_get_fd(source); sock = accept(fd, (struct sockaddr *)&caddr, &caddr_len); /* first get the command */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1) { command = g_strdup(buf); geany_debug("Received IPC command from remote instance: %s", g_strstrip(command)); g_free(command); if (strncmp(buf, "open", 4) == 0) { cl_options.readonly = strncmp(buf+4, "ro", 2) == 0; /* open in readonly? */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { gsize buf_len = strlen(buf); /* remove trailing newline */ if (buf_len > 0 && buf[buf_len - 1] == '\n') buf[buf_len - 1] = '\0'; handle_input_filename(buf); } popup = TRUE; } else if (strncmp(buf, "doclist", 7) == 0) { gchar *doc_list = build_document_list(); if (!EMPTY(doc_list)) socket_fd_write_all(sock, doc_list, strlen(doc_list)); /* send ETX (end-of-text) so reader knows to stop reading */ socket_fd_write_all(sock, "\3", 1); g_free(doc_list); } else if (strncmp(buf, "line", 4) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_line = atoi(buf); } } else if (strncmp(buf, "column", 6) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_column = atoi(buf); } } #ifdef G_OS_WIN32 else if (strncmp(buf, "window", 6) == 0) { # if GTK_CHECK_VERSION(3, 0, 0) HWND hwnd = (HWND) gdk_win32_window_get_handle(gtk_widget_get_window(window)); # else HWND hwnd = (HWND) gdk_win32_drawable_get_handle( GDK_DRAWABLE(gtk_widget_get_window(window))); # endif socket_fd_write(sock, (gchar *)&hwnd, sizeof(hwnd)); } #endif } if (popup) { #ifdef GDK_WINDOWING_X11 GdkWindow *x11_window = gtk_widget_get_window(window); /* Set the proper interaction time on the window. This seems necessary to make * gtk_window_present() really bring the main window into the foreground on some * window managers like Gnome's metacity. * Code taken from Gedit. */ # if GTK_CHECK_VERSION(3, 0, 0) if (GDK_IS_X11_WINDOW(x11_window)) # endif { gdk_x11_window_set_user_time(x11_window, gdk_x11_get_server_time(x11_window)); } #endif gtk_window_present(GTK_WINDOW(window)); #ifdef G_OS_WIN32 gdk_window_show(gtk_widget_get_window(window)); #endif } socket_fd_close(sock); return TRUE; }
/* (Unix domain) socket support to replace the old FIFO code * (taken from Sylpheed, thanks) * Returns the created socket, -1 if an error occurred or -2 if another socket exists and files * were sent to it. */ gint socket_init(gint argc, gchar **argv) { gint sock; #ifdef G_OS_WIN32 HANDLE hmutex; HWND hwnd; socket_init_win32(); hmutex = CreateMutexA(NULL, FALSE, "Geany"); if (! hmutex) { geany_debug("cannot create Mutex\n"); return -1; } if (GetLastError() != ERROR_ALREADY_EXISTS) { /* To support multiple instances with different configuration directories (as we do on * non-Windows systems) we would need to use different port number s but it might be * difficult to get a port number which is unique for a configuration directory (path) * and which is unused. This port number has to be guessed by the first and new instance * and the only data is the configuration directory path. * For now we use one port number, that is we support only one instance at all. */ sock = socket_fd_open_inet(REMOTE_CMD_PORT); if (sock < 0) return -1; return sock; } sock = socket_fd_connect_inet(REMOTE_CMD_PORT); if (sock < 0) return -1; #else gchar *display_name = NULL; const gchar *hostname = g_get_host_name(); GdkDisplay *display = gdk_display_get_default(); gchar *p; /* On OS X with quartz backend gdk_display_get_name() returns hostname * using [NSHost currentHost] (it could return more or less whatever string * as display name is a X11 specific thing). This call can lead to network * query and block for several seconds so better skip it. */ #ifndef GDK_WINDOWING_QUARTZ if (display != NULL) display_name = g_strdup(gdk_display_get_name(display)); #endif if (display_name == NULL) display_name = g_strdup("NODISPLAY"); /* these lines are taken from dcopc.c in kdelibs */ if ((p = strrchr(display_name, '.')) > strrchr(display_name, ':') && p != NULL) *p = '\0'; /* remove characters that may not be acceptable in a filename */ for (p = display_name; *p; p++) { if (*p == ':' || *p == '/') *p = '_'; } if (socket_info.file_name == NULL) socket_info.file_name = g_strdup_printf("%s%cgeany_socket_%s_%s", app->configdir, G_DIR_SEPARATOR, hostname, display_name); g_free(display_name); /* check whether the real user id is the same as this of the socket file */ check_socket_permissions(); sock = socket_fd_connect_unix(socket_info.file_name); if (sock < 0) { remove_socket_link_full(); /* deletes the socket file and the symlink */ return socket_fd_open_unix(socket_info.file_name); } #endif /* remote command mode, here we have another running instance and want to use it */ /* now we send the command line args */ if (argc > 1) { #ifdef G_OS_WIN32 /* first we send a request to retrieve the window handle and focus the window */ socket_fd_write_all(sock, "window\n", 7); if (socket_fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd)) SetForegroundWindow(hwnd); #endif send_open_command(sock, argc, argv); } if (cl_options.list_documents) { socket_get_document_list(sock); } socket_fd_close(sock); return -2; }
gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpointer data) { gint fd, sock; gchar buf[BUFFER_LENGTH]; struct sockaddr_in caddr; socklen_t caddr_len = sizeof(caddr); GtkWidget *window = data; gboolean popup = FALSE; fd = g_io_channel_unix_get_fd(source); sock = accept(fd, (struct sockaddr *)&caddr, &caddr_len); /* first get the command */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1) { if (strncmp(buf, "open", 4) == 0) { cl_options.readonly = strncmp(buf+4, "ro", 2) == 0; /* open in readonly? */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { handle_input_filename(g_strstrip(buf)); } popup = TRUE; } else if (strncmp(buf, "doclist", 7) == 0) { gchar *doc_list = build_document_list(); if (NZV(doc_list)) socket_fd_write_all(sock, doc_list, strlen(doc_list)); else /* send ETX (end-of-text) in case we have no open files, we must send anything * otherwise the client would hang on reading */ socket_fd_write_all(sock, "\3", 1); g_free(doc_list); } else if (strncmp(buf, "line", 4) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_line = atoi(buf); } } else if (strncmp(buf, "column", 6) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_column = atoi(buf); } } #ifdef G_OS_WIN32 else if (strncmp(buf, "window", 6) == 0) { HWND hwnd = (HWND) gdk_win32_drawable_get_handle( GDK_DRAWABLE(gtk_widget_get_window(window))); socket_fd_write(sock, (gchar *)&hwnd, sizeof(hwnd)); } #endif } if (popup) { #ifdef GDK_WINDOWING_X11 /* Set the proper interaction time on the window. This seems necessary to make * gtk_window_present() really bring the main window into the foreground on some * window managers like Gnome's metacity. * Code taken from Gedit. */ gdk_x11_window_set_user_time(gtk_widget_get_window(window), gdk_x11_get_server_time(gtk_widget_get_window(window))); #endif gtk_window_present(GTK_WINDOW(window)); #ifdef G_OS_WIN32 gdk_window_show(gtk_widget_get_window(window)); #endif } socket_fd_close(sock); return TRUE; }
/* (Unix domain) socket support to replace the old FIFO code * (taken from Sylpheed, thanks) * Returns the created socket, -1 if an error occurred or -2 if another socket exists and files * were sent to it. */ gint socket_init(gint argc, gchar **argv) { gint sock; #ifdef G_OS_WIN32 HANDLE hmutex; HWND hwnd; socket_init_win32(); hmutex = CreateMutexA(NULL, FALSE, "Geany"); if (! hmutex) { geany_debug("cannot create Mutex\n"); return -1; } if (GetLastError() != ERROR_ALREADY_EXISTS) { /* To support multiple instances with different configuration directories (as we do on * non-Windows systems) we would need to use different port number s but it might be * difficult to get a port number which is unique for a configuration directory (path) * and which is unused. This port number has to be guessed by the first and new instance * and the only data is the configuration directory path. * For now we use one port number, that is we support only one instance at all. */ sock = socket_fd_open_inet(REMOTE_CMD_PORT); if (sock < 0) return 0; return sock; } sock = socket_fd_connect_inet(REMOTE_CMD_PORT); if (sock < 0) return -1; #else gchar *display_name = gdk_get_display(); gchar *hostname = utils_get_hostname(); gchar *p; if (display_name == NULL) display_name = g_strdup("NODISPLAY"); /* these lines are taken from dcopc.c in kdelibs */ if ((p = strrchr(display_name, '.')) > strrchr(display_name, ':') && p != NULL) *p = '\0'; while ((p = strchr(display_name, ':')) != NULL) *p = '_'; if (socket_info.file_name == NULL) socket_info.file_name = g_strdup_printf("%s%cgeany_socket_%s_%s", app->configdir, G_DIR_SEPARATOR, hostname, display_name); g_free(display_name); g_free(hostname); /* check whether the real user id is the same as this of the socket file */ check_socket_permissions(); sock = socket_fd_connect_unix(socket_info.file_name); if (sock < 0) { remove_socket_link_full(); /* deletes the socket file and the symlink */ return socket_fd_open_unix(socket_info.file_name); } #endif /* remote command mode, here we have another running instance and want to use it */ #ifdef G_OS_WIN32 /* first we send a request to retrieve the window handle and focus the window */ socket_fd_write_all(sock, "window\n", 7); if (socket_fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd)) SetForegroundWindow(hwnd); #endif /* now we send the command line args */ if (argc > 1) { send_open_command(sock, argc, argv); } if (cl_options.list_documents) { socket_get_document_list(sock); } socket_fd_close(sock); return -2; }