ostroff@oswego.Oswego.EDU (Boyd Ostroff) (05/16/91)
Submitted-by: ostroff@oswego.Oswego.EDU (Boyd Ostroff) Posting-number: Volume 1, Issue 22 Archive-name: modemon/part01 Again, I posted this several years ago, but have had numerous requests for it since and think it might be helpful to others (judging from some of the requests I've seen in comp.sys.3b1). This is a re-post, not a revision. MODEMON is a small program and shell script which allow you to configure your modem automatically each time init spawns a new getty (or uugetty) on a serial port. It is compatible with both HDB and the stock UUCP, and setup instructions are included for both. |||| Boyd Ostroff / Tech Director / SUNY Oswego Dept of Theatre / 315-341-2987 |||| Sys Admin at cboard.UUCP / Serving the Performing Arts / 315-947-6414/8N1 |||| ostroff@oswego.oswego.edu / cboard!ostroff@natasha.oswego.edu = = = = = = = = = = = = = = = = CUT HERE = = = = = = = = = = = = = = = = = = = # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by ostroff@cboard.UUCP (Boyd Ostroff) on Wed Aug 16 21:17:21 EDT 1989 # Contents: README modemon.sh modemon.c Makefile echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' +-----------------------------------------------------------------------+ | MODEMON - configure an external modem for use on a Unix PC RS232 port | | by Boyd Ostroff (ostroff@oswego.Oswego.EDU) ver 1.8, 8/15/89 | +-----------------------------------------------------------------------+ This program allows you to send commands to an external modem to properly configure it for incoming calls each time a getty is started. This is often needed when using a modem bi-directionally. The modemcap (or HDB Dialers) file configures the modem for outgoing calls, but neither standard nor HDB UUCP provide a mechanism to re-configure it for incoming calls. The program sends commands to the modem and provides some error checking and logging. A little shell script called "modemon.sh" is placed in /etc/inittab instead of the getty (or uugetty) for the tty port. This shell script calls modemon to initialize the modem and then execs getty. By creating the character-special file /dev/modem with a major number the same as the desired port and minor number of 128, the modemon program can talk to the external modem without the presence of CD (Carrier Detect). COMPILE, TEST AND SETUP ----------------------- Look at the #defines at the beginning of the modemon.c program. As supplied it will use tty000 at 2400 baud - change this as needed. Also check the supplied Makefile - it is also setup to use tty000. Type: make to compile the program. Take a look at the "modemon.sh" shell script. I wrote it for my Hayes- compatible Everex modem, so you may need to modify it to suit your needs. Generally speaking, you should turn off command responses and echo. Also note the final line which exec's /etc/getty (or /usr/lib/uucp/uugetty). I am using 2400 baud and also setting a timeout value of 30 seconds (-t30). Change these to whatever you like. Become root and type: make install This will copy the modemon program and shell script to the /etc directory, create /dev/modem and set file modes. Before proceeding, test the modemon program. First make sure that tty000 is not in use. If a getty is running on it, kill it by typing "getoff.sh 000". Try sending some commands to your modem and observe the response, for example: $ /etc/modemon ATZ modemon: sending "ATZ" ATZ OK If nothing happens check your hardware switches and also modem cable - for full control you will generally need pins 1 through 8 and also pin 20 wired straight through. A simple 3-wire cable will *not* give you proper modem control. If you killed a getty on the port, type "geton.sh 000" to restart it. FINAL INSTALLATION ------------------ You'll need to change your /etc/inittab entry so that init will run modemon.sh. MAKE SURE YOU HAVE A BACKUP COPY of your inittab, then edit the file so your tty000 entry looks like this: 000:2:respawn:/etc/modemon.sh ^ | +---note blank space at the beginning of the line - important!---<<<< You might need to change your entry in /usr/lib/uucp/modemcap (or /usr/lib/uucp/Dialers for HDB). This configures the modem for dial-out use by cu and uucico. You usually want to turn on command echo (AT E1) and responses (AT Q0) and turn off auto-answer (AT S0=0) for dial-out use. The following entries work for me - you might need to experiment a little to get them set up properly for your modem. STANDARD UUCP: ------------- This belongs in the /usr/lib/uucp/modemcap file: # Everex EMAC MD2400+ # Name=everex ev|everex|everex 2400:tr=\r:wp=\r:wk=K:wt=T:wx=0:\ :ta=AT E1 Q0 S0=0 \\N1\r:tb=ATDW:\ :es=\r:\ :d1#1:d5#9:\ :pl=tad1wpwkwptbphtrd5wpd5wpwxwxwp: There should be a corresponding entry in /usr/lib/uucp/L-devices: ACU tty000 everex 2400 HDB UUCP: -------- I added this to my /usr/lib/uucp/Dialers file: # Everex EMAC MD2400+ # everex "" "" \K\M\d\dATE1Q0S0=0\\N0\\Q0\r\c\d\d OK\r \Eatdw\T\r\c 2400 \m\c I have the following entry in my Devices file: ACU tty000,M - Any everex \T Finally, type "telinit q", which will cause the system to read the new inittab, and then type "kill <pid>", where <pid> is the process id (as shown by ps -ef) of the getty (or uugetty) running on tty000. You should be all set! Try to log in at various baud rates on your external modem. If you have problems, you'll probably have to change the initialization string that /etc/modemon.sh sends. Try placing an outgoing call with uucico -x6 (or cu -d) and watch the output for errors; edit the modemcap (or Dialers) file as needed to send the correct modem commands. With a little experimentation you should be able to get your modem working reliably in both directions. SETTING HARDWARE SWITCHES ------------------------- Following is my modem's switch configuration - yours may be different, but notice the *function* of each switch (I'm using an EVEREX EMAC MD2400+). SW1 - ON - DTR must be high for modem to accept input or answer a call SW2 - OFF - Result codes sent as words SW3 - ON - Result codes are not sent SW4 - ON - Commands are not echoed SW5 - ON - Auto-answer enabled (but only if DTR is high) SW6 - ON - DCD follows received carrier signal SW7 - OFF - RJ11 phone jack SW8 - OFF - Enable AT command recognition SW9 - OFF - Use Bell 212A protocol @//E*O*F README// chmod u=rw,g=r,o=r README echo x - modemon.sh sed 's/^@//' > "modemon.sh" <<'@//E*O*F modemon.sh//' # modemon.sh - initialize external modem for dial-in use on tty000 # by Boyd Ostroff (ostroff@oswego.Oswego.EDU) version 1.8, 8/16/89 # this program is run by init, and it execs getty after initializing the modem # you must also have the "modemon" program # the following line should be added to /etc/inittab: # # 000:2:respawn:/etc/modemon.sh # # the meaning of the modem commands are as follows: # (this version for Everex MD2400+, edit as needed to suit your requirements) # # m0 turn off monitor speaker # e0 disable command echoing # q1 turn off response display # s0=2 answer phone on 2nd ring # s9=2 drop line .2 seconds after carrier drops # \n3 set MNP auto-reliable mode # \j0 baud adjust off - modem & computer always talk at 2400 baud # \q1 enable xon/xoff between computer & modem # \t5 set inactivity timer for 5 minutes # &t5 prohibit modem from entering test mode date > /usr/adm/modemlog echo 'initializing modem...' >> /usr/adm/modemlog # first, reset the modem to get to a known state /etc/modemon "atz" >> /usr/adm/modemlog sleep 1 # now send the command string /etc/modemon "at m0 e0 q1 s0=2 s9=2 \j0 \q1 \n3 \t5 &t5" >> /usr/adm/modemlog # fire up a getty on the port (use the following line for standard UUCP) # exec /etc/getty -t30 tty000 2400 # start up uugetty (use the following line for HDB UUCP) exec /usr/lib/uucp/uugetty -t30 tty000 2400 @//E*O*F modemon.sh// chmod u=rw,g=r,o=r modemon.sh echo x - modemon.c sed 's/^@//' > "modemon.c" <<'@//E*O*F modemon.c//' /*--------------------------------------------------------------------------*/ /* modemon.c - send commands to an external modem on Unix PC port tty000 */ /* by Boyd Ostroff (ostroff@oswego.Oswego.EDU) version 1.8, 8/16/89 */ /*--------------------------------------------------------------------------*/ /* May be freely modified and distributed as you see fit. */ /* Designed to work with the shell script "modemon.sh". Please read the */ /* accompanying README file before using. */ /*--------------------------------------------------------------------------*/ #include <stdio.h> #include <signal.h> #include <fcntl.h> #include <termio.h> #define FALSE 0 #define TRUE 1 #define ERROR -1 /* change the next four lines to suit your needs */ #define TIMEOUT 2 /* delay before open on will time out */ #define SLEEPTIME 2 /* delay while modem executes a command */ #define MODEMPORT "/dev/modem" /* this is created by the Makefile */ #define PORTSPEED B2400 /* baud rate as given in termio.h */ static int timeout = FALSE; static char *termname; main(argc,argv) /* program should be called with one argument, which is */ int argc; /* the command string to be sent to the modem. Use */ char *argv[]; /* double quotes (") to protect whitespace. A carriage */ { /* return will be appended to the command string. */ int line; int pid; char *cmd; struct termio original; if ((cmd = argv[1]) == NULL) { printf("modemon: no argument given. Usage: modemon \"command\"\n"); exit(ERROR); } if (argc > 2) { printf("modemon: too many arguments. Usage: modemon \"command\"\n"); exit(ERROR); } printf("modemon: sending \"%s\"\n", cmd); if( (line = ttyopen(MODEMPORT, O_RDWR)) == ERROR) { exit(ERROR); } ioctl(line, TCGETA, &original); /* save initial port settings */ if (set_line(line, PORTSPEED) == ERROR) { exit(ERROR); } if ((pid = fork()) != ERROR) /* start a process to read MODEMPORT */ { if (pid == 0) listen(line); /* this function never returns */ } /* it keeps running until killed */ send_cmd(line, cmd); kill(pid, SIGTERM); /* kill the child process */ wait((int *)0); ioctl(line, TCSETAW, &original); /* restore initial port settings */ close(line); exit(0); } /*--------------------------------------------------------------------------*/ send_cmd(line, what) /* send the command string to the modem */ int line; /* tty file descriptor */ char *what; /* modem command */ { int length; int i; unsigned char c = '\r'; length = strlen(what); for (i=0; i <= length; i++) { write(line, what+i, 1); } write(line, &c, 1); /* append a carriage return to end of cmd */ sleep(SLEEPTIME); /* give modem time to execute the command */ } static int set_timeout() { printf("modemon: timeout on opening %s\n", termname); timeout = TRUE; } set_line(fd, speed) /* configure the port so we can talk to the modem */ int fd, speed; { struct termio tt; if (!isatty(fd)) { printf("modemon: not a valid terminal file descriptor\n"); return(ERROR); } if( ioctl(fd, TCGETA, &tt) == ERROR) { printf("modemon: can't get current line settings\n"); return(ERROR); } tt.c_iflag = (IXON|IXOFF); /* xon/xoff flow control enabled */ tt.c_oflag = 0; tt.c_lflag = 0; tt.c_cflag &=~CBAUD; tt.c_cflag |= speed; tt.c_cc[VMIN] = 1; tt.c_cc[VTIME] = 0; if (ioctl(fd, TCSETAW, &tt) == ERROR) /* flush & reset line */ { printf("modemon: can't change current line settings\n"); return(ERROR); } } ttyopen(filename, flags) /* open the modem port */ char *filename; /* will wait for TIMEOUT seconds, then give up */ int flags; /* see p214 of UNIX SYSTEM PROGRAMMING */ { /* by Haviland and Salama */ int (*sigfn)(); int fd = -1; termname = filename; timeout = FALSE; sigfn = signal(SIGALRM, set_timeout); alarm(TIMEOUT); fd = open(filename, flags); alarm(0); signal(SIGALRM, sigfn); return(timeout ? -1: fd); } listen(line) /* send everything that is read from MODEMPORT to stdout */ int line; /* this is a child process forked off from the original */ { unsigned char c; for(;;) /* loops forever until killed */ { read(line, &c, 1); write(1, &c, 1); } } @//E*O*F modemon.c// chmod u=rw,g=r,o=r modemon.c echo x - Makefile sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//' # Makefile for MODEMON - send initialization commands to a modem # Boyd Ostroff, 7/2/89 - version 2.0 # creates /dev/modem, another entry to the tty000 device driver which # will not block if CD isn't present include $(MAKEINC)/Makepre.h CFLAGS= -O OBJ = modemon.o all: $(OBJ) $(LD) $(LDFLAGS) $(SHAREDLIB) $(OBJ) -o modemon strip modemon install: cp modemon.sh /etc chmod 700 /etc/modemon.sh chown root /etc/modemon.sh chgrp root /etc/modemon.sh cp modemon /etc chmod 700 /etc/modemon chown root /etc/modemon chgrp root /etc/modemon mknod /dev/modem c 0 128 chmod 600 /dev/modem chown root /dev/modem chgrp root /dev/modem clean: rm modemon.o include $(MAKEINC)/Makepost.h @//E*O*F Makefile// chmod u=rw,g=r,o=r Makefile echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 144 847 5320 README 40 238 1401 modemon.sh 156 612 4877 modemon.c 32 98 704 Makefile 372 1795 12302 total !!! wc README modemon.sh modemon.c Makefile | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0 -- David H. Brierley Home: dave@galaxia.newport.ri.us; Work: dhb@quahog.ssd.ray.com Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.newport.ri.us %% Can I be excused, my brain is full. **