Bug with syncronous connects

"A. Craig West" <[email protected]> Wed, 24 Mar 2004 06:00:00 -0500 (EST)
Newsgroups gmane.network.everybuddy.devel
Message-ID <[email protected]>
We had some non-re-entrant code being called in a re-entrant manner, which was
causing all manner of issues with connecting and disconnecting. The fix is
extensive, though. I included my new ebgui directory which contains some
functions for reading and writing to a gui connection, and can be used in
the GUI's. I've included a patch for the eb-console to use it instead...

(I'm not sure I got the formatting right for the two added files...)

--------Patch Begins--------
Index: ebgui/ebgui.c
===================================================================
+++ ebgui/ebgui.c	2004-03-24 03:33:56.000000000 -0500
@@ -0,0 +1,180 @@
+/***************************************************************************
+                     ebgui.c - Global utility functions
+                             -------------------
+                     (C) 2002-2004 by the Everybuddy team
+                            www.everybuddy.com
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ebgui.h"
+
+// EB gui utility functions
+
+int eb_read_fully(int fd, void * data, int len)
+{
+  int pos=0;
+  unsigned char * d=(unsigned char *)data;
+  
+  while(pos<len)
+  {
+    int result=read(fd, d+pos, len-pos);
+    if(result==0) { printf("Read %d chars\n", pos); return pos; }
+    if(result<0) { printf("Whu-oh\n"); return -1; }
+    pos+=result;
+    if(pos<len) { printf("Partial read (%d/%d bytes)\n", pos, len); }
+  }
+  
+  return pos;
+}
+
+int eb_write_fully(int fd, void * data, int len)
+{
+  int pos=0;
+  unsigned char * d=(unsigned char *)data;
+  
+  while(pos<len)
+  {
+    int result=write(fd, d+pos, len-pos);
+    if(result==0) { printf("Wrote %d chars\n", pos); return pos; }
+    if(result<0) { printf("Whu-oh\n"); return -1; }
+    pos+=result;
+    if(pos<len) { printf("Partial write (%d/%d bytes)\n", pos, len); }
+  }
+  
+  return pos;
+}
+
+int eb_write_gui_message(int fd, char ** params, int num_params)
+{
+  int a, lengths[256];
+
+  for (a=0; a<num_params; a++)
+  {
+    lengths[a]=strlen(params[a]);
+  }
+
+  return eb_write_gui_data(fd, (void **)params, lengths, num_params);
+}
+
+int eb_write_gui_data(int fd, void ** params, int * lengths, int num_params)
+{
+  unsigned char c=num_params;
+  int a, total_len, rval;
+  unsigned char *buffer, *ptr;
+
+  /* total packet length is one byte for the number of params, + 2 bytes for
+     each param length, + the length of each param */
+  total_len = 1;
+  for(a=0; a<num_params; a++)
+  {
+    total_len += (lengths[a] + 2);
+  }
+
+  /* Now allocate a big enough buffer */
+  buffer = (unsigned char *)malloc(total_len);
+  if (buffer == NULL)
+    return -1;
+
+  ptr = buffer;
+
+  *(ptr++) = c;
+
+  for(a=0; a<num_params; a++)
+  {
+    int len=lengths[a];
+    c=len/256;
+    *(ptr++) = c;
+    c=len%256;
+    *(ptr++) = c;
+
+    memcpy(ptr, params[a], len);
+    ptr += len;
+  }
+  rval = eb_write_fully(fd, buffer, total_len);
+
+  usleep(100);
+  free(buffer);
+  buffer = ptr = NULL;
+
+  if (rval < 0)
+    return rval;
+
+  return 0;
+}
+
+char ** eb_read_gui_message(int fd, int * num_params)
+{
+  unsigned char c, c2[2];
+  char ** params;
+  int a;
+
+  if(eb_read_fully(fd, &c, 1)<1)
+    return NULL;
+
+  *num_params=c;
+
+  params=(char **)malloc((*num_params+1) * sizeof(char *));
+  if (params == NULL)
+    return NULL;
+
+  for(a=0; a<*num_params; a++)
+  {
+    int size;
+
+    if(eb_read_fully(fd, c2, 2)<2)
+    {
+      if (a > 0)
+	eb_free_gui_message(params, a);
+      return NULL;
+    }
+    size=c2[0]*256+c2[1];
+
+    params[a]=(char *)malloc(size+1);
+    if (params[a] == NULL)
+    {
+      if (a > 0)
+	eb_free_gui_message(params, a);
+      return NULL;
+    }
+
+    if(eb_read_fully(fd, params[a], size)<size)
+    {
+      eb_free_gui_message(params, a+1);
+      return NULL;
+    }
+    params[a][size]='\0';
+  }
+  params[a]=NULL;
+
+  return params;
+}
+
+/* if num_params <= 0 then just free until the first NULL */
+void eb_free_gui_message(char ** params, int num_params)
+{
+  int a;
+  for(a=0; (a <= 0 || a < num_params) && params[a]!=NULL; a++)
+  {
+    if (params[a])
+    {
+      free(params[a]);
+      params[a]=NULL;
+    }
+  }
+  free(params);
+  params=NULL;
+}
+
Index: ebgui/ebgui.c
===================================================================
+++ ebgui/ebgui.h	2004-03-24 03:32:58.000000000 -0500
@@ -0,0 +1,37 @@
+/***************************************************************************
+                       ebgui.h - Global utility functions
+                             -------------------
+                     (C) 2002-2004 by the Everybuddy team
+                            www.everybuddy.com
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef __EBGUI_H__
+#define __EBGUI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// EB gui utility functions
+
+int eb_read_fully(int fd, void * data, int len);
+int eb_write_fully(int fd, void * data, int len);
+int eb_write_gui_message(int fd, char ** params, int num_params);
+int eb_write_gui_data(int fd, void ** params, int * lengths, int num_params);
+char ** eb_read_gui_message(int fd, int * num_params);
+void eb_free_gui_message(char ** params, int num_params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __EBGUI_H__
Index: core/src/util.c
===================================================================
--- core/src/util.c	(revision 311)
+++ core/src/util.c	(working copy)
@@ -34,6 +34,7 @@
 #include "util.h"
 #include "globals.h"
 #include "message_parse.h"
+#include "../ebgui/ebgui.h"
 
 
 // EB global utility functions
@@ -642,7 +643,7 @@
     if(!eb_holding_messages)
     { return; }
 
-    eb_gui_get_held_messages(NULL);
+    eb_gui_get_held_messages(NULL, NULL, 0);
     eb_holding_messages=0;
     eb_gui_broadcast(notify_cmd, 2);
   } else {
@@ -656,36 +657,12 @@
 
 int eread(int fd, void * data, int len)
 {
-  int pos=0;
-  unsigned char * d=(unsigned char *)data;
-  
-  while(pos<len)
-  {
-    int result=read(fd, d+pos, len-pos);
-    if(result==0) { printf("Read %d chars\n", pos); return pos; }
-    if(result<0) { printf("Whu-oh\n"); return -1; }
-    pos+=result;
-    if(pos<len) { printf("Partial read (%d/%d bytes)\n", pos, len); }
-  }
-  
-  return pos;
+  return eb_read_fully(fd, data, len);
 }
 
 int ewrite(int fd, void * data, int len)
 {
-  int pos=0;
-  unsigned char * d=(unsigned char *)data;
-  
-  while(pos<len)
-  {
-    int result=write(fd, d+pos, len-pos);
-    if(result==0) { printf("Wrote %d chars\n", pos); return pos; }
-    if(result<0) { printf("Whu-oh\n"); return -1; }
-    pos+=result;
-    if(pos<len) { printf("Partial write (%d/%d bytes)\n", pos, len); }
-  }
-  
-  return pos;
+  return eb_write_fully(fd, data, len);
 }
 
 char * eb_get_filename(char * subdir)
Index: core/src/proxy.c
===================================================================
--- core/src/proxy.c	(revision 311)
+++ core/src/proxy.c	(working copy)
@@ -109,7 +109,7 @@
     return -1;
   }
 
-  //fcntl(s, F_SETFL, O_NONBLOCK);
+  fcntl(s, F_SETFL, O_NONBLOCK);
 
   if (connect(s,(struct sockaddr *)&sa,sizeof sa) >= 0) { /* connect */
     // wow, instant response! Cool beans...
