Wed, 03 Oct 2001 09:48:33 +0000
[gaim-migrate @ 2430]
boo-yah!
| 2416 | 1 | /* |
| 2 | * gaim | |
| 3 | * | |
| 4 | * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
| 5 | * | |
| 6 | * This program is free software; you can redistribute it and/or modify | |
| 7 | * it under the terms of the GNU General Public License as published by | |
| 8 | * the Free Software Foundation; either version 2 of the License, or | |
| 9 | * (at your option) any later version. | |
| 10 | * | |
| 11 | * This program is distributed in the hope that it will be useful, | |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | * GNU General Public License for more details. | |
| 15 | * | |
| 16 | * You should have received a copy of the GNU General Public License | |
| 17 | * along with this program; if not, write to the Free Software | |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | * | |
| 20 | */ | |
| 21 | ||
| 22 | #ifdef HAVE_CONFIG_H | |
| 23 | #include "config.h" | |
| 24 | #endif | |
| 25 | ||
| 26 | #include <glib.h> | |
| 27 | #include <stdio.h> | |
| 28 | #include <stdlib.h> | |
| 29 | #include <sys/types.h> | |
| 30 | #include <sys/socket.h> | |
| 31 | #include <sys/stat.h> | |
| 32 | #include <sys/un.h> | |
| 33 | #include <unistd.h> | |
| 34 | #include <errno.h> | |
| 35 | #include <signal.h> | |
| 36 | #include <getopt.h> | |
| 37 | ||
| 38 | #include "gaim.h" | |
| 39 | ||
| 40 | static gint UI_fd = -1; | |
| 41 | struct UI { | |
| 42 | GIOChannel *channel; | |
| 43 | guint inpa; | |
| 44 | }; | |
| 45 | GSList *uis = NULL; | |
| 46 | ||
| 47 | static gint gaim_recv(GIOChannel *source, guchar *buf, gint len) | |
| 48 | { | |
| 49 | gint total = 0; | |
| 50 | gint cur; | |
| 51 | ||
| 52 | while (total < len) { | |
| 53 | if (g_io_channel_read(source, buf + total, len - total, &cur) != G_IO_ERROR_NONE) | |
| 54 | return -1; | |
| 55 | if (cur == 0) | |
| 56 | return total; | |
| 57 | total += cur; | |
| 58 | } | |
| 59 | ||
| 60 | return total; | |
| 61 | } | |
| 62 | ||
| 63 | static gboolean UI_readable(GIOChannel *source, GIOCondition cond, gpointer data) | |
| 64 | { | |
| 65 | struct UI *ui = data; | |
| 66 | ||
| 67 | guchar buf[2] = {0, 0}; | |
| 68 | guint32 len; | |
| 69 | ||
| 70 | guchar *in; | |
| 71 | ||
| 72 | gushort type; | |
| 73 | ||
| 74 | /* buf[0] is to specify gaim, buf[1] is for protocol version */ | |
| 75 | if ((gaim_recv(source, buf, 2) != 2) || (buf[0] != 102) || (buf[1] != 1)) { | |
| 76 | debug_printf("UI has abandoned us! (%d %d)\n", buf[0], buf[1]); | |
| 77 | uis = g_slist_remove(uis, ui); | |
| 78 | g_io_channel_close(ui->channel); | |
| 79 | g_source_remove(ui->inpa); | |
| 80 | g_free(ui); | |
| 81 | return FALSE; | |
| 82 | } | |
| 83 | ||
| 84 | /* no byte order worries! this'll change if we go to TCP */ | |
| 85 | if (gaim_recv(source, (guchar *)&len, sizeof(len)) != sizeof(len)) { | |
| 86 | debug_printf("UI has abandoned us!\n"); | |
| 87 | uis = g_slist_remove(uis, ui); | |
| 88 | g_io_channel_close(ui->channel); | |
| 89 | g_source_remove(ui->inpa); | |
| 90 | g_free(ui); | |
| 91 | return FALSE; | |
| 92 | } | |
| 93 | ||
| 94 | in = g_new0(guchar, len + 1); | |
| 95 | gaim_recv(source, in, len); | |
| 96 | ||
| 97 | memcpy(&type, in, sizeof(type)); | |
| 98 | switch (type) { | |
| 99 | /* | |
| 100 | case CUI_TYPE_META: | |
| 101 | meta_handler(ui, in); | |
| 102 | break; | |
| 103 | case CUI_TYPE_PLUGIN: | |
| 104 | plugin_handler(ui, in); | |
| 105 | break; | |
| 106 | case CUI_TYPE_USER: | |
| 107 | user_handler(ui, in); | |
| 108 | break; | |
| 109 | case CUI_TYPE_CONN: | |
| 110 | conn_handler(ui, in); | |
| 111 | break; | |
| 112 | case CUI_TYPE_BUDDY: | |
| 113 | buddy_handler(ui, in); | |
| 114 | break; | |
| 115 | case CUI_TYPE_MESSAGE: | |
| 116 | message_handler(ui, in); | |
| 117 | break; | |
| 118 | case CUI_TYPE_CHAT: | |
| 119 | chat_handler(ui, in); | |
| 120 | break; | |
| 121 | */ | |
| 122 | default: | |
| 123 | debug_printf("unhandled type %d\n", type); | |
| 124 | break; | |
| 125 | } | |
| 126 | ||
| 127 | g_free(in); | |
| 128 | return TRUE; | |
| 129 | } | |
| 130 | ||
| 131 | static gboolean socket_readable(GIOChannel *source, GIOCondition cond, gpointer data) | |
| 132 | { | |
| 133 | struct sockaddr_un saddr; | |
| 134 | gint len; | |
| 135 | gint fd; | |
| 136 | ||
| 137 | struct UI *ui; | |
| 138 | ||
| 139 | if ((fd = accept(UI_fd, (struct sockaddr *)&saddr, &len)) == -1) | |
| 140 | return FALSE; | |
| 141 | ||
| 142 | ui = g_new0(struct UI, 1); | |
| 143 | uis = g_slist_append(uis, ui); | |
| 144 | ||
| 145 | ui->channel = g_io_channel_unix_new(fd); | |
| 146 | ui->inpa = g_io_add_watch(ui->channel, G_IO_IN | G_IO_HUP | G_IO_ERR, UI_readable, ui); | |
| 147 | g_io_channel_unref(ui->channel); | |
| 148 | ||
| 149 | debug_printf("got one\n"); | |
| 150 | return TRUE; | |
| 151 | } | |
| 152 | ||
| 153 | static gint open_socket() | |
| 154 | { | |
| 155 | struct sockaddr_un saddr; | |
| 156 | gint fd; | |
| 157 | ||
| 158 | if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) { | |
| 159 | umask(0177); | |
| 160 | saddr.sun_family = AF_UNIX; | |
| 161 | g_snprintf(saddr.sun_path, 108, "%s/gaim_%s.%d", | |
| 162 | g_get_tmp_dir(), g_get_user_name(), getpid()); | |
| 163 | if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) != -1) | |
| 164 | listen(fd, 100); | |
| 165 | else | |
| 166 | g_log(NULL, G_LOG_LEVEL_CRITICAL, | |
| 167 | "Failed to assign %s to a socket (Error: %s)", | |
| 168 | saddr.sun_path, strerror(errno)); | |
| 169 | } else | |
| 170 | g_log(NULL, G_LOG_LEVEL_CRITICAL, "Unable to open socket: %s", strerror(errno)); | |
| 171 | return fd; | |
| 172 | } | |
| 173 | ||
| 174 | int core_main() | |
| 175 | { | |
| 176 | /* | |
| 177 | GMainLoop *loop; | |
| 178 | */ | |
| 179 | ||
| 180 | #if DEVEL | |
| 181 | GIOChannel *channel; | |
| 182 | ||
| 183 | UI_fd = open_socket(); | |
| 184 | if (UI_fd < 0) | |
| 185 | return 1; | |
| 186 | ||
| 187 | channel = g_io_channel_unix_new(UI_fd); | |
| 188 | g_io_add_watch(channel, G_IO_IN, socket_readable, NULL); | |
| 189 | g_io_channel_unref(channel); | |
| 190 | #endif | |
| 191 | ||
| 192 | /* | |
| 193 | loop = g_main_new(TRUE); | |
| 194 | g_main_run(loop); | |
| 195 | */ | |
| 196 | ||
| 197 | return 0; | |
| 198 | } | |
| 199 | ||
| 200 | void core_quit() | |
| 201 | { | |
| 202 | #ifdef DEVEL | |
| 203 | char buf[1024]; | |
| 204 | close(UI_fd); | |
| 205 | sprintf(buf, "%s/gaim_%s.%d", g_get_tmp_dir(), g_get_user_name(), getpid()); | |
| 206 | unlink(buf); | |
| 207 | #endif | |
| 208 | } |