75# include <sys/types.h>
76# include <sys/socket.h>
78# include <netinet/in.h>
79# include <glib/gstdio.h>
83# include <gdk/gdkwin32.h>
92#ifdef GDK_WINDOWING_X11
98#define SOCKET_IS_VALID(s) ((s) != INVALID_SOCKET)
100#define SOCKET_IS_VALID(s) ((s) >= 0)
101#define INVALID_SOCKET (-1)
103#define BUFFER_LENGTH 4096
109static gint socket_fd_connect_inet (gushort port);
110static gint socket_fd_open_inet (gushort port);
111static void socket_init_win32 (
void);
113static gint socket_fd_connect_unix (
const gchar *path);
114static gint socket_fd_open_unix (
const gchar *path);
117static gint socket_fd_write (gint sock,
const gchar *buf, gint len);
118static gint socket_fd_write_all (gint sock,
const gchar *buf, gint len);
119static gint socket_fd_gets (gint sock, gchar *buf, gint len);
120static gint socket_fd_check_io (gint fd, GIOCondition cond);
121static gint socket_fd_read (gint sock, gchar *buf, gint len);
122static gint socket_fd_recv (gint fd, gchar *buf, gint len, gint flags);
123static gint socket_fd_close (gint sock);
127static void send_open_command(gint sock, gint argc, gchar **argv)
131 g_return_if_fail(argc > 1);
137 socket_fd_write_all(sock,
"line\n", 5);
138 socket_fd_write_all(sock,
line, strlen(
line));
139 socket_fd_write_all(sock,
".\n", 2);
145 gchar *col = g_strdup_printf(
"%d\n",
cl_options.goto_column);
146 socket_fd_write_all(sock,
"column\n", 7);
147 socket_fd_write_all(sock, col, strlen(col));
148 socket_fd_write_all(sock,
".\n", 2);
153 socket_fd_write_all(sock,
"openro\n", 7);
155 socket_fd_write_all(sock,
"open\n", 5);
157 for (i = 1; i < argc && argv[i] !=
NULL; i++)
165 socket_fd_write_all(sock,
"\n", 1);
169 g_printerr(
_(
"Could not find file '%s'."),
filename);
174 socket_fd_write_all(sock,
".\n", 2);
179static void remove_socket_link_full(
void)
181 gchar real_path[512];
191 real_path[len] =
'\0';
199static void socket_get_document_list(gint sock)
201 gchar buf[BUFFER_LENGTH];
207 socket_fd_write_all(sock,
"doclist\n", 8);
211 n_read = socket_fd_read(sock, buf, BUFFER_LENGTH);
214 if (n_read > 0 && buf[n_read - 1] ==
'\3')
217 fwrite(buf, 1, n_read, stdout);
219 while (n_read >= BUFFER_LENGTH);
224static void check_socket_permissions(
void)
226 GStatBuf socket_stat;
231 if (socket_stat.st_uid != getuid())
233 const gchar *msg =
_(
235 "Geany tried to access the Unix Domain socket of another instance running as another user.\n"
236 "This is a fatal error and Geany will now quit.");
237 g_warning(
"%s", msg);
250gint
socket_init(gint argc, gchar **argv, G_GNUC_UNUSED gushort socket_port)
257 hmutex = CreateMutexA(
NULL, FALSE,
"Geany");
263 if (GetLastError() != ERROR_ALREADY_EXISTS)
271 sock = socket_fd_open_inet(socket_port);
277 sock = socket_fd_connect_inet(socket_port);
281 gchar *display_name =
NULL;
282 const gchar *hostname = g_get_host_name();
283 GdkDisplay *display = gdk_display_get_default();
290#ifndef GDK_WINDOWING_QUARTZ
292 display_name = g_strdup(gdk_display_get_name(display));
295 if (display_name ==
NULL)
296 display_name = g_strdup(
"NODISPLAY");
299 if ((p = strrchr(display_name,
'.')) > strrchr(display_name,
':') && p !=
NULL)
302 for (p = display_name; *p; p++)
304 if (*p ==
':' || *p ==
'/')
310 app->
configdir, G_DIR_SEPARATOR, hostname, display_name);
312 g_free(display_name);
315 check_socket_permissions();
320 remove_socket_link_full();
332 socket_fd_write_all(sock,
"window\n", 7);
333 if (socket_fd_read(sock, (gchar *)&hwnd,
sizeof(hwnd)) ==
sizeof(hwnd))
334 SetForegroundWindow(hwnd);
337 send_open_command(sock, argc, argv);
342 socket_get_document_list(sock);
345 socket_fd_close(sock);
369 remove_socket_link_full();
378static void log_error(
const gchar *message_prefix, gint error_code)
381 error_code = error_code == -1 ? WSAGetLastError(): error_code;
382 gchar *error_message = g_win32_error_message(error_code);
384 error_code = error_code == -1 ?
errno: error_code;
385 gchar *error_message = g_strdup(g_strerror(error_code));
387 g_warning(
"%s: %d: %s", message_prefix, error_code, error_message);
388 g_free(error_message);
393static gint socket_fd_connect_unix(
const gchar *path)
396 struct sockaddr_un addr;
398 sock = socket(PF_UNIX, SOCK_STREAM, 0);
401 log_error(
"Failed to create IPC socket",
errno);
405 memset(&addr, 0,
sizeof(addr));
406 addr.sun_family = AF_UNIX;
407 strncpy(addr.sun_path, path,
sizeof(addr.sun_path) - 1);
409 if (connect(sock, (
struct sockaddr *)&addr,
sizeof(addr)) < 0)
411 socket_fd_close(sock);
419static gint socket_fd_open_unix(
const gchar *path)
422 struct sockaddr_un addr;
428 sock = socket(PF_UNIX, SOCK_STREAM, 0);
431 log_error(
"Failed to create IPC socket",
errno);
436 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val,
sizeof(val)) < 0)
438 log_error(
"Failed to set IPC socket option",
errno);
439 socket_fd_close(sock);
452 real_dir = g_build_filename(g_get_user_runtime_dir(),
"geany",
NULL);
454 basename = g_strdup_printf(
"geany_socket.%08x", g_random_int());
455 if (err == 0 || err == EEXIST)
456 real_path = g_build_filename(real_dir, basename,
NULL);
458 real_path = g_build_filename(g_get_tmp_dir(), basename,
NULL);
465 g_warning(
"Socket %s could not be written, using %s as fallback.", real_path, path);
466 SETPTR(real_path, g_strdup(path));
470 else if (symlink(real_path, path) != 0)
472 gint saved_errno =
errno;
473 gchar* message = g_strdup_printf(
474 "Failed to create IPC socket symlink %s -> %s)",
477 log_error(message, saved_errno);
479 socket_fd_close(sock);
483 memset(&addr, 0,
sizeof(addr));
484 addr.sun_family = AF_UNIX;
485 strncpy(addr.sun_path, real_path,
sizeof(addr.sun_path) - 1);
487 if (bind(sock, (
struct sockaddr *)&addr,
sizeof(addr)) < 0)
489 gint saved_errno =
errno;
490 gchar* message = g_strdup_printf(
"Failed to bind IPC socket (%s)", real_path);
491 log_error(message, saved_errno);
493 socket_fd_close(sock);
497 if (listen(sock, 1) < 0)
499 gint saved_errno =
errno;
500 gchar* message = g_strdup_printf(
"Failed to listen on IPC socket (%s)", real_path);
501 log_error(message, saved_errno);
503 socket_fd_close(sock);
507 g_chmod(real_path, 0600);
515static gint socket_fd_close(gint fd)
518 return closesocket(fd);
526static gint socket_fd_open_inet(gushort port)
529 struct sockaddr_in addr;
532 sock = socket(AF_INET, SOCK_STREAM, 0);
533 if (G_UNLIKELY(! SOCKET_IS_VALID(sock)))
535 log_error(
"Failed to create IPC socket", -1);
540 if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &val,
sizeof(val)) < 0)
542 log_error(
"Failed to set IPC socket exclusive option", -1);
543 socket_fd_close(sock);
547 memset(&addr, 0,
sizeof(addr));
548 addr.sin_family = AF_INET;
549 addr.sin_port = htons(port);
550 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
552 if (bind(sock, (
struct sockaddr *)&addr,
sizeof(addr)) < 0)
554 gint saved_errno = WSAGetLastError();
555 gchar* message = g_strdup_printf(
"Failed to bind IPC socket (127.0.0.1:%d)", port);
556 log_error(message, saved_errno);
558 socket_fd_close(sock);
562 if (listen(sock, 1) < 0)
564 gint saved_errno = WSAGetLastError();
565 gchar* message = g_strdup_printf(
"Failed to listen on IPC socket (127.0.0.1:%d)", port);
566 log_error(message, saved_errno);
568 socket_fd_close(sock);
576static gint socket_fd_connect_inet(gushort port)
579 struct sockaddr_in addr;
581 sock = socket(AF_INET, SOCK_STREAM, 0);
582 if (G_UNLIKELY(! SOCKET_IS_VALID(sock)))
584 log_error(
"Failed to create IPC socket", -1);
588 memset(&addr, 0,
sizeof(addr));
589 addr.sin_family = AF_INET;
590 addr.sin_port = htons(port);
591 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
593 if (connect(sock, (
struct sockaddr *)&addr,
sizeof(addr)) < 0)
595 gint saved_errno = WSAGetLastError();
596 gchar* message = g_strdup_printf(
"Failed to connect to IPC socket (127.0.0.1:%d)", port);
597 log_error(message, saved_errno);
599 socket_fd_close(sock);
607static void socket_init_win32(
void)
611 if (WSAStartup(MAKEWORD(2, 2), &wsadata) != NO_ERROR)
619static void handle_input_filename(
const gchar *buf)
621 gchar *utf8_filename, *locale_filename;
624 if (! g_utf8_validate(buf, -1,
NULL))
627 utf8_filename = g_strdup(buf);
632 if (g_str_has_suffix(locale_filename,
".geany"))
640 g_free(utf8_filename);
641 g_free(locale_filename);
645static gchar *build_document_list(
void)
647 GString *doc_list = g_string_new(
NULL);
654 g_string_append(doc_list,
filename);
655 g_string_append_c(doc_list,
'\n');
657 return g_string_free(doc_list, FALSE);
664 gchar buf[BUFFER_LENGTH];
666 struct sockaddr_in caddr;
667 socklen_t caddr_len =
sizeof(caddr);
668 GtkWidget *window = data;
669 gboolean popup = FALSE;
671 fd = g_io_channel_unix_get_fd(source);
672 sock = accept(fd, (
struct sockaddr *)&caddr, &caddr_len);
675 while (socket_fd_gets(sock, buf,
sizeof(buf)) != -1)
680 if (strncmp(buf,
"open", 4) == 0)
682 cl_options.readonly = strncmp(buf+4,
"ro", 2) == 0;
683 while (socket_fd_gets(sock, buf,
sizeof(buf)) != -1 && *buf !=
'.')
685 gsize buf_len = strlen(buf);
688 if (buf_len > 0 && buf[buf_len - 1] ==
'\n')
689 buf[buf_len - 1] =
'\0';
691 handle_input_filename(buf);
695 else if (strncmp(buf,
"doclist", 7) == 0)
697 gchar *doc_list = build_document_list();
698 if (!
EMPTY(doc_list))
699 socket_fd_write_all(sock, doc_list, strlen(doc_list));
701 socket_fd_write_all(sock,
"\3", 1);
704 else if (strncmp(buf,
"line", 4) == 0)
706 while (socket_fd_gets(sock, buf,
sizeof(buf)) != -1 && *buf !=
'.')
713 else if (strncmp(buf,
"column", 6) == 0)
715 while (socket_fd_gets(sock, buf,
sizeof(buf)) != -1 && *buf !=
'.')
723 else if (strncmp(buf,
"window", 6) == 0)
725 HWND hwnd = (HWND) gdk_win32_window_get_handle(gtk_widget_get_window(window));
726 socket_fd_write(sock, (gchar *)&hwnd,
sizeof(hwnd));
733#ifdef GDK_WINDOWING_X11
734 GdkWindow *x11_window = gtk_widget_get_window(window);
740 if (GDK_IS_X11_WINDOW(x11_window))
742 gdk_x11_window_set_user_time(x11_window, gdk_x11_get_server_time(x11_window));
745 gtk_window_present(GTK_WINDOW(window));
747 gdk_window_show(gtk_widget_get_window(window));
751 socket_fd_close(sock);
757static gint socket_fd_gets(gint fd, gchar *buf, gint len)
759 gchar *newline, *bp = buf;
766 if ((n = socket_fd_recv(fd, bp, len, MSG_PEEK)) <= 0)
768 if ((newline = memchr(bp,
'\n', n)) !=
NULL)
769 n = newline - bp + 1;
770 if ((n = socket_fd_read(fd, bp, n)) < 0)
774 }
while (! newline && len);
781static gint socket_fd_recv(gint fd, gchar *buf, gint len, gint flags)
783 if (socket_fd_check_io(fd, G_IO_IN) < 0)
786 return recv(fd, buf, len, flags);
790static gint socket_fd_read(gint fd, gchar *buf, gint len)
792 if (socket_fd_check_io(fd, G_IO_IN) < 0)
796 return recv(fd, buf, len, 0);
798 return read(fd, buf, len);
803static gint socket_fd_check_io(gint fd, GIOCondition cond)
805 struct timeval timeout;
816 flags = fcntl(fd, F_GETFL, 0);
819 log_error(
"fcntl() failed",
errno);
822 if ((flags & O_NONBLOCK) != 0)
828 FD_SET((SOCKET)fd, &fds);
835 select(fd + 1, &fds,
NULL,
NULL, &timeout);
839 select(fd + 1,
NULL, &fds,
NULL, &timeout);
842 if (FD_ISSET(fd, &fds))
854static gint socket_fd_write_all(gint fd,
const gchar *buf, gint len)
860 n = socket_fd_write(fd, buf, len);
872gint socket_fd_write(gint fd,
const gchar *buf, gint len)
874 if (socket_fd_check_io(fd, G_IO_OUT) < 0)
878 return send(fd, buf, len, 0);
880 return write(fd, buf, len);
void dialogs_show_msgbox(GtkMessageType type, const gchar *text,...)
Shows a message box of the type type with text.
File related dialogs, miscellaneous dialogs, font dialog.
Document related actions: new, save, open, etc.
#define DOC_FILENAME(doc)
Returns the filename of the document passed or GEANY_STRING_UNTITLED (e.g.
#define documents
Wraps GeanyData::documents_array so it can be used with C array syntax.
#define foreach_document(i)
Iterates all valid document indexes.
gchar * encodings_convert_to_utf8(const gchar *buffer, gssize size, gchar **used_encoding)
Tries to convert buffer into UTF-8 encoding and store the detected original encoding in used_encoding...
Encoding conversion and Byte Order Mark (BOM) handling.
void main_load_project_from_command_line(const gchar *locale_filename, gboolean use_session)
CommandLineOptions cl_options
gboolean main_handle_filename(const gchar *locale_filename)
gchar * main_get_argv_filename(const gchar *filename)
void geany_debug(gchar const *format,...)
Main program-related commands.
gboolean project_ask_close(void)
gint socket_finalize(void)
struct SocketInfo socket_info
gint socket_init(gint argc, gchar **argv, gushort socket_port)
gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpointer data)
gchar * configdir
User configuration directory, usually ~/.config/geany.
Defines internationalization macros.
gint utils_mkdir(const gchar *path, gboolean create_parent_dirs)
Creates a directory if it doesn't already exist.
gint utils_is_file_writable(const gchar *locale_filename)
gchar * utils_get_locale_from_utf8(const gchar *utf8_text)
Converts the given UTF-8 encoded string into locale encoding.
General utility functions, non-GTK related.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.