Index: core/src/gui_comms.c
===================================================================
--- core/src/gui_comms.c	(revision 313)
+++ core/src/gui_comms.c	(working copy)
@@ -45,6 +45,7 @@
 #include "html.h"
 #include "message_parse.h"
 #include "stream.h"
+#include "../ebgui/ebgui.h"
 
 // Defined as extern in globals.h:
 char * away_msg=NULL;
@@ -115,58 +116,58 @@
 
 void eb_lose_gui(eb_gui * gui);
 void eb_gui_welcome(eb_gui * gui);
-void eb_gui_incoming_command(eb_gui * gui);
+void eb_gui_incoming_command(eb_gui * gui, char ** params, int num_params);
 void eb_gui_incoming(void *data, int source, eb_input_condition condition);
 void eb_gui_connect(void *data, int source, eb_input_condition condition);
 int eb_gui_socket(int * port);
 
-void eb_gui_get_data(eb_gui * gui);
-void eb_gui_put_data(eb_gui * gui);
+void eb_gui_get_data(eb_gui * gui, char ** params, int num_params);
+void eb_gui_put_data(eb_gui * gui, char ** params, int num_params);
 eb_registry_key * eb_gui_data_key(char ** params, int len);
 
-void eb_gui_list_services(eb_gui * gui);
-void eb_gui_list_actions(eb_gui * gui);
-void eb_gui_perform_action(eb_gui * gui);
+void eb_gui_list_services(eb_gui * gui, char ** params, int num_params);
+void eb_gui_list_actions(eb_gui * gui, char ** params, int num_params);
+void eb_gui_perform_action(eb_gui * gui, char ** params, int num_params);
 
 void eb_gui_local_account_update(eb_gui * gui, eb_local_account * acc);
 
-void eb_gui_ignore(eb_gui * gui);
-void eb_gui_unignore(eb_gui * gui);
+void eb_gui_ignore(eb_gui * gui, char ** params, int num_params);
+void eb_gui_unignore(eb_gui * gui, char ** params, int num_params);
 
 void eb_gui_dialog_send(eb_gui *, eb_dialog * d);
-void eb_gui_set_state(eb_gui * gui);
-void eb_gui_add_group(eb_gui * gui);
-void eb_gui_add_contact(eb_gui * gui);
-void eb_gui_add_account(eb_gui * gui);
-void eb_gui_rename_contact(eb_gui * gui);
-void eb_gui_move_contact(eb_gui * gui);
-void eb_gui_move_account(eb_gui * gui);
-void eb_gui_del_group(eb_gui * gui);
-void eb_gui_del_contact(eb_gui * gui);
-void eb_gui_del_account(eb_gui * gui);
-void eb_gui_add_local_account(eb_gui * gui);
-void eb_gui_del_local_account(eb_gui * gui);
+void eb_gui_set_state(eb_gui * gui, char ** params, int num_params);
+void eb_gui_add_group(eb_gui * gui, char ** params, int num_params);
+void eb_gui_add_contact(eb_gui * gui, char ** params, int num_params);
+void eb_gui_add_account(eb_gui * gui, char ** params, int num_params);
+void eb_gui_rename_contact(eb_gui * gui, char ** params, int num_params);
+void eb_gui_move_contact(eb_gui * gui, char ** params, int num_params);
+void eb_gui_move_account(eb_gui * gui, char ** params, int num_params);
+void eb_gui_del_group(eb_gui * gui, char ** params, int num_params);
+void eb_gui_del_contact(eb_gui * gui, char ** params, int num_params);
+void eb_gui_del_account(eb_gui * gui, char ** params, int num_params);
+void eb_gui_add_local_account(eb_gui * gui, char ** params, int num_params);
+void eb_gui_del_local_account(eb_gui * gui, char ** params, int num_params);
 
-void eb_gui_list_pref_page(eb_gui * gui);
-void eb_gui_set_pref_value(eb_gui * gui);
+void eb_gui_list_pref_page(eb_gui * gui, char ** params, int num_params);
+void eb_gui_set_pref_value(eb_gui * gui, char ** params, int num_params);
 
 void eb_gui_buddy_login(eb_gui * gui, eb_account * acc);
 void eb_gui_buddy_update(eb_gui * gui, eb_account * acc);
 void eb_gui_buddy_logout(eb_gui * gui, eb_account * acc);
 
-void eb_gui_set_away(eb_gui * gui);
-void eb_gui_unset_away(eb_gui * gui);
+void eb_gui_set_away(eb_gui * gui, char ** params, int num_params);
+void eb_gui_unset_away(eb_gui * gui, char ** params, int num_params);
 
-void eb_gui_hold_messages(eb_gui * gui);
-void eb_gui_get_held_messages(eb_gui * gui);
+void eb_gui_hold_messages(eb_gui * gui, char ** params, int num_params);
+void eb_gui_get_held_messages(eb_gui * gui, char ** params, int num_params);
 
-void eb_gui_request_group_join(eb_gui * gui);
-void eb_gui_group_close(eb_gui * gui);
-void eb_gui_group_hide(eb_gui * gui);
-void eb_gui_group_invite(eb_gui * gui);
-void eb_gui_group_send(eb_gui * gui);
+void eb_gui_request_group_join(eb_gui * gui, char ** params, int num_params);
+void eb_gui_group_close(eb_gui * gui, char ** params, int num_params);
+void eb_gui_group_hide(eb_gui * gui, char ** params, int num_params);
+void eb_gui_group_invite(eb_gui * gui, char ** params, int num_params);
+void eb_gui_group_send(eb_gui * gui, char ** params, int num_params);
 
-void eb_gui_get_stream(eb_gui * gui);
+void eb_gui_get_stream(eb_gui * gui, char ** params, int num_params);
 
 int eb_gui_socket(int * port)
 {
@@ -273,7 +274,7 @@
     gui->num_params=c;
     gui->params_arrived=0;
     gui->params=(char **)malloc(c*sizeof(char *));
-  } else {
+  } else if (gui->params_arrived < gui->num_params) {
     unsigned char c[2];
     int size;
     char * s;
@@ -301,16 +302,19 @@
 
     if(gui->params_arrived==gui->num_params)
     {
-      eb_gui_incoming_command(gui);
-      for(a=0; a<gui->num_params; a++)
-      {
-        if(gui->params[a]!=NULL)
-        { free(gui->params[a]); gui->params[a]=NULL; }
-      }
+      char ** params = gui->params;
+      int num_params = gui->num_params;
+      gui->params = NULL;
       gui->num_params=0;
       gui->params_arrived=0;
-      free(gui->params);
-      gui->params=NULL;
+      eb_gui_incoming_command(gui, params, num_params);
+      for(a=0; a<num_params; a++)
+      {
+        if(params[a]!=NULL)
+        { free(params[a]); params[a]=NULL; }
+      }
+      free(params);
+      params=NULL;
     }
   }
 }
