#define CONN #include "uucp.h" #include #include #include #include #include #include #define F_NAME 0 #define F_TIME 1 #define F_LINE 2 #define F_SPEED 3 #define F_PHONE 4 #define F_LOGIN 5 jmp_buf Sjbuf; #define INVOKE(a, r) ret = a; if (ret<0) return(r); /******* * conn(system) * char *system; * * conn - place a telephone call to system and * login, etc. * * return codes: * CF_SYSTEM: don't know system * CF_TIME: wrong time to call * CF_DIAL: call failed * CF_LOGIN: login/password dialog failed * * >0 - file no. - connect ok * */ conn(system) char *system; { int ret, nf; int fn; char *flds[50]; DEBUG(4, "gdial %s\n", "called"); INVOKE(gdial(), CF_DIAL) DEBUG(4, "finds %s\n", "called"); INVOKE(nf = finds(system, flds), nf) DEBUG(4, "getto %s\n", "called"); INVOKE(fn = getto(flds), CF_DIAL) DEBUG(4, "login %s\n", "called"); INVOKE(login(nf, flds, fn), CF_LOGIN) return(fn); } /*** * char * * lastc(s) return pointer to last character * char *s; * */ char * lastc(s) char *s; { while (*s != '\0') s++; return(s); } #define MAXDEV 10 #define MAXDCH MAXDEV*20 #define MAXCODE 30 #define MAXCCH MAXCODE*20 /* This array tells us about possible acu's, etc. */ struct Devices { char *D_line; char *D_acu; int D_speed; } Devs [MAXDEV]; char Devbuff[MAXDCH]; struct Codes { char *C_locs; char *C_prefix; } Dialcodes [MAXCODE]; char Codebuff[MAXCCH]; int Dcfull = 0; /*** * gdial() get device and dial info * * return codes: 0 | FAIL */ gdial() { char *flds[10], *lt; char *lb = Devbuff; char *lc = Codebuff; FILE *fn; int nr; struct Devices *pd; struct Codes *pc; if (Dcfull) return(0); fn = fopen(Devfile, "r"); ASSERT(fn != NULL, "CAN'T OPEN %s", Devfile); for (pd = Devs; fgets(lb, 200, fn); pd++) { lt = lastc(lb); nr = getargs(lb, flds); ASSERT(nr == 3, "BAD LINE %s", lb); pd->D_line = flds[0]; pd->D_acu = flds[1]; pd->D_speed = atoi(flds[2]); lb = lt; ASSERT(lb < Devbuff + MAXDCH, "TOO LONG %s", Devbuff); ASSERT(pd < Devs + MAXDEV, "TOO MANY DEVICES %d", MAXCODE); } pd->D_line = NULL; fclose(fn); ASSERT(pd > Devs, "BAD FILE %s", Devfile); /* Now dialcodes, same way */ fn = fopen(Dialfile, "r"); ASSERT(fn != NULL, "CAN'T OPEN %s", Dialfile); for (pc = Dialcodes; fgets(lc, 200, fn); pc++) { lt = lastc(lc); nr = getargs(lc, flds); if (nr == 1) flds[nr++] = ""; ASSERT(nr == 2, "BAD LINE %s", lc); pc->C_locs = flds[0]; pc->C_prefix = flds[1]; lc = lt; ASSERT(lc < Codebuff + MAXCCH, "TOO LONG %s", Codebuff); ASSERT(pc < Dialcodes + MAXCODE, "MANY DEVICES %d", MAXCODE); } pc->C_locs = 0; fclose(fn); return(0); } /*** * ckdev(type, speed, ndev) * char *type, *speed; * int ndev; * * ckdev - return the device number in table Devs for * a device with proper attributes. * * return codes: >= 0 (ok) | FAIL */ ckdev(type, speed, ndev) char *type, *speed; int ndev; { int sp, acu; struct Devices *pd; sp = atoi(speed); acu =(strcmp(type, "ACU") == SAME); for (pd = &Devs[ndev]; pd->D_line != NULL; pd++) { if (sp != pd->D_speed) continue; if (acu && (strcmp(pd->D_acu, "0") != SAME) && !mlock(pd->D_line)) return(ndev = pd - Devs); if (!acu && (strcmp(pd->D_line, type) == SAME) && !mlock(type)) return(ndev = pd - Devs); } return(FAIL); } /*** * getto(flds) connect to remote machine * char *flds[]; * * return codes: * >0 - file number - ok * FAIL - failed */ getto(flds) char *flds[]; { DEBUG(F_PHONE, "call: no. %s ", flds[4]); DEBUG(4, "for sys %s ", flds[F_NAME]); if (strcmp(flds[F_LINE], "ACU") == SAME) return(call(flds)); else return(direct(flds)); } /*** * call(flds) call remote machine * char *flds[]; * * "flds" contains the call information (name, date, type, speed, * phone no. ... * Ndev has the device no. * * return codes: * >0 - file number - ok * FAIL - failed */ call(flds) char *flds[]; { char *pno, pref[20], phone[20]; char *s1, *s2; int dcr; struct Codes *pc; pno = flds[F_PHONE]; s1 = pref; s2 = pno; while (isalpha(*s2)) *s1++ = *s2++; *s1 = '\0'; for (pc = Dialcodes; pc->C_locs; pc++) if (strcmp(pc->C_locs, pref) == SAME) { s1 = pc->C_prefix; break; } sprintf(phone, "%s%s", s1, s2); DEBUG(4, "Dial %s\n", phone); dcr = dialup(phone, flds); DEBUG(4, "dcr returned as %d\n", dcr); if (dcr == FAIL) return(FAIL); return(dcr); } /* file descriptor for call unit */ int Dnf = 0; /*** * dialup(ph, flds) dial remote machine * char *ph; * char *flds[]; * * return codes: * file descriptor - succeeded * FAIL - failed */ dialup(ph, flds) char *ph; char *flds[]; { char dcname[20], dnname[20], phone[20]; struct Devices *pd; int nw, lt, pid, dcf, ndev; extern int Error; extern alarmtr(); for (ndev = 0;;ndev++) { ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev); if (ndev < 0) { logent("AVAILABLE DEVICE", "NO"); DEBUG(4, "NO AVAILABLE DEVICE %s\n", ""); return(FAIL); } pd = &Devs[ndev]; sprintf(dnname, "/dev/%s", pd->D_acu); /* open call unit */ Dnf = open(dnname, 1); if (Dnf >= 0) break; delock(pd->D_line); } sprintf(dcname, "/dev/%s", pd->D_line); sprintf(phone, "%s%s", ph, ACULAST); DEBUG(4, "dc - %s, ", dcname); DEBUG(4, "acu - %s\n", dnname); if (setjmp(Sjbuf)) { DEBUG(1, "DN write %s\n", "timeout"); logent("DIALUP DN write", "TIMEOUT"); kill(pid, 9); close(Dnf); return(FAIL); } signal(SIGALRM, alarmtr); alarm(30); if ((pid = fork()) == 0) { sleep(2); fclose(stdin); fclose(stdout); nw = write(Dnf, phone, lt = strlen(phone)); if (nw != lt) { DEBUG(1, "ACU write %s\n", "error"); logent("DIALUP ACU write", "FAILED"); exit(1); } DEBUG(4, "ACU write ok%s\n", ""); exit(0); } /* open line - will return on carrier */ dcf = open(dcname, 2); DEBUG(4, "dcf is %d\n", dcf); if (dcf < 0) { DEBUG(1, "Line open %s\n", "failed"); logent("DIALUP LINE open", "FAILED"); alarm(0); return(FAIL); } ioctl(dcf, TIOCHPCL, 0); nw = wait(<); alarm(0); fflush(stdout); fixline(dcf, pd->D_speed); DEBUG(4, "Forked %d ", pid); DEBUG(4, "Wait got %d ", nw); DEBUG(4, "Status %o\n", lt); if (lt != 0) { close(dcf); return(FAIL); } return(dcf); } /*** * clsacu() close call unit * * return codes: none */ clsacu() { if (Dnf > 0) { close(Dnf); Dnf = 0; } return; } /*** * direct(flds) connect to hardware line * char *flds[]; * * return codes: * >0 - file number - ok * FAIL - failed */ direct(flds) char *flds[]; { int dcr, ndev; char dcname[20]; ndev = 0; if ((ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev)) < 0) { logent("DEVICE", "NOT AVAILABLE"); return(FAIL); } sprintf(dcname, "/dev/%s", Devs[ndev].D_line); signal(SIGALRM, alarmtr); alarm(10); if (setjmp(Sjbuf)) return(FAIL); dcr = open(dcname, 2); /* read/write */ alarm(0); if (dcr < 0) return(FAIL); fflush(stdout); fixline(dcr, Devs[ndev].D_speed); return(dcr); } #define MAXC 300 /*** * finds(sysnam, flds) set system attribute vector * char *sysnam, *flds[]; * * return codes: * >0 - number of arguments in vector - succeeded * CF_SYSTEM - system name not found * CF_TIME - wrong time to call */ finds(sysnam, flds) char *sysnam, *flds[]; { FILE *fsys; static char info[MAXC]; char **fnp; int na; int fnd = 0; for (fnp = Sysfiles; *fnp != NULL && !fnd; fnp++) { fsys = fopen(*fnp, "r"); if (fsys == NULL) continue; while (!fnd && (fgets(info, MAXC, fsys) != NULL)) { na = getargs(info, flds); if (prefix(sysnam, flds[F_NAME])) fnd = 1; } fclose(fsys); } if (fnd == 0) return(CF_SYSTEM); /* format of fields * 0 name; * 1 time * 2 acu/hardwired * 3 speed * etc */ if (ifdate(flds[F_TIME]) == 0) { DEBUG(1, "Wrong time to call %s\n", sysnam); logent(sysnam, "WRONG TIME TO CALL"); return(CF_TIME); } return(na); } /*** * login(nf, flds, dcr) do log conversation * char *flds[]; * int nf; * * return codes: 0 | FAIL */ login(nf, flds, fn) char *flds[]; int nf, fn; { char *want, *altern; extern char *index(); int k, ok; ASSERT(nf > 4, "TOO FEW LOG FIELDS %d", nf); for (k = F_LOGIN; k < nf; k += 2) { want = flds[k]; ok = FAIL; while (ok != 0) { altern = index(want, '-'); if (altern != NULL) *altern++ = '\0'; DEBUG(4, "wanted %s ", want); ok = expect(want, fn); DEBUG(4, "got %s\n", ok ? "?" : "that"); if (ok == 0) break; if (altern == NULL) { logent("LOGIN", "FAILED"); return(FAIL); } want = index(altern, '-'); if (want != NULL) *want++ = '\0'; sendthem(altern, fn); } sleep(2); sendthem(flds[k+1], fn); } return(0); } struct sg_spds {int sp_val, sp_name;} spds[] = { { 300, B300}, {1200, B1200}, {4800, B4800}, {9600, B9600}, {0, 0} }; /*** * fixline(tty, spwant) set speed/echo/mode... * int tty, spwant; * * return codes: none */ fixline(tty, spwant) int tty, spwant; { struct sgttyb ttbuf; struct sg_spds *ps; int speed = -1; int ret; for (ps = spds; ps->sp_val; ps++) if (ps->sp_val == spwant) speed = ps->sp_name; ASSERT(speed >= 0, "BAD SPEED %d", speed); ioctl(tty, TIOCGETP, &ttbuf); ttbuf.sg_flags |=(ANYP|RAW); ttbuf.sg_flags &= ~(ECHO|ALLDELAY); ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; DEBUG(4, "Speed: want %d ", spwant); DEBUG(4, "use %o ", speed); DEBUG(4, "ps %d\n", ps-spds); ret = ioctl(tty, TIOCSETP, &ttbuf); ASSERT(ret >= 0, "RETURN FROM STTY %d", ret); ioctl(tty, TIOCHPCL, 0); ioctl(tty, TIOCEXCL, 0); return; } #define MR 300 int Error = 0; /*** * expect(str, fn) look for expected string * char *str; * * return codes: * 0 - found * FAIL - lost line or too many characters read * some character - timed out */ expect(str, fn) char *str; int fn; { static char rdvec[MR]; extern alarmtr(); char *rp = rdvec; int nextch = 0, kr; if (strcmp(str, "\"\"") == SAME) return(0); *rp = 0; if (setjmp(Sjbuf)) { return(FAIL); } signal(SIGALRM, alarmtr); while (notin(str, rdvec)) { alarm(MAXCHARTIME); kr = read(fn, &nextch, 1); if (kr <= 0) { DEBUG(4, "kr - %d\n", kr); alarm(0); DEBUG(4, "lost line kr - %d, ", kr); DEBUG(4, "fn - %d\n", fn); logent("LOGIN", "LOST LINE"); return(FAIL); } { int c; c = nextch & 0177; DEBUG(4, "%c", c > 040 ? c : '_'); } if ((*rp = nextch & 0177) != '\0') rp++; *rp = '\0'; if (rp >= rdvec + MR) return(FAIL); } alarm(0); return(0); } /*** * alarmtr() - catch alarm routine for "expect". */ alarmtr() { longjmp(Sjbuf, 1); } /*** * sendthem(str, fn) send line of login sequence * char *str; * * return codes: none */ sendthem(str, fn) char *str; int fn; { int nw, ns; int nulls; if (prefix("BREAK", str)) { sscanf(&str[5], "%1d", &nulls); if (nulls <= 0 || nulls > 10) nulls = 3; /* send break */ DEBUG(5, "%s,", str); DEBUG(5, "%d\n", nulls); genbrk(fn, Bspeed, nulls); return; } if (strcmp(str, "EOT") == SAME) { write(fn, EOTMSG, strlen(EOTMSG)); return; } if (strcmp(str, "") != SAME) { nw = write(fn, str, ns = strlen(str)); ASSERT(nw == ns, "BAD WRITE $s", str); } write(fn, "\n", 1); return; } /*** * genbrk(fn) send equivalent to break * * return codes; none */ genbrk(fn, bspeed, bnulls) int fn, bspeed, bnulls; { struct sgttyb ttbuf; int ret, sospeed; ret = ioctl(fn, TIOCGETP, &ttbuf); DEBUG(5, "ioctl ret %d\n", ret); sospeed = ttbuf.sg_ospeed; ttbuf.sg_ospeed = bspeed; ret = ioctl(fn, TIOCSETP, &ttbuf); DEBUG(5, "ioctl ret %d\n", ret); ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls); ASSERT(ret > 0, "BAD WRITE genbrk %d", ret); ttbuf.sg_ospeed = sospeed; ret = ioctl(fn, TIOCSETP, &ttbuf); ret = write(fn, "@", 1); ASSERT(ret > 0, "BAD WRITE genbrk %d", ret); DEBUG(4, "sent BREAK nulls - %d\n", bnulls); return; } /*** * notin(sh, lg) check for occurrence of substring "sh" * char *sh, *lg; * * return codes: * 0 - found the string * 1 - not in the string */ notin(sh, lg) char *sh, *lg; { while (*lg != '\0') { if (prefix(sh, lg)) return(0); else lg++; } return(1); } /******* * ifdate(s) * char *s; * * ifdate - this routine will check a string (s) * like "MoTu0800-1730" to see if the present * time is within the given limits. * * String alternatives: * Wk - Mo thru Fr * zero or one time means all day * Any - any day * * return codes: * 0 - not within limits * 1 - within limits */ ifdate(s) char *s; { static char *days[]={ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 }; long clock; int i, tl, th, tn, dayok=0; struct tm *localtime(); struct tm *tp; time(&clock); tp = localtime(&clock); while (isalpha(*s)) { for (i = 0; days[i]; i++) { if (prefix(days[i], s)) if (tp->tm_wday == i) dayok = 1; } if (prefix("Wk", s)) if (tp->tm_wday >= 1 && tp->tm_wday <= 5) dayok = 1; if (prefix("Any", s)) dayok = 1; s++; } if (dayok == 0) return(0); i = sscanf(s, "%d-%d", &tl, &th); tn = tp->tm_hour * 100 + tp->tm_min; if (i < 2) return(1); if (tn >= tl && tn <= th) return(1); return(0); }