chiark / gitweb /
Remove build products
[sympathy.git] / apps / mainloop.c
index e3d2190420e2a95c94a8de9c4d87dee351954a91..a54f59cab2a319f5050e341b35b979045c9bc27d 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* 
  * mainloop.c:
  *
  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
  */
 
 static char rcsid[] =
-  "$Id$";
+  "$Id: mainloop.c,v 1.33 2008/05/09 12:35:57 james Exp $";
 
-/*
- * $Log$
+/* 
+ * $Log: mainloop.c,v $
+ * Revision 1.33  2008/05/09 12:35:57  james
+ * *** empty log message ***
+ *
+ * Revision 1.32  2008/03/11 17:56:50  james
+ * *** empty log message ***
+ *
+ * Revision 1.31  2008/03/11 17:56:04  james
+ * *** empty log message ***
+ *
+ * Revision 1.30  2008/03/11 17:47:24  james
+ * *** empty log message ***
+ *
+ * Revision 1.29  2008/03/10 11:49:32  james
+ * *** empty log message ***
+ *
+ * Revision 1.28  2008/03/07 13:56:39  james
+ * *** empty log message ***
+ *
+ * Revision 1.27  2008/03/07 13:16:02  james
+ * *** empty log message ***
+ *
+ * Revision 1.26  2008/03/06 21:34:09  james
+ * *** empty log message ***
+ *
+ * Revision 1.25  2008/03/06 21:33:02  james
+ * *** empty log message ***
+ *
+ * Revision 1.24  2008/03/06 16:49:39  james
+ * *** empty log message ***
+ *
+ * Revision 1.23  2008/03/06 16:49:05  james
+ * *** empty log message ***
+ *
+ * Revision 1.22  2008/03/03 06:04:42  james
+ * *** empty log message ***
+ *
+ * Revision 1.21  2008/03/02 10:27:24  james
+ * *** empty log message ***
+ *
+ * Revision 1.20  2008/02/28 16:57:51  james
+ * *** empty log message ***
+ *
+ * Revision 1.19  2008/02/28 16:37:16  james
+ * *** empty log message ***
+ *
+ * Revision 1.18  2008/02/28 11:27:48  james
+ * *** empty log message ***
+ *
+ * Revision 1.17  2008/02/27 09:42:53  james
+ * *** empty log message ***
+ *
+ * Revision 1.16  2008/02/27 09:42:21  james
+ * *** empty log message ***
+ *
+ * Revision 1.15  2008/02/27 01:31:38  james
+ * *** empty log message ***
+ *
+ * Revision 1.14  2008/02/27 01:31:14  james
+ * *** empty log message ***
+ *
+ * Revision 1.13  2008/02/26 23:56:12  james
+ * *** empty log message ***
+ *
+ * Revision 1.12  2008/02/26 23:23:16  james
+ * *** empty log message ***
+ *
+ * Revision 1.11  2008/02/24 00:43:55  james
+ * *** empty log message ***
+ *
+ * Revision 1.10  2008/02/23 13:05:57  staffcvs
+ * *** empty log message ***
+ *
+ * Revision 1.9  2008/02/23 11:48:51  james
+ * *** empty log message ***
+ *
+ * Revision 1.8  2008/02/22 23:39:30  james
+ * *** empty log message ***
+ *
+ * Revision 1.7  2008/02/20 20:16:07  james
+ * *** empty log message ***
+ *
+ * Revision 1.6  2008/02/20 19:44:37  james
+ * @@
+ *
+ * Revision 1.5  2008/02/20 18:31:44  james
+ * *** empty log message ***
+ *
+ * Revision 1.4  2008/02/20 17:18:33  james
+ * *** empty log message ***
+ *
+ * Revision 1.3  2008/02/20 02:11:35  james
+ * *** empty log message ***
+ *
  * Revision 1.2  2008/02/16 10:58:52  james
  * *** empty log message ***
  *
@@ -57,10 +150,11 @@ static char rcsid[] =
 
 #include <sys/time.h>
 #include <sympathy.h>
+#include "mainloop.h"
 
-#include "client.h"
 #include "clients.h"
 
+
 typedef struct
 {
   int nclients;
@@ -86,7 +180,12 @@ get_status (TTY * t, Clients * cs)
   tty_get_status (t, &tty_status);
 
   status.bootstrap = 1;
-  status.nclients = cs->n;
+
+  if (cs)
+    status.nclients = cs->n;
+  else
+    status.nclients = 0;
+
   status.lines = tty_status.lines;
   status.baud = tty_status.baud;
   status.crtscts = (tty_status.termios.c_cflag & CRTSCTS) ? 1 : 0;
@@ -223,11 +322,11 @@ check_status (Context * c, Clients * cs)
   status = get_status (c->t, cs);
   if (!memcmp (&status, &old_status, sizeof (status)))
     return;
-  old_status = status;
-
 
   log_line_changes (c, old_status.lines, status.lines);
 
+  old_status = status;
+
   ptr += sprintf (ptr, "CTRL-B ");
 
   t = c->t->name;
@@ -258,7 +357,6 @@ check_status (Context * c, Clients * cs)
       while (*t)
         *(ptr++) = *(t++);
     }
-
 #if 0
   if (status.lines & TIOCM_CD)
     {
@@ -278,119 +376,234 @@ check_status (Context * c, Clients * cs)
     sprintf (ptr, ", %d client%s", status.nclients,
              (status.nclients == 1) ? "" : "s");
 
+  if (c->tp->biterrs)
+    {
+
+      ptr +=
+        sprintf (ptr, ", %d err%s", c->tp->biterrs,
+                 (c->tp->biterrs == 1) ? "" : "s");
+
+      if (c->tp->guessed_baud == -1)
+        {
+          ptr += sprintf (ptr, " try higher");
+        }
+      else if (c->tp->guessed_baud > 0)
+        {
+          ptr += sprintf (ptr, " try %db", c->tp->guessed_baud);
+        }
+    }
+
   *ptr = 0;
 
-  send_status (cs, buf);
+#if 0
+  log_f (c->l, "%s:%d %s", __FILE__, __LINE__, buf);
+#endif
+
+  if (cs)
+    send_status (cs, buf);
+  else
+    cmd_new_status (c->d, c, buf);
+
 }
 
 
-  TTY *t;
-  Log *l;
-  t= ptty_open (NULL, NULL);
-  //t = serial_open ("/dev/cellmodem", 0);
-l=file_log_new ("log");
+static int
+msg_from_server (ANSI * a, IPC_Msg * m, Context * c)
+{
+  int err = 0;
+  switch (m->hdr.type)
+    {
 
+    case IPC_MSG_TYPE_NOOP:
+      break;
+    case IPC_MSG_TYPE_DEBUG:
+      // fprintf (stderr,"%p [%d] %s\n", m, m->hdr.size , m->debug.msg );
+      break;
+    case IPC_MSG_TYPE_HISTORY:
+      history_add (c->h, m->history.history.line);
+      break;
+    case IPC_MSG_TYPE_VT102:
+      if (sizeof (VT102) != m->vt102.len)
+        crash_out ("sizeof(VT102) differs in client and server");
+
+      *(c->v) = m->vt102.vt102;
+
+      if (a->one_shot)
+        {
+          a->one_shot (a, &c->v->crt);
+          err++;                /* Simulate a fatal write error enclosing tty 
+                                 */
+        }
+      break;
+    case IPC_MSG_TYPE_TERM:
+      err += tty_parse (c, m->term.term, m->term.len);
+      break;
+    case IPC_MSG_TYPE_STATUS:
+      cmd_new_status (c->d, c, m->status.status);
+      break;
+    default:
+      fprintf (stderr, "Unhandeled message type %d\n", m->hdr.type);
+    }
+  return err;
+}
 