@@ -346,140 +350,140 @@
   }
 }
 
-void eb_gui_incoming_command(eb_gui * gui)
+void eb_gui_incoming_command(eb_gui * gui, char ** params, int num_params)
 {
-  void (*action_func)(eb_gui *);
+  void (*action_func)(eb_gui *, char** params, int num_params);
   int min_params=0;
 
   action_func=NULL;
 
-  if(gui->num_params==0)
+  if(num_params==0)
   {
     eb_debug(DBG_CORE, "GUI SENT EMPTY COMMAND!\n");
     return;
   }
 
-  if(!strcmp(gui->params[0], "get_data"))
+  if(!strcmp(params[0], "get_data"))
   {
     action_func=eb_gui_get_data;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "put_data")) {
+  } else if (!strcmp(params[0], "put_data")) {
     action_func=eb_gui_put_data;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "list_contacts")) {
+  } else if (!strcmp(params[0], "list_contacts")) {
     action_func=eb_gui_list_contacts;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "list_local_accounts")) {
+  } else if (!strcmp(params[0], "list_local_accounts")) {
     action_func=eb_gui_list_accounts;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "list_services")) {
+  } else if (!strcmp(params[0], "list_services")) {
     action_func=eb_gui_list_services;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "message_send")) {
+  } else if (!strcmp(params[0], "message_send")) {
     action_func=eb_gui_send_message;
     min_params=6;
-  } else if (!strcmp(gui->params[0], "list_actions")) {
+  } else if (!strcmp(params[0], "list_actions")) {
     action_func=eb_gui_list_actions;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "perform_action")) {
+  } else if (!strcmp(params[0], "perform_action")) {
     action_func=eb_gui_perform_action;
     min_params=3; // sometimes more...
-  } else if (!strcmp(gui->params[0], "resolve_dialog")) {
+  } else if (!strcmp(params[0], "resolve_dialog")) {
     action_func=eb_gui_resolve_dialog;
     min_params=2; // also sometimes more
-  } else if (!strcmp(gui->params[0], "sign_on_all")) {
+  } else if (!strcmp(params[0], "sign_on_all")) {
     eb_sign_on_all();
     return;
-  } else if (!strcmp(gui->params[0], "sign_off_all")) {
+  } else if (!strcmp(params[0], "sign_off_all")) {
     eb_sign_off_all();
     return;
-  } else if (!strcmp(gui->params[0], "set_local_account_status")) {
+  } else if (!strcmp(params[0], "set_local_account_status")) {
     action_func=eb_gui_set_state;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "join_group_chat")) {
+  } else if (!strcmp(params[0], "join_group_chat")) {
     action_func=eb_gui_request_group_join;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "close_group_chat")) {
+  } else if (!strcmp(params[0], "close_group_chat")) {
     action_func=eb_gui_group_close;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "hide_group_chat")) {
+  } else if (!strcmp(params[0], "hide_group_chat")) {
     action_func=eb_gui_group_hide;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "group_chat_invite")) {
+  } else if (!strcmp(params[0], "group_chat_invite")) {
     action_func=eb_gui_group_invite;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "group_chat_send")) {
+  } else if (!strcmp(params[0], "group_chat_send")) {
     action_func=eb_gui_group_send;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "add_group")) {
+  } else if (!strcmp(params[0], "add_group")) {
     action_func=eb_gui_add_group;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "add_contact")) {
+  } else if (!strcmp(params[0], "add_contact")) {
     action_func=eb_gui_add_contact;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "add_account")) {
+  } else if (!strcmp(params[0], "add_account")) {
     action_func=eb_gui_add_account;
     min_params=6;
-  } else if (!strcmp(gui->params[0], "rename_contact")) {
+  } else if (!strcmp(params[0], "rename_contact")) {
     action_func=eb_gui_rename_contact;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "move_contact")) {
+  } else if (!strcmp(params[0], "move_contact")) {
     action_func=eb_gui_move_contact;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "move_account")) {
+  } else if (!strcmp(params[0], "move_account")) {
     action_func=eb_gui_move_account;
     min_params=6;
-  } else if (!strcmp(gui->params[0], "del_group")) {
+  } else if (!strcmp(params[0], "del_group")) {
     action_func=eb_gui_del_group;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "del_contact")) {
+  } else if (!strcmp(params[0], "del_contact")) {
     action_func=eb_gui_del_contact;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "del_account")) {
+  } else if (!strcmp(params[0], "del_account")) {
     action_func=eb_gui_del_account;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "add_local_account")) {
+  } else if (!strcmp(params[0], "add_local_account")) {
     action_func=eb_gui_add_local_account;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "del_local_account")) {
+  } else if (!strcmp(params[0], "del_local_account")) {
     action_func=eb_gui_del_local_account;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "ignore_contact")) {
+  } else if (!strcmp(params[0], "ignore_contact")) {
     action_func=eb_gui_ignore;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "unignore_contact")) {
+  } else if (!strcmp(params[0], "unignore_contact")) {
     action_func=eb_gui_unignore;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "list_pref_page")) {
+  } else if (!strcmp(params[0], "list_pref_page")) {
     action_func=eb_gui_list_pref_page;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "set_pref_value")) {
+  } else if (!strcmp(params[0], "set_pref_value")) {
     action_func=eb_gui_set_pref_value;
     min_params=4;
-  } else if (!strcmp(gui->params[0], "unset_away")) {
+  } else if (!strcmp(params[0], "unset_away")) {
     action_func=eb_gui_unset_away;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "set_away")) {
+  } else if (!strcmp(params[0], "set_away")) {
     action_func=eb_gui_set_away;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "message_hold")) {
+  } else if (!strcmp(params[0], "message_hold")) {
     action_func=eb_gui_hold_messages;
     min_params=2;
-  } else if (!strcmp(gui->params[0], "get_held_messages")) {
+  } else if (!strcmp(params[0], "get_held_messages")) {
     action_func=eb_gui_get_held_messages;
     min_params=1;
-  } else if (!strcmp(gui->params[0], "get_stream")) {
+  } else if (!strcmp(params[0], "get_stream")) {
     action_func=eb_gui_get_stream;
     min_params=3;
-  } else if (!strcmp(gui->params[0], "html_strip")) {
-    if(gui->num_params>=2)
-    { gui->html=(gui->params[1][0]=='0'); }
+  } else if (!strcmp(params[0], "html_strip")) {
+    if(num_params>=2)
+    { gui->html=(params[1][0]=='0'); }
     return;
-  } else if (!strcmp(gui->params[0], "msg_capable")) {
-    if(gui->num_params>=2)
-    { gui->msg_capable=(gui->params[1][0]=='1'); }
+  } else if (!strcmp(params[0], "msg_capable")) {
+    if(num_params>=2)
+    { gui->msg_capable=(params[1][0]=='1'); }
     return;
-  } else if (!strcmp(gui->params[0], "list_group_chats")) {
+  } else if (!strcmp(params[0], "list_group_chats")) {
     EList * n;
     for(n=group_chats; n!=NULL; n=n->next)
     {
@@ -489,7 +493,7 @@
       eb_gui_announce_group_chat(gui, chat);
     }
     return;
-  } else if (!strcmp(gui->params[0], "save_config")) {
+  } else if (!strcmp(params[0], "save_config")) {
     char * tmp_name=malloc(strlen(eb_config_dir)+32);
     strcpy(tmp_name, eb_config_dir);
     strcat(tmp_name, "everybuddy.conf");
@@ -502,11 +506,11 @@
   {
     eb_do_client_error(gui, "Unknown command");
   } else {
-    if(gui->num_params<min_params)
+    if(num_params<min_params)
     {
       eb_do_client_error(gui, "Insufficient arguments");
     } else {
-      action_func(gui);
+      action_func(gui, params, num_params);
     }
   }
 }
