1*33581Srick #ifndef lint 2*33581Srick static char sccsid[] = "@(#)conn.c 5.12 (Berkeley) 02/24/88"; 3*33581Srick #endif 413642Ssam 523596Sbloom #include <signal.h> 613642Ssam #include "uucp.h" 713642Ssam #include <setjmp.h> 813642Ssam #include <ctype.h> 913642Ssam #include <errno.h> 1017834Sralph #ifdef USG 1113642Ssam #include <termio.h> 1213642Ssam #include <fcntl.h> 1313642Ssam #endif 1417834Sralph #ifndef USG 1513642Ssam #include <sgtty.h> 1613642Ssam #endif 1717834Sralph #ifdef BSD4_2 1817834Sralph #include <sys/time.h> 1917834Sralph #else 2017834Sralph #include <time.h> 2117834Sralph #endif 2213642Ssam 2313642Ssam #define MAXC 1000 2413642Ssam 2513642Ssam extern jmp_buf Sjbuf; 2617834Sralph jmp_buf Cjbuf; 2718619Sralph extern int errno, onesys; 2817834Sralph extern char *sys_errlist[]; 2918619Sralph extern char MaxGrade, DefMaxGrade; 3013642Ssam 3113642Ssam /* Parity control during login procedure */ 3213642Ssam #define P_ZERO 0 3313642Ssam #define P_ONE 1 3413642Ssam #define P_EVEN 2 3513642Ssam #define P_ODD 3 3617834Sralph 3717834Sralph #define ABORT -2 3817834Sralph 3917834Sralph char *AbortOn = NULL; 4013642Ssam char par_tab[128]; /* must be power of two */ 4117834Sralph int linebaudrate; /* used for the sleep test in pk1.c */ 4213642Ssam int next_fd = -1; /* predicted fd to close interrupted opens */ 4325705Sbloom 4425705Sbloom char *PCP = "PCP"; /* PC Pursuit device type */ 4525127Sbloom /* 4625127Sbloom * catch alarm routine for "expect". 4713642Ssam */ 4813642Ssam alarmtr() 4913642Ssam { 5013642Ssam signal(SIGALRM, alarmtr); 5113642Ssam if (next_fd >= 0) { 5213642Ssam if (close(next_fd)) 5313642Ssam logent("FAIL", "ACU LINE CLOSE"); 5413642Ssam next_fd = -1; 5513642Ssam } 5613642Ssam longjmp(Sjbuf, 1); 5713642Ssam } 5813642Ssam 5925705Sbloom /* This template is for seismo to call ihnp4 6025705Sbloom * the 3 lines marked ---> will be overwritten for the appropriate city 6125705Sbloom */ 6225705Sbloom #define PCP_BAUD 3 6325705Sbloom #define PCP_PHONE 4 6433562Srick #define PCP_CITY 14 6533562Srick #define PCP_PASSWORD 16 6633562Srick #define PCP_RPHONE 20 6733562Srick #define NPCFIELDS 23 6825705Sbloom 6925705Sbloom static char *PCFlds[] = { 7025705Sbloom "PC-PURSUIT", 7125705Sbloom "Any", 7225705Sbloom "ACU", 7325705Sbloom "1200", 7433562Srick CNULL, 7533562Srick CNULL, 7633562Srick "P_ZERO", /* Telenet insists on zero parity */ 7725705Sbloom "ABORT", 7833562Srick "BUSY", /* Abort on Busy Signal */ 7933562Srick CNULL, 8033562Srick "\\d\\d\\r\\d\\r", /* Get telenet's attention */ 8133562Srick "TERMINAL=~3-\r-TERM~3-\r-TERM~5", /* Terminal type ? */ 8233562Srick "\\r", 8333562Srick "@", /* telenet's prompt */ 8433562Srick "D/DCWAS/21,telenetloginstring", /* overwritten later */ 8533562Srick "PASSWORD", 8633562Srick CNULL, /* telenet password */ 8733562Srick "CONNECTED", /* We're now talking to a Hayes in the remote city */ 8833562Srick "ATZ", /* Reset it */ 8933562Srick "OK", 9033562Srick "ATDT6907171", /* overwritten */ 9133562Srick "CONNECT", 9233562Srick "\\d\\r", /* We're in !*/ 9333562Srick CNULL, 9425705Sbloom }; 9525705Sbloom 9633562Srick static char PCP_brand[25]; 9725705Sbloom 9818619Sralph /* 9918619Sralph * place a telephone call to system and login, etc. 10013642Ssam * 10113642Ssam * return codes: 10213642Ssam * CF_SYSTEM: don't know system 10313642Ssam * CF_TIME: wrong time to call 10413642Ssam * CF_DIAL: call failed 10513642Ssam * CF_NODEV: no devices available to place call 10613642Ssam * CF_LOGIN: login/password dialog failed 10713642Ssam * 10813642Ssam * >0 - file no. - connect ok 10913642Ssam */ 11013642Ssam 11113642Ssam int Dcf = -1; 11217834Sralph char *Flds[MAXC/10]; 11325966Sbloom char LineType[10]; 11417834Sralph extern int LocalOnly; 11513642Ssam 11613642Ssam conn(system) 11713642Ssam char *system; 11813642Ssam { 11925705Sbloom int nf; 12018619Sralph char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE]; 12113642Ssam register FILE *fsys; 12213642Ssam int fcode = 0; 12313642Ssam 12413642Ssam nf = 0; 12513642Ssam 12613642Ssam fsys = fopen(SYSFILE, "r"); 12713642Ssam ASSERT(fsys != NULL, "CAN'T OPEN", SYSFILE, 0); 12813642Ssam 12917834Sralph DEBUG(4, "finds (%s) called\n", system); 13025127Sbloom keeplooking: 13117834Sralph while((nf = finds(fsys, system, info, Flds)) > 0) { 13225966Sbloom strncpy(LineType, Flds[F_LINE], 10); 13317834Sralph if (LocalOnly) { 13425966Sbloom if (strcmp("TCP", LineType) 13525966Sbloom && strcmp("DIR", LineType) 13625966Sbloom && strcmp("LOCAL", LineType) ) { 13725705Sbloom fcode = CF_TIME; 13825705Sbloom continue; 13925705Sbloom } 14017834Sralph } 14123596Sbloom sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); 14218619Sralph if (!onesys && MaxGrade != DefMaxGrade && 14325705Sbloom !iswrk(file, "chk", Spool, wkpre)) { 14425705Sbloom fcode = CF_TIME; 14525705Sbloom continue; 14625705Sbloom } 14725705Sbloom /* For GTE's PC Pursuit */ 14825966Sbloom if (snccmp(LineType, PCP) == SAME) { 14925705Sbloom FILE *dfp; 15025705Sbloom int status; 15125705Sbloom static struct Devices dev; 15233562Srick 15325705Sbloom dfp = fopen(DEVFILE, "r"); 15425705Sbloom ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); 15525705Sbloom while ((status=rddev(dfp, &dev)) != FAIL 15625705Sbloom && strcmp(PCP, dev.D_type) != SAME) 15725705Sbloom ; 15825705Sbloom fclose(dfp); 15925705Sbloom if (status == FAIL) 16025705Sbloom continue; 16125705Sbloom if (mlock(PCP) == FAIL) { 16225705Sbloom fcode = CF_NODEV; 16325705Sbloom logent("DEVICE", "NO"); 16425705Sbloom continue; 16525705Sbloom } 16625705Sbloom PCFlds[PCP_BAUD] = dev.D_class; 16725705Sbloom PCFlds[PCP_PHONE] = dev.D_calldev; 16833562Srick sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s", 16933562Srick Flds[F_CLASS], 17033562Srick index(Flds[F_CLASS], '/') == NULL ? "/12" : "", 17133562Srick dev.D_arg[D_CHAT]); 17233562Srick PCFlds[PCP_PASSWORD] = dev.D_line; 17333562Srick strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7); 17425705Sbloom strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand)); 17533562Srick if ((fcode = getto(PCFlds)) < 0) { 17633562Srick rmlock(PCP); 17725705Sbloom continue; 17833562Srick } 17925705Sbloom Dcf = fcode; 18025705Sbloom fcode = login(NPCFIELDS, PCFlds, Dcf); 18133562Srick if (fcode == SUCCESS) 18233562Srick break; 18333562Srick fcode = CF_DIAL; 18433562Srick rmlock(PCP); 18533562Srick /* end PC Pursuit */ 18633562Srick } else if ((fcode = getto(Flds)) > 0) { 18733562Srick Dcf = fcode; 18813642Ssam break; 18933562Srick } 19013642Ssam } 19113642Ssam 19225127Sbloom if (nf <= 0) { 19325127Sbloom fclose(fsys); 19417834Sralph return fcode ? fcode : nf; 19525127Sbloom } 19613642Ssam 19725705Sbloom 19825705Sbloom if (fcode >= 0) { 19925705Sbloom DEBUG(4, "login %s\n", "called"); 20033562Srick fcode = login(nf, Flds, Dcf); } 20125705Sbloom if (fcode < 0) { 20213642Ssam clsacu(); 20325705Sbloom if (fcode == ABORT) { 20425127Sbloom fcode = CF_DIAL; 20525127Sbloom goto keeplooking; 20625127Sbloom } else { 20725127Sbloom fclose(fsys); 20823596Sbloom return CF_LOGIN; 20925127Sbloom } 21013642Ssam } 21125127Sbloom fclose(fsys); 21225705Sbloom fioclex(Dcf); 21325705Sbloom return Dcf; 21413642Ssam } 21513642Ssam 21625127Sbloom /* 21725127Sbloom * connect to remote machine 21813642Ssam * 21913642Ssam * return codes: 22013642Ssam * >0 - file number - ok 22113642Ssam * FAIL - failed 22213642Ssam */ 22313642Ssam 22413642Ssam getto(flds) 22513642Ssam register char *flds[]; 22613642Ssam { 22713642Ssam register struct condev *cd; 22813642Ssam int nulldev(), diropn(); 22925127Sbloom char *line; 23013642Ssam 23117834Sralph DEBUG(4, "getto: call no. %s ", flds[F_PHONE]); 23213642Ssam DEBUG(4, "for sys %s\n", flds[F_NAME]); 23313642Ssam 23425127Sbloom if (snccmp(flds[F_LINE], "LOCAL") == SAME) 23525127Sbloom line = "ACU"; 23625127Sbloom else 23725127Sbloom line = flds[F_LINE]; 23825127Sbloom #ifdef DIALINOUT 23925127Sbloom if (snccmp(line, "ACU") != SAME) 24025127Sbloom reenable(); 24125127Sbloom #endif DIALINOUT 24213642Ssam CU_end = nulldev; 24325705Sbloom if (snccmp(line, PCP) == SAME) { 24425705Sbloom for(cd = condevs; cd->CU_meth != NULL; cd++) { 24525705Sbloom if (snccmp(PCP_brand, cd->CU_brand) == SAME) { 24625705Sbloom CU_end = cd->CU_clos; 24725705Sbloom return diropn(flds); 24825705Sbloom } 24913642Ssam } 25025705Sbloom logent(PCP_brand, "UNSUPPORTED ACU TYPE"); 25125705Sbloom } else { 25225705Sbloom for (cd = condevs; cd->CU_meth != NULL; cd++) { 25325705Sbloom if (snccmp(cd->CU_meth, line) == SAME) { 25425705Sbloom DEBUG(4, "Using %s to call\n", cd->CU_meth); 25525705Sbloom return (*(cd->CU_gen))(flds); 25625705Sbloom } 25725705Sbloom } 25825705Sbloom DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]); 25913642Ssam } 26017834Sralph return diropn(flds); /* search failed, so use direct */ 26117834Sralph } 26213642Ssam 26325127Sbloom /* 26425127Sbloom * close call unit 26513642Ssam * 26613642Ssam * return codes: none 26713642Ssam */ 26813642Ssam 26913642Ssam int (*CU_end)() = nulldev; 27013642Ssam clsacu() 27113642Ssam { 27217834Sralph /* make *sure* Dcf is no longer exclusive. 27317834Sralph * Otherwise dual call-in/call-out modems could get stuck. 27417834Sralph * Unfortunately, doing this here is not ideal, but it is the 27517834Sralph * easiest place to put the call. 27617834Sralph * Hopefully everyone honors the LCK protocol, of course 27717834Sralph */ 27825705Sbloom #ifdef TIOCNXCL 27923596Sbloom if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0) 28023596Sbloom DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]); 28117834Sralph #endif 28217834Sralph if (setjmp(Sjbuf)) 28317834Sralph logent(Rmtname, "CLOSE TIMEOUT"); 28417834Sralph else { 28517834Sralph signal(SIGALRM, alarmtr); 28617834Sralph alarm(20); 28717834Sralph (*(CU_end))(Dcf); 28817834Sralph alarm(0); 28917834Sralph } 29013642Ssam if (close(Dcf) == 0) { 29113642Ssam DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf); 29213642Ssam logent("clsacu", "NOT CLOSED by CU_clos"); 29313642Ssam } 29413642Ssam Dcf = -1; 29513642Ssam CU_end = nulldev; 29613642Ssam } 29713642Ssam 29825127Sbloom /* 29925127Sbloom * expand phone number for given prefix and number 30013642Ssam */ 30113642Ssam 30213642Ssam exphone(in, out) 30313642Ssam register char *in, *out; 30413642Ssam { 30513642Ssam FILE *fn; 30613642Ssam char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH]; 30713642Ssam char buf[BUFSIZ]; 30813642Ssam register char *s1; 30913642Ssam 31017834Sralph if (!isascii(*in) || !isalpha(*in)) { 31113642Ssam strcpy(out, in); 31213642Ssam return; 31313642Ssam } 31413642Ssam 31513642Ssam s1=pre; 31617834Sralph while (isascii(*in) && isalpha(*in)) 31713642Ssam *s1++ = *in++; 31813642Ssam *s1 = '\0'; 31913642Ssam s1 = npart; 32013642Ssam while (*in != '\0') 32113642Ssam *s1++ = *in++; 32213642Ssam *s1 = '\0'; 32313642Ssam 32413642Ssam tpre[0] = '\0'; 32513642Ssam if ((fn = fopen(DIALFILE, "r")) == NULL) 32613642Ssam DEBUG(2, "CAN'T OPEN %s\n", DIALFILE); 32713642Ssam else { 32813642Ssam while (cfgets(buf, BUFSIZ, fn)) { 32917834Sralph if (sscanf(buf, "%s%s", p, tpre) != 2) 33017834Sralph continue; 33113642Ssam if (strcmp(p, pre) == SAME) 33213642Ssam goto found; 33313642Ssam tpre[0] = '\0'; 33413642Ssam } 33513642Ssam DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre); 33613642Ssam found:; 33713642Ssam fclose(fn); 33813642Ssam } 33913642Ssam 34013642Ssam strcpy(out, tpre); 34113642Ssam strcat(out, npart); 34213642Ssam } 34313642Ssam 34418619Sralph /* 34518619Sralph * read and decode a line from device file 34613642Ssam * 34713642Ssam * return code - FAIL at end-of file; 0 otherwise 34813642Ssam */ 34913642Ssam 35013642Ssam rddev(fp, dev) 35113642Ssam register struct Devices *dev; 35213642Ssam FILE *fp; 35313642Ssam { 35417834Sralph register int na; 35513642Ssam 35617834Sralph if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp)) 35717834Sralph return FAIL; 35817834Sralph na = getargs(dev->D_argbfr, dev->D_arg, 20); 35917834Sralph ASSERT(na >= 4, "BAD DEVICE ENTRY", dev->D_argbfr, 0); 36017834Sralph if (na == 4) { 36117834Sralph dev->D_brand = ""; 36217834Sralph na++; 36317834Sralph } 36413642Ssam dev->D_speed = atoi(fdig(dev->D_class)); 36517834Sralph dev->D_numargs = na; 36617834Sralph return 0; 36713642Ssam } 36813642Ssam 36918619Sralph /* 37018619Sralph * set system attribute vector 37113642Ssam * 37213642Ssam * return codes: 37313642Ssam * >0 - number of arguments in vector - succeeded 37413642Ssam * CF_SYSTEM - system name not found 37513642Ssam * CF_TIME - wrong time to call 37613642Ssam */ 37713642Ssam 37813642Ssam finds(fsys, sysnam, info, flds) 37913642Ssam char *sysnam, info[], *flds[]; 38013642Ssam FILE *fsys; 38113642Ssam { 38213642Ssam int na; 38313642Ssam int fcode = 0; 38413642Ssam 38513642Ssam /* format of fields 38613642Ssam * 0 name; 38713642Ssam * 1 time 38813642Ssam * 2 acu/hardwired 38913642Ssam * 3 speed 39013642Ssam * etc 39113642Ssam */ 39213642Ssam while (cfgets(info, MAXC, fsys) != NULL) { 39317834Sralph na = getargs(info, flds, MAXC/10); 39423596Sbloom if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME) 39513642Ssam continue; 39618619Sralph if (ifdate(flds[F_TIME]) != FAIL) 39713642Ssam /* found a good entry */ 39817834Sralph return na; 39913642Ssam DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]); 40013642Ssam fcode = CF_TIME; 40113642Ssam } 40217834Sralph return fcode ? fcode : CF_SYSTEM; 40313642Ssam } 40413642Ssam 40518619Sralph /* 40618619Sralph * do login conversation 40713642Ssam * 40823596Sbloom * return codes: SUCCESS | FAIL 40913642Ssam */ 41013642Ssam 41113642Ssam login(nf, flds, fn) 41213642Ssam register char *flds[]; 41313642Ssam int nf, fn; 41413642Ssam { 41513642Ssam register char *want, *altern; 41613642Ssam int k, ok; 41713642Ssam 41817834Sralph ASSERT(nf > 4, "TOO FEW LOG FIELDS", CNULL, nf); 41917834Sralph if (setjmp(Cjbuf)) 42017834Sralph return FAIL; 42117834Sralph AbortOn = NULL; 42213642Ssam for (k = F_LOGIN; k < nf; k += 2) { 42313642Ssam want = flds[k]; 42433562Srick if (want == NULL) 42533562Srick want = ""; 42613642Ssam ok = FAIL; 42717834Sralph while (ok != SUCCESS) { 42813642Ssam altern = index(want, '-'); 42913642Ssam if (altern != NULL) 43013642Ssam *altern++ = '\0'; 43117834Sralph if (strcmp(want, "ABORT") == 0) { 43217834Sralph AbortOn = flds[k+1]; 43317834Sralph DEBUG(4, "ABORT ON: %s\n", AbortOn); 43417834Sralph goto nextfield; 43517834Sralph } 43625705Sbloom DEBUG(4, "wanted \"%s\"\n", want); 43713642Ssam ok = expect(want, fn); 43817834Sralph DEBUG(4, "got: %s\n", ok ? "?" : "that"); 43917834Sralph if (ok == FAIL) { 44017834Sralph if (altern == NULL) { 44117834Sralph logent("LOGIN", _FAILED); 44217834Sralph return FAIL; 44317834Sralph } 44417834Sralph want = index(altern, '-'); 44517834Sralph if (want != NULL) 44617834Sralph *want++ = '\0'; 44717834Sralph sendthem(altern, fn); 44817834Sralph } else 44917834Sralph if (ok == ABORT) { 45033562Srick char sbuf[MAXFULLNAME]; 45133562Srick sprintf(sbuf, "LOGIN ABORTED on \"%s\"", AbortOn); 45233562Srick logent(sbuf, _FAILED); 45323596Sbloom return ABORT; 45417834Sralph } 45513642Ssam } 45617834Sralph sleep(1); 45713642Ssam if (k+1 < nf) 45813642Ssam sendthem(flds[k+1], fn); 45917834Sralph nextfield: ; 46013642Ssam } 46117834Sralph return SUCCESS; 46213642Ssam } 46313642Ssam 46413642Ssam 46517834Sralph /* conditional table generation to support odd speeds */ 46613642Ssam struct sg_spds {int sp_val, sp_name;} spds[] = { 46713642Ssam #ifdef B50 46813642Ssam { 50, B50}, 46913642Ssam #endif 47013642Ssam #ifdef B75 47113642Ssam { 75, B75}, 47213642Ssam #endif 47313642Ssam #ifdef B110 47413642Ssam { 110, B110}, 47513642Ssam #endif 47613642Ssam #ifdef B150 47713642Ssam { 150, B150}, 47813642Ssam #endif 47913642Ssam #ifdef B200 48013642Ssam { 200, B200}, 48113642Ssam #endif 48213642Ssam #ifdef B300 48313642Ssam { 300, B300}, 48413642Ssam #endif 48513642Ssam #ifdef B600 48613642Ssam {600, B600}, 48713642Ssam #endif 48813642Ssam #ifdef B1200 48913642Ssam {1200, B1200}, 49013642Ssam #endif 49113642Ssam #ifdef B1800 49213642Ssam {1800, B1800}, 49313642Ssam #endif 49413642Ssam #ifdef B2000 49513642Ssam {2000, B2000}, 49613642Ssam #endif 49713642Ssam #ifdef B2400 49813642Ssam {2400, B2400}, 49913642Ssam #endif 50013642Ssam #ifdef B3600 50113642Ssam {3600, B3600}, 50213642Ssam #endif 50313642Ssam #ifdef B4800 50413642Ssam {4800, B4800}, 50513642Ssam #endif 50613642Ssam #ifdef B7200 50713642Ssam {7200, B7200}, 50813642Ssam #endif 50913642Ssam #ifdef B9600 51013642Ssam {9600, B9600}, 51113642Ssam #endif 51213642Ssam #ifdef B19200 51317834Sralph {19200, B19200}, 51413642Ssam #endif 51517834Sralph #ifdef EXTA 51617834Sralph {19200, EXTA}, 51717834Sralph #endif 51813642Ssam {0, 0} 51913642Ssam }; 52013642Ssam 52118619Sralph /* 52218619Sralph * set speed/echo/mode... 52313642Ssam * 52413642Ssam * return codes: none 52513642Ssam */ 52613642Ssam 52713642Ssam fixline(tty, spwant) 52813642Ssam int tty, spwant; 52913642Ssam { 53017834Sralph #ifdef USG 53113642Ssam struct termio ttbuf; 53217834Sralph #else !USG 53313642Ssam struct sgttyb ttbuf; 53417834Sralph #endif !USG 53513642Ssam register struct sg_spds *ps; 53613642Ssam int speed = -1; 53713642Ssam 53813642Ssam for (ps = spds; ps->sp_val; ps++) 53913642Ssam if (ps->sp_val == spwant) 54013642Ssam speed = ps->sp_name; 54117834Sralph ASSERT(speed >= 0, "BAD SPEED", CNULL, speed); 54217834Sralph #ifdef USG 54323596Sbloom if (ioctl(tty, TCGETA, &ttbuf) < 0) 54423596Sbloom return FAIL; 54513642Ssam /* ttbuf.sg_flags = (ANYP|RAW); 54613642Ssam ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */ 54713642Ssam ttbuf.c_iflag = (ushort)0; 54813642Ssam ttbuf.c_oflag = (ushort)0; 54913642Ssam ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD); 55013642Ssam ttbuf.c_lflag = (ushort)0; 55113642Ssam ttbuf.c_cc[VMIN] = 6; 55213642Ssam ttbuf.c_cc[VTIME] = 1; 55323596Sbloom if (ioctl(tty, TCSETA, &ttbuf) < 0) 55423596Sbloom return FAIL; 55517834Sralph #else !USG 55623596Sbloom if (ioctl(tty, TIOCGETP, &ttbuf) < 0) 55723596Sbloom return FAIL; 55813642Ssam ttbuf.sg_flags = (ANYP|RAW); 55913642Ssam ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; 56023596Sbloom if (ioctl(tty, TIOCSETP, &ttbuf) < 0) 56123596Sbloom return FAIL; 56213642Ssam #endif 56317834Sralph #ifndef USG 56423596Sbloom if (ioctl(tty, TIOCHPCL, STBNULL) < 0) 56523596Sbloom return FAIL; 56623596Sbloom if (ioctl(tty, TIOCEXCL, STBNULL) < 0) 56723596Sbloom return FAIL; 56813642Ssam #endif 56917834Sralph linebaudrate = spwant; 57023596Sbloom return SUCCESS; 57113642Ssam } 57213642Ssam 57317834Sralph #define MR 100 57413642Ssam 57518619Sralph /* 57618619Sralph * look for expected string 57713642Ssam * 57813642Ssam * return codes: 57913642Ssam * 0 - found 58013642Ssam * FAIL - lost line or too many characters read 58113642Ssam * some character - timed out 58213642Ssam */ 58313642Ssam 58413642Ssam expect(str, fn) 58513642Ssam register char *str; 58613642Ssam int fn; 58713642Ssam { 58814592Skarels char rdvec[MR]; 58917834Sralph register char *rp = rdvec, *strptr; 59017834Sralph int kr, cnt_char; 59113642Ssam char nextch; 59225127Sbloom int timo = MAXMSGTIME; 59313642Ssam 59417834Sralph if (*str == '\0' || strcmp(str, "\"\"") == SAME) 59517834Sralph return SUCCESS; 59617834Sralph /* Cleanup str, convert \0xx strings to one char */ 59717834Sralph for (strptr = str; *strptr; strptr++) { 59817834Sralph if (*strptr == '\\') 59917834Sralph switch(*++strptr) { 60017834Sralph case 's': 60117834Sralph DEBUG(5, "BLANK\n", CNULL); 60217834Sralph *strptr = ' '; 60317834Sralph break; 60417834Sralph default: 60517834Sralph strptr--; /* back up to backslash */ 60617834Sralph sscanf(strptr + 1,"%o", &cnt_char); 60717834Sralph DEBUG(6, "BACKSLASHED %02xH\n", cnt_char); 60817834Sralph *strptr = (char) (cnt_char); 60917834Sralph strcpy(&strptr[1], &strptr[4]); 61017834Sralph } 61117834Sralph } 61217834Sralph 61325127Sbloom strptr = index(str, '~'); 61425127Sbloom if (strptr != NULL) { 61525127Sbloom *strptr++ = '\0'; 61625127Sbloom timo = atoi(strptr); 61725127Sbloom if (timo <= 0) 61825127Sbloom timo = MAXMSGTIME; 61925127Sbloom } 62025127Sbloom 62117834Sralph if (setjmp(Sjbuf)) 62217834Sralph return FAIL; 62313642Ssam signal(SIGALRM, alarmtr); 62425127Sbloom alarm(timo); 62525127Sbloom *rp = 0; 62613642Ssam while (notin(str, rdvec)) { 62725705Sbloom int c; 62817834Sralph if(AbortOn != NULL && !notin(AbortOn, rdvec)) { 62917834Sralph DEBUG(1, "Call aborted on '%s'\n", AbortOn); 63017834Sralph alarm(0); 63117834Sralph return ABORT; 63217834Sralph } 63313642Ssam kr = read(fn, &nextch, 1); 63413642Ssam if (kr <= 0) { 63513642Ssam alarm(0); 63613642Ssam DEBUG(4, "lost line kr - %d\n, ", kr); 63713642Ssam logent("LOGIN", "LOST LINE"); 63817834Sralph return FAIL; 63913642Ssam } 64013642Ssam c = nextch & 0177; 64125705Sbloom if (c == '\0') 64225705Sbloom continue; 64325705Sbloom DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c); 64425705Sbloom *rp++ = c; 64513642Ssam if (rp >= rdvec + MR) { 64617834Sralph register char *p; 64717834Sralph for (p = rdvec+MR/2; p < rp; p++) 64817834Sralph *(p-MR/2) = *p; 64917834Sralph rp -= MR/2; 65013642Ssam } 65113642Ssam *rp = '\0'; 65213642Ssam } 65313642Ssam alarm(0); 65417834Sralph return SUCCESS; 65513642Ssam } 65613642Ssam 65713642Ssam 65813642Ssam /* 65913642Ssam * Determine next file descriptor that would be allocated. 66013642Ssam * This permits later closing of a file whose open was interrupted. 66113642Ssam * It is a UNIX kernel problem, but it has to be handled. 66213642Ssam * unc!smb (Steve Bellovin) probably first discovered it. 66313642Ssam */ 66413642Ssam getnextfd() 66513642Ssam { 66613642Ssam close(next_fd = open("/", 0)); 66713642Ssam } 66813642Ssam 66917834Sralph /* 67017834Sralph * send line of login sequence 67113642Ssam * 67213642Ssam * return codes: none 67313642Ssam */ 67413642Ssam sendthem(str, fn) 67513642Ssam register char *str; 67613642Ssam int fn; 67713642Ssam { 67813642Ssam register char *strptr; 67913642Ssam int i, n, cr = 1; 68017834Sralph register char c; 68113642Ssam static int p_init = 0; 68213642Ssam 68325705Sbloom DEBUG(5, "send \"%s\"\n", str); 68413642Ssam 68513642Ssam if (!p_init) { 68613642Ssam p_init++; 68713642Ssam bld_partab(P_EVEN); 68813642Ssam } 68913642Ssam 69013642Ssam if (prefix("BREAK", str)) { 69113642Ssam sscanf(&str[5], "%1d", &i); 69213642Ssam if (i <= 0 || i > 10) 69313642Ssam i = 3; 69413642Ssam /* send break */ 69513642Ssam genbrk(fn, i); 69613642Ssam return; 69713642Ssam } 69813642Ssam 69913642Ssam if (prefix("PAUSE", str)) { 70013642Ssam sscanf(&str[5], "%1d", &i); 70113642Ssam if (i <= 0 || i > 10) 70213642Ssam i = 3; 70313642Ssam /* pause for a while */ 70413642Ssam sleep((unsigned)i); 70513642Ssam return; 70613642Ssam } 70713642Ssam 70813642Ssam if (strcmp(str, "EOT") == SAME) { 70913642Ssam p_chwrite(fn, '\04'); 71013642Ssam return; 71113642Ssam } 71213642Ssam 71313642Ssam /* Send a '\n' */ 71425705Sbloom if (strcmp(str, "LF") == SAME) { 71525705Sbloom p_chwrite(fn, '\n'); 71625705Sbloom return; 71725705Sbloom } 71813642Ssam 71913642Ssam /* Send a '\r' */ 72025705Sbloom if (strcmp(str, "CR") == SAME) { 72125705Sbloom p_chwrite(fn, '\r'); 72225705Sbloom return; 72325705Sbloom } 72413642Ssam 72513642Ssam /* Set parity as needed */ 72613642Ssam if (strcmp(str, "P_ZERO") == SAME) { 72713642Ssam bld_partab(P_ZERO); 72813642Ssam return; 72913642Ssam } 73013642Ssam if (strcmp(str, "P_ONE") == SAME) { 73113642Ssam bld_partab(P_ONE); 73213642Ssam return; 73313642Ssam } 73413642Ssam if (strcmp(str, "P_EVEN") == SAME) { 73513642Ssam bld_partab(P_EVEN); 73613642Ssam return; 73713642Ssam } 73813642Ssam if (strcmp(str, "P_ODD") == SAME) { 73913642Ssam bld_partab(P_ODD); 74013642Ssam return; 74113642Ssam } 74213642Ssam 74313642Ssam /* If "", just send '\r' */ 74417834Sralph if (strcmp(str, "\"\"") == SAME) { 74517834Sralph p_chwrite(fn, '\r'); 74617834Sralph return; 74717834Sralph } 74817834Sralph 74925705Sbloom strptr = str; 75025705Sbloom while ((c = *strptr++) != '\0') { 75117834Sralph if (c == '\\') { 75217834Sralph switch(*strptr++) { 75325705Sbloom case '\0': 75425705Sbloom DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL); 75525705Sbloom --strptr; 75625705Sbloom continue; 75717834Sralph case 's': 75817834Sralph DEBUG(5, "BLANK\n", CNULL); 75925705Sbloom c = ' '; 76017834Sralph break; 76117834Sralph case 'd': 76217834Sralph DEBUG(5, "DELAY\n", CNULL); 76317834Sralph sleep(1); 76417834Sralph continue; 76525705Sbloom case 'n': 76625705Sbloom DEBUG(5, "NEW LINE\n", CNULL); 76725705Sbloom c = '\n'; 76825705Sbloom break; 76917834Sralph case 'r': 77017834Sralph DEBUG(5, "RETURN\n", CNULL); 77125705Sbloom c = '\r'; 77217834Sralph break; 77317834Sralph case 'b': 77417834Sralph if (isdigit(*strptr)) { 77517834Sralph i = (*strptr++ - '0'); 77617834Sralph if (i <= 0 || i > 10) 77717834Sralph i = 3; 77817834Sralph } else 77913642Ssam i = 3; 78017834Sralph /* send break */ 78117834Sralph genbrk(fn, i); 78217834Sralph if (*strptr == '\0') 78317834Sralph cr = 0; 78413642Ssam continue; 78517834Sralph case 'c': 78617834Sralph if (*strptr == '\0') { 78717834Sralph DEBUG(5, "NO CR\n", CNULL); 78817834Sralph cr = 0; 78925705Sbloom } else 79025705Sbloom DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL); 79113642Ssam continue; 79225705Sbloom #define isoctal(x) ((x >= '0') && (x <= '7')) 79317834Sralph default: 79425705Sbloom if (isoctal(strptr[-1])) { 79517834Sralph i = 0; 79617834Sralph n = 0; 79725705Sbloom --strptr; 79825705Sbloom while (isoctal(*strptr) && ++n <= 3) 79925705Sbloom i = i * 8 + (*strptr++ - '0'); 80025705Sbloom DEBUG(5, "\\%o\n", i); 80117834Sralph p_chwrite(fn, (char)i); 80217834Sralph continue; 80317834Sralph } 80413642Ssam } 80525705Sbloom } 80625705Sbloom p_chwrite(fn, c); 80713642Ssam } 80813642Ssam 80913642Ssam if (cr) 81013642Ssam p_chwrite(fn, '\r'); 81113642Ssam return; 81213642Ssam } 81313642Ssam 81413642Ssam p_chwrite(fd, c) 81513642Ssam int fd; 81617834Sralph char c; 81713642Ssam { 81817834Sralph c = par_tab[c&0177]; 81917834Sralph if (write(fd, &c, 1) != 1) { 82017834Sralph logent(sys_errlist[errno], "BAD WRITE"); 82117834Sralph longjmp(Cjbuf, 2); 82217834Sralph } 82313642Ssam } 82413642Ssam 82513642Ssam /* 82613642Ssam * generate parity table for use by p_chwrite. 82713642Ssam */ 82813642Ssam bld_partab(type) 82913642Ssam int type; 83013642Ssam { 83113642Ssam register int i, j, n; 83213642Ssam 83313642Ssam for (i = 0; i < sizeof(par_tab); i++) { 83413642Ssam n = 0; 83513642Ssam for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j) 83613642Ssam n++; 83713642Ssam par_tab[i] = i; 83813642Ssam if (type == P_ONE 83913642Ssam || (type == P_EVEN && (n&01) != 0) 84013642Ssam || (type == P_ODD && (n&01) == 0)) 84113642Ssam par_tab[i] |= sizeof(par_tab); 84213642Ssam } 84313642Ssam } 84413642Ssam 84518619Sralph /* 84618619Sralph * check for occurrence of substring "sh" 84713642Ssam * 84813642Ssam * return codes: 84913642Ssam * 0 - found the string 85013642Ssam * 1 - not in the string 85113642Ssam */ 85213642Ssam notin(sh, lg) 85313642Ssam register char *sh, *lg; 85413642Ssam { 85513642Ssam while (*lg != '\0') { 85613642Ssam if (wprefix(sh, lg)) 85718619Sralph return 0; 85813642Ssam else 85913642Ssam lg++; 86013642Ssam } 86118619Sralph return 1; 86213642Ssam } 86313642Ssam 86418619Sralph /* 86523596Sbloom * Allow multiple date specifications separated by ','. 86613642Ssam */ 86718619Sralph ifdate(p) 86818619Sralph register char *p; 86913642Ssam { 87025705Sbloom register char *np; 87118619Sralph register int ret, g; 87223596Sbloom int rtime, i; 87313642Ssam 87423596Sbloom /* pick up retry time for failures */ 87523596Sbloom /* global variable Retrytime is set here */ 87623596Sbloom if ((np = index(p, ';')) == NULL) { 87723596Sbloom Retrytime = RETRYTIME; 87823596Sbloom } else { 87923596Sbloom i = sscanf(np+1, "%d", &rtime); 88023596Sbloom if (i < 1 || rtime < 0) 88123596Sbloom rtime = 5; 88223596Sbloom Retrytime = rtime * 60; 88323596Sbloom } 88423596Sbloom 88518619Sralph ret = FAIL; 88618619Sralph MaxGrade = '\0'; 88718619Sralph do { 88823596Sbloom np = strpbrk(p, ",|"); /* prefer , but allow | for compat */ 88923596Sbloom if (np) 89023596Sbloom *np = '\0'; 89118619Sralph g = ifadate(p); 89218619Sralph DEBUG(11,"ifadate returns %o\n", g); 89318619Sralph if (g != FAIL) { 89418619Sralph ret = SUCCESS; 89518619Sralph if (g > MaxGrade) 89618619Sralph MaxGrade = g; 89718619Sralph } 89823596Sbloom if (np) 89923596Sbloom *np = ','; 90023596Sbloom p = np + 1; 90123596Sbloom } while (np); 90223596Sbloom if (MaxGrade == '\0') 90323596Sbloom MaxGrade = DefMaxGrade; 90418619Sralph return ret; 90513642Ssam } 90613642Ssam 90718619Sralph /* 90818619Sralph * this routine will check a string (string) 90913642Ssam * like "MoTu0800-1730" to see if the present 91013642Ssam * time is within the given limits. 91113642Ssam * SIDE EFFECT - Retrytime is set 91213642Ssam * 91313642Ssam * return codes: 91413642Ssam * 0 - not within limits 91513642Ssam * 1 - within limits 91613642Ssam */ 91713642Ssam 91818619Sralph ifadate(string) 91918619Sralph char *string; 92013642Ssam { 92113642Ssam static char *days[]={ 92213642Ssam "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 92313642Ssam }; 92413642Ssam time_t clock; 92518619Sralph register char *s = string; 92617834Sralph int i, tl, th, tn, dayok=0; 92713642Ssam struct tm *localtime(); 92813642Ssam struct tm *tp; 92918619Sralph char *p, MGrade; 93013642Ssam 93123596Sbloom if ((p = index(s, '/')) == NULL) 93218619Sralph MGrade = DefMaxGrade; 93318619Sralph else 93418619Sralph MGrade = p[1]; 93518619Sralph 93613642Ssam time(&clock); 93713642Ssam tp = localtime(&clock); 93817834Sralph while (isascii(*s) && isalpha(*s)) { 93913642Ssam for (i = 0; days[i]; i++) { 94013642Ssam if (prefix(days[i], s)) 94113642Ssam if (tp->tm_wday == i) 94213642Ssam dayok = 1; 94313642Ssam } 94413642Ssam 94513642Ssam if (prefix("Wk", s)) 94613642Ssam if (tp->tm_wday >= 1 && tp->tm_wday <= 5) 94713642Ssam dayok = 1; 94813642Ssam if (prefix("Any", s)) 94913642Ssam dayok = 1; 95017834Sralph if (prefix("Evening", s)) { 95117834Sralph /* Sat or Sun */ 95217834Sralph if (tp->tm_wday == 6 || tp->tm_wday == 0 95317834Sralph || tp->tm_hour >= 17 || tp->tm_hour < 8) 95417834Sralph dayok = 1; 95517834Sralph } 95617834Sralph if (prefix("Night", s)) { 95717834Sralph if (tp->tm_wday == 6 /* Sat */ 95818619Sralph || tp->tm_hour >= 23 || tp->tm_hour < 8 95918619Sralph /* Sunday before 5pm */ 96018619Sralph || (tp->tm_wday == 0 && tp->tm_hour < 17)) 96117834Sralph dayok = 1; 96217834Sralph } 96325705Sbloom if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */ 96425705Sbloom /* Sat or Sun */ 96525705Sbloom if (tp->tm_wday == 6 || tp->tm_wday == 0 96625705Sbloom || tp->tm_hour >= 18 || tp->tm_hour < 7) 96725705Sbloom dayok = 1; 96825705Sbloom } 96913642Ssam s++; 97013642Ssam } 97113642Ssam 97218619Sralph if (dayok == 0 && s != string) 97318619Sralph return FAIL; 97413642Ssam i = sscanf(s, "%d-%d", &tl, &th); 97518619Sralph if (i < 2) 97618619Sralph return MGrade; 97718619Sralph tn = tp->tm_hour * 100 + tp->tm_min; 97818619Sralph if (th < tl) { /* crosses midnight */ 97918619Sralph if (tl <= tn || tn < th) 98018619Sralph return MGrade; 98125966Sbloom } else { 98217834Sralph if (tl <= tn && tn < th) 98318619Sralph return MGrade; 98425966Sbloom } 98518619Sralph return FAIL; 98613642Ssam } 98713642Ssam 98818619Sralph /* 98918619Sralph * find first digit in string 99013642Ssam * 99113642Ssam * return - pointer to first digit in string or end of string 99213642Ssam */ 99313642Ssam char * 99413642Ssam fdig(cp) 99513642Ssam register char *cp; 99613642Ssam { 99713642Ssam register char *c; 99813642Ssam 99913642Ssam for (c = cp; *c; c++) 100013642Ssam if (*c >= '0' && *c <= '9') 100113642Ssam break; 100217834Sralph return c; 100313642Ssam } 100413642Ssam 100513642Ssam /* 100613642Ssam * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 100713642Ssam * Strings are compared as if they contain all capital letters. 100813642Ssam */ 100913642Ssam snccmp(s1, s2) 101013642Ssam register char *s1, *s2; 101113642Ssam { 101213642Ssam char c1, c2; 101313642Ssam 101425127Sbloom if (islower(*s1)) 101525127Sbloom c1 = toupper(*s1); 101625127Sbloom else 101725127Sbloom c1 = *s1; 101825127Sbloom if (islower(*s2)) 101925127Sbloom c2 = toupper(*s2); 102025127Sbloom else 102125127Sbloom c2 = *s2; 102213642Ssam 102313642Ssam while (c1 == c2) { 102425127Sbloom if (*s1++ == '\0') 102517834Sralph return 0; 102613642Ssam s2++; 102725127Sbloom if (islower(*s1)) 102825127Sbloom c1 = toupper(*s1); 102925127Sbloom else 103025127Sbloom c1 = *s1; 103125127Sbloom if (islower(*s2)) 103225127Sbloom c2 = toupper(*s2); 103325127Sbloom else 103425127Sbloom c2 = *s2; 103513642Ssam } 103617834Sralph return c1 - c2; 103713642Ssam } 103825127Sbloom 103917834Sralph /* 104025127Sbloom * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 104125127Sbloom * Strings are compared as if they contain all capital letters. 104225127Sbloom */ 104325127Sbloom sncncmp(s1, s2, n) 104425127Sbloom register char *s1, *s2; 104525127Sbloom register int n; 104625127Sbloom { 104725127Sbloom char c1, c2; 104825127Sbloom 104925127Sbloom if (islower(*s1)) 105025127Sbloom c1 = toupper(*s1); 105125127Sbloom else 105225127Sbloom c1 = *s1; 105325127Sbloom if (islower(*s2)) 105425127Sbloom c2 = toupper(*s2); 105525127Sbloom else 105625127Sbloom c2 = *s2; 105725127Sbloom 105825127Sbloom while ( --n >= 0 && c1 == c2) { 105925127Sbloom if (*s1++ == '\0') 106025127Sbloom return 0; 106125127Sbloom s2++; 106225127Sbloom if (islower(*s1)) 106325127Sbloom c1 = toupper(*s1); 106425127Sbloom else 106525127Sbloom c1 = *s1; 106625127Sbloom if (islower(*s2)) 106725127Sbloom c2 = toupper(*s2); 106825127Sbloom else 106925127Sbloom c2 = *s2; 107025127Sbloom } 107125127Sbloom return n<0 ? 0 : (c1 - c2); 107225127Sbloom } 107325127Sbloom /* 107417834Sralph * do chat script 107517834Sralph * occurs after local port is opened, 107617834Sralph * before 'dialing' the other machine. 107717834Sralph */ 107817834Sralph dochat(dev, flds, fd) 107917834Sralph register struct Devices *dev; 108017834Sralph char *flds[]; 108117834Sralph int fd; 108217834Sralph { 108317834Sralph register int i; 108417834Sralph register char *p; 108517834Sralph char bfr[sizeof(dev->D_argbfr)]; 108617834Sralph 108717834Sralph if (dev->D_numargs <= 5) 108817834Sralph return(0); 108917834Sralph DEBUG(4, "dochat called %d\n", dev->D_numargs); 109017834Sralph for (i = 0; i < dev->D_numargs-5; i++) { 109117834Sralph sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]); 109217834Sralph if (strcmp(bfr, dev->D_arg[D_CHAT+i])) { 109317834Sralph p = malloc((unsigned)strlen(bfr)+1); 109417834Sralph if (p != NULL) { 109517834Sralph strcpy(p, bfr); 109617834Sralph dev->D_arg[D_CHAT+i] = p; 109717834Sralph } 109817834Sralph } 109917834Sralph } 110017834Sralph /* following is a kludge because login() arglist is a kludge */ 110117834Sralph i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd); 110217834Sralph /* 110317834Sralph * If login() last did a sendthem(), must pause so things can settle. 110417834Sralph * But don't bother if chat failed. 110517834Sralph */ 110617834Sralph if (i == 0 && (dev->D_numargs&01)) 110717834Sralph sleep(2); 110817834Sralph return(i); 110917834Sralph } 111025705Sbloom 111125705Sbloom /* 111225705Sbloom * fix kill/echo/raw on line 111325705Sbloom * 111425705Sbloom * return codes: none 111525705Sbloom */ 111625705Sbloom fixmode(tty) 111725705Sbloom register int tty; 111825705Sbloom { 111925705Sbloom #ifdef USG 112025705Sbloom struct termio ttbuf; 112125705Sbloom #else !USG 112225705Sbloom struct sgttyb ttbuf; 112325705Sbloom #endif !USG 112425705Sbloom register struct sg_spds *ps; 112525705Sbloom int speed; 112625705Sbloom 112725705Sbloom if (IsTcpIp) 112825705Sbloom return; 112925705Sbloom #ifdef USG 113025705Sbloom ioctl(tty, TCGETA, &ttbuf); 113125705Sbloom ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0; 113225705Sbloom speed = ttbuf.c_cflag &= (CBAUD); 113325705Sbloom ttbuf.c_cflag |= (CS8|CREAD); 113425705Sbloom ttbuf.c_cc[VMIN] = 6; 113525705Sbloom ttbuf.c_cc[VTIME] = 1; 113625705Sbloom ioctl(tty, TCSETA, &ttbuf); 113725705Sbloom #else !USG 113825705Sbloom ioctl(tty, TIOCGETP, &ttbuf); 113925705Sbloom ttbuf.sg_flags = (ANYP | RAW); 114025705Sbloom ioctl(tty, TIOCSETP, &ttbuf); 114125705Sbloom speed = ttbuf.sg_ispeed; 114225705Sbloom ioctl(tty, TIOCEXCL, STBNULL); 114325705Sbloom #endif !USG 114425705Sbloom 114525705Sbloom for (ps = spds; ps->sp_val; ps++) 114625705Sbloom if (ps->sp_name == speed) { 114725705Sbloom linebaudrate = ps->sp_val; 114825705Sbloom DEBUG(9,"Incoming baudrate is %d\n", linebaudrate); 114925705Sbloom return; 115025705Sbloom } 115125705Sbloom ASSERT(linebaudrate >= 0, "BAD SPEED", CNULL, speed); 115225705Sbloom } 115325705Sbloom 1154