/* * 8 space tabs for this file */ /* dcpsys.c Revised edition of dcp Stuart Lynne May/87 Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart Lynne 1987 */ /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ /* Support routines */ #include "ndir.h" #include "dcp.h" #define MAXLOGTRY 3 #define TIMEOUT -1 #define PROTOS "g" /* available protocoles */ Proto Protolst[] = { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk, '\0'}; #define EOTMSG "\004\r\004\r" procref getpkt, sendpkt, openpk, closepk; static char *flds[60]; static int kflds; static char proto[5]; static char S_sysline[BUFSIZ], S_sysdevice[16], S_sysspeed[16]; extern void wmsg(); extern int rmsg(); static void setproto(); static int checktime(); /****************************************/ /* Sub Systems */ /****************************************/ /* g e t s y s t e m Process a systems file (L.sys) entry. Null lines or lines starting with '#' are comments. */ char getsystem() { do { /* flush to next non-comment line */ if (fgets(S_sysline, BUFSIZ, fsys) == nil(char)) return 'A'; /* end-of-file */ } while ((*S_sysline == '\0') || (*S_sysline == '\n') || (*S_sysline == '#')); printmsg(8, "sysline=\"%s\"", S_sysline); kflds = getargs(S_sysline, flds); strcpy(rmtname, flds[FLD_REMOTE]); strcpy(S_sysdevice, flds[FLD_DEVICE]); /* strcpy(type, flds[FLD_TYPE]); */ strcpy(S_sysspeed, flds[FLD_SPEED]); strcpy(proto, flds[FLD_PROTO]); if (debuglevel >= 4) { int i; for (i = FLD_EXPECT; i < kflds; i += 2) printmsg(6, "expect [%02d]:\t%s\nsend [%02d]:\t%s", i, flds[i], i + 1, flds[i + 1]); } printmsg(2, "remote=%s, call-time=%s,", rmtname, flds[FLD_CCTIME]); printmsg(2, "device=%s, speed=%s, protocol=%s", S_sysdevice, S_sysspeed, proto); fwork = nil(FILE); if (checktime(flds[FLD_CCTIME]) && ( equal(Rmtname, "all") || equaln(Rmtname, rmtname, 7) || (equal(Rmtname, "any") && scandir(rmtname) == 'S'))) { if (fwork != nil(FILE)) /* in case matched with scandir */ fclose(fwork); return 'S'; /* startup this system */ } else return 'G'; } /*getsystem*/ /* c h e c k n a m e Look up a system name in our systems (L.sys) file. Only the first 7 characters of a system name is significant. */ static int checkname(name) char *name; { FILE *ff; char line[BUFSIZ]; if ((ff = FOPEN(s_systems, "r", TEXT)) == nil(FILE)) return FAILED; while (fgets(line, BUFSIZ, ff) != nil(char)) { printmsg(3, "checkname: got '%s', want '%s'", line, name); if (equaln(name, line, 7)) { fclose(ff); return OK; /* OK, we like you */ } } fclose(ff); return FAILED; /* Who are you? */ } /*checkname*/ /* c h e c k t i m e Check if we may make a call at this time *** to be implemented. Again, didn't think it crucial. */ static int checktime(xtime) char *xtime; { printmsg(2, "checktime: %s", xtime); return TRUE; /* OK, go to it */ } /*checktime*/ /* s y s e n d End UUCP session negotiation */ char sysend() { char msg[80]; msg[1] = '\0'; msgtime = 2 * MSGTIME; /* while (msg[1] != 'O') { */ wmsg("OOOOOO", TRUE); if (rmsg(msg, TRUE) == TIMEOUT) goto hang; /*}*/ hang: wmsg("OOOOOO", TRUE); closeline(); return (remote == MASTER) ? 'I' : 'A'; } /*sysend*/ /* w m s g write a ^P type msg to the remote uucp */ void wmsg(msg, synch) char *msg; int synch; { if (synch) swrite("\0\020", 2); swrite(msg, strlen(msg)); if (synch) swrite("\0", 1); } /*wmsg*/ /* r m s g read a ^P msg from UUCP */ int rmsg(msg, synch) char *msg; int synch; { int i; char ch; /* flush until next ^P */ if (synch) do if (sread(&ch, 1, msgtime) < 1) return TIMEOUT; while ((ch & 0x7f) != '\020'); for (i = 0; (i < 132) && (ch != '\0'); ) { if (sread(&ch, 1, msgtime) < 1) return TIMEOUT; ch &= 0x7f; if (ch == '\r' || ch == '\n') ch = '\0'; msg[i++] = ch; } return strlen(msg); } /*rmsg*/ /* s t a r t u p */ char startup() { char msg[80]; if (remote == MASTER) { msgtime = 2 * MSGTIME; if (rmsg(msg, TRUE) == TIMEOUT) return 'Y'; printmsg(2, "1st msg = %s", msg); if (msg[5] == '=' && !equaln(&msg[6], rmtname, 7)) return 'Y'; /* wrong host */ /* sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel); */ /* -Q0 -x16 remote debuglevel set */ sprintf(msg, "S%.7s", nodename); wmsg(msg, TRUE); if (rmsg(msg, TRUE) == TIMEOUT) return 'Y'; printmsg(2, "2nd msg = %s", msg); if (!equaln(&msg[1], "OK", 2)) return 'Y'; if (rmsg(msg, TRUE) == TIMEOUT) return 'Y'; printmsg(2, "3rd msg = %s", msg); if (msg[0] != 'P' || (strchr(&msg[1], proto[0]) == nil(char))) { wmsg("UN", TRUE); return 'Y'; /* no common protocol */ } else { sprintf(msg, "U%c", proto[0]); wmsg(msg, TRUE); } setproto(proto[0]); return 'D'; } else { char tmp1[20], tmp2[20]; msgtime = 2 * MSGTIME; sprintf(msg, "Shere=%s", nodename); wmsg(msg, TRUE); if (rmsg(msg, TRUE) == TIMEOUT) return 'Y'; sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2); sscanf(tmp2, "-x%d", &debuglevel); printmsg(1, "debuglevel set to %d by remote", debuglevel); printmsg(2, "1st msg from remote = %s", msg); if (checkname(rmtname)) return 'Y'; wmsg("ROK", TRUE); sprintf(msg, "P%s", PROTOS); wmsg(msg, TRUE); if (rmsg(msg, TRUE) == TIMEOUT) return 'Y'; if (msg[0] != 'U' || (strchr(PROTOS, msg[1]) == nil(char))) return 'Y'; proto[0] = msg[1]; setproto(proto[0]); return 'R'; } } /*startup*/ /* s e t p r o t o set the protocol to be used */ static void setproto(wanted) char wanted; { Proto *tproto; for (tproto = Protolst; tproto->type != '\0' && tproto->type != wanted; tproto++) { printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type); } if (tproto->type == '\0') { printmsg(0, "setproto: You said I have it but I cant find it!"); exit(1); } getpkt = tproto->a; sendpkt = tproto->b; openpk = tproto->c; closepk = tproto->d; } /*setproto*/ #define prefix(small,large) (equaln((small), (large), strlen(small))) #define notin(str,log) (strstr((log), (str)) == nil(char)) /* e x p e c t s t r */ #define MAXHIST 300 int expectstr(str, timeout) char *str; int timeout; { static char history[MAXHIST]; char *rp = history; printmsg(1, "wanted %s", str); if (equal(str, "\"\"")) /* expects nothing */ return TRUE; *rp = 0; while (notin(str, history)) { char ch; if (sread(&ch, 1, timeout) < 1) return FALSE; if ((*rp = (ch & 0x7f)) != '\0') rp++; *rp = '\0'; if (rp >= history + MAXHIST) return FALSE; } return TRUE; } /*expectstr*/ int writestr(s) register char *s; { register char last; int nocr; last = '\0'; nocr = FALSE; while (*s) { if (last == '\\') { switch (*s) { case 'd': /* delay */ case 'D': sleep(2); break; case 'c': /* don't output CR at end of string */ case 'C': nocr = TRUE; break; case 'r': /* carriage return */ case 'R': case 'm': case 'M': swrite("\r", 1); break; case 'n': /* new line */ case 'N': swrite("\n", 1); break; case 'b': /* backspace */ case 'B': swrite("\b", 1); break; case 't': /* tab */ case 'T': swrite("\t", 1); break; case 's': /* space */ case 'S': swrite(" ", 1); break; case 'z': /* set serial port speed */ case 'Z': SIOSpeed(++s); while (*s != '\0' && *s != '\\') s++; if (*s == '\\') s++; break; default: /* ordinary character */ swrite(s, 1); } last = '\0'; } else if (*s != '\\') /* backslash */ swrite(s, 1); else last = *s; s++; } return nocr; } /*writestr*/ /* s e n d s t r Send line of login sequence */ static void sendstr(str) char *str; { printmsg(2, "sending %s", str); if (equaln(str, "BREAK", 5)) { int nulls; nulls = atoi(&str[5]); if (nulls <= 0 || nulls > 10) nulls = 3; ssendbrk(nulls); /* send a break signal */ return; } if (equal(str, "EOT")) { swrite(EOTMSG, strlen(EOTMSG)); return; } if (equal(str, "\"\"")) *str = '\0'; if (!equal(str,"")) { if (!writestr(str)) { swrite("\r", 1); } } else swrite("\r", 1); return; } /*sendstr*/ /* s e n d e x p e c t */ static int sendexpect(send, expect, timeout) char *send, *expect; int timeout; { sendstr(send); return expectstr(expect, timeout); } /*sendexpect*/ /* d i a l */ static int dial() { char buf[4]; if (!equal(flds[FLD_TYPE], "HAYES")) { printmsg(0, "dial: unsupported dialer %s", flds[FLD_TYPE]); return FALSE; } printmsg(3, "dial: calling host %s", rmtname); if (openline(S_sysdevice, "2400")) return FALSE; printmsg(0, "hayes: trying 2400"); if (sendexpect("ATZ", "OK", 2) != TRUE) { sendexpect("\\d+++\\d", "OK", 2); if (sendexpect("ATZ", "OK", 2) != TRUE) { printmsg(0, "hayes: trying 1200"); SIOSpeed("1200"); if (sendexpect("ATZ", "OK", 2) != TRUE) { sendexpect("\\d+++\\d", "OK", 2); if (sendexpect("ATZ", "OK", 2) != TRUE) return FALSE; } } } printmsg(0, "hayes: got modem response"); /*(sendstr("\\d\\dATS7=30"); expectstr("OK", 40);*/ sendstr("\\d\\dATX4\\c"); if (sendexpect(S_sysspeed, "CONNECT ", 40) == TRUE) { printmsg(3, "hayes: got CONNECT"); if (sread(buf, 4, 4) == 4) { printmsg(3, "hayes: speed select %s", buf); /* set speed appropriately */ SIOSpeed(buf); } return TRUE; } else return FALSE; } /*dial*/ /* c a l l u p script processor - nothing fancy! */ char callup() { char *exp, *alternate; int ok, i; printmsg(0, "callup: calling host \"%s\"", rmtname); if (!equal(flds[FLD_TYPE], "DIR")) { if (dial() == FALSE) return 'G'; } else if (openline(S_sysdevice, S_sysspeed)) return 'G'; for (i = FLD_EXPECT; i < kflds; i += 2) { exp = flds[i]; printmsg(2, "expecting %d of %d \"%s\"", i, kflds, exp); ok = FALSE; while (ok != TRUE) { alternate = strchr(exp, '-'); if (alternate != nil(char)) *alternate++ = '\0'; ok = expectstr(exp, 30); if (ok) { printmsg(2, "got that"); break; } else printmsg(1, "got ???"); if (alternate == nil(char)) { printmsg(0, "LOGIN FAILED"); return 'Y'; } exp = strchr(alternate, '-'); if (exp != nil(char)) *exp++ = '\0'; printmsg(0, "sending alternate"); sendstr(alternate); } /*while*/ printmsg(2, "sending %d of %d \"%s\"", i + 1, kflds, flds[i + 1]); sleep(1); sendstr(flds[i + 1]); } /*for*/ return 'P'; } /*callup*/ /* s c a n d i r Scan spooling directory for C.* files for the remote host (rmtname) returns: A - abort Y - can't open file S - ok Q - no files */ char scandir(remote) char *remote; { char callpfx[40]; int pfxlen; DIR *dirp; struct direct *dp; if ((dirp = opendir(spooldir)) == nil(DIR)) { printmsg(0, "scandir: couldn't opendir() %s", spooldir); return 'A'; } sprintf(callpfx, CALLFILE, remote); pfxlen = strlen(callpfx); printmsg(5, "scandir: \"%s\"", callpfx); while ((dp = readdir(dirp)) != nil(struct direct)) { printmsg(10, " %s", dp->d_name); if (equaln(callpfx, dp->d_name, pfxlen)) { printmsg(5, "scandir: matched"); strcpy(workfile, dp->d_name); closedir(dirp); if ((fwork = FOPEN(workfile, "r", TEXT)) == nil(FILE)) return 'Y'; return 'S'; } } printmsg(5, "scandir: not matched"); closedir(dirp); return 'Q'; } /*scandir*/ /* x s c a n d i r Scan spooling directory for X.* files, for 'uuxqt'. */ char *xscandir(xname) char xname[]; { DIR *dirp; struct direct *dp; int pfxlen; if ((dirp = opendir(spooldir)) == nil(DIR)) { printmsg(0, "xscandir: couldn't opendir() %s", spooldir); return nil(char); } printmsg(5, "xscandir: \"%s\"", XQTPFX); pfxlen = strlen(XQTPFX); while ((dp = readdir(dirp)) != nil(struct direct)) { printmsg(10, " %s", dp->d_name, XQTPFX); if (equaln(XQTPFX, dp->d_name, pfxlen)) { printmsg(5, "xscandir: matched"); strcpy(xname, dp->d_name); closedir(dirp); return xname; } } printmsg(5, "xscandir: not matched"); closedir(dirp); return nil(char); } /*xscandir*/ #if FALSE /* slowrite - comunication slow write. needed for auto-baud modems */ void slowrite(st) char *st; { int len, j; char c; len = strlen(st); printmsg(2, "sent %s", st); for (j = 0; j < len; j++) { swrite(&st[j], 1); ddelay(80000); } } /*slowrite*/ /* d d e l a y */ void ddelay(dtime) int dtime; { int i, j; for (i = 0; i < dtime; i++) { } } /*ddelay*/ #endif