@@ -566,34 +570,12 @@
 
 void eb_gui_send(eb_gui * gui, char ** command, int num_params)
 {
-  static int plen[256];
-  int a;
-
-  for(a=0; a<num_params; a++)
-  {
-    plen[a]=strlen(command[a]);
-  }
-
-  eb_gui_send_data(gui, command, plen, num_params);
+  eb_write_gui_message(gui->write_fd, command, num_params);
 }
 
 void eb_gui_send_data(eb_gui * gui, char ** command, int * lengths, int num_params)
 {
-  unsigned char c=num_params;
-  int a;
-
-  if(write(gui->write_fd, &c, 1)<1)
-  { return; } // dud socket, let the cleanup routines take care of it
-
-  for(a=0; a<num_params; a++)
-  {
-    c=lengths[a]/256;
-    write(gui->write_fd, &c, 1);
-    c=lengths[a]%256;
-    write(gui->write_fd, &c, 1);
-
-    write(gui->write_fd, command[a], lengths[a]);
-  }
+  eb_write_gui_data(gui->write_fd, (void **)command, lengths, num_params);
 }
 
 void eb_gui_broadcast(char ** command, int num_params)
@@ -674,9 +656,9 @@
   return NULL;
 }
 
-void eb_gui_get_data(eb_gui * gui)
+void eb_gui_get_data(eb_gui * gui, char ** params, int num_params)
 {
-  eb_registry_key * key=eb_gui_data_key(gui->params+2, gui->num_params-2);
+  eb_registry_key * key=eb_gui_data_key(params+2, num_params-2);
   char * notify_cmd[6];
   int a;
 
@@ -684,23 +666,23 @@
   { eb_do_client_error(gui, "Invalid data path specification"); return; }
 
   notify_cmd[0]="return_data";
-  notify_cmd[1]=gui->params[1];
-  notify_cmd[2]=eb_get_value(key, gui->params[1]);
-  for(a=2; a<gui->num_params; a++)
+  notify_cmd[1]=params[1];
+  notify_cmd[2]=eb_get_value(key, params[1]);
+  for(a=2; a<num_params; a++)
   {
-    notify_cmd[a+1]=gui->params[a];
+    notify_cmd[a+1]=params[a];
   }
 
-  eb_gui_send(gui, notify_cmd, gui->num_params+1);
+  eb_gui_send(gui, notify_cmd, num_params+1);
 }
 
-void eb_gui_put_data(eb_gui * gui)
+void eb_gui_put_data(eb_gui * gui, char ** params, int num_params)
 {
-  eb_registry_key * key=eb_gui_data_key(gui->params+3, gui->num_params-3);
+  eb_registry_key * key=eb_gui_data_key(params+3, num_params-3);
   if(key==NULL)
   { eb_do_client_error(gui, "Invalid data path specification"); return; }
 
-  eb_put_value(key, gui->params[1], gui->params[2]);
+  eb_put_value(key, params[1], params[2]);
 }
 
 // little util functions
@@ -733,7 +715,7 @@
   free(notify_command);
 }
 
-void eb_gui_list_services(eb_gui * gui)
+void eb_gui_list_services(eb_gui * gui, char ** params, int num_params)
 {
   char buf[16];
   char * begin_serv[]={"list_service", "", "", buf};
@@ -793,7 +775,7 @@
   eb_gui_send(gui, end_cmd, 1);
 }
 
-void eb_gui_list_accounts(eb_gui * gui)
+void eb_gui_list_accounts(eb_gui * gui, char ** params, int num_params)
 {
   char * done_command[]={"list_local_accounts_done"};
   char * notify_command[]={"list_local_account", "", ""};
@@ -813,7 +795,7 @@
   eb_gui_send(gui, done_command, 1);
 }
 
-void eb_gui_list_contacts(eb_gui * gui)
+void eb_gui_list_contacts(eb_gui * gui, char ** params, int num_params)
 {
   EList * g;
   EList * c;
@@ -867,7 +849,7 @@
   eb_gui_send(gui, done_command, 1);
 }
 
