a working version?
authordjk <djk>
Sun, 26 Mar 2000 14:18:24 +0000 (14:18 +0000)
committerdjk <djk>
Sun, 26 Mar 2000 14:18:24 +0000 (14:18 +0000)
with debugging

src/Makefile
src/client.c
src/debug.c [new file with mode: 0755]
src/debug.h [new file with mode: 0644]

index 09d6864585cd34d62c61b51bf809a5da5e770403..2794782599cd25b99f297f687acd88fef6217108 100644 (file)
@@ -4,7 +4,7 @@
 
 CFLAGS = -g -O
 
-CLIENTOBJ = client.o sel.o cmsg.o chain.o
+CLIENTOBJ = client.o sel.o cmsg.o chain.o debug.o
 CLIENTBIN = client
 
 $(CLIENTBIN) : $(CLIENTOBJ)
index 640c2b4467dc648e655b990ffd164d66ebd9e893..3dadfc59785c3dcab353538d14e7aa4e04c85384 100644 (file)
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+#include <termios.h>
 
 #include "sel.h"
 #include "cmsg.h"
+#include "debug.h"
 
 #define TEXT 1
 #define MSG 2
 #define MAXBUFL 1024
 
+#define DBUF 1
+#define DMSG 2
+
 typedef struct 
 {
        int cnum;                                       /* the connection number */
@@ -46,6 +51,8 @@ typedef struct
        reft *inq;                                      /* input queue */
        reft *outq;                                     /* output queue */
        sel_t *sp;                                      /* my select fcb address */
+       int echo;                                       /* echo characters back to this cnum */
+       struct termios t;                       /* any termios associated with this cnum */
 } fcb_t;
 
 char *node_addr = "localhost"; /* the node tcp address */
@@ -53,11 +60,13 @@ int node_port = 27754;                      /* the tcp port of the node at the above address */
 char *call;                                            /* the caller's callsign */
 char *connsort;                                        /* the type of connection */
 fcb_t *in;                                             /* the fcb of 'stdin' that I shall use */
-fcb_t *out;                                            /* the fcb of 'stdout' that I shall use */
 fcb_t *node;                                   /* the fcb of the msg system */
 char nl = '\n';                                        /* line end character */
 char ending = 0;                               /* set this to end the program */
 char send_Z = 1;                               /* set a Z record to the node on termination */
+char echo = 1;                                 /* echo characters on stdout from stdin */
+
+void terminate(int);
 
 /*
  * utility routines - various
@@ -71,8 +80,8 @@ void die(char *s, ...)
        va_start(ap, s);
        vsprintf(buf, s, ap);
        va_end(ap);
-       fprintf(stderr, buf);
-       exit(-1);
+       fprintf(stderr,"%s\n", buf);
+       terminate(-1);
 }
 
 char *strupper(char *s)
@@ -156,7 +165,7 @@ void send_msg(fcb_t *f, char let, char *s, int l)
 int fcb_handler(sel_t *sp, int in, int out, int err)
 {
        fcb_t *f = sp->fcb;
-       cmsg_t *mp;
+       cmsg_t *mp, *omp;
        
        /* input modes */
        if (in) {
@@ -184,36 +193,67 @@ int fcb_handler(sel_t *sp, int in, int out, int err)
                        return 0;
                }
 
+               dbgdump(DBUF, "in ->", buf, r);
+               
                /* create a new message buffer if required */
                if (!f->in)
