chiark / gitweb /
*** empty log message ***
[sympathy.git] / apps / sympathyd.c
index a535ac6a34c7a7bb38e63ca8c73ea0f87c5b3e26..bdf81323008ab1e7967169d7d91c814bcc677493 100644 (file)
@@ -6,10 +6,41 @@
  *
  */
 
-static char rcsid[] = "$Id$";
+static char rcsid[] =
+  "$Id$";
 
 /*
  * $Log$
+ * Revision 1.12  2008/02/15 03:32:07  james
+ * *** empty log message ***
+ *
+ * Revision 1.11  2008/02/14 16:21:17  james
+ * *** empty log message ***
+ *
+ * Revision 1.10  2008/02/14 10:39:14  james
+ * *** empty log message ***
+ *
+ * Revision 1.9  2008/02/14 10:34:47  james
+ * *** empty log message ***
+ *
+ * Revision 1.8  2008/02/14 10:34:30  james
+ * *** empty log message ***
+ *
+ * Revision 1.7  2008/02/14 02:46:44  james
+ * *** empty log message ***
+ *
+ * Revision 1.6  2008/02/14 00:57:58  james
+ * *** empty log message ***
+ *
+ * Revision 1.5  2008/02/13 18:05:06  james
+ * *** empty log message ***
+ *
+ * Revision 1.4  2008/02/13 17:21:55  james
+ * *** empty log message ***
+ *
+ * Revision 1.3  2008/02/08 15:06:52  james
+ * *** empty log message ***
+ *
  * Revision 1.2  2008/02/07 15:42:49  james
  * *** empty log message ***
  *
@@ -18,36 +49,316 @@ static char rcsid[] = "$Id$";
  *
  */
 
-#include "sympathy.h"
-#include "ipc.h"
+#include <sys/time.h>
+#include <sympathy.h>
+
+#include "client.h"
+#include "clients.h"
+
+typedef struct
+{
+  int nclients;
+  int lines;
+  int baud;
+  int crtscts;
+  int cd_edge_sec;
+  int blocked;
+  int bootstrap;
+} Status;
+
+static Status
+get_status (TTY * t, Clients * cs)
+{
+  static struct timeval last_cd_edge = { 0 };
+  static int last_cd_state = -1;
+  int cd;
+  struct timeval now, dif;
+
+  TTY_Status tty_status = { 0 };
+  Status status;
+
+  tty_get_status (t, &tty_status);
+
+  status.bootstrap = 1;
+  status.nclients = cs->n;
+  status.lines = tty_status.lines;
+  status.baud = tty_status.baud;
+  status.crtscts = (tty_status.termios.c_cflag & CRTSCTS) ? 1 : 0;
+  status.blocked = tty_status.blocked;
+
+  cd = (tty_status.lines & TIOCM_CD) ? 1 : 0;
+
+  if (cd != last_cd_state)
+    {
+      gettimeofday (&last_cd_edge, NULL);
+      last_cd_state = cd;
+    }
+
+  gettimeofday (&now, NULL);
+  timersub (&now, &last_cd_edge, &dif);
+  status.cd_edge_sec = dif.tv_sec;
+
+  return status;
+}
 