-void eb_gui_send_message(eb_gui * gui)
+void eb_gui_send_message(eb_gui * gui, char ** params, int num_params)
 {
   EList * l;
   eb_group * group=NULL;
@@ -875,8 +857,8 @@
   eb_account * acc=NULL;
   eb_account * backup=NULL;
 
-  group=eb_get_group(gui->params[1]);
-  cont=eb_get_contact(gui->params[1], gui->params[2]);
+  group=eb_get_group(params[1]);
+  cont=eb_get_contact(params[1], params[2]);
 
   if(cont==NULL)
   {
@@ -895,15 +877,15 @@
     if(backup==NULL || (backup->status==EB_ACCOUNT_OFFLINE && thisacc->status!=EB_ACCOUNT_OFFLINE))
     { backup=thisacc; }
 
-    if(!strcmp(thisacc->buddy_of->handle, gui->params[3])
-     && !strcmp(thisacc->buddy_of->service_name, gui->params[4])
-     && !strcmp(thisacc->handle, gui->params[5]))
+    if(!strcmp(thisacc->buddy_of->handle, params[3])
+     && !strcmp(thisacc->buddy_of->service_name, params[4])
+     && !strcmp(thisacc->handle, params[5]))
     {
       acc=thisacc;
       break;
     }
 
-    if(!strcmp(thisacc->buddy_of->service_name, gui->params[4]))
+    if(!strcmp(thisacc->buddy_of->service_name, params[4]))
     {
       acc=thisacc; // if there's an exact match later on, it will be overridden, but if not, use it!
     }
@@ -919,7 +901,7 @@
 
   if(acc->buddy_of->service->sc->send_im)
   {
-    char * msg=strdup(gui->params[6]);
+    char * msg=strdup(params[6]);
     msg=acc->buddy_of->service->sc->send_im(acc, msg);
     if(msg==NULL) { return; }
 
@@ -960,7 +942,7 @@
 }
 
 
-void eb_gui_list_actions(eb_gui * gui)
+void eb_gui_list_actions(eb_gui * gui, char ** params, int num_params)
 {
   char * done_cmd[]={"list_actions_done"};
 
@@ -972,24 +954,24 @@
   eb_gui_send(gui, done_cmd, 1);
 }
 
-void eb_gui_perform_action(eb_gui * gui)
+void eb_gui_perform_action(eb_gui * gui, char ** params, int num_params)
 {
   void * target=NULL;
   EList * actions=NULL;
   EList * n;
 
-  if(!strcmp(gui->params[1], "buddy"))
+  if(!strcmp(params[1], "buddy"))
   {
-    eb_account * acc=eb_get_account(gui->params[3], gui->params[4], gui->params[5]);
+    eb_account * acc=eb_get_account(params[3], params[4], params[5]);
     if(acc==NULL) { return; }
     actions=acc->buddy_of->service->buddy_actions;
-  } else if(!strcmp(gui->params[1], "groupchat")) {
-    eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[3]));
+  } else if(!strcmp(params[1], "groupchat")) {
+    eb_group_chat * chat=eb_get_group_chat(atoi(params[3]));
     if(chat==NULL) { eb_do_client_error(gui, "No such chat"); return; }
     target=chat;
     actions=chat->account->service->groupchat_actions;
-  } else if(!strcmp(gui->params[1], "group_users")) {
-    eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[3]));
+  } else if(!strcmp(params[1], "group_users")) {
+    eb_group_chat * chat=eb_get_group_chat(atoi(params[3]));
     if(chat==NULL) { eb_do_client_error(gui, "No such chat"); return; }
 
     actions=chat->account->service->group_user_actions;
@@ -997,27 +979,27 @@
     for(n=chat->users; n!=NULL; n=n->next)
     {
       eb_group_chat_user * user=(eb_group_chat_user *)n->data;
-      if(!strcmp(user->handle, gui->params[4]))
+      if(!strcmp(user->handle, params[4]))
       { target=user; break; }
     }
 
     if(target==NULL)
     { eb_do_client_error(gui, "No such user in chatroom"); return; }
-  } else if(!strcmp(gui->params[1], "group")) {
-    target=eb_get_group(gui->params[3]);
+  } else if(!strcmp(params[1], "group")) {
+    target=eb_get_group(params[3]);
     if(target==NULL)
     { eb_do_client_error(gui, "No such group"); return; }
     actions=eb_group_actions;
-  } else if(!strcmp(gui->params[1], "contact")) {
-    target=eb_get_contact(gui->params[3], gui->params[4]);
+  } else if(!strcmp(params[1], "contact")) {
+    target=eb_get_contact(params[3], params[4]);
     if(target==NULL)
     { eb_do_client_error(gui, "No such contact"); return; }
     actions=eb_contact_actions;
-  } else if(!strcmp(gui->params[1], "buddy_generic")) {
-    eb_account * acc=eb_get_account(gui->params[3], gui->params[4], gui->params[5]);
+  } else if(!strcmp(params[1], "buddy_generic")) {
+    eb_account * acc=eb_get_account(params[3], params[4], params[5]);
     if(acc==NULL) { eb_do_client_error(gui, "No such account"); return; }
     actions=eb_buddy_actions;
-  } else if(!strcmp(gui->params[1], "general")) {
+  } else if(!strcmp(params[1], "general")) {
     target=NULL;
     actions=eb_general_actions;
   } else {
@@ -1028,7 +1010,7 @@
   for(n=actions; n!=NULL; n=n->next)
   {
     eb_action * action=(eb_action *)n->data;
-    if(!strcmp(action->name, gui->params[2]))
+    if(!strcmp(action->name, params[2]))
     { action->callback(target); return; }
   }
 
@@ -1323,13 +1305,13 @@
   eb_gui_dialog_send(NULL, d);
 }
 
-void eb_gui_resolve_dialog(eb_gui * gui)
+void eb_gui_resolve_dialog(eb_gui * gui, char ** params, int num_params)
 {
   EList * l;
   eb_dialog * d=NULL;
   char buf[32];
   char * resolve_command[]={"dialog_resolved", buf};
-  int code=atoi(gui->params[1]);
+  int code=atoi(params[1]);
 
   for(l=dialogs; l!=NULL; l=l->next)
   {
@@ -1360,7 +1342,7 @@
 
       for(n=ld->options; n!=NULL; n=n->next)
       {
-        if(!strcmp((char *)n->data, gui->params[2]))
+        if(!strcmp((char *)n->data, params[2]))
         { found=1; break; }
       }
 
@@ -1370,7 +1352,7 @@
         return;
       }
 
-      ld->callback(ld->tag, gui->params[2]);
+      ld->callback(ld->tag, params[2]);
 
       for(n=ld->options; n!=NULL; n=n->next)
       { free(n->data); }
@@ -1386,9 +1368,9 @@
       eb_yesno_dialog * ynd=(eb_yesno_dialog *)d->data;
 
       int result = 0;
-      if(!strcmp("1", gui->params[2]))
+      if(!strcmp("1", params[2]))
 	result = 1;
-      else if(!strcmp("0", gui->params[2]))
+      else if(!strcmp("0", params[2]))
 	result = 0;
       else
       {
@@ -1407,7 +1389,7 @@
     case(EB_TEXT_DIALOG) : {
       eb_text_dialog * td=(eb_text_dialog *)d->data;
 
-      td->callback(td->tag, gui->params[2]);
+      td->callback(td->tag, params[2]);
 
       free(td->title);
       free(td->message);
@@ -1433,9 +1415,9 @@
   eb_gui_broadcast(resolve_command, 2);
 }
 
-void eb_gui_request_group_join(eb_gui * gui)
+void eb_gui_request_group_join(eb_gui * gui, char ** params, int num_params)
 {
-  eb_local_account * acc=eb_get_local_account(gui->params[1], gui->params[2]);
+  eb_local_account * acc=eb_get_local_account(params[1], params[2]);
 
   if(acc==NULL) { eb_do_client_error(gui, "No such local account"); return; }
 
@@ -1446,12 +1428,12 @@
   { eb_do_client_error(gui, "This local account is not ready to join a group chat"); return; }
 
   if(acc->service->sc->join_group_chat)
-  { acc->service->sc->join_group_chat(acc, gui->params[3]); }
+  { acc->service->sc->join_group_chat(acc, params[3]); }
 }
 
-void eb_gui_group_close(eb_gui * gui)
+void eb_gui_group_close(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[1]));
+  eb_group_chat * chat=eb_get_group_chat(atoi(params[1]));
 
   if(chat==NULL) { eb_do_client_error(gui, "No such chat room"); return; }
 
@@ -1463,30 +1445,30 @@
   }
 }
 
-void eb_gui_group_hide(eb_gui * gui)
+void eb_gui_group_hide(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[1]));
+  eb_group_chat * chat=eb_get_group_chat(atoi(params[1]));
 
   if(chat==NULL) { eb_do_client_error(gui, "No such chat room"); return; }
 
   eb_hide_group_chat(chat);
 }
 
-void eb_gui_group_send(eb_gui * gui)
+void eb_gui_group_send(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[1]));
+  eb_group_chat * chat=eb_get_group_chat(atoi(params[1]));
 
   if(chat==NULL) { eb_do_client_error(gui, "No such chat room"); return; }
 
   if(chat->account->service->sc->group_chat_send)
   {
-    char * msg=strdup(gui->params[2]);
+    char * msg=strdup(params[2]);
 
     msg=chat->account->service->sc->group_chat_send(chat, msg);
 
     if(msg!=NULL)
     {
-      char * notify_command[]={"group_chat_send", gui->params[1], msg};
+      char * notify_command[]={"group_chat_send", params[1], msg};
 
       eb_gui_broadcast(notify_command, 3);
       free(msg);
@@ -1494,38 +1476,38 @@
   }
 }
 
