chiark / gitweb /
serialmgrd: Support recent versions of perl
[sympathy.git] / apps / clients.c
index 234c0ed5dbe390f618130747183a43034381ee27..9f97a676d59e0b105de56b8272ad873883ba70a4 100644 (file)
-/*
+/* 
  * clients.c:
  *
- * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
+ * Copyright (c) 2008 James McKenzie <sympathy@madingley.org>,
  * All rights reserved.
  *
  */
 
-static char rcsid[] = "$Id$";
+static char rcsid[] = "$Id: clients.c,v 1.25 2008/05/09 12:35:57 james Exp $";
 
-/*
- * $Log$
+/* 
+ * $Log: clients.c,v $
+ * Revision 1.25  2008/05/09 12:35:57  james
+ * *** empty log message ***
+ *
+ * Revision 1.24  2008/03/11 17:56:04  james
+ * *** empty log message ***
+ *
+ * Revision 1.23  2008/03/11 17:47:24  james
+ * *** empty log message ***
+ *
+ * Revision 1.22  2008/03/07 14:16:44  james
+ * *** empty log message ***
+ *
+ * Revision 1.21  2008/03/07 14:13:40  james
+ * *** empty log message ***
+ *
+ * Revision 1.20  2008/03/07 13:56:39  james
+ * *** empty log message ***
+ *
+ * Revision 1.19  2008/03/07 13:16:02  james
+ * *** empty log message ***
+ *
+ * Revision 1.18  2008/03/03 18:16:16  james
+ * *** empty log message ***
+ *
+ * Revision 1.17  2008/03/03 18:15:19  james
+ * *** empty log message ***
+ *
+ * Revision 1.16  2008/03/03 06:04:42  james
+ * *** empty log message ***
+ *
+ * Revision 1.15  2008/03/02 10:27:24  james
+ * *** empty log message ***
+ *
+ * Revision 1.14  2008/02/28 16:57:51  james
+ * *** empty log message ***
+ *
+ * Revision 1.13  2008/02/28 16:37:16  james
+ * *** empty log message ***
+ *
+ * Revision 1.12  2008/02/28 12:12:24  james
+ * *** empty log message ***
+ *
+ * Revision 1.11  2008/02/23 11:48:51  james
+ * *** empty log message ***
+ *
+ * Revision 1.10  2008/02/22 17:06:59  james
+ * *** empty log message ***
+ *
+ * Revision 1.9  2008/02/20 18:49:11  staffcvs
+ * *** empty log message ***
+ *
+ * Revision 1.8  2008/02/20 18:31:44  james
+ * *** empty log message ***
+ *
+ * Revision 1.7  2008/02/15 23:52:12  james
+ * *** empty log message ***
+ *
+ * Revision 1.6  2008/02/15 03:32:07  james
+ * *** empty log message ***
+ *
+ * Revision 1.5  2008/02/14 10:34:47  james
+ * *** empty log message ***
+ *
+ * Revision 1.4  2008/02/14 10:34:30  james
+ * *** empty log message ***
+ *
+ * Revision 1.3  2008/02/14 02:46:44  james
+ * *** empty log message ***
+ *
+ * Revision 1.2  2008/02/14 00:57:58  james
+ * *** empty log message ***
+ *
  * Revision 1.1  2008/02/13 18:05:06  james
  * *** empty log message ***
  *
  */
 
 #include <sympathy.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <malloc.h>
 #include "clients.h"
 
 
-void clients_output (Clients *c, void *_buf, int len)
+void
+client_initialize (Client * c, Context * ctx)
+{
+  send_history (ctx->h, c);
+  send_vt102 (ctx->v, c);
+  c->initialized = 1;
+}
+
+void
+client_execute_message (Client * client, IPC_Msg * m, Context * c)
 {
+  switch (m->hdr.type)
+    {
+    case IPC_MSG_TYPE_NOOP:
+      break;
+    case IPC_MSG_TYPE_DEBUG:
+      log_f (c->l, "<debug message %s>", m->debug.msg);
+      break;
+    case IPC_MSG_TYPE_KEY:
+      vt102_send (c, m->key.key);
+      break;
+    case IPC_MSG_TYPE_SETBAUD:
+      tty_set_baud (c->t, m->setbaud.baud);
+      tty_parse_reset (c);
+      log_f (c->l, "<baud changed to %d>", m->setbaud.baud);
+      break;
+    case IPC_MSG_TYPE_SENDBREAK:
+      log_f (c->l, "<break sent>");
+      tty_send_break (c->t);
+      break;
+    case IPC_MSG_TYPE_SETFLOW:
+      log_f (c->l, "<flow control turned %s>",
+             m->setflow.flow ? "on" : "off");
+      tty_set_flow (c->t, m->setflow.flow);
+      break;
+    case IPC_MSG_TYPE_SETANSI:
+      vt102_set_ansi (c->v, m->setansi.ansi);
+      break;
+    case IPC_MSG_TYPE_HANGUP:
+      log_f (c->l, "<hangup initiated>");
+      tty_hangup (c->t);
+      break;
+    case IPC_MSG_TYPE_SETSIZE:
+      vt102_resize (c, m->setsize.winsize);
+      break;
+    case IPC_MSG_TYPE_RESET:
+      vt102_reset (c);
+      break;
+    case IPC_MSG_TYPE_INITIALIZE:
+      client_initialize (client, c);
+      break;
+    case IPC_MSG_TYPE_KILLME:
+      client->dead++;
+      break;
 
+    default:
+      log_f (c->l, "<Unhandled message type %d>", m->hdr.type);
+    }
 }
 