-void mainloop (TTY *tty,Socket *server_socket,Socket *client_socket,Ansi *a,Log *log)
+
+void
+mainloop (Context * c, ANSI * ansi, Socket * server_socket,
+          Socket * client_socket)
 {
   fd_set rfds, wfds;
-  Context c;
   Clients *clients;
 
-  c.v = vt102_new ();
-  c.h = history_new (200);
-  c.l = log
+  c->tp = tty_parser_new ();
+  c->u = utf8_new ();
 
   /* are we being fed by a tty or a socket */
-  if (client_socket) {
-       if (server_socket) abort();
-       c.s = client_socket;  
-        c.k = keydis_ipc_new (client_socket);
-  } else {
-       if (!tty) abort();
-       c.t = tty;
-       c.k = keydis_vt102_new ();
-  }
-
-  /* do we have an upstream terminal to talk to*/
-  if (ansi) {
-       c.d = cmd_new ();
-  } else {
-       c.d = NULL;
-  }
-
-
-  if (server_socket) {
-       if(client_socket) abort();
-       clients = clients_new ();
-  } else {
-       clients=NULL;
-  }
+  if (client_socket)
+    {
+      if (server_socket)
+        crash_out ("mainloop cannot both be a server and a client");
+      c->k = keydis_ipc_new (client_socket);
+    }
+  else
+    {
+      if (!c->t)
+        crash_out ("mainloop must have either a client_socket or a terminal");
+      c->k = keydis_vt102_new ();
+    }
+
+  /* do we have an upstream terminal to talk to */
+  /* if so start a command parser */
+  if (ansi)
+    {
+      c->d = cmd_new ();
+    }
+  else
+    {
+      c->d = NULL;
+    }
+
+
+  vt102_reset (c);
+
+
+  if (server_socket)
+    {
+      if (client_socket)
+        crash_out ("mainloop cannot both be a server and a client");
+      clients = clients_new ();
+    }
+  else
+    {
+      clients = NULL;
+    }
 
   for (;;)
     {
-      struct timeval tv = { 1, 0 };
+      struct timeval tv = { 0, 250000 };
 
-      check_status (&c, clients);
+      if ((c->d) && (c->d->disconnect))
+        break;
+
+      /* update the status lines, locally or remotely */
+      if (c->t)
+        check_status (c, clients);
 
       FD_ZERO (&rfds);
       FD_ZERO (&wfds);
 
-       if (c.t)
-          tty_pre_select (c.t, &rfds, &wfds);
+      if (c->t)
+        tty_pre_select (c->t, &rfds, &wfds);
+
+      if (server_socket)
+        {
+          FD_SET (server_socket->fd, &rfds);
+          clients_pre_select (clients, &rfds, &wfds);
+        }
 
-       if (server_socket) {
-      FD_SET (server_socket->fd, &rfds);
-      clients_pre_select (clients, &rfds, &wfds);
-       }
+      if (client_socket)
+        socket_pre_select (client_socket, &rfds, &wfds);
 
-       if (client_socket)
-      socket_pre_select (client_socket, &rfds, &wfds);
+      if (ansi && ansi->terminal)
+        tty_pre_select (ansi->terminal, &rfds, &wfds);
 
       select (FD_SETSIZE, &rfds, &wfds, NULL, &tv);
 
-      /*any message from clients, or new connexions*/
-      if (server_socket) {
-      Socket *cs;
-      if (FD_ISSET (server_socket->fd, &rfds) && ((cs = socket_accept (s))))
+      /* any message from clients, or new connexions */
+      if (server_socket)
         {
-          {
-            Client *cl;
-            /*New client connexion */
-            cl = clients_new_client (clients, cs, &c);
+          Socket *new_client_socket;
+          if (FD_ISSET (server_socket->fd, &rfds)
+              && ((new_client_socket = socket_accept (server_socket))))
+            {
+              {
+                Client *new_client;
+                /* New client connexion */
+                new_client =
+                  clients_new_client (clients, new_client_socket, c);
 
-            send_history (c.h, cl);
-            send_vt102 (c.v, cl);
 
-          }
-        }
+              }
+            }
 
-      clients_post_select (clients, &c, &rfds, &wfds);
-      }
+          clients_post_select (clients, c, &rfds, &wfds);
+        }
 
-      /*any data from the port*/
-      if (c.t && FD_ISSET (c.t->rfd, &rfds))
+      /* any data from the port */
+      if (c->t && FD_ISSET (c->t->rfd, &rfds))
         {
           char buf[IPC_MAX_BUF];
           int red;
 
-          red = c.t->recv (c.t, buf, sizeof (buf));
+          red = c->t->recv (c->t, buf, sizeof (buf));
 
           if (red < 0)
             break;
 
           if (red)
             {
-              send_output (clients, buf, red);
-              vt102_parse (&c, buf, red);
+              if (clients)
+                send_output (clients, buf, red);
+              if (tty_parse (c, buf, red))
+                break;
+            }
+        }
+
+
+
+      /* any data from the server */
+      if (client_socket)
+        {
+          int err = 0;
+
+          if (socket_post_select (client_socket, &rfds, &wfds))
+            break;
+
+          while (client_socket->msg && !err)
+            {
+              err += msg_from_server (ansi, client_socket->msg, c);
+              socket_consume_msg (client_socket);
             }
+
+          if (err)
+            break;
         }
 
 
+      /* update our local screen */
+      if (ansi)
+        {
+          if (ansi->dispatch)
+            if (ansi->dispatch (ansi, c))
+              break;
 
+          if (ansi->update)
+            if (ansi->update (ansi, c))
+              break;
+        }
     }
 
-  clients_shutdown (clients);
-  terminal_atexit ();
-  printf ("QUAT\n");
+  if (clients)
+    clients_shutdown (clients, c);
+  log_f (c->l, "<sympathy is now terminating>");
 }