-void eb_gui_group_invite(eb_gui * gui)
+void eb_gui_group_invite(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group_chat * chat=eb_get_group_chat(atoi(gui->params[1]));
+  eb_group_chat * chat=eb_get_group_chat(atoi(params[1]));
 
   if(chat==NULL) { eb_do_client_error(gui, "No such chat room"); return; }
 
   if(chat->account->service->sc->group_chat_invite)
-  { chat->account->service->sc->group_chat_invite(chat, gui->params[2]); }
+  { chat->account->service->sc->group_chat_invite(chat, params[2]); }
 }
 
-void eb_gui_set_state(eb_gui * gui)
+void eb_gui_set_state(eb_gui * gui, char ** params, int num_params)
 {
-  eb_local_account * acc=eb_get_local_account(gui->params[1], gui->params[2]);
+  eb_local_account * acc=eb_get_local_account(params[1], params[2]);
 
   if(acc==NULL) { eb_do_client_error(gui, "No such account"); return; }
 
   if(acc->service->sc->set_current_state)
-  { acc->service->sc->set_current_state(acc, gui->params[3]); }
+  { acc->service->sc->set_current_state(acc, params[3]); }
 }
 
-void eb_gui_add_group(eb_gui * gui)
+void eb_gui_add_group(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group * group=eb_get_group(gui->params[1]);
+  eb_group * group=eb_get_group(params[1]);
 
   if(group!=NULL) { eb_do_client_error(gui, "Group already exists"); return; }
 
-  eb_add_group(gui->params[1]);
+  eb_add_group(params[1]);
 }
 
-void eb_gui_del_group(eb_gui * gui)
+void eb_gui_del_group(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group * group=eb_get_group(gui->params[1]);
+  eb_group * group=eb_get_group(params[1]);
 
   if(group==NULL) { eb_do_client_error(gui, "No such group"); return; }
 
@@ -1538,41 +1520,41 @@
   eb_del_group(group);
 }
 
