home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
perkinelmeridris
/
pe7pho.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-12-07
|
14KB
|
539 lines
/* pe7pho.c */
/*
* P h o n e File Transfer Utility
*
* usage:
* phone -i -d -v -l -b -a -p -h -c
*
* where i=init modem <flag>, d=debug level <number>, v=verbose <flag>,
* l=line <device>, b=baud rate <number>, a=answer <flag>,
* p=phone number <string>, h=hang-up request <'a' or 'o'>,
* c=direct connect <'a' or 'o'>
*/
/*
* Modification History:
*
* June 85 - Init write. Dan L. Eisner, Perkin-Elmer Corp.
*
*/
#include <std.h> /* Standard IDRIS definitions */
#include <sys.h> /* Idris system subroutines */
/*#include "sgtty.h" /* Special TTY speed definations */
#include "pe7tty.h" /* Special TTY speed definations */
/* Symbol Definitions */
#define BUFSIZE 80 /* A buffer size for I/O */
#define MYTIME 10 /* Seconds after which I should be timed out */
#define TRUE -1 /* Boolean constants */
#define FALSE 0
/* Global Variables */
int
iflg {0}, /* Indicates to init the modem */
aflg {0}, /* Indicates modem mode */
vflg {0}, /* Indicates verbose mode */
hflg {0}, /* Indicates to hang up the phone */
cflg {0}, /* direct connection thru a modem flag */
timint {0}, /* This is the present time out interval */
debug {0}; /* indicates level of debugging output (0=none) */
char modem_data[BUFSIZE] {0};/* Temp buffer for modem command data */
FILE ttyfd {0}; /* File descriptor of tty for I/O */
struct tty
savemode {0}, /* tty saved mode */
ttymode {0}; /* tty raw mode */
/*
* m a i n
*
* Main routine - parse command and options, set up the
* tty lines, and dispatch to the appropriate routine.
*/
main(argc,argv)
int argc; /* Character pointers to and count of */
char **argv; /* command line arguments */
{
char *ttyname, /* tty name for LINE argument */
*ph_num, /* Phone number for PHONE argument */
result_code, /* The code the modem answered with */
tmp[6]; /* Retry counter buffer */
int speed; /* speed of assigned tty, */
int dial_count; /* Number of times we have dialed the phone */
int answer_count; /* The number of times we tried to answer phone */
int pflg; /* A flag to set if there is a phone number */
int pdial; /* Pulse dialing flag */
/* Make sure there's a command line */
if (argc < 2)
Usage("phone -i -d# -v -l/dev/tty# -b<rate> -a -p<tel. no> -h -c\n");
iflg = FALSE;
aflg = FALSE;
hflg = FALSE;
vflg = FALSE;
cflg = FALSE; /* Turn off all parse flags */
ttyname = 0; /* We did not get a line assignment (pointer) */
ph_num = NULL; /* Set the phone number pointer to a null */
pflg = FALSE; /* ... and the flag to FALSE */
speed = 0; /* Preset the speed to no change */
debug = FALSE; /* Turn off the debug mode */
getflags(&argc,&argv, "i,a,v,h?,c?,l*,p*,b#,d#:F",
&iflg, &aflg, &vflg, &hflg, &cflg, &ttyname, &ph_num, &speed, &debug);
/* Done parsing */
if (debug > 0)
vflg = TRUE; /* Force verbose during debug */
pflg = (ph_num != 0);/* Set up a phone number flag */
if (!aflg && !pflg && !hflg && !cflg && !iflg)
Usage("We need to do something?");
if ((aflg + pflg) > 1)
Usage("Dial and answer the phone?");
if (cflg && (aflg || pflg))
Usage("Direct connect and dial at same time?");
if (hflg != 0 && (aflg || pflg))
Usage("Hang-up after connecting?");
if (cflg == 'a' || cflg == 'A')
aflg = TRUE; /* make it answer */
if (cflg == 'o' || cflg == 'O')
pflg = TRUE; /* force the dial routine to work */
if (aflg || pflg)
iflg = TRUE; /* force int of modem */
if (ttyname == 0) /* If LINE was not specified, we */
ttyname = "/dev/lnk0";/* operate with link tty */
ttyfd = open(ttyname, UPDATE, 0);/* Open the tty line */
if (ttyfd < 0)
Usage("Cannot open %s.", ttyname);
/* Put the proper tty into the correct mode */
egtty(ttyfd, &savemode);/* Save the inputed mode */
egtty(ttyfd,&ttymode); /* set for changing the setup */
ttymode.t_mode |= (M_ALL|M_RAW|MR_XON);
ttymode.t_mode &= ~(M_ECHO | M_2STOP);
ttymode.t_min = 128;
ttymode.t_time = 0;
timint = 0;
if (speed) /* User specified a speed? */
{
switch(speed) /* Get internal system code */
{
case 110: speed = B110; ttymode.t_mode &= M_2STOP; break;
case 150: speed = B150; break;
case 300: speed = B300; break;
case 1200: speed = B1200; break;
case 2400: speed = B2400; break;
case 4800: speed = B4800; break;
case 9600: speed = B9600; break;
default: Usage("Bad line speed.");
}
ttymode.t_ispeed = speed;
ttymode.t_ospeed = speed;
}
estty(ttyfd, &ttymode); /* Put asg'd tty in raw mode */
if (debug)
{
printf("Main 1: A=%d, H=%d, D=%d, ", aflg, hflg, cflg);
printf("L=%s, P=%s\n", ttyname, ph_num);
printf(" Line speed to remote host is %d\n",speed);
printf("Main 2: Bits for ttyfd %x\n",ttymode.t_mode);
}
/* All set up, now execute the command that was given. */
if (iflg) /* Init the modem */
{
timint = MYTIME / 2;
ttymode.t_time = timint * 10;
estty(ttyfd, &ttymode); /* Put tty in short time mode */
if (vflg) printmsg("Initializing the modem");
if ((result_code = init_modem()) <= 0)
Usage("Can not initilize the modem, return = %d\n",result_code);
}
if (pflg)
{
timint = 0;
ttymode.t_time = 0;
estty(ttyfd, &ttymode); /* Put tty in long time mode */
/* If the first character of the phone number is a p then set
up pulse dialing. */
if (*ph_num == 'p' || *ph_num == 'P')
{
pdial = TRUE;
ph_num++;
}
else
pdial = FALSE; /* Set pulse dialing to FALSE */
dial_count = 0;
if (vflg) printmsg("Dialing %s", ph_num);
do
{
if (dial_count++ >= 5)
Usage("Dial count expired");
modem_write(pdial ? "ATPD" : "ATTD", FALSE);
if (!cflg)
modem_write(ph_num,FALSE);
modem_write("\r",FALSE);
if(vflg)
write(STDERR, &tmp, decode(&tmp, 3, "%2i\r", dial_count));
}
while ((result_code = get_result()) == '3'); /* keep dialing */
if (result_code != '1' && result_code != '5')
{
init_modem();
Usage(" \007ERROR, BAD RESULT CODE: 0x%x\r",result_code);
}
if (vflg)
printmsg("Connect at %s\n",
result_code == '5' ? "1200 Baud" : "300 Baud");
sleep(2); /* Wait for other side to be ready */
timint = MYTIME;
ttymode.t_time = timint * 10; /* Reset time out */
estty(ttyfd, &ttymode);
} /* End of pflg */
if (aflg)
{
answer_count = 0;
if (!cflg) /* Direct mode is off? */
{
timint = 30; /* set the time to 30 sec. */
ttymode.t_time = 50;/* Make the time out as big as I can */
estty(ttyfd, &ttymode);
if (vflg) printmsg("Waiting for ring");
do
{
if (answer_count++ >= 10)
Usage("Answer count expired.");
if(vflg)
write(STDERR, &tmp, decode(&tmp, 3, "%2i\r",
answer_count));
}
/* wait for phone to ring (but count tries) */
while ((result_code = get_result()) != '2');
modem_write("ATS2=28A\r",FALSE); /* Answer the phone */
result_code = get_result();
}
else /* !cflg */
{
timint = 0;
ttymode.t_time = 0; /* set time out */
estty(ttyfd, &ttymode);
if (vflg) printmsg("Waiting for connection");
do
{
if (answer_count++ >= 5)
Usage("Answer counter expired.");
modem_write("ATS2=28A\r",FALSE); /* Answer the phone */
if(vflg)
write(STDERR, &tmp, decode(&tmp, 3, "%2i\r",
answer_count));
}
while ((result_code = get_result()) == '3');
} /* end of else !cflg */
if (result_code != '1' && result_code != '5')
Usage("Modem failed to answer correctly.");
if (vflg)
printmsg("Answered at %s\n",
result_code == '5' ? "1200 Baud" : "300 Baud");
timint = MYTIME;
ttymode.t_time = timint * 10; /* Reset time out */
estty(ttyfd, &ttymode); /* Put tty in time out mode */
} /* end of aflg */
if (hflg)
{
timint = MYTIME / 5;
ttymode.t_time = timint * 10; /* restore time out count */
estty(ttyfd, &ttymode);
if(vflg) printmsg("Hanging up");
hang_modem(); /* Hang up the phone */
} /* end of else !hflg */
estty(ttyfd, &savemode);
exit(YES);
}
/*
* p r i n t m s g
*
* printmsg - like printf with "Phone: " preappended
*/
printmsg(fmt, a1, a2, a3, a4, a5)
TEXT *fmt;
{
char cp[BUFSIZE];
cpystr(&cp, "Phone: ", fmt, "\n", NULL);
printf(&cp, a1, a2, a3, a4, a5);
}
/*
* U s a g e
*
* Print formatted message and the exit with a status of NO
*/
Usage(message, a1, a2, a3, a4, a5)
char *message;
{
char cp[BUFSIZE];
cpystr(&cp, "Phone usage: ", message, "\n", NULL);
printf(&cp, a1, a2, a3, a4, a5);
if (ttyfd > 0)
estty(ttyfd, &savemode); /* restore the tty */
exit(NO);
}
/*
* p r i n t f
*
* Print formatted output. Convert from UNIX to IDRIS
*/
printf(msg, a1, a2, a3, a4, a5)
char *msg;
{
char t,
*cpp,
cp[BUFSIZE]; /* Line pointer for the reformatted string */
cpp = cp; /* Init the buffer pointer */
while ((t = *cpp++ = *msg++) != NULL)
if (t == '%')
switch(t = *msg)
{
case 'd': *cpp++ = 'i';
t = *msg++; /* Scrap character */
break;
case 'c': *cpp++ = 'a';
*cpp++ = 'c';
t = *msg++; /* Scrap character */
break;
case 'x': *cpp++ = 'h';
*cpp++ = 'i';
t = *msg++; /* Scrap character */
break;
case 's': *cpp++ = 'p';
t = *msg++; /* Scrap character */
break;
case '\0': break;
default: *cpp++ = *msg++;
}
putfmt(&cp, a1, a2, a3, a4, a5);
}
/*
* i n i t _ m o d e m
*
* Init the modem. first try to reset then if not successful then try to
* escape the modem, and reset.
* The routine returns a result of '0' to '5' or a negative number for timeout
*/
char init_modem()
{
int tries;
char tmp;
if (debug) printf("Init_modem 1:\n");
for (tries = 1; tries <= 4; tries++)
{
sleep(1); /* Wait for a bit */
if (tries >= 2)
{
modem_write("\34\34\34",FALSE);
if ((tmp = get_result()) != '0')
{
modem_write("\35\35\35",FALSE);
if ((tmp = get_result()) != '0')
{
modem_write("+++",FALSE);
tmp = get_result();
}
}
}
modem_write("\rATZ\r", FALSE);
if ((tmp = get_result()) == '0') break;
if (debug) printf("Init_modem 2: tries = %d\n",tries);
}
if (tries > 4) return(tmp);
sleep(2); /* wait for a while while the modem resets */
modem_write("AT E0 F1 Q0 V1 X1 S0=0 S5=255 S2=29 \r",TRUE);
if (debug) printf("Init_modem exit\n");
return(get_result());
}
/*
* h a n g _ m o d e m
*
* Hang up the modem. First escape to the command mode, then hang up the
* phone.
* The routine returns a result of '0' or a negative number for timeout
*/
char hang_modem()
{
int tries;
char tmp;
if (debug) printf("Hang_modem 1:\n");
for (tries = 1; tries <= 4; tries++)
{
sleep(2); /* Wait for a bit each time */
modem_write((hflg == 'a' || hflg == 'A') ?
"\34\34\34" : "\35\35\35", FALSE);
if ((tmp = get_result()) != '0')
{
modem_write("\34\34\34",FALSE);
if ((tmp = get_result()) != '0')
{
modem_write("\35\35\35",FALSE);
if ((tmp = get_result()) != '0')
{
modem_write("+++",FALSE);
tmp = get_result();
}
}
}
modem_write("ATH0\r", FALSE);
if ((tmp = get_result()) == '0') break;
if (debug) printf("Hang_modem 2: tries = %d\n",tries);
}
if (debug) printf("Hang_modem exit\n");
return(tmp);
}
/*
* g e t _ r e s u l t
*
* This routine finds out the result code from the modem.
*/
char get_result()
{
int tmpx; /* The status and goes here */
char result;
result = 0; /* Reset the result flag */
while (result == 0) /* do till something comes in that we recognize */
{
if ((tmpx = modem_read(&modem_data)) <= 0)
result = -1;
else if (modem_data[substr(&modem_data, "OK")])
result = '0';
else if (modem_data[substr(&modem_data, "CONNECT 1200")])
result = '5';
else if (modem_data[substr(&modem_data, "RING")])
result = '2';
else if (modem_data[substr(&modem_data, "NO CARRIER")])
result = '3';
else if (modem_data[substr(&modem_data, "ERROR")])
result = '4';
else if (modem_data[substr(&modem_data, "CONNECT")])
result = '1';
if (debug)
printf("Get_result 1: %c, %d, \"%s\"\n",result,tmpx,modem_data);
} /* End of while loop */
if (debug)
printf("Get_result 2: %c, %d, \"%s\"\n",result,tmpx,modem_data);
return(result);
}
/*
* m o d e m _ w r i t e
*
* send a string to the modem. If eat is TRUE, eat a single echo per xmitted
* character. Does not account for echoed \n's after \r's. Current version
* turns off command echo anyway, so no difference.
*/
modem_write(s, eat)
char *s;
int eat;
{
char t;
int tmpx;
tmpx = 1;
while (*s)
{
write(ttyfd, s++, 1);
if (eat)
if ((tmpx = ioread(&t)) <= 0) break;
}
return(tmpx);
}
/*
* m o d e m _ r e a d
*
* Modem read routine. This routine reads the returned control data from
* The modem.
*/
modem_read(t)
char *t;
{
char chr;
BYTES point;
point = t; /* Set pointer to start of the string */
while (TRUE)
{
if (ioread(t) <= 0) break; /* If an error or eof then exit */
if (*t == '\n') /* What was the last character? */
{
*t++ = '\134'; *t++ = 'n'; /* Make the return into a \n */
break; /* If it was an EOL then exit */
}
if ((chr = *t) < ' ')
{
*t++ = '\134'; *t = chr + '@'; /* Make control to alpha */
}
t++; /* Bump the pointer */
}
*t = NULL; /* Make sure the string ends with a null */
return(t - point); /* Return a character counter */
}
/*
* i o r e a d
*
* Read a character from the i/o channel
*/
ioread(t)
char *t;
{
ULONG time_end,
time();
int result;
if (timint > 0)
{
time_end = time() + timint;
while (time_end >= time())
if ((result = read(ttyfd, t, 1)) > 0) break;
}
else
result = read(ttyfd, t, 1);
return(result);
}
/* pe7pho.c End-of-file */