-Clients *clients_new(void)
+
+void
+client_free (Client * c)
 {
+  if (c->s)
+    socket_free (c->s);
 
+  free (c);
+#if 0
+  fprintf (stderr, "Client at %p freed\n", c);
+#endif
+}
+
+Client *
+clients_new_client (Clients * cs, Socket * s, Context * ctx)
+{
+  Client *c;
+
+  c = (Client *) xmalloc (sizeof (Client));
+
+  c->initialized = 0;
+  c->dead = 0;
+  c->s = s;
+  c->next = cs->head;
+
+  cs->head = c;
+  cs->n++;
+
+#if 0
+  fprintf (stderr, "Client at %p created\n", c);
+#endif
 
+  log_f (ctx->l, "<client %p connected - now %d clients>", c, cs->n);
 
-return NULL;
+  if (ipc_msg_send_debug (s, "new_client"))
+    c->dead++;
+
+  return c;
 }
 
-void clients_pre_select (Clients *c, fd_set *rfds, fd_set *wfds)
+void
+clients_reap (Clients * cs, Context * ctx)
 {
+  Client **p, *c;
+
 
+  for (p = &cs->head; *p;)
+    {
+      Client *c = *p;
 
+      if (c->dead)
+        {
+          *p = c->next;
+          client_free (c);
+          cs->n--;
+          log_f (ctx->l, "<client %p disconnected - now %d clients>", c,
+                 cs->n);
+        }
+      else
+        {
+          p = &(c->next);
+        }
+    }
 }
 
-void clients_post_select(Clients *c,Context *ctx, fd_set *rfds, fd_set *wfds)
+Clients *
+clients_new (void)
 {
+  Clients *ret = (Clients *) xmalloc (sizeof (Clients));
+
+  ret->n = 0;
+  ret->head = NULL;
 
+  return ret;
+}
+
+void
+clients_pre_select (Clients * cs, fd_set * rfds, fd_set * wfds)
+{
+  Client *c;
 
+  for (c = cs->head; c; c = c->next)
+    {
+      socket_pre_select (c->s, rfds, wfds);
+    }
 }
 
-Client * clients_new_client(Clients *c,Socket *s,Context *ctx)
+void
+clients_post_select (Clients * cs, Context * ctx, fd_set * rfds,
+                     fd_set * wfds)
 {
+  Client *c;
+  int deaded = 0;
 
-ipc_msg_send_debug(s,"fishsoup");
-socket_free(s);
+  for (c = cs->head; c; c = c->next)
+    {
+      if (socket_post_select (c->s, rfds, wfds))
+        {
+          c->dead++;
+          deaded++;
+        }
 
-return NULL;
+      if (c->s->msg)
+        {
+          client_execute_message (c, c->s->msg, ctx);
+          socket_consume_msg (c->s);
+          if (c->dead)
+            deaded++;
+        }
+
+    }
+
+  if (deaded)
+    clients_reap (cs, ctx);
 }
 
-void clients_shutdown(Clients *c)
+
+void
+clients_shutdown (Clients * cs, Context * ctx)
 {
+  Client *c;
+
+  for (c = cs->head; c; c = c->next)
+    {
+      c->dead++;
+    }
+
+
+  clients_reap (cs, ctx);
+}
 
 
 
+
+
+
+int
+send_status (Clients * cs, char *msg)
+{
+  char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_status)];
+  IPC_Msg_status *m = (IPC_Msg_status *) mbuf;
+  int len;
+
+  Client *c;
+
+  if (!msg)
+    return;
+  len = strlen (msg) + 1;
+
+  if (!len)
+    return;
+  if (len > IPC_MAX_BUF)
+    len = IPC_MAX_BUF;
+
+  m->size = len + sizeof (IPC_Msg_status);
+  m->type = IPC_MSG_TYPE_STATUS;
+  strncpy (m->status, msg, IPC_MAX_BUF);
+  m->status[IPC_MAX_BUF - 1] = 0;
+
+  for (c = cs->head; c; c = c->next)
+    {
+      if (!c->dead && c->initialized)
+        if (ipc_msg_send (c->s, (IPC_Msg *) m))
+          c->dead++;
+    }
+
+  return len;
+}
+
+
+int
+send_output (Clients * cs, void *buf, int len)
+{
+  char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_term)];
+  IPC_Msg_term *m = (IPC_Msg_term *) mbuf;
+
+  Client *c;
+
+  if (!len)
+    return;
+  if (len > IPC_MAX_BUF)
+    len = IPC_MAX_BUF;
+
+  m->size = len + sizeof (IPC_Msg_term);
+  m->type = IPC_MSG_TYPE_TERM;
+  m->len = len;
+  memcpy (m->term, buf, len);
+
+  for (c = cs->head; c; c = c->next)
+    {
+      if (!c->dead && c->initialized)
+        if (ipc_msg_send (c->s, (IPC_Msg *) m))
+          c->dead++;
+    }
+
+
+  return len;
+}
+
+void
+send_history (History * h, Client * c)
+{
+  int rptr = h->wptr;
+
+  HISTORY_INC (h, rptr);
+
+  HISTORY_INC (h, rptr);
+  while (rptr != h->wptr)
+    {
+      History_ent *l = &h->lines[rptr];
+      if (l->valid)
+        {
+
+          if (ipc_msg_send_history (c->s, l))
+            c->dead++;
+
+        }
+      HISTORY_INC (h, rptr);
+    }
+}
+
+void
+send_vt102 (VT102 * v, Client * c)
+{
+  if (ipc_msg_send_vt102 (c->s, v))
+    c->dead++;
+
 }