Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uwm.edu!rpi!uupsi!jpradley!jpr From: jpr@jpradley.jpr.com (Jean-Pierre Radley) Newsgroups: comp.dcom.modems Subject: Re: T2500/SCO Xenix Configuration Message-ID: <1991Apr02.061149.15216@jpradley.jpr.com> Date: 2 Apr 91 06:11:49 GMT References: <1991Mar29.233228.17548@netcom.COM> <390@alchemy.UUCP> <398@alchemy.UUCP> Organization: NYC Public Unix Lines: 1863 In article <398@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >In article <1991Mar29.233228.17548@netcom.COM> gandrews@netcom.COM (Greg Andrews) writes: >>In article <390@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >>Note that the dialTBIT distributed with SCO Xenix (and Unix) was written >>for the TrailBlazer Plus modem and not the T2500. It can't handle the >>V.32 result codes that the modem will return, so it chokes on V.32 calls. >>There are hacked versions of dialTBIT on the net (dunno where). > >If anyone knows of such a thing, I'd love to hear about it as it would >be nice to have it understand V.32 connections, etc. OK, I captured dialTBALL.c once. --------------------------------------------- /* * Function: dialer program for the Telebit Trailblazer * * Usage: dial ttyname telnumber speed * dial -h ttyname speed * dial -z ttyname speed * * Returns: 0x80 bit = 1 if connection failed * 0x10 bit = 1 if line is also used for dialin #ifndef HDUU * 0x0f if msb=1: error code * if msb=0: connected baud rate (0=same as dialed baud) * * Note: getty calls the dialer with -h whenever it starts up * on a line enabled in /etc/ttys and listed in Devices with * this dialer. * * The user should call the dialer with -z to initialize * the modem when it is first installed: the -z option writes * default settings into the non-volatile memory of the modem. * * Error codes are split into two catagories: 1) (codes 0-11) * Local problems are defined as tty port, or modem problems: * problems that can be worked around by using a different device. * 2) (codes 12-15) Remote problems such as phone busy, no * answer, etc. Attempts to connect to this remote system * should be stopped. * * Documents: Telebit Trailblazer manual * Telebit T2500 manual * Telebit Trailblazer Plus PC manual (T18PC) * * Note: This source file can be used both for the old UUCP and * for the new HoneyDanBer UUCP. For the latter, HDUU may * be defined to avoid calls to the HD ungetty program - which * assumes that uugetty is used, and so simply returns SUCCESS. * However, dialer binaries for the old UUCP are equally valid * for the new HoneyDanBer UUCP (but make an unnecessary call * to the null ungetty, supplied for backward compatibility). * * Note: Changes for Telebit T2500 and TrailblazerPlus PC modems made * by Scott O'Connell & Bill Blue (ipars!scotto, crash!bblue) */ static char sccsid[] = "@(#)dialTBALL.c 89/11/23 "; #define SLIP #include #include #include #include #include #include #include #include #include /* * define T2500 for the T2500, TPC for the T18PC, or V3 for the older * rev 3 ROMS on a standard Trailblazer, either here or in the makefile. * If all are undefined, default becomes standard newer Trailblazer. * * also, define WAITFORDT to always wait for dialtone before continuing. * * define SLOWRITE if a one second delay seems necessary prior to each * modem *string* write. It was a default in the original dialer. */ #define T2500 /**/ * #define TPC /**/ /* #define V3 /**/ #define WAITFORDT /**/ /* define SLOWRITE /**/ #ifndef B19200 #define B19200 EXTA #endif #ifndef B38400 #define B38400 EXTB #endif /* return codes: these are set up so that an abort signal at any time can */ /* set the fail bit and return to the caller with the correct status */ #define RC_BAUD 0x0f /* CBAUD connected at (0=same as dialed speed)*/ #define RC_ENABLED 0x10 /* enabled flag: 1 = ungetty -r required to */ /* restore the line */ #define RC_FAIL 0x80 /* 1 = failed to connect */ /* error return codes */ #define RCE_NULL 0 /* general purpose or unknown error code */ #define RCE_INUSE 1 /* line in use */ #define RCE_SIG 2 /* signal aborted dialer */ #define RCE_ARGS 3 /* invalid arguments */ #define RCE_PHNO 4 /* invalid phone number */ #define RCE_SPEED 5 /* invalid baud rate -or- bad connect baud */ #define RCE_OPEN 6 /* can't open line */ #define RCE_IOCTL 7 /* ioctl error */ #define RCE_TIMOUT 8 /* timeout */ #define RCE_NOTONE 9 /* no dial tone */ #define RCE_HANGUP 10 /* hangup failed */ #define RCE_NORESP 11 /* Modem didn't respond. */ #define RCE_BUSY 13 /* phone is busy */ #define RCE_NOCARR 14 /* no carrier */ #define RCE_ANSWER 15 /* no answer */ #define SUCCESS 0 /* ungetty return codes */ #define UG_NOTENAB 0 #define UG_ENAB 1 #define UG_RESTART 1 #define UG_FAIL 2 #define SAME 0 #define MAXLINE 256 #define UNGETTY "/usr/lib/uucp/ungetty" #define DEBUG(l, f, s) if (Debug >= l) fprintf(stderr, f, s) #ifndef DBG #define DBG 0 #endif /* * MDSETUP - set up for DIDO - don't assume anything about modem state * or defaults. * * NOTE: 82 characters is the maximum for a Telebit command line. * * &F - Reload factory defaults * E0 - Don't echo commands * F1 - Turn off echoplex (no local echo) * M0 - Speaker disabled at all times * Note: M0 does not apply to the PC card version. It has no speaker! * Q4 - Don't be quiet, but don't tell us about RINGs * V1 - Verbose on; return english result codes * X3 - Use extended codes including MNP and PEP codes * S0=1 - Answer on first ring * S2=043 - Set escape sequence to be +++ * S6=12 - Set # seconds to wait for dialtone (default is 2) used TPC only * S7=40 - Set connect timeout to default value * S10=4 - Set for T2500 only, loss of carrier to disconnect delay * S25=2 - Set for T2500 only, DTR down time for action * S45=0 - Disable remote modem access * S48=1 - All 8 bits are significant * S50=0 - Use automatic connect speed determination * S51=254 - Set serial port baud rate automatically, using 19200 for PEP. * S52=2 - Go on hook when dtr drops and reset to NV-RAM * S53=1 - DCD signal tracks remote carrier, DSR on when modem ready * S54=3 - Pass BREAK signal to remote modem * S55=0 - Respond sanely to command escape sequence * S58=2 - DTE uses CTS/RTS flow control. * S59=052 - Set prompt to "*" (?) * S60=0 - Use 8 data, 1 stop, no parity * S66=0 - Don't lock interface speed, just go with the flow. * S68=255 - DCE uses whatever flow control DTE uses * S92=0 - Issue PEP tones at the beginning of answer sequence * S95=2 - Set MNP Auto-Reliable mode * S110=255 - Use data compression when the remote modem requests it. * Note: S110 doesn't seem to work in Trailblazer Rev-3 ROMS * S111=255 - Accept any protocol * &W - Write all of this into Non-Volatile RAM * Note: &W does not apply to the PC card version. It has no NVRAM! * * Note that we have to break the setup string into two command lines. */ #ifdef T2500 #define MDSETUP1 "AT&FE0F1M0Q4V1X3S2=043S10=4S25=2S45=0S48=1S50=0S51=254S52=2S53=1S54=3\r" #define MDSETUP2 "ATS55=0S58=2S60=0S66=0S68=255S92=0S95=2S110=255S111=255&W\r" #endif #ifdef TPC #define MDSETUP1 "AT&FE0F1Q4V1X3S6=12S2=043S45=0S48=1S50=0S51=254S52=2S53=1S54=3\r" #define MDSETUP2 "ATS55=0S58=2S60=0S66=0S68=255S92=0s110=255S111=255\r" #endif #ifdef V3 /* this is currently specific to crash wrt s51, s66 and s95 */ #define MDSETUP1 "AT&FE0F1M0Q4V1X3S2=043S45=0S48=1S50=0S51=254S52=2S53=1S54=3\r" #define MDSETUP2 "ATS55=0S58=2S60=0S66=0S68=255S92=0S95=2S111=255&W\r" #endif #if !defined(T2500) && !defined(TPC) && !defined(V3) #define MDSETUP1 "AT&FE0F1M0Q4V1X3S2=043S45=0S48=1S50=0S51=254S52=2\r" #define MDSETUP2 "ATS53=1S54=3S55=0S58=2S60=0S66=0S68=255S92=1S110=255S111=255&W\r" #endif /* * MDXONXOFF - Use XON/XOFF flow control * * S58=3 DTE Uses XON/XOFF flow control (DCE will follow DTE) */ #define MDXONXOFF "ATS58=3\r" /* * MDDIALKERM - Dial an answering TBIT modem using kermit protocol. * * S7=60 - Give it a full minute to get a PEP recognition code * S50=255 - Force PEP mode operation * S111=10 - Use kermit (no parity) protocol. */ #define MDDIALKERM "ATS7=60S50=255S111=10\r" /* * MDDIALUUCP - Dial an answering TBIT modem using uucp G protocol. * * S7=60 - Give it a full minute to get a PEP recognition code * S50=255 - Force PEP mode operation * S111=30 - Use uucp G protocol. */ #define MDDIALUUCP "ATS7=60S50=255S111=30\r" /* * MDDIALXMDM - Dial an answering TBIT modem using [xy]modem protocol. * * S7=60 - Give it a full minute to get a PEP recognition code * S50=255 - Force PEP mode operation * S111=20 - Use [xy]modem protocol. */ #define MDDIALXMDM "ATS7=60S50=255S111=20\r" /* * MDCOMPRESS - Set compression mode on * * S110=1 - Data compression is enabled provided the connect is PEP * - and the remote end is allows compression. */ #define MDCOMPRESS "ATS110=1\r" /* * MDFORCEPEP - Force a PEP mode connection * * S7=60 - Give it a full minute to get a PEP recognition code * S50=255 - Force PEP mode operation */ #define MDFORCEPEP "ATS7=60S50=255\r" /* * MDFORCEV32 - Force a V32 mode connection * * S50=6 - Force V.32 operation */ #define MDFORCEV32 "ATS50=6\r" /* T2500 */ /* * MDMNPMODE - Set up MNP mode for slow connections * * S95=2 - Enable Auto-reliable mode */ #define MDMNPMODE "ATS95=2\r" /* * MDECHOSUP - Enable Echo Supressor Compensation * * S121=1 - Enable Echo Suppressor Compensation */ #define MDECHOSUP "ATS121=1\r" /* * MDUNLOCK - Unlock interface speed. */ #define MDUNLOCK "ATS66=0\r" /* * MDVALID - Allow only these characters to reach the modem. */ #define MDVALID "0123456789CcEeFfKkMmNnPpRrTtUuVvWwXx*#,!/()-" /* T2500 (added "Vv" to valid list) */ /* * MDESCAPE - Takes modem out of online state to accept commands. */ #define MDESCAPE "+++" /* * MDHANGUP - Force modem to drop carrier. */ #define MDHANGUP "ATH\r" /* * MDRESET - Reset modem to default power-up state. */ #define MDRESET "ATZ\r" /* * MDDIALOUT - Minor changes to set when dialing out. * * S66=1 - Lock the interface speed. * S95=0 - Disable MNP mode unless requested otherwise * S110=0 - Disable data compression unless requested otherwise */ #ifdef T2500 #define MDDIALOUT "ATS66=1S95=0S110=255\r" #endif #ifdef V3 #define MDDIALOUT "ATS66=1S95=0\r" #endif #if !defined(T2500) && !defined(V3) #define MDDIALOUT "ATS66=1S110=255\r" #endif /* * MDATTN - Get modems attention */ #define MDATTN "AT\r" /* * MDDSBLESC - Disable escape sequence */ #define MDDSBLESC "ATS2=128\r" /* * These defines are used to determine how long the dialer timeout * should be. MDPULSDLY can be changed, but MDPAUSDLY requires * reprogramming modem register S8 to be effective. */ #define MDPULSCHR 'P' #define MDPULSDLY 15 #define MDPAUSCHR ',' #define MDPAUSDLY 2 #define DIAL_RETRY 4 /* * Possible messages produced by modem. */ #define OK 0 /* Command succesful */ #define NOCARRIER 1 /* Connect timeout has occurred */ #define ERROR 2 /* Command error encountered */ #define NODIALTONE 3 /* No dial tone was detected */ #define BUSY 4 /* Remote telephone is busy */ #define NOANSWER 5 /* Remote site did not answer */ #define RRING 6 /* Remote site is ringing */ #define CONNECT300REL 7 /* Connection established @ 300 using MNP */ #define CONNECT1200REL 8 /* Connection established @ 1200 using MNP */ #define CONNECT2400REL 9 /* Connection established @ 2400 using MNP */ #define CONNECT300 10 /* Connection established @ 300 */ #define CONNECT1200 11 /* Connection established @ 1200 */ #define CONNECT2400 12 /* Connection established @ 2400 */ #define CONNECTFASTKERM 13 /* Connection established @ 19200/Kermit */ #define CONNECTFASTXMDM 14 /* Connection established @ 19200/Xmodem */ #define CONNECTFASTUUCP 15 /* Connection established @ 19200/UUCP */ #define CONNECTFAST 16 /* Connection established using PEP */ /* T2500 (17-20) */ #define CONNECT4800 17 /* Connection established @ 4800 */ #define CONNECT4800REL 18 /* Connection established @ 4800 using MNP */ #define CONNECT9600 19 /* Connection established @ 9600 */ #define CONNECT9600REL 20 /* Connection established @ 9600 using MNP */ #ifdef SLIP #define LOGIN 21 /* login prompt */ #define PASS 22 /* password prompt */ #endif char *mdmsgs[] = { /* 0 */ "OK", /* 1 */ "NO CARRIER", /* 2 */ "ERROR", /* Note: The original SCO dialer defined "NO DIALTONE". In my testing * I have learned that the Trailblazer Plus PC, the Trailblazer * and the T2500 respond with "NO DIAL TONE". This may need to * be changed for your modem. -- Scott */ /* 3 */ "NO DIAL TONE", /* 4 */ "BUSY", /* 5 */ "NO ANSWER", /* 6 */ "RRING", /* 7 */ "CONNECT 300/REL", /* 8 */ "CONNECT 1200/REL", /* 9 */ "CONNECT 2400/REL", /* 10 */ "CONNECT 300", /* 11 */ "CONNECT 1200", /* 12 */ "CONNECT 2400", /* 13 */ "CONNECT FAST/KERM", /* 14 */ "CONNECT FAST/XMDM", /* 15 */ "CONNECT FAST/UUCP", /* 16 */ "CONNECT FAST", /* 17 */ "CONNECT 4800", /* T2500 */ /* 18 */ "CONNECT 4800/REL", /* T2500 */ /* 19 */ "CONNECT 9600", /* T2500 */ /* 20 */ "CONNECT 9600/REL", /* T2500 */ #ifdef SLIP /* 21 */ "ogin:", /* 22 */ "ord:", #endif 0 }; char *strchr(); int alrmint(); int abort(); struct termio term; /* for storing tty parameters */ int Debug = DBG; /* set when debug flag is given */ int dialing; /* set while modem is dialing */ int fd = -1; /* file descriptor for acu */ int errflag = 0; /* set on errors */ int hflag = 0; /* set to hangup modem */ int zflag = 0; /* set to setup modem */ int highbaud, lowbaud; /* baud rate limits */ int retcode = RC_FAIL; /* return code */ int compress = 0; /* set if compression requested */ int mnpmode = 0; /* set if MNP mode requested */ int forcepep = 0; /* set if PEP mode requested */ int forcev32 = 0; /* set if V32 mode requested (T2500) */ int echosup = 0; /* echo supressor compensation */ int xonxoff = 0; /* XON/XOFF flow control mode */ int speedlock = 1; /* set when baud rate is locked */ int kermcall = 0; /* set if kermit call */ int uucall = 0; /* set if uucico call */ int xmdmcall = 0; /* set if [xy]modem call */ int timeout; /* how long to wait for alarm */ int dial_retry = DIAL_RETRY; /* dial retry count */ int pid; /* stores child's pid */ int c; /* temporary storage */ char command[MAXLINE]; /* modem command buffer */ char *p; /* temporary storage */ char *acu; /* device to dial through */ char *phone; /* phone number to dial */ extern int optind; /* for getopt () */ extern char *optarg; /* for getopt () */ #ifdef SLIP int slipline = 0; /* set if SLIP connection */ char lockname[64], *meslip, *themslip; FILE *fp1; #endif /* SLIP */ #define toprint(x) ((x)<' '?((x)+'@'):'?') /* vgets - Format one character in "always printable" format (like cat -v) */ char * vgets(c, f) unsigned char c; FILE *f; { static char buffer[10]; char *pnt; pnt = buffer; if (iscntrl(c) || !isprint(c)) { if (!isascii(c)) { /* Top bit is set */ *pnt++ = 'M'; *pnt++ = '-'; c = toascii(c); /* Strip it */ } if (iscntrl(c)) { /* Not printable */ *pnt++ = '^'; c = toprint(c); /* Make it printable */ } } *pnt++ = c; *pnt = '\0'; return(buffer); } /* * translate the pairs of characters present in the first * string whenever the first of the pair appears in the second * string. */ static void translate(ttab, str) register char *ttab, *str; { register char *s; for(;*ttab && *(ttab+1); ttab += 2) for(s=str;*s;s++) if(*ttab == *s) *s = *(ttab+1); } main (argc,argv) int argc; char *argv[]; { /* * Reenable all those signals we want to know about */ signal(SIGILL, SIG_DFL); signal(SIGIOT, SIG_DFL); signal(SIGEMT, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGSEGV, SIG_DFL); signal(SIGSYS, SIG_DFL); signal(SIGTERM, abort); /* * Parse command line options. */ while ((c = getopt(argc, argv, "hzsx:")) != EOF) { switch(c) { case 'h': hflag++; break; case 'z': zflag++; break; case 'x': Debug = atoi(optarg); break; #ifdef SLIP case 's': slipline++; break; #endif /* SLIP */ case '?': errflag++; break; } } if (Debug) { fprintf (stderr, "dialer args "); for (c=0; c 80) cleanup(RC_FAIL | RCE_PHNO | retcode); redial: DEBUG(3, "DIALING %s\n", command); if (mdwrite(command) == -1) cleanup(RC_FAIL | retcode); dialing = 1; DEBUG(6, "wait for connect - timeout %d\n", timeout); switch (mdread(timeout)) { case OK: case ERROR: if (dial_retry--) goto redial; cleanup(RC_FAIL | RCE_NULL | retcode); case CONNECT300: /* c = matchbaud(B300, lowbaud, highbaud); */ /* cleanup(retcode | c); */ case CONNECT1200: /* c = matchbaud(B1200, lowbaud, highbaud); */ /* cleanup(retcode | c); */ case CONNECT2400: /* c = matchbaud(B2400, lowbaud, highbaud); */ /* cleanup(retcode | c); */ case CONNECTFAST: case CONNECTFASTKERM: case CONNECTFASTXMDM: case CONNECTFASTUUCP: case CONNECT300REL: /* not included in original */ case CONNECT1200REL: /* binary file */ case CONNECT2400REL: /* ----------- */ case CONNECT4800: /* T2500 */ case CONNECT4800REL: /* T2500 */ case CONNECT9600: /* T2500 */ case CONNECT9600REL: /* T2500 */ #ifdef SLIP if (slipline) sliplog(); #endif /* SLIP */ cleanup(retcode); case NOANSWER: cleanup(RC_FAIL | RCE_ANSWER | retcode); case NODIALTONE: cleanup(RC_FAIL | RCE_NOTONE | retcode); case NOCARRIER: cleanup(RC_FAIL | RCE_NOCARR | retcode); case BUSY: cleanup(RC_FAIL | RCE_BUSY | retcode); default: cleanup(RC_FAIL | retcode); } } /* * hangup(htime) * * Function: Forces the modem to drop carrier and hang up the phone. * Reads are allowed htime seconds before timeout. * * Returns: 0 if disconnect completed. * -1 on failure, phone may still be connected. * */ nil (sig) int sig; { signal (sig, nil); } hangup (htime) int htime; { int retry = 4, rcode = -1; int old_retcode = retcode; int (*s)(); DEBUG(6, "hangup - timeout %d\n", htime); #ifdef SLOWRITE sleep(1); #endif s = signal(SIGALRM, nil); /* alarms are non-fatal here */ retcode = (RC_FAIL | RCE_HANGUP); /* In case we are interrupted */ while (retry-- && rcode == -1) { /* * Send an escape to the modem to take it off-line. */ if (mdwrite (MDESCAPE) == -1) { retcode = old_retcode; return (rcode); } /* Give it a minute to think about it */ sleep (1); /* * MDESCAPE will return OK only if online, * so ignore error return */ mdflush (); /* waste "OK" if we were on line */ /* * First sync the baud rate. * Don't bother sending the hangup stuff * if we couldn't even sync baud rates. */ if (mdsync () != RC_FAIL) { if (mdwrite (MDHANGUP) == -1) { retcode = old_retcode; return (rcode); } switch(mdread (htime)) { case OK: case NOCARRIER: /* T2500 */ rcode = 0; } } if (retry && rcode != 0) { /* * Try closing the line and re-opening it. This * should cause a reset due to the DTR transition. * Give the modem a couple of seconds to reset. */ DEBUG (3, "FAILED, Re-trying hangup%c", '\n'); mdclose (); sleep (2); mdopen (); } } if (rcode == -1) { long now; (void) time (&now); fprintf (stderr, "dialer: HANGUP FAILED at %s", ctime (&now)); } else { DEBUG(3, "Disabling escape%c", '\n'); mdwrite (MDDSBLESC); /* disable escape */ } signal (SIGALRM, s); retcode = old_retcode; return (rcode); } /* * mdread (rtime) * * Function: Reads from the ACU until it finds a valid response (found * in mdmsgs) or times out after rtime seconds. * * Returns: The index in mdmsgs of the modem response found. * -1 on timeout. * */ mdread(rtime) int rtime; { char **mp; register char *bp; char buf[MAXLINE]; bp = buf; alarm(rtime); DEBUG(6, "MODEM returned %s", "<<"); while (read(fd, &c, 1) == 1) { c &= 0177; if ((*bp = c) != '\0') *++bp = '\0'; DEBUG(6, "%s", vgets(c)); if (bp >= buf + MAXLINE) { alarm(0); DEBUG(4,">>-%s\n","FAIL"); return(-1); } if (c == '\r') { if (substr("RRING", buf) == 0) { bp = buf; DEBUG(6,">>-%s\n", "OK"); DEBUG(4,"got %s\n","RRING"); DEBUG(6, "MODEM returned %s", "<<"); continue; } for (mp = mdmsgs; *mp; ++mp) if (substr(*mp, buf) == 0) { alarm(0); DEBUG(6,">>-%s\n", "OK"); DEBUG(4,"got %s\n",mdmsgs[mp - mdmsgs]); return(mp - mdmsgs); } } } alarm(0); DEBUG(6,">>-%s","FAIL"); DEBUG(4, " no response\n", 0); return(-1); } /* mdflush() * * Function: Flushes input clists for modem */ mdflush() { ioctl(fd, TCFLSH, 0) ; } /* * mdwrite(c) * * Function: Outputs the string pointed to by c to the ACU device. * * Returns: 0 on completion. * -1 on write errors. * */ mdwrite(c) register char *c; { int err; /* * Give modem a chance to recover before writing. */ sleep(1); DEBUG(6, "Sent MODEM %s", "<<"); while (*c) { if ((err = write(fd, c, 1)) != 1) { char buf[16]; DEBUG(6, ">>-%s\n", "FAIL"); DEBUG(1, "ACU write error (errno=%d)\n", errno); return(-1); } DEBUG(6, "%s", vgets(*c)); c++; } DEBUG(6, ">>-%s\n", "OK"); return(0); } /* * substr(s, l) * * Function: Checks for the presence of the string pointed to by s * somewhere within the string pointed to by l. * * Returns: 0 if found. * -1 if not found. */ substr(s, l) char *s; register char *l; { int len; len = strlen(s); while ((l = strchr(l, *s)) != NULL) { if (strncmp(s, l, len) == SAME) return(0); l++; } return(-1); } /* * alrmint() * * Function: Catches alarm calls (signal 14) and exits. * * Returns: No return. Exits with status RC_FAIL. */ alrmint() { DEBUG(4, "\nTimeout waiting for %s\n", dialing ? "carrier" : "acu"); cleanup(RC_FAIL | RCE_TIMOUT | retcode); } /* * cleanup(stat) * * Function: Closes device file and exits. * * Returns: No return. Exits with status stat. */ cleanup (stat) int stat; { if (stat & RC_FAIL) /* if we failed, drop DTR (in abort) */ { retcode = stat; abort(0); } else { /* else, return */ exit(stat); } } /* * Exit, making sure the modem hangs up and we * don't leave the tty ungetty'ed. */ abort (sig) int sig; { int error = retcode & ~(RC_FAIL | RC_ENABLED); signal(SIGINT, SIG_IGN); signal(sig, SIG_IGN); if (error != RCE_HANGUP) { if (hangup (timeout) == -1) { retcode |= (RC_FAIL); } else { /* * No need to call dial -h again. */ retcode &= ~RC_ENABLED; } } if (re_getty ("abort") == RC_FAIL) { retcode |= RC_FAIL; } if (fd != -1) { ioctl(fd, TCGETA, &term); term.c_cflag |= HUPCL; /* make sure modem hangs up */ ioctl(fd, TCSETA, &term); mdclose (); } if (sig) retcode |= (RC_FAIL | RCE_SIG); exit (retcode); } /* * checkbaud(n) * * Function: Check for valid baud rates * * Returns: The baud rate in struct termio c_cflag fashion * */ checkbaud(n) int n; { int baudrate; switch(n) { case 300: baudrate = B300; break; case 1200: baudrate = B1200; break; case 2400: baudrate = B2400; break; case 4800: baudrate = B4800; break; case 9600: baudrate = B9600; break; case 19200: baudrate = B19200; break; case 38400: baudrate = B38400; break; default: fprintf(stderr, "dial: Bad speed: %d\n", n); exit(RC_FAIL | RCE_SPEED); } return(baudrate); } /* * matchbaud(connect, high, low) * * Function: determine dialer return code based on connect, high, and low * baud rates * * Returns: 0 if connected baud == high baud * Bxxxxx if low baud <= connected baud <= high baud * RCE_SPEED if connected baud rate is out of range */ matchbaud(cbaud, low, high) int cbaud, low, high; { /* uucp/cu assume highest baud */ if ((cbaud == high) || (high > B9600)) return(0); /* T2500 */ if (low <= cbaud && cbaud < high) return(cbaud); return(RC_FAIL | RCE_SPEED); } /* * In order to figure out our baud rate, the modem needs * an "a" character. We send it twice for good measure, * and pause 1/4 second after each one. */ mdsync() { int (*old_alrm)(); char buf[MAXLINE]; int count = 0, n; /* Note: While the earlier Telebit modems needed this syncing * routine, the T2500 with Rev-1 ROMS would miss the * next command sent after the mdsync(). This was because * of a lower case 'a' being sent prior to an upper case * 'AT'. I have been told this is fixed in Rev-2 ROMS, * but since I haven't seen my T2500 miss an 'AT' yet, * I bypass the syncing routine. -- Scott */ #ifdef T2500 return(0); /* T2500 */ #endif /* T2500 */ old_alrm = signal(SIGALRM, nil); /* alarms are non-fatal here */ DEBUG (7, "Syncing baud rate...", ""); while (++count < 6) { /* * Send 'a''a'... to make the modem sync to our * baud rate. */ sendsync (); /* * Send ATQ4 to make sure the modem has response codes * enabled. If the modem is talking our speed, this will * always result in "OK". First we eat output from * the modem. */ mdflush (); mdwrite ("ATQ4\r"); /* * If we don't get "OK" in 2 seconds, we ain't gonna. */ if (mdread(2) == OK ) { break; } } /* * At debug level 9, we print an 'a' every time we send one. * These dots make things look prettier. */ DEBUG (9, "%s", "..."); signal (SIGALRM, old_alrm); if (count < 10) { DEBUG (7, "%s\n", "done."); return (0); } else { DEBUG (7, "%s\n", "FAIL"); return (RC_FAIL); } } #define NSYNCS 4 /* Number of a's to send each time */ /* * Sendsync: Send a's to make the modem sync to our baud rate. */ sendsync () { int count = 0; while (count++ < NSYNCS) { write (fd, "a", 1); DEBUG (9, "%c", 'a'); nap (250L); /* wait between each one */ } } /* * Open the modem and set the baud rate. Sets the global variable * "fd". */ int mdopen () { /* * Must open with O_NDELAY set or the open may hang. */ DEBUG (8, "mdopen(): opening %s\n", acu); if ((fd = open(acu, O_RDWR | O_NDELAY)) < 0) { fprintf(stderr, "dial: Can't open device: %s\n", acu); exit(RC_FAIL | RCE_OPEN | retcode); } /* * set line for no echo and correct speed. * If hanging up, issue commands at high baud to enable auto answer * at all speeds. */ signal(SIGINT, abort); errflag = ioctl(fd, TCGETA, &term); term.c_cflag &= ~(CBAUD | HUPCL); term.c_cflag |= (CLOCAL /* | CTSFLOW | RTSFLOW */); term.c_cflag |= hflag ? (HUPCL | highbaud) : highbaud; term.c_lflag &= ~ECHO; term.c_cc[VMIN] = '\1'; term.c_cc[VTIME] = '\0'; errflag = ioctl(fd, TCSETA, &term); if (errflag) { char buf[16]; DEBUG(1, "dial: ioctl error on %s", acu); DEBUG(1, " errno=%d\n", errno); cleanup(RC_FAIL | RCE_IOCTL | retcode); } DEBUG(6,"set ioctl on %s, ", acu); DEBUG(6,"baudrate = 0%o\n", term.c_cflag & CBAUD); /* * Reopen line with clocal so we can talk without carrier present */ c = fd; if ((fd = open(acu, O_RDWR)) < 0) { fprintf(stderr, "dial: Can't open device local: %s\n", acu); exit(RC_FAIL | RCE_OPEN | retcode); } close(c); return (fd); } mdclose () { DEBUG (8, "mdclose(): closing %s\n", acu); ioctl(fd, TCGETA, &term); term.c_cflag |= HUPCL; /* make sure modem hangs up */ ioctl(fd, TCSETA, &term); close (fd); } /* * Call ungetty to send a signal to the getty on a line. * * returns: * RC_FAIL - failure * SUCCESS - success */ ungetty (string) char *string; { #ifndef HDUU if ((pid = fork()) == 0) { DEBUG (7, "%s: ungetty", string); DEBUG (7, " %s called\n", acu); execl (UNGETTY, "ungetty", acu, NULL); exit (-1); } while (((c = wait(&errflag)) != pid) && c != -1) ; switch ((errflag >> 8) & 0xff) { case UG_NOTENAB: /* line acquired: not enabled */ retcode = SUCCESS; break; case UG_ENAB: /* line acquired: need ungetty -r when done */ retcode = RC_ENABLED; break; case UG_FAIL: /* could not acquire line */ DEBUG (1, "%s: ungetty failed:", string); DEBUG (1, " %x", UG_FAIL); exit (RC_FAIL | RCE_INUSE); case 255: exit (RC_FAIL); } #else retcode = SUCCESS; /* uugetty does not require ungetty */ #endif } /* * Restore the getty on the acu. * * returns: * RC_FAIL - failure * SUCCESS - success */ re_getty (string) char *string; { #ifndef HDUU /* call ungetty to see if we need to switch to dialin */ if ((pid = fork()) == 0) { DEBUG (7, "%s: ungetty -t", string); DEBUG (7, " %s called\n", acu); execl (UNGETTY, "ungetty", "-t", acu, NULL); exit(-1); } while (((c = wait(&errflag)) != pid) && c != -1) ; if (((errflag>>8) & 0xff) != UG_RESTART) { DEBUG (7, "%s: no ungetty -r needed", string); return (SUCCESS); } DEBUG (7, "%s: ungetty -r needed\n", string); if ((pid = fork()) == 0) { DEBUG (7, "%s: ungetty -r", string); DEBUG (7, " %s called\n", acu); execl (UNGETTY, "ungetty", "-r", acu, NULL); exit (-1); } while (((c = wait(&errflag)) != pid) && c != -1) ; if (((errflag >> 8) & 0xff) == UG_FAIL) { return (RC_FAIL); } else #endif { return (SUCCESS); } } #ifdef SLIP /* * Wait on a child process */ fwait(pid) register int pid; { register int w; int status; int (*onhup) (), (*onint) (); onint = signal(SIGINT, SIG_IGN); onhup = signal(SIGHUP, SIG_IGN); /* should we add a SIG_IGN for SIGALRM? */ while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; (void) signal(SIGINT, onint); (void) signal(SIGHUP, onhup); return(status); } sliplock() { char *s; int otherpid,outerr; s=strrchr(acu, '/'); sprintf(lockname,"/usr/spool/uucp/LCK..%s",++s); if((fp1 = fopen(lockname, "r")) != (FILE *)0) { if(fscanf(fp1,"%10d", &otherpid) == 1) outerr=(kill(otherpid,0) == 0 || errno == EPERM); (void) fclose(fp1); if (outerr) exit(RC_FAIL); else unlink(lockname); } if((fp1 = fopen(lockname, "w")) != NULL) { /* create a lockfile */ (void)chmod(lockname, 0444); (void)fprintf(fp1,"%10d\n", getpid()); fclose(fp1); } } sliplog() { int pid, status, outerr, otherpid,pd; char sliplock[64], temp[64], *s; char sbaud[10], sspid[20], unit[20]; FILE *fp; signal(SIGINT,SIG_IGN); alarm(0); /* off any pending alarm */ sleep(4); sprintf(command,"Scrash\r"); mdwrite(command); sleep(2); sprintf(command,"whatnot\r"); mdwrite(command); printf("Login complete.\n"); sleep(3); s=strrchr(acu, '/'); pd=getpid(); sprintf(command,"/etc/setslip %s %s > /tmp/ss%d",acu,"19200",pd); system(command); sleep(8); /* was 2 */ sprintf(command,"/tmp/ss%d",pd); if((fp=fopen(command,"r")) != (FILE *)0) { fscanf(fp,"%s", unit); (void) fclose(fp); } unlink(command); if (pid = fork()) status = fwait(pid); else { /* child */ execl("/etc/ifconfig","ifconfig",unit,"inet",meslip,themslip,0); exit(1); } if (pid = fork()) status = fwait(pid); else { /* child */ execl("/etc/ifconfig","ifconfig",unit,"inet","up",0); exit(1); } printf("Link activated.\n"); sleep(10); if (pid = fork()) { printf("SLIP startup complete. Use 'sldetach %s' to terminate.\n",unit); sleep(1); } else { /* child */ if((fp1 = fopen(lockname, "w")) != NULL) { /* create a lockfile */ (void)chmod(lockname, 0444); (void)fprintf(fp1,"%10d\n", getpid()); fclose(fp1); } sprintf(sliplock,"/usr/spool/locks/slippid.%s",unit); if((fp1 = fopen(sliplock, "r")) != (FILE *)0) { if(fscanf(fp1,"%10d", &otherpid) == 1) outerr=(kill(otherpid,0) == 0 || errno == EPERM); (void) fclose(fp1); for(;outerr;) { /* still alive... */ sleep(5); outerr=(kill(otherpid,0) == 0 || errno == EPERM); } } if(fd != -1) { mdclose(); sleep(1); } unlink(lockname); exit(1); } } #endif /* SLIP */ --- End of forwarded message from MAILER-DAEMON@trout.nosc.mil (Mail Delivery Subsystem) -- Jean-Pierre Radley NYC Public Unix jpr@jpradley.jpr.com CIS: 72160,1341