-int main(int argc,char *argv[])
+static char *
+line_to_name (int l)
 {
-int fd;
-struct sockaddr_un sun={0};
 
-fd=socket(PF_UNIX,SOCK_STREAM,0);
-if (fd<0) {
-       perror("socket");
-       exit(1);
+  switch (l)
+    {
+#ifdef TIOCM_LE
+    case TIOCM_LE:
+      return "LE";
+#endif
+#ifdef TIOCM_DTR
+    case TIOCM_DTR:
+      return "DTR";
+#endif
+#ifdef TIOCM_RTS
+    case TIOCM_RTS:
+      return "RTS";
+#endif
+#ifdef TIOCM_ST
+    case TIOCM_ST:
+      return "ST";
+#endif
+#ifdef TIOCM_SR
+    case TIOCM_SR:
+      return "SR";
+#endif
+#ifdef TIOCM_CTS
+    case TIOCM_CTS:
+      return "CTS";
+#endif
+#ifdef TIOCM_CD
+    case TIOCM_CD:
+      return "CD";
+#endif
+#ifdef TIOCM_RI
+    case TIOCM_RI:
+      return "RI";
+#endif
+#ifdef TIOCM_DSR
+    case TIOCM_DSR:
+      return "DSR";
+#endif
+    }
+  return "??";
+}
+
+static void
+log_line_changes (Context * ctx, int old, int new)
+{
+  int dif = old ^ new;
+  int c = 1;
+  char buf[1024], *ptr = buf;
+  char *n;
+
+  if (!dif)
+    return;
+  if (!ctx->l)
+    return;
+
+  n = "<Modem lines changed:";
+
+  while (*n)
+    *(ptr++) = *(n++);
+
+  while (dif >= c)
+    {
+
+      if (dif & c)
+        {
+          *(ptr++) = ' ';
+          *(ptr++) = (new & c) ? '+' : '-';
+          n = line_to_name (c);
+          while (*n)
+            *(ptr++) = *(n++);
+        }
+
+      c <<= 1;
+    }
+  *(ptr++) = '>';
+  *ptr = 0;
+
+
+  ctx->l->log (ctx->l, buf);
+
 }
 
-sun.sun_family=AF_UNIX;
-strcpy(sun.sun_path,SOCKPATH);
+static char *
+do_line (char *ptr, int lines, int line)
+{
+  char *lname;
+
+  if (!(lines & line))
+    return ptr;
+  lname = line_to_name (line);
 
-unlink(SOCKPATH);
+  while (*lname)
+    *(ptr++) = *(lname++);
 
-if (bind(fd,(struct sockaddr *) &sun,sizeof(sun))<0)  {
-       perror("bind");
-       exit(1);
+  return ptr;
 }
 
-if (listen(fd,5)<0) {
-       perror("listen");
-       exit(1);
+
+
+static void
+check_status (Context * c, Clients * cs)
+{
+  static Status old_status = { 0 };
+  Status status;
+  char buf[1024];
+  char *ptr = buf;
+  char *t;
+
+  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);
+
+  ptr += sprintf (ptr, "CTRL-B ");
+
+  t = c->t->name;
+  if (!strncmp (t, "/dev/", 5))
+    t += 5;
+  while (*t)
+    *(ptr++) = *(t++);
+
+  ptr += sprintf (ptr, " %db", status.baud);
+
+  ptr = do_line (ptr, status.lines, TIOCM_RTS);
+  ptr = do_line (ptr, status.lines, TIOCM_CTS);
+  ptr = do_line (ptr, status.lines, TIOCM_DTR);
+  ptr = do_line (ptr, status.lines, TIOCM_DSR);
+  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 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);
+    }
+#endif
+
+  ptr +=
+    sprintf (ptr, ", %d client%s", status.nclients,
+             (status.nclients == 1) ? "" : "s");
+
+  *ptr = 0;
+
+  send_status (cs, buf);
 }
 
+int
+main (int argc, char *argv[])
+{
+  fd_set rfds, wfds;
+  Context c;
+  Socket *s, *cs;
+  Clients *clients;
+
+
+#if 0
+  construct_possible_lock_files ("/dev/modem");
+  return 0;
+#endif
+
+  s = socket_listen ("socket");
+
+  c.t = ptty_open (NULL, NULL);
+  c.v = vt102_new ();
+  c.h = history_new (200);
+  c.l = file_log_new ("log");
+  c.k = keydis_vt102_new ();
+  c.d = NULL;
+
+
+  clients = clients_new ();
+
+  for (;;)
+    {
+      struct timeval tv = { 1, 0 };
+
+      check_status (&c, clients);
+
+      FD_ZERO (&rfds);
+      FD_ZERO (&wfds);
+
+      tty_pre_select (c.t, &rfds, &wfds);
+
+      FD_SET (s->fd, &rfds);
+
+      socket_pre_select (s, &rfds, &wfds);
+
+      clients_pre_select (clients, &rfds, &wfds);
+
+      select (FD_SETSIZE, &rfds, &wfds, NULL, &tv);
+
+      if (FD_ISSET (s->fd, &rfds) && ((cs = socket_accept (s))))
+        {
+          {
+            Client *cl;
+            /*New client connexion */
+            cl = clients_new_client (clients, cs, &c);
+
+            send_history (c.h, cl);
+            send_vt102 (c.v, cl);
+
+          }
+        }
+
+
+      clients_post_select (clients, &c, &rfds, &wfds);
+
+      if (FD_ISSET (c.t->rfd, &rfds))
+        {
+          char buf[IPC_MAX_BUF];
+          int red;
+
+          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);
+            }
+        }
+
 
 
+    }
 
+  clients_shutdown (clients);
+  terminal_atexit ();
+  printf ("QUAT\n");
 }