chiark / gitweb /
Remove build products
[sympathy.git] / apps / mainloop.c
index 25718c48685f55fd183ab7949a9fe32b3c1b4e15..a54f59cab2a319f5050e341b35b979045c9bc27d 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* 
  * mainloop.c:
  *
  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
@@ -7,10 +7,46 @@
  */
 
 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 ***
  *
@@ -118,9 +154,9 @@ static char rcsid[] =
 
 #include "clients.h"
 
-Context *context;
 
-typedef struct {
+typedef struct
+{
   int nclients;
   int lines;
   int baud;
@@ -157,10 +193,11 @@ get_status (TTY * t, Clients * cs)
 
   cd = (tty_status.lines & TIOCM_CD) ? 1 : 0;
 
-  if (cd != last_cd_state) {
-    gettimeofday (&last_cd_edge, NULL);
-    last_cd_state = cd;
-  }
+  if (cd != last_cd_state)
+    {
+      gettimeofday (&last_cd_edge, NULL);
+      last_cd_state = cd;
+    }
 
   gettimeofday (&now, NULL);
   timersub (&now, &last_cd_edge, &dif);
@@ -173,44 +210,45 @@ static char *
 line_to_name (int l)
 {
 
-  switch (l) {
+  switch (l)
+    {
 #ifdef TIOCM_LE
-  case TIOCM_LE:
-    return "LE";
+    case TIOCM_LE:
+      return "LE";
 #endif
 #ifdef TIOCM_DTR
-  case TIOCM_DTR:
-    return "DTR";
+    case TIOCM_DTR:
+      return "DTR";
 #endif
 #ifdef TIOCM_RTS
-  case TIOCM_RTS:
-    return "RTS";
+    case TIOCM_RTS:
+      return "RTS";
 #endif
 #ifdef TIOCM_ST
-  case TIOCM_ST:
-    return "ST";
+    case TIOCM_ST:
+      return "ST";
 #endif
 #ifdef TIOCM_SR
-  case TIOCM_SR:
-    return "SR";
+    case TIOCM_SR:
+      return "SR";
 #endif
 #ifdef TIOCM_CTS
-  case TIOCM_CTS:
-    return "CTS";
+    case TIOCM_CTS:
+      return "CTS";
 #endif
 #ifdef TIOCM_CD
-  case TIOCM_CD:
-    return "CD";
+    case TIOCM_CD:
+      return "CD";
 #endif
 #ifdef TIOCM_RI
-  case TIOCM_RI:
-    return "RI";
+    case TIOCM_RI:
+      return "RI";
 #endif
 #ifdef TIOCM_DSR
-  case TIOCM_DSR:
-    return "DSR";
+    case TIOCM_DSR:
+      return "DSR";
 #endif
-  }
+    }
   return "??";
 }
 
@@ -232,18 +270,20 @@ log_line_changes (Context * ctx, int old, int new)
   while (*n)
     *(ptr++) = *(n++);
 
-  while (dif >= c) {
+  while (dif >= c)
+    {
 
-    if (dif & c) {
-      *(ptr++) = ' ';
-      *(ptr++) = (new & c) ? '+' : '-';
-      n = line_to_name (c);
-      while (*n)
-        *(ptr++) = *(n++);
-    }
+      if (dif & c)
+        {
+          *(ptr++) = ' ';
+          *(ptr++) = (new & c) ? '+' : '-';
+          n = line_to_name (c);
+          while (*n)
+            *(ptr++) = *(n++);
+        }
 
-    c <<= 1;
-  }
+      c <<= 1;
+    }
   *(ptr++) = '>';
   *ptr = 0;
 
@@ -304,45 +344,54 @@ check_status (Context * c, Clients * cs)
   ptr = do_line (ptr, status.lines, TIOCM_RI);
   ptr = do_line (ptr, status.lines, TIOCM_CD);
 
-  if (status.blocked) {
-    t = ", Locked";
-    while (*t)
-      *(ptr++) = *(t++);
-  }
-
-  if (status.crtscts) {
-    t = ", Flow";
-    while (*t)
-      *(ptr++) = *(t++);
-  }
+  if (status.blocked)
+    {
+      t = ", Locked";
+      while (*t)
+        *(ptr++) = *(t++);
+    }
+
+  if (status.crtscts)
+    {
+      t = ", Flow";
+      while (*t)
+        *(ptr++) = *(t++);
+    }
 #if 0
-  if (status.lines & TIOCM_CD) {
-    ptr +=
-      sprintf (ptr, ", On %d.%d", status.cd_edge_sec / 60,
-               status.cd_edge_sec % 60);
-  } else {
-    ptr +=
-      sprintf (ptr, ", Off %d.%d", status.cd_edge_sec / 60,
-               status.cd_edge_sec % 60);
-  }
+  if (status.lines & TIOCM_CD)
+    {
+      ptr +=
+        sprintf (ptr, ", On %d.%d", status.cd_edge_sec / 60,
+                 status.cd_edge_sec % 60);
+    }
+  else
+    {
+      ptr +=
+        sprintf (ptr, ", Off %d.%d", status.cd_edge_sec / 60,
+                 status.cd_edge_sec % 60);
+    }
 #endif
 
   ptr +=
     sprintf (ptr, ", %d client%s", status.nclients,
              (status.nclients == 1) ? "" : "s");
 
-  if (c->tp->biterrs) {
+  if (c->tp->biterrs)
+    {
 
-    ptr +=
-      sprintf (ptr, ", %d err%s", c->tp->biterrs,
-               (c->tp->biterrs == 1) ? "" : "s");
+      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);
+      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;
 
@@ -361,182 +410,200 @@ check_status (Context * c, Clients * cs)
 static int
 msg_from_server (ANSI * a, IPC_Msg * m, Context * c)
 {
-  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)
-      abort ();
-
-    *(c->v) = m->vt102.vt102;
-
-    if (a->one_shot) {
-      a->one_shot (a, &c->v->crt);
-      return 1;
+  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);
     }
-    break;
-  case IPC_MSG_TYPE_TERM:
-    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 0;
+  return err;
 }
 
 
 void
-mainloop (TTY * tty, Socket * server_socket, Socket * client_socket,
-          ANSI * ansi, Log * log, int nhistory, CRT_Pos * size)
+mainloop (Context * c, ANSI * ansi, Socket * server_socket,
+          Socket * client_socket)
 {
   fd_set rfds, wfds;
-  Context c = { 0 };
   Clients *clients;
 
-  context = &c;
-
-  c.tp = tty_parser_new ();
-  c.u = utf8_new ();
+  c->tp = tty_parser_new ();
+  c->u = utf8_new ();
 
-  c.v = vt102_new (size);
-  c.h = history_new (nhistory);
-  c.l = log;
   /* are we being fed by a tty or a socket */
-  if (client_socket) {
-    if (server_socket)
-      abort ();
-    c.k = keydis_ipc_new (client_socket);
-  } else {
-    if (!tty)
-      abort ();
-    c.t = tty;
-    c.k = keydis_vt102_new ();
-  }
+  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;
-  }
+  if (ansi)
+    {
+      c->d = cmd_new ();
+    }
+  else
+    {
+      c->d = NULL;
+    }
 
 
-  vt102_reset (&c);
+  vt102_reset (c);
 
 
-  if (server_socket) {
-    if (client_socket)
-      abort ();
-    clients = clients_new ();
-  } else {
-    clients = NULL;
-  }
+  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 = { 0, 250000 };
+  for (;;)
+    {
+      struct timeval tv = { 0, 250000 };
 
-    if ((c.d) && (c.d->disconnect))
-      break;
+      if ((c->d) && (c->d->disconnect))
+        break;
 
-    /*update the status lines, locally or remotely */
-    if (c.t)
-      check_status (&c, clients);
+      /* update the status lines, locally or remotely */
+      if (c->t)
+        check_status (c, clients);
 
-    FD_ZERO (&rfds);
-    FD_ZERO (&wfds);
+      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);
+      if (ansi && ansi->terminal)
+        tty_pre_select (ansi->terminal, &rfds, &wfds);
 
-    select (FD_SETSIZE, &rfds, &wfds, NULL, &tv);
+      select (FD_SETSIZE, &rfds, &wfds, NULL, &tv);
 
-    /*any message from clients, or new connexions */
-    if (server_socket) {
-      Socket *new_client_socket;
-      if (FD_ISSET (server_socket->fd, &rfds)
-          && ((new_client_socket = socket_accept (server_socket)))) {
+      /* any message from clients, or new connexions */
+      if (server_socket)
         {
-          Client *new_client;
-          /*New client connexion */
-          new_client = clients_new_client (clients, new_client_socket, &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, new_client);
-          send_vt102 (c.v, new_client);
+              }
+            }
 
+          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))
+        {
+          char buf[IPC_MAX_BUF];
+          int red;
 
-    /*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 < 0)
-        break;
+          if (red)
+            {
+              if (clients)
+                send_output (clients, buf, red);
+              if (tty_parse (c, buf, red))
+                break;
+            }
+        }
 
-      if (red) {
-        if (clients)
-          send_output (clients, buf, red);
-        tty_parse (&c, buf, red);
-      }
-    }
 
 
+      /* any data from the server */
+      if (client_socket)
+        {
+          int err = 0;
 
-    /*any data from the server */
-    if (client_socket) {
-      int one_shot;
-      if (socket_post_select (client_socket, &rfds, &wfds))
-        break;
+          if (socket_post_select (client_socket, &rfds, &wfds))
+            break;
 
-      while (client_socket->msg) {
-        if (msg_from_server (ansi, client_socket->msg, &c))
-          one_shot++;
+          while (client_socket->msg && !err)
+            {
+              err += msg_from_server (ansi, client_socket->msg, c);
+              socket_consume_msg (client_socket);
+            }
 
-        socket_consume_msg (client_socket);
-      }
-      if (one_shot)
-        break;
-    }
+          if (err)
+            break;
+        }
 
 
-    /*update our local screen */
-    if (ansi) {
-      if (ansi->dispatch)
-        ansi->dispatch (ansi, &c);
+      /* update our local screen */
+      if (ansi)
+        {
+          if (ansi->dispatch)
+            if (ansi->dispatch (ansi, c))
+              break;
 
-      if (ansi->update)
-        ansi->update (ansi, &c);
+          if (ansi->update)
+            if (ansi->update (ansi, c))
+              break;
+        }
     }
-  }
 
   if (clients)
-    clients_shutdown (clients);
+    clients_shutdown (clients, c);
+  log_f (c->l, "<sympathy is now terminating>");
 }