/* * sympathy.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id$"; /* * $Log$ * Revision 1.13 2008/02/15 23:52:12 james * *** empty log message *** * * 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 *** * * Revision 1.1 2008/02/05 14:25:49 james * *** empty log message *** * */ #include #include #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; } static char * line_to_name (int l) { 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 = "= 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); } static char * do_line (char *ptr, int lines, int line) { char *lname; if (!(lines & line)) return ptr; lname = line_to_name (line); *(ptr++) = ' '; while (*lname) *(ptr++) = *(lname++); return ptr; } 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.t = serial_open ("/dev/cellmodem", 0); 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"); }