X-Git-Url: http://gb7djk.dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=src%2Fclient.c;h=382c852b1310752ddbcdf707b45b84b4ce3b530d;hb=bff9ecf00b14e7d71d9504088a2fd7b9e5115fe1;hp=8c52d53ffa921839d491a76ed137c0aeccfef971;hpb=632bda2671a8b0cf73b1a0bffa7b906c8744b14f;p=spider.git diff --git a/src/client.c b/src/client.c index 8c52d53f..382c852b 100644 --- a/src/client.c +++ b/src/client.c @@ -81,6 +81,7 @@ char *connsort; /* the type of connection */ fcb_t *in; /* the fcb of 'stdin' that I shall use */ fcb_t *node; /* the fcb of the msg system */ char nl = '\n'; /* line end character */ +char mode = 1; /* 0 - ax25, 1 - normal telnet, 2 - nlonly telnet */ 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 */ @@ -89,6 +90,8 @@ char *root = "/spider"; /* root of data tree, can be overridden by DXSPI int timeout = 60; /* default timeout for logins and things */ int paclen = DEFPACLEN; /* default buffer size for outgoing packets */ int tabsize = 8; /* default tabsize for text messages */ +char *connsort = "local"; /* the connection variety */ + myregex_t iscallreg[] = { /* regexes to determine whether this is a reasonable callsign */ { @@ -232,29 +235,46 @@ 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; + if (nl == '\r') + *mp->inp++ = nl; + else { + if (mode != 2) + *mp->inp++ = '\r'; + *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; @@ -268,9 +288,10 @@ 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) { + if (ending == 0 && in) { char *p, buf[MAXBUFL]; int r; @@ -283,14 +304,16 @@ 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; */ + dbg(DBUF,"got errno %d in input", errno); ending++; return 0; } } else if (r == 0) { - if (f->sort == MSG) - send_Z = 0; +/* if (f->sort == MSG) + send_Z = 0; */ + dbg(DBUF, "ending normally"); ending++; return 0; } @@ -333,7 +356,7 @@ int fcb_handler(sel_t *sp, int in, int out, int err) *mp->inp++ = *p++; } break; - case '\b': + case 0x08: case 0x7f: if (mp->inp > mp->data) mp->inp--; @@ -372,30 +395,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; @@ -431,8 +484,9 @@ lout:; case EAGAIN: goto lend; default: - if (f->sort == MSG) - send_Z = 0; +/* if (f->sort == MSG) + send_Z = 0; */ + dbg(DBUF,"got errno %d in output", errno); ending++; return; } @@ -450,6 +504,29 @@ lend:; return 0; } +/* + * set up the various mode flags, NL endings and things + */ +void setmode(char *m) +{ + connsort = strlower(m); + if (eq(connsort, "telnet") || eq(connsort, "local") || eq(connsort, "nlonly")) { + nl = '\n'; + echo = 1; + mode = eq(connsort, "nlonly") ? 2 : 1; + } else if (eq(connsort, "ax25")) { + nl = '\r'; + echo = 0; + mode = 0; + } else if (eq(connsort, "connect")) { + nl = '\n'; + echo = 0; + mode = 3; + } else { + die("Connection type must be \"telnet\", \"nlonly\", \"ax25\", \"login\" or \"local\""); + } +} + /* * things to do with initialisation */ @@ -496,24 +573,13 @@ lerr: die("Must have at least a callsign (for now)"); 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\""); - } + setmode(argv[optind]); } else { - connsort = "local"; - nl = '\n'; - echo = 1; + setmode("local"); } /* this is kludgy, but hey so is the rest of this! */ - if (!eq(connsort, "ax25") && paclen == DEFPACLEN) { + if (mode != 0 && paclen == DEFPACLEN) { paclen = MAXPACLEN; } } @@ -555,6 +621,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); @@ -563,7 +630,7 @@ void term_timeout(int i) void terminate(int i) { if (node && send_Z && call) { - send_msg(node, 'Z', "", 0); + send_msg(node, 'Z', "bye", 3); } signal(SIGALRM, term_timeout); @@ -575,8 +642,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); } @@ -702,9 +771,11 @@ main(int argc, char *argv[]) } /* is this a login? */ - if (eq(call, "LOGIN")) { + if (eq(call, "LOGIN") || eq(call, "login")) { + char buf[MAXPACLEN+1]; - int r; + char callsign[MAXCALLSIGN+1]; + int r, i; int f = xopen("data", "issue", 0); if (f > 0) { while ((r = read(f, buf, paclen)) > 0) { @@ -722,19 +793,32 @@ main(int argc, char *argv[]) signal(SIGALRM, login_timeout); alarm(timeout); write(0, "login: ", 7); - r = read(0, buf, 20); - if (r <= 0) - die("No login or error (%d)", errno); + dbgdump(DBUF, "<-out", "login: ", 7); + for (i = 0;;) { + char *p; + r = read(0, buf, 20); + dbgdump(DBUF, "in ->", buf, r); + if (r <= 0) + die("No login or error (%d)", errno); + write(0, buf, r); + dbgdump(DBUF, "<-out", buf, r); + for (p = buf; p < buf+r; ++p) { + if (i < MAXCALLSIGN) { + if (*p == '\r' || *p == '\n') + goto lgotcall; + else if (isalnum(*p) || *p == '-') + callsign[i++] = *p; + else + die("%c is not a valid callsign character", *p); + } else + die("callsign entered is too long"); + } + } +lgotcall: signal(SIGALRM, SIG_IGN); alarm(0); - while (r > 0) { - if (buf[r-1] == ' ' || buf[r-1] == '\r' || buf[r-1] == '\n') - --r; - else - break; - } - buf[r] = 0; - call = strupper(buf); + callsign[i]= 0; + call = strupper(callsign); } /* check the callsign */ @@ -746,7 +830,8 @@ main(int argc, char *argv[]) in = fcb_new(0, TEXT); in->sp = sel_open(0, in, "STDIN", fcb_handler, TEXT, SEL_INPUT); if (tcgetattr(0, &in->t) < 0) { - echo = 0; +/* echo = 0; */ + in->echo = echo; in->t_set = 0; } else { struct termios t = in->t;