-void eb_gui_add_contact(eb_gui * gui)
+void eb_gui_add_contact(eb_gui * gui, char ** params, int num_params)
 {
-  eb_group * group=eb_get_group(gui->params[1]);
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
+  eb_group * group=eb_get_group(params[1]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
 
   if(group==NULL) { eb_do_client_error(gui, "No such group"); return; }
   if(contact!=NULL)
   { eb_do_client_error(gui, "A contact with this name already exists"); return; }
 
-  eb_add_contact(group, gui->params[2]);
+  eb_add_contact(group, params[2]);
 
   return;
 }
 
-void eb_gui_rename_contact(eb_gui * gui)
+void eb_gui_rename_contact(eb_gui * gui, char ** params, int num_params)
 {
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
 
-  eb_rename_contact(contact, gui->params[3]);
+  eb_rename_contact(contact, params[3]);
 }
 
-void eb_gui_move_contact(eb_gui * gui)
+void eb_gui_move_contact(eb_gui * gui, char ** params, int num_params)
 {
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
-  eb_group * group=eb_get_group(gui->params[3]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
+  eb_group * group=eb_get_group(params[3]);
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
   if(group==NULL) { eb_do_client_error(gui, "No such target group"); return; }
 
   eb_move_contact(contact, group);
 }
 
-void eb_gui_del_contact(eb_gui * gui)
+void eb_gui_del_contact(eb_gui * gui, char ** params, int num_params)
 {
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
   if(contact->accounts!=NULL) { eb_do_client_error(gui, "Contact still has accounts"); }
   if(contact->locked)
@@ -1581,11 +1563,11 @@
   eb_del_contact(contact);
 }
 
-void eb_gui_add_account(eb_gui * gui)
+void eb_gui_add_account(eb_gui * gui, char ** params, int num_params)
 {
-  eb_account * adding=eb_get_account(gui->params[3], gui->params[4], gui->params[5]);
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
-  eb_local_account * buddy_of=eb_get_local_account(gui->params[3], gui->params[4]);
+  eb_account * adding=eb_get_account(params[3], params[4], params[5]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
+  eb_local_account * buddy_of=eb_get_local_account(params[3], params[4]);
 
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
   if(buddy_of==NULL) { eb_do_client_error(gui, "No such local account"); return; }
@@ -1608,7 +1590,7 @@
 
   adding=(eb_account *)malloc(sizeof(eb_account));
 
-  adding->handle=strdup(gui->params[5]);
+  adding->handle=strdup(params[5]);
   adding->status_string=strdup("(Offline)");
   adding->status=EB_ACCOUNT_OFFLINE;
   adding->contact=contact;
@@ -1621,10 +1603,10 @@
   }
 }
 
-void eb_gui_move_account(eb_gui * gui)
+void eb_gui_move_account(eb_gui * gui, char ** params, int num_params)
 {
-  eb_account * account=eb_get_account(gui->params[1], gui->params[2], gui->params[3]);
-  eb_contact * contact=eb_get_contact(gui->params[4], gui->params[5]);
+  eb_account * account=eb_get_account(params[1], params[2], params[3]);
+  eb_contact * contact=eb_get_contact(params[4], params[5]);
 
   if(account==NULL) { eb_do_client_error(gui, "No such buddy account"); return; }
   if(contact==NULL) { eb_do_client_error(gui, "No such destination contact"); return; }
@@ -1632,9 +1614,9 @@
   eb_move_account(account, contact);
 }
 
-void eb_gui_del_account(eb_gui * gui)
+void eb_gui_del_account(eb_gui * gui, char ** params, int num_params)
 {
-  eb_account * account=eb_get_account(gui->params[1], gui->params[2], gui->params[3]);
+  eb_account * account=eb_get_account(params[1], params[2], params[3]);
 
   if(account==NULL) { eb_do_client_error(gui, "No such account"); return; }
   if(account->locked)
@@ -1651,21 +1633,21 @@
   }
 }
 
-void eb_gui_add_local_account(eb_gui * gui)
+void eb_gui_add_local_account(eb_gui * gui, char ** params, int num_params)
 {
   eb_local_account * acc=(eb_local_account *)malloc(sizeof(eb_local_account));
-  eb_service * service=eb_get_service(gui->params[2]);
+  eb_service * service=eb_get_service(params[2]);
   char * tmp_name;
-  char * add_command[]={"add_local_account", gui->params[1], gui->params[2]};
+  char * add_command[]={"add_local_account", params[1], params[2]};
 
   if(service==NULL || service==&dummy_service)
   { eb_do_client_error(gui, "No plugin loaded for this service"); return; }
 
-  if(eb_get_local_account(gui->params[1], gui->params[2])!=NULL)
+  if(eb_get_local_account(params[1], params[2])!=NULL)
   { eb_do_client_error(gui, "This account already exists"); return; }
 
-  acc->handle=strdup(gui->params[1]);
-  acc->service_name=strdup(gui->params[2]);
+  acc->handle=strdup(params[1]);
+  acc->service_name=strdup(params[2]);
   acc->status_string=strdup("Offline");
   acc->connected=acc->ready=0;
   acc->buddies=NULL;
@@ -1691,10 +1673,10 @@
   map_orphaned_buddies();
 }
 
-void eb_gui_del_local_account(eb_gui * gui)
+void eb_gui_del_local_account(eb_gui * gui, char ** params, int num_params)
 {
-  eb_local_account * acc=eb_get_local_account(gui->params[1], gui->params[2]);
-  char * notify_command[]={"del_local_account", gui->params[1], gui->params[2]};
+  eb_local_account * acc=eb_get_local_account(params[1], params[2]);
+  char * notify_command[]={"del_local_account", params[1], params[2]};
   EList * n;
 
   if(acc==NULL)
@@ -1768,17 +1750,17 @@
   eb_gui_broadcast(notify_command, 3);
 }
 
-void eb_gui_ignore(eb_gui * gui)
+void eb_gui_ignore(eb_gui * gui, char ** params, int num_params)
 {
-  char * ignore_command[]={"ignore_contact", gui->params[1], gui->params[2], gui->params[3]};
+  char * ignore_command[]={"ignore_contact", params[1], params[2], params[3]};
   EList * n;
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
 
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
 
   if(contact->ignore!=NULL) { free(contact->ignore); }
 
-  contact->ignore=strdup(gui->params[3]);
+  contact->ignore=strdup(params[3]);
   eb_put_value(contact->config_key, "ignore", "1");
   eb_put_value(contact->config_key, "ignore_message", contact->ignore);
 
@@ -1793,11 +1775,11 @@
   eb_gui_broadcast(ignore_command, 4);
 }
 
-void eb_gui_unignore(eb_gui * gui)
+void eb_gui_unignore(eb_gui * gui, char ** params, int num_params)
 {
-  char * unignore_command[]={"unignore_contact", gui->params[1], gui->params[2]};
+  char * unignore_command[]={"unignore_contact", params[1], params[2]};
   EList * n;
-  eb_contact * contact=eb_get_contact(gui->params[1], gui->params[2]);
+  eb_contact * contact=eb_get_contact(params[1], params[2]);
 
   if(contact==NULL) { eb_do_client_error(gui, "No such contact"); return; }
 
@@ -1827,17 +1809,17 @@
 
 // Prefs stuff
 
-void eb_gui_list_pref_page(eb_gui * gui)
+void eb_gui_list_pref_page(eb_gui * gui, char ** params, int num_params)
 {
-  char * list_pref_page[]={"list_pref_page", gui->params[1], ""};
-  char * begin_subpages[]={"list_subpages", gui->params[1], ""};
-  char * list_subpage[]={"list_subpage", gui->params[1], "", ""};
+  char * list_pref_page[]={"list_pref_page", params[1], ""};
+  char * begin_subpages[]={"list_subpages", params[1], ""};
+  char * list_subpage[]={"list_subpage", params[1], "", ""};
   char * end_subpages[]={"list_subpages_done"};
-  char * begin_components[]={"list_components", gui->params[1]};
-  char * list_component[]={"list_component", gui->params[1], "", "", "", ""}; // expand this
+  char * begin_components[]={"list_components", params[1]};
+  char * list_component[]={"list_component", params[1], "", "", "", ""}; // expand this
   char * end_components[]={"list_components_done"};
   char * end_pref_page[]={"list_pref_page_done"};
-  eb_pref_page * page=eb_get_pref_page(gui->params[1]);
+  eb_pref_page * page=eb_get_pref_page(params[1]);
   EList * n;
 
   if(page==NULL) { eb_do_client_error(gui, "No such page"); return; }
@@ -1896,17 +1878,17 @@
   eb_gui_send(gui, end_pref_page, 1);
 }
 
-void eb_gui_set_pref_value(eb_gui * gui)
+void eb_gui_set_pref_value(eb_gui * gui, char ** params, int num_params)
 {
-  eb_pref_page * page=eb_get_pref_page(gui->params[1]);
+  eb_pref_page * page=eb_get_pref_page(params[1]);
   eb_pref * pref;
 
   if(page==NULL) { eb_do_client_error(gui, "No such page"); return; }
 
-  pref=eb_get_component(page, gui->params[2]);
+  pref=eb_get_component(page, params[2]);
   if(pref==NULL) { eb_do_client_error(gui, "No such component"); return; }
 
-  eb_put_value(pref->target, pref->valuename, gui->params[3]);
+  eb_put_value(pref->target, pref->valuename, params[3]);
   if(pref->callback)
   {
     pref->callback(pref, pref->callback_tag);
@@ -2011,22 +1993,22 @@
   if(plain!=NULL) { free(plain); }
 }
 
-void eb_gui_set_away(eb_gui * gui)
+void eb_gui_set_away(eb_gui * gui, char ** params, int num_params)
 {
-  eb_set_away(gui->params[1], gui->params[2]);
+  eb_set_away(params[1], params[2]);
 }
 
-void eb_gui_unset_away(eb_gui * gui)
+void eb_gui_unset_away(eb_gui * gui, char ** params, int num_params)
 {
   eb_unset_away();
 }
 
-void eb_gui_hold_messages(eb_gui * gui)
+void eb_gui_hold_messages(eb_gui * gui, char ** params, int num_params)
 {
-  eb_hold_messages(gui->params[1][0]=='1');
+  eb_hold_messages(params[1][0]=='1');
 }
 
-void eb_gui_get_held_messages(eb_gui * gui)
+void eb_gui_get_held_messages(eb_gui * gui, char ** params, int num_params)
 {
   char * notify_cmd[8];
   char buf[32];
@@ -2105,23 +2087,23 @@
   if(error!=0) { eb_show_error("Could not transfer the requested chat log. Is the ID correct?", "Log error"); }
 }
 
-void eb_gui_get_stream(eb_gui * gui)
+void eb_gui_get_stream(eb_gui * gui, char ** params, int num_params)
 {
   // This will be a generalised call to request a stream from any of several sources.
   // (chat logs, emoticons, completed file transfers...)
   // ...but it's just chat logs for now.
   int id=eb_stream_next_id();
   char buf[16];
-  char * notify_cmd[4]={"get_stream", gui->params[0], gui->params[1], buf};
+  char * notify_cmd[4]={"get_stream", params[0], params[1], buf};
   
   sprintf(buf, "%d", id);
   
-  if(!strcmp(gui->params[1], "log"))
+  if(!strcmp(params[1], "log"))
   {
     char * fnam;
-    if(strstr(gui->params[2], "/")) { eb_do_client_error(gui, "Invalid path"); return; }
-    fnam=(char *)malloc(strlen(eb_config_dir)+strlen(gui->params[2])+16);
-    sprintf(fnam, "%slogs/%s", eb_config_dir, gui->params[2]);
+    if(strstr(params[2], "/")) { eb_do_client_error(gui, "Invalid path"); return; }
+    fnam=(char *)malloc(strlen(eb_config_dir)+strlen(params[2])+16);
+    sprintf(fnam, "%slogs/%s", eb_config_dir, params[2]);
     eb_gui_send(gui, notify_cmd, 4);
     eb_stream_file(gui, fnam, EB_STREAM_OUT, streamerr_cb, gui, id);
     free(fnam);
Index: core/src/gui_comms.h
===================================================================
--- core/src/gui_comms.h	(revision 311)
+++ core/src/gui_comms.h	(working copy)
@@ -48,13 +48,13 @@
 
 void eb_local_account_update(eb_local_account * acc);
 
-void eb_gui_list_contacts(eb_gui * gui);
-void eb_gui_list_accounts(eb_gui * gui);
+void eb_gui_list_contacts(eb_gui * gui, char ** params, int num_params);
+void eb_gui_list_accounts(eb_gui * gui, char ** params, int num_params);
 
-void eb_gui_resolve_dialog(eb_gui * gui);
+void eb_gui_resolve_dialog(eb_gui * gui, char ** params, int num_params);
 void eb_do_client_error(eb_gui * gui, char * error);
 
-void eb_gui_send_message(eb_gui * gui);
+void eb_gui_send_message(eb_gui * gui, char ** params, int num_params);
 
 void eb_gui_got_message(eb_account * remote, eb_html_item * message);
 void eb_gui_notify_3rdperson(eb_contact * contact, eb_html_item * message);
@@ -62,7 +62,7 @@
 
 void eb_gui_announce_group_chat(eb_gui * gui, eb_group_chat * chat);
 
-void eb_gui_get_held_messages(eb_gui * gui);
+void eb_gui_get_held_messages(eb_gui * gui, char ** params, int num_params);
 
 void new_plugin_notify(eb_plugin * p);
 void plugin_update_notify(eb_plugin * p);
Index: core/src/Makefile.am
===================================================================
--- core/src/Makefile.am	(revision 311)
+++ core/src/Makefile.am	(working copy)
@@ -19,7 +19,7 @@
 eb_lite_SOURCES = accounts.c actions.c contactlist.c debug.c elist.c \
 	gui_comms.c groupchat.c html.c main.c md5.c message_parse.c misc_cb.c \
 	plugin.c plugin_api.c prefs.c proxy.c registry.c staticmods.c \
-	stream.c util.c $(WIN32_SRC)
+	stream.c util.c ../../ebgui/ebgui.c $(WIN32_SRC)
 
 regbrowser_SOURCES = registry.c regbrowser.c elist.c
 
Index: core/plugins/toc/libtoc.c
===================================================================
--- core/plugins/toc/libtoc.c	(revision 311)
+++ core/plugins/toc/libtoc.c	(working copy)
@@ -1318,6 +1318,8 @@
 
 void toc_signoff( toc_conn * conn )
 {
+	if (!conn)
+		return;
 #ifdef DEBUG
 	printf( "toc_signoff BEFORE %d %d\n", conn->fd, conn->seq_num );
 #endif
Index: core/plugins/msn/msn_bittybits.C
===================================================================
--- core/plugins/msn/msn_bittybits.C	(revision 311)
+++ core/plugins/msn/msn_bittybits.C	(working copy)
@@ -84,6 +84,9 @@
   llist * connlist;
   connlist=connections;
 
+  if (!conn)
+    return;
+
   if(conn->type!=CONN_FTP)
   { ext_closing_connection(conn); }
 
Index: eb-console/GUIcomms.c
===================================================================
--- eb-console/GUIcomms.c	(revision 311)
+++ eb-console/GUIcomms.c	(working copy)
@@ -1,12 +1,5 @@
 #include <stdio.h>
 #include <unistd.h>
-#ifdef __MINGW32__
-#include <winsock2.h>
-#define ECONNREFUSED WSAECONNREFUSED
-#define read(a,b,c) recv(a,b,c,0)
-#define write(a,b,c) send(a,b,c,0)
-#define usleep(a) Sleep(a)
-#else
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/poll.h>
@@ -14,9 +7,9 @@
 #include <fcntl.h>
 #include <netinet/in.h>
 #include <netdb.h>
-#endif
 #include <sys/types.h>
 #include <errno.h>
+#include "../ebgui/ebgui.h"
 
 // Everybuddy GUI communications code
 
@@ -24,60 +17,17 @@
 
 int send_gui_message(char ** command, int num_params)
 {
-  unsigned char c=num_params;
-  int a;
-
-  write(gui_out, &c, 1);
-
-  for(a=0; a<num_params; a++)
-  {
-    int len=strlen(command[a]);
-    c=len/256;
-    write(gui_out, &c, 1);
-    c=len%256;
-    write(gui_out, &c, 1);
-
-    write(gui_out, command[a], len);
-  }
-
-  usleep(100);
-
-  return 0;
+  return eb_write_gui_message(gui_out, command, num_params);
 }
 
 char ** read_gui_message(int * num_params)
 {
-  unsigned char c, c2[2];
-  char ** command;
-  int a;
-
-  if(read_m(gui_in, &c, 1)<1) { printf("ouchie 1\n"); return NULL; }
-  *num_params=c;
-
-  command=(char **)malloc((*num_params+1) * sizeof(char *));
-
-  for(a=0; a<*num_params; a++)
-  {
-    int size;
-
-    if(read_m(gui_in, c2, 2)<2) { printf("ouchie 2\n"); return NULL; }
-    size=c2[0]*256+c2[1];
-
-    command[a]=(char *)malloc(size+1);
-    if(read_m(gui_in, command[a], size)<size) { printf("ouchie 3\n"); return NULL; } // OUCH! mem leak, CBA to fix
-    command[a][size]='\0';
-  }
-  command[a]=NULL;
-
-  return command;
+  return eb_read_gui_message(gui_in, num_params);
 }
 
 void free_gui_message(char ** cmd)
 {
-  int a;
-  for(a=0; cmd[a]!=NULL; a++)
-  { free(cmd[a]); }
-  free(cmd);
+  return eb_free_gui_message(cmd, -1);
 }
 
 int connect_gui_socket(char * hostname, int port, unsigned char * cookie)
@@ -85,10 +35,6 @@
   struct sockaddr_in sa;
   struct hostent     *hp;
   int a;
-#ifdef __MINGW32__
-  WSADATA wsaData;
-  WSAStartup(MAKEWORD(2,0),&wsaData);
-#endif
 
   if ((hp= gethostbyname(hostname)) == NULL) { /* do we know the host's */
     errno= ECONNREFUSED;                       /* address? */
@@ -107,30 +53,8 @@
     return(-1);
   }
 
-  write(gui_out, cookie, 8);
+  eb_write_fully(gui_out, cookie, 8);
   gui_in=gui_out;
   return 0;
 }
 
-int read_m(int sock, char * dest, int num)
-{
-  int pos=0;
-  int read_result=0;
-  int a;
-
-  while(pos<num)
-  {
-    read_result=read(sock, dest+pos, num-pos);
-    if(read_result<1) { return -1; }
-    pos+=read_result;
-
-    if(num>2)
-    {
-      //for(a=0; a<read_result; a++) { printf("%c", dest[pos+a]); }
-      //printf("\n");
-    }
-  }
-
-  return num;
-}
-
Index: eb-console/Makefile
===================================================================
--- eb-console/Makefile	(revision 311)
+++ eb-console/Makefile	(working copy)
@@ -1,7 +1,7 @@
 CFLAGS=-g
 
-eb-console: GUIcomms.o eb-console.o elist.o ebparse.o
-	gcc -g -o eb-console GUIcomms.o eb-console.o elist.o ebparse.o -lreadline -lcurses
+eb-console: GUIcomms.o eb-console.o elist.o ebparse.o ../ebgui/ebgui.o
+	gcc -g -o eb-console GUIcomms.o eb-console.o elist.o ebparse.o ../ebgui/ebgui.o -lreadline -lcurses
 
 clean:
 	rm -f eb-console *.o
--------Patch Ends--------

-- 
Craig West         Ph: (416) 666-1645	|  It's not a bug,
[email protected]              	|  It's a feature...