chiark / gitweb /
*** empty log message ***
[sympathy.git] / apps / sympathyd.c
index 4845c95c27866344aeda50bab0abbcc8ae725a29..49dd3120bc759b37522d2aca31aeabc9951adc0b 100644 (file)
@@ -6,10 +6,26 @@
  *
  */
 
-static char rcsid[] = "$Id$";
+static char rcsid[] =
+  "$Id$";
 
 /*
  * $Log$
+ * 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 ***
  *
@@ -21,40 +37,292 @@ static char rcsid[] = "$Id$";
  *
  */
 
-#include "sympathy.h"
-#include "ipc.h"
+#include <sys/time.h>
+#include <sympathy.h>
 
-#include "../src/crt.h"
-#include "../src/vt102.h"
+#include "client.h"
+#include "clients.h"
 
+typedef struct
+{
+  int nclients;
+  int lines;
+  int baud;
+  int crtscts;
+  int cd_edge_sec;
+  int bootstrap;
+} Status;
 
-int main(int argc,char *argv[])
+static Status
+get_status (TTY * t, Clients * cs)
 {
-int fd;
-struct sockaddr_un sun={0};
+  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;
+
+  cd = (tty_status.lines & TIOCM_CD) ? 1 : 0;
 
-fd=socket(PF_UNIX,SOCK_STREAM,0);
-if (fd<0) {
-       perror("socket");
-       exit(1);
+  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;
 }
 
-sun.sun_family=AF_UNIX;
-strcpy(sun.sun_path,SOCKPATH);
+static char *
+line_to_name (int l)
+{
 
-unlink(SOCKPATH);
+  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);
 
-if (bind(fd,(struct sockaddr *) &sun,sizeof(sun))<0)  {
-       perror("bind");
-       exit(1);
 }
 
-if (listen(fd,5)<0) {
-       perror("listen");
-       exit(1);
+static char *
+do_line (char *ptr,int lines, int line)
+{
+  char *lname;
+
+  if (!(lines & line))
+    return ptr;
+  lname = line_to_name (line);
+
+  while (*lname)
+    *(ptr++) = *(lname++);
+
+  return ptr;
 }
 
 
-printf("sizeof(VT102)=%d\n",sizeof(VT102));
 
+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);
+
+  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);
+
+  if (status.crtscts) {
+       t=", Flow";
+  while (*t)
+    *(ptr++) = *(t++);
+    }
+  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);
+    }
+
+  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;
+
+
+  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);
+
+
+  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");
 }