X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=src%2Fclient.c;h=3cd88068d54aa65f282f9230c936b85681a3282b;hb=e331b7540595fc6e23151f2daec58aeca3fbcd62;hp=c6be0cb80ba7afff42cb16ad2d6dd096953cb761;hpb=f265dcaf61a0da8dc80fccd2e6fe3fff46d512df;p=spider.git diff --git a/src/client.c b/src/client.c index c6be0cb8..3cd88068 100644 --- a/src/client.c +++ b/src/client.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "sel.h" #include "cmsg.h" @@ -43,7 +44,10 @@ #define MAXPATHLEN 256 #endif +#define DEFPACLEN 128 #define MAXPACLEN 236 +#define MAXCALLSIGN 9 + #define DBUF 1 #define DMSG 2 @@ -63,6 +67,13 @@ typedef struct char buffer_it; /* buffer outgoing packets for paclen */ } fcb_t; +typedef struct +{ + char *in; + regex_t *regex; +} myregex_t; + + char *node_addr = "localhost"; /* the node tcp address, can be overridden by DXSPIDER_HOST */ int node_port = 27754; /* the tcp port of the node at the above address can be overidden by DXSPIDER_PORT*/ char *call; /* the caller's callsign */ @@ -76,9 +87,33 @@ char echo = 1; /* echo characters on stdout from stdin */ char int_tabs = 0; /* interpret tabs -> spaces */ char *root = "/spider"; /* root of data tree, can be overridden by DXSPIDER_ROOT */ int timeout = 60; /* default timeout for logins and things */ -int paclen = 128; /* default buffer size for outgoing packets */ +int paclen = DEFPACLEN; /* default buffer size for outgoing packets */ int tabsize = 8; /* default tabsize for text messages */ +myregex_t iscallreg[] = { /* regexes to determine whether this is a reasonable callsign */ + { + "^[A-Z]+[0-9]+[A-Z]+[1-9]?$", 0 /* G1TLH G1TLH1 */ + }, + { + "^[0-9]+[A-Z]+[0-9]+[A-Z]+[1-9]?$", 0 /* 2E0AAA 2E0AAA1 */ + }, + { + "^[A-Z]+[0-9]+[A-Z]+-[1-9]$", 0 /* G1TLH-2 */ + }, + { + "^[0-9]+[A-Z]+[0-9]+[A-Z]+-[1-9]$", 0 /* 2E0AAA-2 */ + }, + { + "^[A-Z]+[0-9]+[A-Z]+-1[0-5]$", 0 /* G1TLH-11 */ + }, + { + "^[0-9]+[A-Z]+[0-9]+[A-Z]+-1[0-5]$", 0 /* 2E0AAA-11 */ + }, + { + 0, 0 + } +}; + void terminate(int); /* @@ -133,33 +168,16 @@ int xopen(char *dir, char *name, int mode) int iscallsign(char *s) { - char *p, ch, state = 0; + myregex_t *rp; + + if (strlen(s) > MAXCALLSIGN) + return 0; - ch = *p; - while (ch) { - switch (state) { - case 0: /* initial numerics */ - if (isalpha(ch)) { - if (p == s) - state = 10; - else - state = 1; - } if (isdigit(ch)) { - ; - } else - goto lend; - break; - case 1: /* letter(s) */ - case 10: /* had an initial character */ - if (isdigit(ch)) - state = 11; - - } - ch = ++*p; + for (rp = iscallreg; rp->in; ++rp) { + if (regexec(rp->regex, s, 0, 0, 0) == 0) + return 1; } - -lend: - return 1; + return 0; } /* @@ -199,6 +217,10 @@ void send_text(fcb_t *f, char *s, int l) f->obuf = mp = cmsg_new(paclen+1, f->sort, f); } + /* remove trailing spaces */ + while (l > 0 &&isspace(s[l-1])) + --l; + for (p = s; p < s+l; ) { if (mp->inp >= mp->data + paclen) { flush_text(f); @@ -210,29 +232,40 @@ void send_text(fcb_t *f, char *s, int l) flush_text(f); f->obuf = mp = cmsg_new(paclen+1, f->sort, f); } - *mp->inp++ = nl; + *mp->inp++ = '\n'; if (!f->buffer_it) flush_text(f); } -void send_msg(fcb_t *f, char let, char *s, int l) +void send_msg(fcb_t *f, char let, unsigned char *s, int l) { cmsg_t *mp; int ln; int myl = strlen(call)+2+l; mp = cmsg_new(myl+4+1, f->sort, f); - ln = htonl(myl); - memcpy(mp->inp, &ln, 4); - mp->inp += 4; *mp->inp++ = let; strcpy(mp->inp, call); mp->inp += strlen(call); *mp->inp++ = '|'; if (l > 0) { - memcpy(mp->inp, s, l); - mp->inp += l; - } + unsigned char *p; + for (p = s; p < s+l; ++p) { + if (mp->inp >= mp->data + (myl - 4)) { + int off = mp->inp - mp->data; + myl += 256; + mp = realloc(mp, myl); + mp->inp = mp->data + off; + } + + if (*p < 0x20 || *p > 0x7e || *p == '%') { + sprintf(mp->inp, "%%%02X", *p & 0xff); + mp->inp += strlen(mp->inp); + } else + *mp->inp++ = *p; + } + } + *mp->inp++ = '\n'; *mp->inp = 0; cmsg_send(f->outq, mp, 0); f->sp->flags |= SEL_OUTPUT; @@ -246,6 +279,7 @@ int fcb_handler(sel_t *sp, int in, int out, int err) { fcb_t *f = sp->fcb; cmsg_t *mp, *omp; + unsigned char c; /* input modes */ if (in) { @@ -261,14 +295,14 @@ int fcb_handler(sel_t *sp, int in, int out, int err) case EAGAIN: goto lout; default: - if (f->sort == MSG) - send_Z = 0; +/* if (f->sort == MSG) + send_Z = 0; */ ending++; return 0; } } else if (r == 0) { - if (f->sort == MSG) - send_Z = 0; +/* if (f->sort == MSG) + send_Z = 0; */ ending++; return 0; } @@ -350,30 +384,60 @@ int fcb_handler(sel_t *sp, int in, int out, int err) case MSG: p = buf; while (r > 0 && p < &buf[r]) { + unsigned char ch = *p++; + + if (mp->inp >= mp->data + (MAXBUFL-1)) { + mp->state = 0; + mp->inp = mp->data; + dbg(DMSG, "Message longer than %d received", MAXBUFL); + } - /* build up the size into the likely message length (yes I know it's a short) */ switch (mp->state) { - case 0: - case 1: - mp->state++; - break; - case 2: - case 3: - mp->size = (mp->size << 8) | (*p++ & 0xff); - if (mp->size > MAXBUFL) - die("Message size too big from node (%d > %d)", mp->size, MAXBUFL); - mp->state++; - break; - default: - if (mp->inp - mp->data < mp->size) { - *mp->inp++ = *p++; - } - if (mp->inp - mp->data >= mp->size) { + case 0: + if (ch == '%') { + c = 0; + mp->state = 1; + } else if (ch == '\n') { /* kick it upstairs */ + *mp->inp = 0; dbgdump(DMSG, "QUEUE MSG", mp->data, mp->inp - mp->data); cmsg_send(f->inq, mp, 0); mp = f->in = cmsg_new(MAXBUFL+1, f->sort, f); + } else if (ch < 0x20 || ch > 0x7e) { + dbg(DMSG, "Illegal character (0x%02X) received", *p); + mp->inp = mp->data; + } else { + *mp->inp++ = ch; } + break; + + case 1: + mp->state = 2; + if (ch >= '0' && ch <= '9') + c = (ch - '0') << 4; + else if (ch >= 'A' && ch <= 'F') + c = (ch - 'A' + 10) << 4; + else if (ch >= 'a' && ch <= 'a') + c = (ch - 'a' + 10) << 4; + else { + dbg(DMSG, "Illegal hex char (%c) received in state %d", ch, mp->state); + mp->inp = mp->data; + mp->state = 0; + } + break; + + case 2: + if (ch >= '0' && ch <= '9') + *mp->inp++ = c | (ch - '0'); + else if (ch >= 'A' && ch <= 'F') + *mp->inp++ = c | (ch - 'A' + 10); + else if (ch >= 'a' && ch <= 'a') + *mp->inp++ = c | (ch - 'a' + 10); + else { + dbg(DMSG, "Illegal hex char (%c) received in state %d", ch, mp->state); + mp->inp = mp->data; + } + mp->state = 0; } } break; @@ -409,8 +473,8 @@ lout:; case EAGAIN: goto lend; default: - if (f->sort == MSG) - send_Z = 0; +/* if (f->sort == MSG) + send_Z = 0; */ ending++; return; } @@ -489,6 +553,11 @@ lerr: nl = '\n'; echo = 1; } + + /* this is kludgy, but hey so is the rest of this! */ + if (!eq(connsort, "ax25") && paclen == DEFPACLEN) { + paclen = MAXPACLEN; + } } void connect_to_node() @@ -528,6 +597,7 @@ void term_timeout(int i) if (in && in->t_set) tcsetattr(0, TCSANOW, &in->t); if (node) { + shutdown(node->cnum, 3); close(node->cnum); } exit(i); @@ -535,8 +605,8 @@ void term_timeout(int i) void terminate(int i) { - if (send_Z && call) { - send_msg(node, 'Z', "", 0); + if (node && send_Z && call) { + send_msg(node, 'Z', "bye", 3); } signal(SIGALRM, term_timeout); @@ -548,8 +618,10 @@ void terminate(int i) } if (in && in->t_set) tcsetattr(0, TCSADRAIN, &in->t); - if (node) + if (node) { + shutdown(node->cnum, 3); close(node->cnum); + } exit(i); } @@ -659,6 +731,21 @@ main(int argc, char *argv[]) signal(SIGPWR, terminate); #endif + /* compile regexes for iscallsign */ + { + myregex_t *rp; + for (rp = iscallreg; rp->in; ++rp) { + regex_t reg; + int r = regcomp(®, rp->in, REG_EXTENDED|REG_ICASE|REG_NOSUB); + if (r) + die("regcomp returned %d for '%s'", r, rp->in); + rp->regex = malloc(sizeof(regex_t)); + if (!rp->regex) + die("out of room - compiling regexes"); + *rp->regex = reg; + } + } + /* is this a login? */ if (eq(call, "LOGIN")) { char buf[MAXPACLEN+1]; @@ -693,9 +780,11 @@ main(int argc, char *argv[]) } buf[r] = 0; call = strupper(buf); - if (!iscallsign(call)) { - die("Sorry, %s isn't a valid callsign", buf); - } + } + + /* check the callsign */ + if (!iscallsign(call)) { + die("Sorry, %s isn't a valid callsign", call); } /* connect up stdin */