Mercurial > pidgin
diff src/core.c @ 5859:022786c7ab53
[gaim-migrate @ 6290]
CUI is gone, long live gaim-remote! The old CUI functionality, which was
for remote-controlling gaim, is now a Core Plugin, so any future UI
(including the current, normal gaim gtk UI) can be remote-controlled.
Applications will soon be able to link against the library and header files
and provide their own remote-control of gaim, but why bother? :) If you
use gaim-remote, make sure to load the new plugin. It won't auto-load.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Sat, 14 Jun 2003 06:06:40 +0000 |
parents | 86456ec3ca25 |
children | 059d95c67cda |
line wrap: on
line diff
--- a/src/core.c Fri Jun 13 23:49:26 2003 +0000 +++ b/src/core.c Sat Jun 14 06:06:40 2003 +0000 @@ -1,7 +1,6 @@ /* * gaim * - * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,521 +27,4 @@ #include <stdlib.h> #include <sys/types.h> -#ifdef _WIN32 -#include <winsock.h> -#include <io.h> -#else -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#endif -#include <sys/stat.h> -#include <errno.h> -#include <signal.h> -#include <getopt.h> -#include <stdarg.h> -#include <string.h> - -#include "gaim.h" -#include "gaim-socket.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -#ifndef _WIN32 -static gint UI_fd = -1; -#endif -int gaim_session = 0; -GSList *uis = NULL; - -static guchar *UI_build(guint32 *len, guchar type, guchar subtype, va_list args) -{ - guchar *buffer; - guint32 pos; - int size; - void *data; - - *len = sizeof(guchar) * 2 + 4; - buffer = g_malloc(*len); - pos = 0; - - memcpy(buffer + pos, &type, sizeof(type)); pos += sizeof(type); - memcpy(buffer + pos, &subtype, sizeof(subtype)); pos += sizeof(subtype); - - /* we come back and do size last */ - pos += 4; - - size = va_arg(args, int); - while (size != -1) { - *len += size; - buffer = g_realloc(buffer, *len); - - data = va_arg(args, void *); - memcpy(buffer + pos, data, size); - pos += size; - - size = va_arg(args, int); - } - - pos -= sizeof(guchar) * 2 + 4; - - /* now we do size */ - memcpy(buffer + sizeof(guchar) * 2, &pos, 4); - - return buffer; -} - -gint UI_write(struct UI *ui, guchar *data, gint len) -{ - GError *error = NULL; - gint sent; - /* we'll let the write silently fail because the read will pick it up as dead */ - g_io_channel_write_chars(ui->channel, data, len, &sent, &error); - if (error) - g_error_free(error); - return sent; -} - -void UI_build_write(struct UI *ui, guchar type, guchar subtype, ...) -{ - va_list ap; - gchar *data; - guint32 len; - - va_start(ap, subtype); - data = UI_build(&len, type, subtype, ap); - va_end(ap); - - UI_write(ui, data, len); - - g_free(data); -} - -void UI_broadcast(guchar *data, gint len) -{ - GSList *u = uis; - while (u) { - struct UI *ui = u->data; - UI_write(ui, data, len); - u = u->next; - } -} - -void UI_build_broadcast(guchar type, guchar subtype, ...) -{ - va_list ap; - gchar *data; - guint32 len; - - if (!uis) - return; - - va_start(ap, subtype); - data = UI_build(&len, type, subtype, ap); - va_end(ap); - - UI_broadcast(data, len); - - g_free(data); -} - -#ifndef _WIN32 -static void meta_handler(struct UI *ui, guchar subtype, guchar *data) -{ - struct gaim_cui_packet *p; - GError *error = NULL; - switch (subtype) { - case CUI_META_LIST: - break; - case CUI_META_QUIT: - while (uis) { - ui = uis->data; - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - g_source_remove(ui->inpa); - g_free(ui); - } - do_quit(); - break; - case CUI_META_DETACH: - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - g_source_remove(ui->inpa); - g_free(ui); - break; - case CUI_META_PING: - p = cui_packet_new(CUI_TYPE_META, CUI_META_ACK); - cui_send_packet(g_io_channel_unix_get_fd(ui->channel), p); - cui_packet_free(p); - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled meta subtype %d\n", subtype); - break; - } - - if(error) - g_error_free(error); -} - -static void plugin_handler(struct UI *ui, guchar subtype, guchar *data) -{ -#ifdef GAIM_PLUGINS - guint id; - GaimPlugin *p; - - switch (subtype) { - /* - case CUI_PLUGIN_LIST: - break; - */ - case CUI_PLUGIN_LOAD: - gaim_plugin_load(gaim_plugin_probe(data)); - break; - case CUI_PLUGIN_UNLOAD: - memcpy(&id, data, sizeof(id)); - p = g_list_nth_data(gaim_plugins_get_loaded(), id); - if (p) { - gaim_plugin_unload(p); - } - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled plugin subtype %d\n", subtype); - break; - } -#endif -} - -static void user_handler(struct UI *ui, guchar subtype, guchar *data) -{ - guint id; - GaimAccount *account; - - switch (subtype) { - /* - case CUI_USER_LIST: - break; - case CUI_USER_ADD: - break; - case CUI_USER_REMOVE: - break; - case CUI_USER_MODIFY: - break; - */ - case CUI_USER_SIGNON: - if (!data) - return; - memcpy(&id, data, sizeof(id)); - account = g_list_nth_data(gaim_accounts_get_all(), id); - if (account) - serv_login(account); - /* don't need to do anything here because the UI will get updates from other handlers */ - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled user subtype %d\n", subtype); - break; - } -} - -static void message_handler(struct UI *ui, guchar subtype, guchar *data) -{ - switch (subtype) { - case CUI_MESSAGE_LIST: - break; - case CUI_MESSAGE_SEND: - if (!data) - return; - { - guint id; - GaimConnection *gc; - guint len; - char *who, *msg; - gint flags; - int pos = 0; - - memcpy(&id, data + pos, sizeof(id)); - pos += sizeof(id); - gc = g_list_nth_data(gaim_connections_get_all(), id); - if (!gc) - return; - - memcpy(&len, data + pos, sizeof(len)); - pos += sizeof(len); - who = g_strndup(data + pos, len + 1); - pos += len; - - memcpy(&len, data + pos, sizeof(len)); - pos += sizeof(len); - msg = g_strndup(data + pos, len + 1); - pos += len; - - memcpy(&flags, data + pos, sizeof(flags)); - serv_send_im(gc, who, msg, -1, flags); - - g_free(who); - g_free(msg); - } - break; - case CUI_MESSAGE_RECV: - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled message subtype %d\n", subtype); - break; - } -} - -static gint gaim_recv(GIOChannel *source, guchar *buf, gint len) -{ - gint total = 0; - gint cur; - - GError *error = NULL; - - while (total < len) { - if (g_io_channel_read_chars(source, buf + total, len - total, &cur, &error) != G_IO_STATUS_NORMAL) { - if (error) - g_error_free(error); - return -1; - } - if (cur == 0) - return total; - total += cur; - } - - return total; -} - -static void remote_handler(struct UI *ui, guchar subtype, guchar *data, int len) -{ - const char *resp; - char *send; - switch (subtype) { - case CUI_REMOTE_CONNECTIONS: - break; - case CUI_REMOTE_URI: - send = g_malloc(len + 1); - memcpy(send, data, len); - send[len] = 0; - resp = handle_uri(send); - g_free(send); - /* report error */ - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled remote subtype %d\n", subtype); - break; - } -} - -static gboolean UI_readable(GIOChannel *source, GIOCondition cond, gpointer data) -{ - struct UI *ui = data; - - guchar type; - guchar subtype; - guint32 len; - - GError *error = NULL; - - guchar *in; - - /* no byte order worries! this'll change if we go to TCP */ - if (gaim_recv(source, &type, sizeof(type)) != sizeof(type)) { - gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n"); - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - if(error) { - g_error_free(error); - error = NULL; - } - g_source_remove(ui->inpa); - g_free(ui); - return FALSE; - } - - if (gaim_recv(source, &subtype, sizeof(subtype)) != sizeof(subtype)) { - gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n"); - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - if(error) { - g_error_free(error); - error = NULL; - } - g_source_remove(ui->inpa); - g_free(ui); - return FALSE; - } - - if (gaim_recv(source, (guchar *)&len, sizeof(len)) != sizeof(len)) { - gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n"); - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - if(error) { - g_error_free(error); - error = NULL; - } - g_source_remove(ui->inpa); - g_free(ui); - return FALSE; - } - - if (len) { - in = g_new0(guchar, len); - if (gaim_recv(source, in, len) != len) { - gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n"); - uis = g_slist_remove(uis, ui); - g_io_channel_shutdown(ui->channel, TRUE, &error); - if(error) { - g_error_free(error); - error = NULL; - } - g_source_remove(ui->inpa); - g_free(ui); - return FALSE; - } - } else - in = NULL; - - switch (type) { - case CUI_TYPE_META: - meta_handler(ui, subtype, in); - break; - case CUI_TYPE_PLUGIN: - plugin_handler(ui, subtype, in); - break; - case CUI_TYPE_USER: - user_handler(ui, subtype, in); - break; - /* - case CUI_TYPE_CONN: - conn_handler(ui, subtype, in); - break; - case CUI_TYPE_BUDDY: - buddy_handler(ui, subtype, in); - break; - */ - case CUI_TYPE_MESSAGE: - message_handler(ui, subtype, in); - break; - /* - case CUI_TYPE_CHAT: - chat_handler(ui, subtype, in); - break; - */ - case CUI_TYPE_REMOTE: - remote_handler(ui, subtype, in, len); - break; - default: - gaim_debug(GAIM_DEBUG_WARNING, "cui", - "Unhandled type %d\n", type); - break; - } - - if (in) - g_free(in); - return TRUE; -} - -static gboolean socket_readable(GIOChannel *source, GIOCondition cond, gpointer data) -{ - struct sockaddr_un saddr; - gint len = sizeof(saddr); - gint fd; - - struct UI *ui; - - if ((fd = accept(UI_fd, (struct sockaddr *)&saddr, &len)) == -1) - return FALSE; - - ui = g_new0(struct UI, 1); - uis = g_slist_append(uis, ui); - - ui->channel = g_io_channel_unix_new(fd); - ui->inpa = g_io_add_watch(ui->channel, G_IO_IN | G_IO_HUP | G_IO_ERR, UI_readable, ui); - g_io_channel_unref(ui->channel); - - gaim_debug(GAIM_DEBUG_MISC, "cui", "Got one\n"); - return TRUE; -} - -static gint open_socket() -{ - struct sockaddr_un saddr; - gint fd; - - while (gaim_session_exists(gaim_session)) - gaim_session++; - - gaim_debug(GAIM_DEBUG_MISC, "cui", "Session: %d\n", gaim_session); - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) { - mode_t m = umask(0177); - saddr.sun_family = AF_UNIX; - - g_snprintf(saddr.sun_path, sizeof(saddr.sun_path), "%s" G_DIR_SEPARATOR_S "gaim_%s.%d", - g_get_tmp_dir(), g_get_user_name(), gaim_session); - if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) != -1) - listen(fd, 100); - else { - g_log(NULL, G_LOG_LEVEL_CRITICAL, - "Failed to assign %s to a socket (Error: %s)", - saddr.sun_path, strerror(errno)); - return -1; - } - umask(m); - } else - g_log(NULL, G_LOG_LEVEL_CRITICAL, "Unable to open socket: %s", strerror(errno)); - return fd; -} -#endif /*! _WIN32*/ - -int core_main() -{ - /* - GMainLoop *loop; - */ -#ifndef _WIN32 - GIOChannel *channel; -#endif - - gaim_set_blist(gaim_blist_new()); - gaim_blist_load(); - -#ifndef _WIN32 - - UI_fd = open_socket(); - if (UI_fd < 0) - return 1; - - channel = g_io_channel_unix_new(UI_fd); - g_io_add_watch(channel, G_IO_IN, socket_readable, NULL); - g_io_channel_unref(channel); -#endif - - /* - loop = g_main_new(TRUE); - g_main_run(loop); - */ - - return 0; -} - -void core_quit() -{ - /* don't save prefs after plugins are gone... */ -#ifndef _WIN32 - char buf[1024]; - close(UI_fd); - snprintf(buf, 1024, "%s" G_DIR_SEPARATOR_S "gaim_%s.%d", - g_get_tmp_dir(), g_get_user_name(), gaim_session); - - unlink(buf); - - gaim_debug(GAIM_DEBUG_MISC, "core", "Removed core\n"); -#endif -}