v01i022: modemon - automatically configure your modem, Part01/01

Boyd Ostroff ostroff at oswego.Oswego.EDU
Thu May 16 03:23:18 AEST 1991


Submitted-by: ostroff at 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 at oswego.oswego.edu / cboard!ostroff at 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 at 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 at 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 at 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 at 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 at galaxia.newport.ri.us; Work: dhb at quahog.ssd.ray.com
Send comp.sources.3b1 submissions to comp-sources-3b1 at galaxia.newport.ri.us
%% Can I be excused, my brain is full. **



More information about the Comp.sources.3b1 mailing list