From a605c88ba3a0180d5783722c2c877f2ab8b01659 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Wed, 1 Apr 2015 22:43:44 -0300 Subject: Rewritten as a client-server application, similar to urxvt{d,c}. --- Td.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 Td.c (limited to 'Td.c') diff --git a/Td.c b/Td.c new file mode 100644 index 0000000..22a847b --- /dev/null +++ b/Td.c @@ -0,0 +1,142 @@ +/* + * Td.c + * T daemon. Saves resources by uniting all T windows under the same process. + * + * This file is part of T. + * + * T is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * T is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * T. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "T.h" + +#define MSGBUF_MAXLEN 64 + +static int bind_socket(); +static TMessage handle_message(TMessage msg); +static gboolean socket_g_io_watch(GIOChannel *source, GIOCondition condition, gpointer data); + +static int +bind_socket() +{ + struct sockaddr_un sock_addr; + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sun_family = AF_UNIX; + strncpy(sock_addr.sun_path, SOCKPATH, sizeof(sock_addr.sun_path) - 1); + + /* Remove old socket */ + if (!access(sock_addr.sun_path, F_OK) && unlink(sock_addr.sun_path) < 0) + err("Failed to remove socket file at " SOCKPATH, EXIT_FAILURE); + if (!access(CONFIG_SOCKDIR, F_OK) && rmdir(CONFIG_SOCKDIR) < 0) + err("Failed to remove socket directory at " CONFIG_SOCKDIR, EXIT_FAILURE); + + /* Create a new directory */ + if (mkdir(CONFIG_SOCKDIR, S_IRWXU) < 0) + err("Failed to create socket directory at " CONFIG_SOCKDIR, EXIT_FAILURE); + + int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock_fd < 0) + err("Failed to create socket", EXIT_FAILURE); + + if (bind(sock_fd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0) + err("Failed to bind the socket to the file at " SOCKPATH, EXIT_FAILURE); + + return sock_fd; +} + +static TMessage +handle_message(TMessage msg) +{ + switch (msg) { + case MSG_NEWWIN: + new_window(); + return MSG_OK; + + case MSG_EXIT: + if (num_open_windows() == 0) { + gtk_main_quit(); + return MSG_OK; + } + return MSG_ERROR; + + default: + return MSG_ERROR; + } +} + +static gboolean +socket_g_io_watch(GIOChannel *source, GIOCondition condition, gpointer data) +{ + int sock_fd = g_io_channel_unix_get_fd(source); + int client_fd = accept(sock_fd, NULL, NULL); + if (client_fd < 0) { + wrn("accept() failed"); + return TRUE; + } + + TMessage msg; + int len = recv(client_fd, &msg, sizeof(msg), 0); + if (len < 0) { + wrn("recv() failed"); + goto socket_g_io_watch_cleanup; + } + + msg = handle_message(msg); + write(client_fd, &msg, sizeof(msg)); + +socket_g_io_watch_cleanup: + close(client_fd); + return TRUE; +} + +int +main(int argc, char *argv[]) +{ + int sock_fd; + + gtk_init(&argc, &argv); + + sock_fd = bind_socket(); + if (listen(sock_fd, SOMAXCONN) < 0) + err("Failed to listen to socket", EXIT_SUCCESS); + + /* poll the socket in the main loop */ + GIOChannel *sock_chan = g_io_channel_unix_new(sock_fd); + g_io_add_watch(sock_chan, G_IO_IN, socket_g_io_watch, NULL); + + gtk_main(); + + /* clean up */ + close(sock_fd); + unlink(SOCKPATH); + + return EXIT_SUCCESS; +} -- cgit v1.2.3