From 3b52d4a1eb273c6e6eff14223baf69c0a309899c Mon Sep 17 00:00:00 2001 From: djk Date: Sun, 26 Mar 2000 14:18:24 +0000 Subject: [PATCH] a working version? with debugging --- src/Makefile | 2 +- src/client.c | 199 +++++++++++++++++++++++++++++++++------------- src/debug.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/debug.h | 25 ++++++ 4 files changed, 388 insertions(+), 56 deletions(-) create mode 100755 src/debug.c create mode 100644 src/debug.h diff --git a/src/Makefile b/src/Makefile index 09d68645..27947825 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) diff --git a/src/client.c b/src/client.c index 640c2b44..3dadfc59 100644 --- a/src/client.c +++ b/src/client.c @@ -29,14 +29,19 @@ #include #include #include +#include #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] |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 index 00000000..d4899434 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,218 @@ +/* + * debug routines + * + * Copyright (c) 1998 Dirk Koopman G1TLH + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..54ff802f --- /dev/null +++ b/src/debug.h @@ -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 -- 2.34.1