bbs@alchemy.UUCP (BBS Administration) (03/29/91)
After trying for several days to get things to work the way I want them, I am putting my faith in the hands of USENET... My system is a '386 machine running SCO Xenix v2.3.2GT. I have a "dumb" serial card installed and have a Telebit T2500 attached using "tty1A". I have set up the "/etc/ttys" file to use the "gettydefs" entry that locks the speed between the computer and the modem at 19200 bps (it's label is "n" in the gettydefs file). I have configured the "Devices" file to use the "dialTBIT" dialer and have appended "u" to the phone number of systems I network with that have a Telebit modem. Here's what I want to be able to do: 1) Connect, via uucico, to other machines running Unix and transfer files. This seems to work rather well with my current setup. I followed the instructions on page 14 of the "Fast Start Guide" and this operation seems to work consistently. 2) Allow users to dial into my BBS at any speed supported by the T2500. This works sporadically. One problem is that, after I connect at PEP speed during a UUCP exchange with my feed site, my T2500 will only connect with modems dialing in at PEP speed. I have configured the "A" profile with "S50=0" and "S92=1" so that automatic speed detection is used, and PEP tones come last, but things still do not get reset properly after my UUCP exchange. I went so far as to use my terminal program (called XCMALT) to talk directly to the modem after a PEP connection and issue an "ATZ" in the hopes that this would reset the modem to the proper state. When I dialed in with another computer, my modem picked up the phone, then paused for a while, sent no tones at all, then hung up. I'm not sure, but I think that if I do an "ATZ" then examine things with an "AT&N" then write things back with an "AT&W" that >then< the modem answers correctly (I think). And when it does answer, it will continue to answer correctly until I dial out again at PEP speed (or maybe it dies when someone else dials in at PEP speed, I'm not too sure at what point it decides to go out to lunch). 3) Allow me to dial out using XCMALT to various systems and when I'm done, reset to the proper mode for users to dial in. Usually, this works, but not always. I think that sometimes the S50 register gets set to 255 (via the "dialTBIT" dialer which is used when I connect to my feed site) and is still set when I try to connect to a 2400 bps modem. If I issue an ATZ then the "S50=0" setting gets loaded into memory and I can connect. [End of description of problems] My questions are: 1) How do the settings in Profile "A" (I have the physical button set to this profile and the S255 register set to 0 so the T2500 observes this setting) get loaded back into memory once uucico stops and the getty on tty1A is respawned so users can dial in at ANY speed? 2) A stupid question? How can one examine the CURRENT settings in memory of the T2500? All I could find was the &N commands that shows you what is in NRAM, but nothing about how to display the current settings in RAM? 3) How do I solve all my problems? I would think there must be many people out there using the exact same hardware I am, and running it on the exact same software. Can someone please tell me how they set up their system? Is there something I'm missing in the "/usr/lib/uucp" directory that is improperly configured or something? Could someone send a copy of the relevant files? Did anyone modify the dialTBIT.c program to make it work better (?) with the T2500 (or I heard of someone who modified it to use a "v" after the phone number to >require< that the connection be made at v32)? If it's any help: here's the profile "A" settings: E0 F1 M0 Q4 P V1 W0 X1 Y0 &P0 &T4 Version GF7.00-T2500SA S00=001 S01=000 S02=043 S03=013 S04=010 S05=008 S06=002 S07=040 S08=002 S09=006 S10=007 S11=070 S12=050 S18=000 S25=005 S26=000 S38=000 S41=000 S45=000 S47=004 S48=000 S49=000 S50=000 S51:005 S52:001 S54:003 S55:003 S56=017 S57=019 S58=003 S59=000 S61:099 S62=003 S63=001 S64:001 S65=000 S66:001 S67:001 S68:003 S69=000 S90=000 S91=000 S92:001 S93=008 S94=001 S95:002 S96=001 S97:001 S98=003 S100=000 S101=000 S102=000 S104=000 S105=001 S106:001 S107=020 S110=255 S111=255 S112=001 S121=000 S130:005 S131:001 S150=000 S151=004 S152=001 S153=001 S154=000 S155=000 S157=000 S158=000 S160=010 S161=020 S162=002 S163=003 S164=007 S169=000 S255=000 Oh, and one more interesting thing I found today... I wrote a gateway program between Unix and a BBS system called "ProLine" (it runs on Apple II computers). The transport mechanism is simply Xmodem. After installing the T2500 the Unix system could >receive< files from the Apple (since the Apple is in control of sending each packet) but when the Unix side sends a file using Xmodem, the "send" light goes on and stays on without waiting for the Apple to ACK the packets. If I simply change modems, this problem goes away, so it must be the T2500 (or could it be related to flow control, XON/XOFF, something like that?) Hoping to hear from all you Telebit experts! -- John John Donahue, Senior Partner | UUCP: ucrmath!alchemy!{bbs, gumby} | The Future Alchemy Software Designs | INET: {bbs, gumby}@alchemy.UUCP | Begins Now -------------------+---------+------------------------------------+----------- Communique On-line | +1-714-278-0862 {12, 24, 96v32, 19.2k} T2500 | Next Wave: Information System | Alchemy Software Designs Support System | Communique
gandrews@netcom.COM (Greg Andrews) (03/30/91)
In article <390@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >After trying for several days to get things to work the way I want them, I >am putting my faith in the hands of USENET... > >My system is a '386 machine running SCO Xenix v2.3.2GT. I have a "dumb" >serial card installed and have a Telebit T2500 attached using "tty1A". >I have set up the "/etc/ttys" file to use the "gettydefs" entry that >locks the speed between the computer and the modem at 19200 bps (it's >label is "n" in the gettydefs file). I have configured the "Devices" >file to use the "dialTBIT" dialer and have appended "u" to the phone >number of systems I network with that have a Telebit modem. > >Here's what I want to be able to do: > >1) Connect, via uucico, to other machines running Unix and transfer files. > >This seems to work rather well with my current setup. I followed the >instructions on page 14 of the "Fast Start Guide" and this operation >seems to work consistently. > The Fast Start Guide simply can't compete with a real, live SCO Xenix setup guide available from Telebit Tech Support. 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). > >2) Allow users to dial into my BBS at any speed supported by the T2500. > >This works sporadically. One problem is that, after I connect at PEP >speed during a UUCP exchange with my feed site, my T2500 will only >connect with modems dialing in at PEP speed. I have configured the >"A" profile with "S50=0" and "S92=1" so that automatic speed detection >is used, and PEP tones come last, but things still do not get reset >properly after my UUCP exchange. I went so far as to use my terminal >program (called XCMALT) to talk directly to the modem after a PEP >connection and issue an "ATZ" in the hopes that this would reset the >modem to the proper state. When I dialed in with another computer, >my modem picked up the phone, then paused for a while, sent no tones >at all, then hung up. > >I'm not sure, but I think that if I do an "ATZ" then examine things >with an "AT&N" then write things back with an "AT&W" that >then< the >modem answers correctly (I think). And when it does answer, it will >continue to answer correctly until I dial out again at PEP speed >(or maybe it dies when someone else dials in at PEP speed, I'm not >too sure at what point it decides to go out to lunch). > Set your S52 register to 2. That will do the equivalent of "ATZ" after every call out and in, resetting your S50 back to 0. > >3) Allow me to dial out using XCMALT to various systems and when I'm >done, reset to the proper mode for users to dial in. > >Usually, this works, but not always. > [theory about cause of problem deleted - use the S52=2 above] > >My questions are: > >1) How do the settings in Profile "A" (I have the physical button set to >this profile and the S255 register set to 0 so the T2500 observes this >setting) get loaded back into memory once uucico stops and the getty on >tty1A is respawned so users can dial in at ANY speed? > If an "ATZ" command is sent to the modem, or DTR drops when S52=2. > >2) A stupid question? How can one examine the CURRENT settings in memory >of the T2500? All I could find was the &N commands that shows you what >is in NRAM, but nothing about how to display the current settings in RAM? > "ATN?" does that. > >3) How do I solve all my problems? > The ones you described above? S52=2. > >[bunch of stuff deleted] > >E0 F1 M0 Q4 P V1 W0 X1 Y0 &P0 &T4 Version GF7.00-T2500SA >S00=001 S01=000 S02=043 S03=013 S04=010 S05=008 S06=002 S07=040 S08=002 S09=006 >S10=007 S11=070 S12=050 S18=000 S25=005 S26=000 S38=000 >S41=000 S45=000 S47=004 S48=000 S49=000 >S50=000 S51:005 S52:001 S54:003 S55:003 S56=017 S57=019 S58=003 S59=000 >S61:099 S62=003 S63=001 S64:001 S65=000 S66:001 S67:001 S68:003 S69=000 >S90=000 S91=000 S92:001 S93=008 S94=001 S95:002 S96=001 S97:001 S98=003 >S100=000 S101=000 S102=000 S104=000 S105=001 S106:001 S107=020 >S110=255 S111=255 S112=001 >S121=000 S130:005 S131:001 >S150=000 S151=004 S152=001 S153=001 S154=000 S155=000 S157=000 S158=000 >S160=010 S161=020 S162=002 S163=003 S164=007 S169=000 S255=000 > The S58=3 setting will hose your XMODEM, YMODEM, and uucp file transfers unless they are spoofed by the modem (available only in PEP and V.32/MNP connections). S58=0 might be a better setting, or S58=2 S68=255 if your system can support RTS/CTS flow control. > >Oh, and one more interesting thing I found today... I wrote a gateway >program between Unix and a BBS system called "ProLine" (it runs on >Apple II computers). The transport mechanism is simply Xmodem. After >installing the T2500 the Unix system could >receive< files from the >Apple (since the Apple is in control of sending each packet) but >when the Unix side sends a file using Xmodem, the "send" light goes >on and stays on without waiting for the Apple to ACK the packets. If >I simply change modems, this problem goes away, so it must be the >T2500 (or could it be related to flow control, XON/XOFF, something >like that?) > Sounds like you have the spoofing turned on for XMODEM/YMODEM. You don't seem to have S111=20, so you must be setting it in a dialer script or including an 'x' in the phone number for dialTBIT. Or the other system is calling you and they have S111=20 in their modem when they call. Why do you call this a 'problem'? -- .------------------------------------------------------------------------. | Greg Andrews | UUCP: {apple,amdahl,claris}!netcom!gandrews | | | Internet: gandrews@netcom.COM | `------------------------------------------------------------------------'
jpr@jpradley.jpr.com (Jean-Pierre Radley) (03/31/91)
In article <390@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >This works sporadically. One problem is that, after I connect at PEP >speed during a UUCP exchange with my feed site, my T2500 will only >connect with modems dialing in at PEP speed. I have configured the >"A" profile with "S50=0" and "S92=1" so that automatic speed detection >is used, and PEP tones come last, but things still do not get reset >properly after my UUCP exchange. I went so far as to use my terminal >program (called XCMALT) to talk directly to the modem after a PEP >connection and issue an "ATZ" in the hopes that this would reset the >modem to the proper state. When I dialed in with another computer, >my modem picked up the phone, then paused for a while, sent no tones >at all, then hung up. That shouldn't be necessary. On completion, uucico would be calling dialTBIT again to hang up the modem and reset it. >3) Allow me to dial out using XCMALT to various systems and when I'm >done, reset to the proper mode for users to dial in. XCMALT, like dialTBIT, drops DTR for a moment or so, which is designed to have the modem reset. Works if S52=2. >2) A stupid question? How can one examine the CURRENT settings in memory >of the T2500? All I could find was the &N commands that shows you what >is in NRAM, but nothing about how to display the current settings in RAM? It's ATN?, which is in the manual... >3) How do I solve all my problems? There's a dialTBALL.c that was propagated, which encompasses the TB2500; the Xenix 2.3 dialTBIT was written before that modem was sold. Do you need that? Email me back. -- Jean-Pierre Radley NYC Public Unix jpr@jpradley.jpr.com CIS: 72160,1341
bbs@alchemy.UUCP (BBS Administration) (03/31/91)
In article <1991Mar29.233228.17548@netcom.COM> gandrews@netcom.COM (Greg Andrews) writes: >In article <390@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >>This seems to work rather well with my current setup. I followed the >>instructions on page 14 of the "Fast Start Guide" and this operation >>seems to work consistently. >The Fast Start Guide simply can't compete with a real, live SCO Xenix >setup guide available from Telebit Tech Support. So, just dial 1-800-TELEBIT and ask for one? I guess maybe I should send in my registration card first (do they check?) >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. >>2) Allow users to dial into my BBS at any speed supported by the T2500. >Set your S52 register to 2. That will do the equivalent of "ATZ" >after every call out and in, resetting your S50 back to 0. The problem >was< the dialTBIT program. I modified it to do an ATZ just before it closed the modem port and this fixed things up. I also changed S52 to 2 though and it didn't adversly affect anything, so I'm going to leave it set to 2 -- thanks! >>2) A stupid question? How can one examine the CURRENT settings in memory >>of the T2500? >"ATN?" does that. Once again, thanks. I guess I should have looked harder, but I also thought it might be discussed someplace during installation. [My register settings] >The S58=3 setting will hose your XMODEM, YMODEM, and uucp file transfers >unless they are spoofed by the modem (available only in PEP and V.32/MNP >connections). S58=0 might be a better setting, or S58=2 S68=255 if your >system can support RTS/CTS flow control. Here's the deal: You are correct. That was the problem. Once I changed S58 to 0, the other site connecting at 2400 bps (thus >not< spoofing the UUCP "g" protocol) was able to transfer files. Thanks! Still, there are problems. Once this was changed, I called another system at V.32 speed and issued the "uulog" command which sent an enormous amount of data to my system. At the same time, I was reading the man page on my machine for "uulog" (which happens to be on the same page as UUCP and is quite lengthy, plus nroff is a CPU pig, etc.) and the data being transmitted to my machine was stopped and could not be started again until I manually pressed ^Q. Obviously, if this were to happen during a UUCICO exchange, I doubt the ^Q would be sent. This occurred when I used the S58=2 and S68=255 method you also mentioned. It would appear that >no< flow control is bad, and that makes sense. But I'm wondering how to overcome the fact that my system does not properly interpret the RST/CTS signals. Is the solution installing the FAS serial driver (I have version 2.08 dated February 3, 1991 -- is this the latest?) or installing the NS16550AFN UART chip on my "dumb" serial card or both? Or is it something else altogether? >.------------------------------------------------------------------------. >| Greg Andrews | UUCP: {apple,amdahl,claris}!netcom!gandrews | >| | Internet: gandrews@netcom.COM | >`------------------------------------------------------------------------' Once again, THANK YOU for answering this article! I was at the end of my rope and am really happy to have access to USENET. Now, my rope has been lengthened, but I'm at your mercy once again... Hope to get more great answers soon, -- John John Donahue, Senior Partner | UUCP: ucrmath!alchemy!{bbs, gumby} | The Future Alchemy Software Designs | INET: {bbs, gumby}@alchemy.UUCP | Begins Now -------------------+---------+------------------------------------+----------- Communique On-line | +1-714-278-0862 {12, 24, 96v32, 19.2k} T2500 | Next Wave: Information System | Alchemy Software Designs Support System | Communique
jpr@jpradley.jpr.com (Jean-Pierre Radley) (04/02/91)
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 <stdio.h> #include <signal.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include <termio.h> #include <errno.h> #include <string.h> #include <ctype.h> /* * 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<argc; c++) { fprintf (stderr, ":%s", argv[c]); } fprintf(stderr, "\n"); } if (hflag || zflag) { if (argc - optind != 2) errflag++ ; } #ifdef SLIP else if (slipline) { if (argc - optind != 5) errflag++; } #endif else { if (argc - optind != 3) errflag++ ; } if (errflag) { if (hflag) { fprintf (stderr, "Usage:\t%s -h devicename speed\n", argv[0]); } else if (zflag) { fprintf (stderr, "Usage:\t%s -z devicename speed\n", argv[0]); } else #ifdef SLIP if (slipline) { fprintf(stderr, "Usage:\t%s -s devicename number speed ipme ipthem\n", argv[0]); } else #endif { fprintf (stderr, "Usage:\t%s devicename number speed\n", argv[0]); } exit(RC_FAIL | RCE_ARGS); } acu = argv[optind++]; if (!(hflag || zflag)) { phone = strdup(argv[optind++]); translate("=,-,", phone); if (strlen(phone) != strspn(phone, MDVALID)) { fprintf(stderr, "dial: Bad phone number %s\n", phone); exit(RC_FAIL | RCE_PHNO); } if (strpbrk(phone, "CcEeFfKkMmNnPpTtUuVvXx")) /* T2500 added "Vv" */ { char *phoneno, *ptr; if (strpbrk(phone, "Cc")) { compress++; DEBUG(4, "COMPRESS MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Ee")) { echosup++; DEBUG(4, "ECHO SUPRESSOR COMPENSATION REQUESTED%s", "\n"); } if (strpbrk(phone, "Ff")) { xonxoff++; DEBUG(4, "XON/XOFF MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Mm")) { mnpmode++; DEBUG(4, "MNP MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Pp")) { forcepep++; DEBUG(4, "PEP MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Vv")) { forcev32++; DEBUG(4, "V32 MODE REQUESTED%s", "\n"); /* T2500 */ } if (strpbrk(phone, "Uu")) { if (strpbrk(phone, "KkXx")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "UUCP phone number, stripping %s\n", phone); uucall++; } else if (strpbrk(phone, "Kk")) { if (strpbrk(phone, "UuXx")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "KERMIT phone number, stripping %s\n", phone); kermcall++; } else if (strpbrk(phone, "Xx")) { if (strpbrk(phone, "KkUu")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "[XY]MODEM phone number, stripping %s\n", phone); xmdmcall++; } phoneno = strdup(phone); *phone = '\0'; while ((ptr = strpbrk (phoneno, "CcEeFfKkMmNnPpTtUuVvXxMm")) != NULL) /* T2500 added Vv */ { *ptr = '\0'; strcat(phone, phoneno); phoneno = ++ptr; } strcat(phone, phoneno); DEBUG(5,"PROTOCOL phone number, got %s\n", phone); } } lowbaud = highbaud = checkbaud (atoi (argv[optind])); DEBUG (6, "checkbaud claims low/high baud is 0%o\n", lowbaud); /* test for a range of baudrates */ if ((p = strchr (argv[optind], '-')) != NULL) { *p++ = '\0'; highbaud = checkbaud (atoi(p)); DEBUG (6, "checkbaud claims high baud is 0%o\n", highbaud); } if (!hflag) { ungetty ("dialer"); } #ifdef SLIP if (slipline) { meslip = strdup(argv[++optind]); themslip = strdup(argv[++optind]); DEBUG(4,"SLIP meslip: %s\n", meslip); DEBUG(4,"SLIP themslip: %s\n", themslip); sliplock(); } #endif /* SLIP */ /* * Open the modem file. */ mdopen (); /* * Timeout after 10 seconds if no response */ timeout = 10; signal(SIGALRM, alrmint); /* * Hangup and exit if requested */ if (hflag) { DEBUG(1, "Hangup sequence begun%c", '\n'); if (hangup (timeout) == -1) { cleanup (RC_FAIL | RCE_HANGUP); } cleanup (re_getty ("hangup")); } /* * Since this is the first connect, the modem needs to * figure out our baud rate. */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } /* * Initialize the modem */ if (zflag) { DEBUG(6, "Initializing modem at %s\n", acu); if (mdwrite(MDSETUP1) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } /* * Since MDSETUP1 sets the "autobaud" mode, it forgot our * baud rate... */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } if (mdwrite (MDSETUP2) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } cleanup (re_getty ("modem init")); } /* * Reset and put modem into command mode */ reset: DEBUG(3, "Resetting modem%c", '\n'); if (mdwrite(MDRESET) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { if (hangup(timeout) == -1) { cleanup(RC_FAIL | retcode | RCE_HANGUP); } goto reset; } /* * Must wait at least 0.5 seconds after reset * for Telebit to recover and receive commands. * Then, since MDRESET made it forget our baud rate, * we need to mdsync() again. */ nap(500L); if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } #ifdef TPC /* Initialize the modem since ATZ loses setup... (great modem) */ DEBUG(6, "Initializing modem (PC) at %s\n", acu); if (mdwrite(MDSETUP1) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } /* * Since MDSETUP1 sets the "autobaud" mode, it forgot our * baud rate... */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } if (mdwrite (MDSETUP2) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } cleanup (re_getty ("modem init")); #endif /* TPC */ /* * Set up modem for generic dial out settings. */ DEBUG(3, "Setting DIAL OUT mode%c", '\n'); if (mdwrite(MDDIALOUT) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } #ifdef LATER /* * If we were given a specific baudrate to use, and that * baudrate less than or equal to 9600, unlock the modem speed. */ #ifdef T2500 if ((lowbaud == highbaud) && (highbaud <= B9600)) #else if ((lowbaud == highbaud) && (highbaud <= B2400)) #endif { char speedstr[9], speed[5]; DEBUG(3, "Unlocking modem speed%c", '\n'); if (mdwrite(MDUNLOCK) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } strcpy(speedstr, "ATS50=0\r"); switch (lowbaud) { case B300: strcpy(speedstr, "ATS50=1\r"); strcpy(speed,"300"); break; case B1200: strcpy(speedstr, "ATS50=2\r"); strcpy(speed,"1200"); break; case B2400: strcpy(speedstr, "ATS50=3\r"); strcpy(speed,"2400"); break; #ifdef T2500 case B9600: strcpy(speedstr, "ATS50=6\r"); strcpy(speed,"9600"); break; #endif } DEBUG(3, "Setting modem connect speed to %s baud\n", speed); if (mdwrite(speedstr) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } speedlock = 0; } #endif /* LATER */ /* * If kermcall is non-zero, we need to set up the modem for kermit * and tell it not to connect to anything else. */ if (kermcall) { DEBUG(3, "Setting KERMIT mode%c", '\n'); if (mdwrite(MDDIALKERM) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If uucall is non-zero, we need to set the modem up for uucp * G protocol, and tell it not to connect to anything else. */ else if (uucall) { DEBUG(3, "Setting UUCP mode%c", '\n'); if (mdwrite(MDDIALUUCP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If xmdmcall is non-zero, we need to set up the modem for [xy]modem * and tell it not to connect to anything else. */ else if (xmdmcall) { DEBUG(3, "Setting XMODEM mode%c", '\n'); if (mdwrite(MDDIALXMDM) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If compress is non-zero, we need to set up the modem for * in-line data compression. */ if (compress) { DEBUG(3, "Setting COMPRESS mode%c", '\n'); if (mdwrite(MDCOMPRESS) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If mnpmode is non-zero, we enable the modem * to use MNP mode. */ if (mnpmode) { DEBUG(3, "Setting MNP mode%c", '\n'); if (mdwrite(MDMNPMODE) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If forcepep is non-zero, we need to force the modem * to use PEP mode. */ if (forcepep) { DEBUG(3, "Setting PEP mode%c", '\n'); if (mdwrite(MDFORCEPEP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If forcev32 is non-zero, we need to force the modem (T2500) * to use V32 mode. */ if (forcev32) { DEBUG(3, "Setting V32 mode%c", '\n'); if (mdwrite(MDFORCEV32) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If echosup is non-zero, we enable the modem's * echo supressor compensation logic. */ if (echosup) { DEBUG(3, "Setting ECHO SUPRESSOR COMPENSATION mode%c", '\n'); if (mdwrite(MDECHOSUP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If xonxoff is non-zero, we enable the modem's * echo supressor compensation logic. */ if (xonxoff) { DEBUG(3, "Setting XON/XOFF mode%c", '\n'); if (mdwrite(MDXONXOFF) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * Build up the phone number */ #ifdef WAITFORDT sprintf(command, "ATDTW%s\r", phone); #else sprintf(command, "ATDT%s\r", phone); #endif /* * Set up a timeout for the connect. * Add in MDPAUSDLY seconds more for each pause character * Pulse dialing takes MDPULSDLY seconds longer too */ timeout = 6 * strlen(phone) + 15; if (uucall) timeout *= 3; for (p = phone; (p = strchr(p, MDPAUSCHR)) != NULL; p++) timeout += MDPAUSDLY; if (strchr(phone, MDPULSCHR) != NULL) timeout += MDPULSDLY; if (timeout < 30) timeout = 30; /* command string can only be 80 characters including "AT" */ if (strlen(command) > 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'<pause>'a'<pause>... 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
Jean-pierre_Radley@f170.n771.z3.fidonet.org (Jean-pierre Radley) (04/03/91)
From: jpr@jpradley.jpr.com (Jean-Pierre Radley) Lines: 1863 Organization: NYC Public Unix 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 <stdio.h> #include <signal.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include <termio.h> #include <errno.h> #include <string.h> #include <ctype.h> /* * 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<argc; c++) { fprintf (stderr, ":%s", argv[c]); } fprintf(stderr, "\n"); } if (hflag || zflag) { if (argc - optind != 2) errflag++ ; } #ifdef SLIP else if (slipline) { if (argc - optind != 5) errflag++; } #endif else { if (argc - optind != 3) errflag++ ; } if (errflag) { if (hflag) { fprintf (stderr, "Usage:\t%s -h devicename speed\n", argv[0]); } else if (zflag) { fprintf (stderr, "Usage:\t%s -z devicename speed\n", argv[0]); } else #ifdef SLIP if (slipline) { fprintf(stderr, "Usage:\t%s -s devicename number speed ipme ipthem\n", argv[0]); } else #endif { fprintf (stderr, "Usage:\t%s devicename number speed\n", argv[0]); } exit(RC_FAIL | RCE_ARGS); } acu = argv[optind++]; if (!(hflag || zflag)) { phone = strdup(argv[optind++]); translate("=,-,", phone); if (strlen(phone) != strspn(phone, MDVALID)) { fprintf(stderr, "dial: Bad phone number %s\n", phone); exit(RC_FAIL | RCE_PHNO); } if (strpbrk(phone, "CcEeFfKkMmNnPpTtUuVvXx")) /* T2500 added "Vv" */ { char *phoneno, *ptr; if (strpbrk(phone, "Cc")) { compress++; DEBUG(4, "COMPRESS MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Ee")) { echosup++; DEBUG(4, "ECHO SUPRESSOR COMPENSATION REQUESTED%s", "\n"); } if (strpbrk(phone, "Ff")) { xonxoff++; DEBUG(4, "XON/XOFF MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Mm")) { mnpmode++; DEBUG(4, "MNP MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Pp")) { forcepep++; DEBUG(4, "PEP MODE REQUESTED%s", "\n"); } if (strpbrk(phone, "Vv")) { forcev32++; DEBUG(4, "V32 MODE REQUESTED%s", "\n"); /* T2500 */ } if (strpbrk(phone, "Uu")) { if (strpbrk(phone, "KkXx")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "UUCP phone number, stripping %s\n", phone); uucall++; } else if (strpbrk(phone, "Kk")) { if (strpbrk(phone, "UuXx")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "KERMIT phone number, stripping %s\n", phone); kermcall++; } else if (strpbrk(phone, "Xx")) { if (strpbrk(phone, "KkUu")) { fprintf (stderr, "dial: cannot specify two protocols\n"); exit(RC_FAIL | RCE_PHNO); } DEBUG(4, "[XY]MODEM phone number, stripping %s\n", phone); xmdmcall++; } phoneno = strdup(phone); *phone = '\0'; while ((ptr = strpbrk (phoneno, "CcEeFfKkMmNnPpTtUuVvXxMm")) != NULL) /* T2500 added Vv */ { *ptr = '\0'; strcat(phone, phoneno); phoneno = ++ptr; } strcat(phone, phoneno); DEBUG(5,"PROTOCOL phone number, got %s\n", phone); } } lowbaud = highbaud = checkbaud (atoi (argv[optind])); DEBUG (6, "checkbaud claims low/high baud is 0%o\n", lowbaud); /* test for a range of baudrates */ if ((p = strchr (argv[optind], '-')) != NULL) { *p++ = '\0'; highbaud = checkbaud (atoi(p)); DEBUG (6, "checkbaud claims high baud is 0%o\n", highbaud); } if (!hflag) { ungetty ("dialer"); } #ifdef SLIP if (slipline) { meslip = strdup(argv[++optind]); themslip = strdup(argv[++optind]); DEBUG(4,"SLIP meslip: %s\n", meslip); DEBUG(4,"SLIP themslip: %s\n", themslip); sliplock(); } #endif /* SLIP */ /* * Open the modem file. */ mdopen (); /* * Timeout after 10 seconds if no response */ timeout = 10; signal(SIGALRM, alrmint); /* * Hangup and exit if requested */ if (hflag) { DEBUG(1, "Hangup sequence begun%c", '\n'); if (hangup (timeout) == -1) { cleanup (RC_FAIL | RCE_HANGUP); } cleanup (re_getty ("hangup")); } /* * Since this is the first connect, the modem needs to * figure out our baud rate. */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } /* * Initialize the modem */ if (zflag) { DEBUG(6, "Initializing modem at %s\n", acu); if (mdwrite(MDSETUP1) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } /* * Since MDSETUP1 sets the "autobaud" mode, it forgot our * baud rate... */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } if (mdwrite (MDSETUP2) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } cleanup (re_getty ("modem init")); } /* * Reset and put modem into command mode */ reset: DEBUG(3, "Resetting modem%c", '\n'); if (mdwrite(MDRESET) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { if (hangup(timeout) == -1) { cleanup(RC_FAIL | retcode | RCE_HANGUP); } goto reset; } /* * Must wait at least 0.5 seconds after reset * for Telebit to recover and receive commands. * Then, since MDRESET made it forget our baud rate, * we need to mdsync() again. */ nap(500L); if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } #ifdef TPC /* Initialize the modem since ATZ loses setup... (great modem) */ DEBUG(6, "Initializing modem (PC) at %s\n", acu); if (mdwrite(MDSETUP1) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } /* * Since MDSETUP1 sets the "autobaud" mode, it forgot our * baud rate... */ if (mdsync () == RC_FAIL) { cleanup (RC_FAIL | retcode); } if (mdwrite (MDSETUP2) == -1) { cleanup (RC_FAIL | retcode); } if (mdread (timeout) != OK) { cleanup (RC_FAIL | retcode); } cleanup (re_getty ("modem init")); #endif /* TPC */ /* * Set up modem for generic dial out settings. */ DEBUG(3, "Setting DIAL OUT mode%c", '\n'); if (mdwrite(MDDIALOUT) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } #ifdef LATER /* * If we were given a specific baudrate to use, and that * baudrate less than or equal to 9600, unlock the modem speed. */ #ifdef T2500 if ((lowbaud == highbaud) && (highbaud <= B9600)) #else if ((lowbaud == highbaud) && (highbaud <= B2400)) #endif { char speedstr[9], speed[5]; DEBUG(3, "Unlocking modem speed%c", '\n'); if (mdwrite(MDUNLOCK) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } strcpy(speedstr, "ATS50=0\r"); switch (lowbaud) { case B300: strcpy(speedstr, "ATS50=1\r"); strcpy(speed,"300"); break; case B1200: strcpy(speedstr, "ATS50=2\r"); strcpy(speed,"1200"); break; case B2400: strcpy(speedstr, "ATS50=3\r"); strcpy(speed,"2400"); break; #ifdef T2500 case B9600: strcpy(speedstr, "ATS50=6\r"); strcpy(speed,"9600"); break; #endif } DEBUG(3, "Setting modem connect speed to %s baud\n", speed); if (mdwrite(speedstr) == -1) { cleanup(RC_FAIL | retcode); } if (mdread(timeout) != OK) { cleanup(RC_FAIL | retcode); } speedlock = 0; } #endif /* LATER */ /* * If kermcall is non-zero, we need to set up the modem for kermit * and tell it not to connect to anything else. */ if (kermcall) { DEBUG(3, "Setting KERMIT mode%c", '\n'); if (mdwrite(MDDIALKERM) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If uucall is non-zero, we need to set the modem up for uucp * G protocol, and tell it not to connect to anything else. */ else if (uucall) { DEBUG(3, "Setting UUCP mode%c", '\n'); if (mdwrite(MDDIALUUCP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If xmdmcall is non-zero, we need to set up the modem for [xy]modem * and tell it not to connect to anything else. */ else if (xmdmcall) { DEBUG(3, "Setting XMODEM mode%c", '\n'); if (mdwrite(MDDIALXMDM) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If compress is non-zero, we need to set up the modem for * in-line data compression. */ if (compress) { DEBUG(3, "Setting COMPRESS mode%c", '\n'); if (mdwrite(MDCOMPRESS) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If mnpmode is non-zero, we enable the modem * to use MNP mode. */ if (mnpmode) { DEBUG(3, "Setting MNP mode%c", '\n'); if (mdwrite(MDMNPMODE) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If forcepep is non-zero, we need to force the modem * to use PEP mode. */ if (forcepep) { DEBUG(3, "Setting PEP mode%c", '\n'); if (mdwrite(MDFORCEPEP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If forcev32 is non-zero, we need to force the modem (T2500) * to use V32 mode. */ if (forcev32) { DEBUG(3, "Setting V32 mode%c", '\n'); if (mdwrite(MDFORCEV32) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If echosup is non-zero, we enable the modem's * echo supressor compensation logic. */ if (echosup) { DEBUG(3, "Setting ECHO SUPRESSOR COMPENSATION mode%c", '\n'); if (mdwrite(MDECHOSUP) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * If xonxoff is non-zero, we enable the modem's * echo supressor compensation logic. */ if (xonxoff) { DEBUG(3, "Setting XON/XOFF mode%c", '\n'); if (mdwrite(MDXONXOFF) == -1) cleanup(RC_FAIL | retcode); if (mdread(timeout) != OK) cleanup(RC_FAIL | retcode); } /* * Build up the phone number */ #ifdef WAITFORDT sprintf(command, "ATDTW%s\r", phone); #else sprintf(command, "ATDT%s\r", phone); #endif /* * Set up a timeout for the connect. * Add in MDPAUSDLY seconds more for each pause character * Pulse dialing takes MDPULSDLY seconds longer too */ timeout = 6 * strlen(phone) + 15; if (uucall) timeout *= 3; for (p = phone; (p = strchr(p, MDPAUSCHR)) != NULL; p++) timeout += MDPAUSDLY; if (strchr(phone, MDPULSCHR) != NULL) timeout += MDPULSDLY; if (timeout < 30) timeout = 30; /* command string can only be 80 characters including "AT" */ if (strlen(command) > 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'<pause>'a'<pause>... 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 --- rfmail 0.3.9 * Origin: Bonafido Usenet <====> Fido Gateway. (3:771/170.0) SEEN-BY: 771/170 180 220 400 772/20 FSC-Control: PATH: 771/170
gandrews@netcom.COM (Greg Andrews) (04/03/91)
In article <398@alchemy.UUCP> bbs@alchemy.UUCP (BBS Administration) writes: >In article <1991Mar29.233228.17548@netcom.COM> gandrews@netcom.COM (Greg Andrews) writes: > >>The Fast Start Guide simply can't compete with a real, live SCO Xenix >>setup guide available from Telebit Tech Support. > >So, just dial 1-800-TELEBIT and ask for one? I guess maybe I should send >in my registration card first (do they check?) > Nope, you don't have to be registered to receive support from Telebit. > >>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. > I've seen at least one person mention that they have an altered version of dialTBIT available for you. They posted a message since my last one, so you may already have seen it. (note that they may not want to mail umpteen copies to everyone in the world! Netlanders should find the message and ask nicely...) > >>The S58=3 setting will hose your XMODEM, YMODEM, and uucp file transfers >>unless they are spoofed by the modem (available only in PEP and V.32/MNP >>connections). S58=0 might be a better setting, or S58=2 S68=255 if your >>system can support RTS/CTS flow control. > >Here's the deal: > >You are correct. That was the problem. Once I changed S58 to 0, the other >site connecting at 2400 bps (thus >not< spoofing the UUCP "g" protocol) >was able to transfer files. Thanks! > >Still, there are problems. >[description of problems deleted] > Most of the trouble you're seeing is related to flow control. You're right, running without flow control can make trouble for you. Uucp doesn't need flow control so much as interactive sessions would. If you change the modem to use RTS/CTS flow control, then you need to also change the computer to use it. DialTBIT opens the port with RTS/CTS line disciplines enabled, and I believe cu will retain them. As someone else mentioned a couple of weeks ago (and I confirmed on my system), SCO's uucico will turn all flow control off in the computer. Even RTS/CTS. To enable RTS/CTS flow control for logins, you would need to insert the CTSFLOW keyword into your /etc/gettydefs entries. My attempts to put in RTSFLOW were successful for 9600 and slower speeds, but not for the 19200 (EXTA) entry. I had to leave the RTSFLOW parameter out of the 19200 and 38400 entries (the 38400 entry was for T1600 testing, not for the T2500). My results were obtained on SCO Unix where the kernel reports a version of 3.2.0 at boot-up time. Other versions of SCO Unix, Open Desktop, or SCO Xenix may behave differently. Any further efforts to use RTS/CTS flow control on a stock 'COM1' or 'COM2' port would need a different tty driver from SCO, or replacing the SCO driver with something like the FAS driver. > >Once again, THANK YOU for answering this article! I was at the end of my >rope and am really happy to have access to USENET. Now, my rope has been >lengthened, but I'm at your mercy once again... > Don't give up until you've at least called tech support! At the very least, it would have saved you several days of frustration... -- .------------------------------------------------------------------------. | Greg Andrews | UUCP: {apple,amdahl,claris}!netcom!gandrews | | | Internet: gandrews@netcom.COM | `------------------------------------------------------------------------'