-                       f->in = cmsg_new(MAXBUFL, sp->sort, f);
+                       f->in = cmsg_new(MAXBUFL, f->sort, f);
                mp = f->in;
 
                switch (f->sort) {
                case TEXT:
                        p = buf;
+                       if (f->echo)
+                               omp = cmsg_new(3*r, f->sort, f);
                        while (r > 0 && p < &buf[r]) {
+
+                               /* echo processing */
+                               if (f->echo) {
+                                       switch (*p) {
+                                       case '\b':
+                                       case 0x7f:
+                                               strcpy(omp->inp, "\b \b");
+                                               omp->inp += strlen(omp->inp);
+                                               break;
+                                       default:
+                                               *omp->inp++ = *p;
+                                       }
+                               }
                                
-                               /*
-                                * if we have a nl then send the message upstairs
-                                * start a new message
-                                */
-                               
-                               if (*p == nl) {
-                                       if (mp->inp == mp->data)
-                                               *mp->inp++ = ' ';
-                                       *mp->inp = 0;              /* zero terminate it, but don't include it in the length */
-                                       cmsg_send(f->inq, mp, 0);
-                                       f->in = mp = cmsg_new(MAXBUFL, sp->sort, f);
+                               /* character processing */
+                               switch (*p) {
+                               case '\b':
+                               case 0x7f:
+                                       if (mp->inp > mp->data)
+                                               mp->inp--;
                                        ++p;
-                               } else {
-                                       if (mp->inp < &mp->data[MAXBUFL])
-                                               *mp->inp++ = *p++;
-                                       else {
-                                               mp->inp = mp->data;
+                                       break;
+                               default:
+                                       if (*p == nl) {
+                                               if (mp->inp == mp->data)
+                                                       *mp->inp++ = ' ';
+                                               *mp->inp = 0;              /* zero terminate it, but don't include it in the length */
+                                               dbgdump(DMSG, "QUEUE TEXT", mp->data, mp->inp-mp->data);
+                                               cmsg_send(f->inq, mp, 0);
+                                               f->in = mp = cmsg_new(MAXBUFL, f->sort, f);
+                                               ++p;
+                                       } else {
+                                               if (mp->inp < &mp->data[MAXBUFL])
+                                                       *mp->inp++ = *p++;
+                                               else {
+                                                       mp->inp = mp->data;
+                                               }
                                        }
                                }
                        }
+                       
+                       /* queue any echo text */
+                       if (f->echo) {
+                               dbgdump(DMSG, "QUEUE ECHO TEXT", omp->data, omp->inp - omp->data);
+                               cmsg_send(f->outq, omp, 0);
+                               f->sp->flags |= SEL_OUTPUT;
+                       }
+                       
                        break;
 
                case MSG:
@@ -224,16 +264,20 @@ int fcb_handler(sel_t *sp, int in, int out, int err)
                                switch (mp->state) {
                                case 0:
                                case 1:
+                                       mp->state++;
+                                       break;
                                case 2:
                                case 3:
-                                       mp->size = (mp->size << 8) | *p++;
+                                       mp->size = (mp->size << 8) | (*p++ & 0xff);
                                        mp->state++;
                                        break;
                                default:
                                        if (mp->inp - mp->data < mp->size) {
                                                *mp->inp++ = *p++;
-                                       } else {
+                                       } 
+                                       if (mp->inp - mp->data >= mp->size) {
                                                /* kick it upstairs */
+                                               dbgdump(DMSG, "QUEUE MSG", mp->data, mp->inp - mp->data);
                                                cmsg_send(f->inq, mp, 0);
                                                mp = f->in = cmsg_new(MAXBUFL, f->sort, f);
                                        }
@@ -261,6 +305,9 @@ lout:;
                }
                l = mp->size - (mp->inp - mp->data);
                if (l > 0) {
+                       
+                       dbgdump(DBUF, "<-out", mp->inp, l);
+                       
                        r = write(f->cnum, mp->inp, l);
                        if (r < 0) {
                                switch (errno) {
@@ -282,8 +329,8 @@ lout:;
                if (mp->inp - mp->data >= mp->size) {
                        cmsg_callback(mp, 0);
                        f->out = 0;
-                       if (!is_chain_empty(f->outq))
-                               sp->flags &= ~SEL_OUTPUT;
+/*                     if (is_chain_empty(f->outq))
+                       sp->flags &= ~SEL_OUTPUT; */
                }
        }
 lend:;
@@ -296,26 +343,49 @@ lend:;
 
 void initargs(int argc, char *argv[])
 {
-       int i;
-       if (argc >= 2) {
-               call = strupper(argv[1]);
+       int i, c, err = 0;
+
+       while ((c = getopt(argc, argv, "x:")) > 0) {
+               switch (c) {
+               case 'x':
+                       dbginit("client");
+                       dbgset(atoi(optarg));
+                       break;
+               default:
+                       ++err;
+                       goto lerr;
+               }
+       }
+
+lerr:
+       if (err) {
+               die("usage: client [-x nn] <call>|login [local|telnet|ax25]");
+       }
+       
+       if (optind < argc) {
+               call = strupper(argv[optind]);
                if (eq(call, "LOGIN"))
                        die("login not implemented (yet)");
+               ++optind;
        }
        if (!call)
                die("Must have at least a callsign (for now)");
 
-       if (argc >= 3) {
-               connsort = strlower(argv[2]);
+       if (optind < argc) {
+               connsort = strlower(argv[optind]);
                if (eq(connsort, "telnet") || eq(connsort, "local")) {
                        nl = '\n';
+                       echo = 1;
                } else if (eq(connsort, "ax25")) {
                        nl = '\r';
+                       echo = 0;
                } else {
                        die("2nd argument must be \"telnet\" or \"ax25\" or \"local\"");
                }
        } else {
                connsort = "local";
+               nl = '\n';
+               echo = 1;
        }
 }
 
@@ -353,11 +423,10 @@ void connect_to_node()
 void term_timeout(int i)
 {
        /* none of this is going to be reused so don't bother cleaning up properly */
-       if (out)
-               out = 0;
+       if (in)
+               tcsetattr(0, TCSANOW, &in->t);
        if (node) {
                close(node->cnum);
-               node = 0;
        }
        exit(i);
 }
@@ -371,10 +440,12 @@ void terminate(int i)
        signal(SIGALRM, term_timeout);
        alarm(10);
        
-       while ((out && !is_chain_empty(out->outq)) ||
+       while ((in && !is_chain_empty(in->outq)) ||
                   (node && !is_chain_empty(node->outq))) {
                sel_run();
        }
+       if (in)
+               tcsetattr(0, TCSANOW, &in->t);
        if (node) 
                close(node->cnum);
        exit(i);
@@ -388,7 +459,11 @@ void process_stdin()
 {
        cmsg_t *mp = cmsg_next(in->inq);
        if (mp) {
-               send_msg(node, 'I', mp->data, mp->size);
+               dbg(DMSG, "MSG size: %d", mp->size);
+       
+               if (mp->size > 0 && mp->inp > mp->data) {
+                       send_msg(node, 'I', mp->data, mp->size);
+               }
                cmsg_callback(mp, 0);
        }
 }
@@ -397,27 +472,33 @@ void process_node()
 {
        cmsg_t *mp = cmsg_next(node->inq);
        if (mp) {
-               char *p = strchr(mp->data, '|');
-               if (p)
-                       p++;
-               switch (mp->data[0]) {
-               case 'Z':
-                       send_Z = 0;
-                       ending++;
-                       return;
-               case 'D':
-                       if (p) {
-                               int l = mp->inp - (unsigned char *) p;
-                               send_text(out, p, l);
+               dbg(DMSG, "MSG size: %d", mp->size);
+       
+               if (mp->size > 0 && mp->inp > mp->data) {
+                       char *p = strchr(mp->data, '|');
+                       if (p)
+                               p++;
+                       switch (mp->data[0]) {
+                       case 'Z':
+                               send_Z = 0;
+                               ending++;
+                               return;
+                       case 'E':
+                               if (isdigit(*p))
+                                       in->echo = *p - '0';
+                               break;
+                       case 'D':
+                               if (p) {
+                                       int l = mp->inp - (unsigned char *) p;
+                                       send_text(in, p, l);
                        }
-                       break;
-               default:
-                       break;
-               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
                cmsg_callback(mp, 0);
        }
-       if (is_chain_empty(out->outq))
-               fsync(out->cnum);
 }
 
 /*
@@ -439,8 +520,15 @@ main(int argc, char *argv[])
        /* connect up stdin, stdout and message system */
        in = fcb_new(0, TEXT);
        in->sp = sel_open(0, in, "STDIN", fcb_handler, TEXT, SEL_INPUT);
-       out = fcb_new(1, TEXT);
-       out->sp = sel_open(1, out, "STDOUT", fcb_handler, TEXT, 0);
+       if (tcgetattr(0, &in->t) < 0) 
+               die("tcgetattr (%d)", errno);
+       {
+               struct termios t = in->t;
+               t.c_lflag &= ~(ECHO|ECHONL|ICANON);
+               if (tcsetattr(0, TCSANOW, &t) < 0) 
+                       die("tcsetattr (%d)", errno);
+               in->echo = echo;
+       }
        connect_to_node();
 
        /* tell the cluster who I am */
@@ -461,3 +549,4 @@ main(int argc, char *argv[])
 
 
 
+
diff --git a/src/debug.c b/src/debug.c
new file mode 100755 (executable)
index 0000000..d489943
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * debug routines
+ *
+ * Copyright (c) 1998 Dirk Koopman G1TLH
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#define LOGDIR "./dbg"
+
+static char opened = 0;
+unsigned long dbglevel = 0;
+static int pid;
+static char *prog;
+static FILE *f;
+static int thisday;
+static time_t systime;
+
+void (*dbgproc)();
+char dbgbuf[1500];
+
+static int getdayno(time_t t)
+{
+       struct tm *tm;
+       
+       tm = gmtime(&t);
+       return tm->tm_mday;
+}
+
+static char *genlogname(char *dir, char *fn, int day, int readonly)
+{
+       static char buf[256];
+       struct stat s;
+       
+       sprintf(buf, "%s/%s_%d", dir, fn, day);
+       
+       /* look to see if this is out of date, if it is remove it */
+       if (!readonly && stat(buf, &s) >= 0) {
+               if (systime - s.st_mtime > (7*24*60*60)) 
+                       unlink(buf);
+       }
+       return buf;
+}
+
+static void rotate_log()
+{
+       int i;
+       char *fn;
+       
+       i = getdayno(systime);
+       if (i != thisday) {
+               thisday = i;
+               dbghup();
+       }
+}
+
+void dbghup()
+{
+       char *fn;
+       
+       if (f) {
+               fclose(f);
+               f = 0;
+       }
+       if (!f) {
+               if (!thisday)
+                       thisday = getdayno(systime);
+        fn = genlogname(LOGDIR, "log", thisday, 0);
+               f = fopen(fn, "a");
+    }
+       
+       if (!f)
+               die("can't open %s (%d) for debug", fn, errno);
+}
+
+char *dbgtime()
+{
+       time_t t;
+       char *ap;
+       static char buf[30];
+       
+       ap = ctime(&systime);
+       sprintf(buf, "%2.2s%3.3s%4.4s %8.8s", &ap[8], &ap[4], &ap[20], &ap[11]);
+       return buf;
+}
+
+void dbginit(char *ident)
+{
+       pid = getpid();
+       prog = strdup(ident);
+       time(&systime);
+       mkdir(LOGDIR, 01777);
+       dbghup();
+}
+
+void dbgadd(unsigned long level)
+{
+    dbglevel |= level;
+}
+
+void dbgsub(unsigned long level)
+{
+    dbglevel &= ~level;
+}
+
+void dbgset(unsigned long level)
+{
+    dbglevel = level;
+}
+
+unsigned long dbgget()
+{
+       return dbglevel;
+}
+
+void dbgread(char *s)
+{
+    unsigned long level = strtoul(s, 0, 0);
+    dbgset(level);
+}
+
+void dbg(unsigned long level, char *format, ...)
+{
+    if (f && DBGLEVEL(level)) {
+               char dbuf[100];
+        char buf[1500-100];
+               int i;
+        va_list ap;
+               
+               time(&systime);
+               
+               rotate_log();
+               
+        sprintf(dbuf, "%s %s[%d,%04x] ", dbgtime(), prog, pid, level);
+        va_start(ap, format);
+        vsprintf(buf, format, ap);
+               i = strlen(buf);
+               if (i>1 && buf[i-1] == '\n')
+                       buf[i-1] = 0;
+               fprintf(f, dbuf);
+               fprintf(f, buf);
+               fputc('\n', f);
+        va_end(ap);
+               fflush(f);
+
+               /* save for later */
+               if (dbgproc) {
+                       sprintf(dbgbuf, "%s%s", dbuf, buf);
+                       (dbgproc)(dbgbuf);
+               }
+    }
+}
+
+void dbgdump(unsigned long level, char *dir, unsigned char *s, int lth)
+{
+    if (f && DBGLEVEL(level)) {
+        int c, l;
+        unsigned char *p2, *p1;
+        char *p, buf[120];
+               
+               time(&systime);
+
+               rotate_log();
+               
+        sprintf(buf, "%s %s[%d,%04x] %s Lth: %d", dbgtime(), prog, pid, level, dir, lth);
+        fprintf(f, "%s\n", buf);
+               if (dbgproc) {
+                       (dbgproc)(buf);
+               }
+
+        /* calc how many blocks of 8 I can do */
+        c = 80 / 8;
+        c /= 3;
+
+        for (p = buf, p2 = s; p2 < s + lth; p2 += c * 8, p = buf) {
+            int i, l = c * 8;
+            sprintf(p, "%4d: ", p2 - s);
+            p += strlen(p);
+            for (p1 = p2; p1 < s + lth && p1 < p2 + l; ++p1) {
+                sprintf(p, "%02X", *p1);
+                p += strlen(p);
+            }
+            for ( ;p1 < p2 + l; ++p1) {
+                sprintf(p, "  ");
+                p += strlen(p);
+            }
+            sprintf(p, " ");
+            p += strlen(p);
+            for (p1 = p2; p1 < s + lth && p1 < p2 + l; ++p1) {
+                sprintf(p, "%c", (*p1 >= ' ' && *p1 <= 0x7e) ? *p1 : '.'); 
+                p += strlen(p);
+            }
+            fprintf(f, "%s\n", buf);
+                       if (dbgproc) {
+                               (dbgproc)(buf);
+                       }
+        }
+    }
+       fflush(f);
+}
+
+void dbgclose()
+{
+    if (f) {
+        fclose(f);
+        opened = 0;
+    }
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644 (file)
index 0000000..54ff802
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * debug routines
+ *
+ * Copyright (c) 1998 Dirk Koopman G1TLH
+ *
+ * $Id$
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+extern unsigned long dbglevel;
+#define DBGLEVEL(mask) ((dbglevel & mask) == mask)
+void dbghup();
+void dbginit(char *);
+void dbg(unsigned long, char *, ...);
+void dbgadd(unsigned long);
+void dbgsub(unsigned long);
+void dbgset(unsigned long);
+void dbgread(char *);
+void dbgdump(unsigned long, char *, unsigned char *, int);
+void dbgclose();
+unsigned long dbgget();
+extern void (*dbgproc)();
+extern char dbgbuf[];
+#endif